OILS / doc / ul-table.md View on Github | oilshell.org

366 lines, 272 significant
1ul-table: Markdown Tables Without New Syntax
2================================
3
4Our `ul-table` plugin allows you to write HTML **tables** as bulleted
5**lists**.
6
7Why?
8
9- Because writing and maintaining `<tr>` and `<td>` and `</td>` and `</tr>` is
10 tedious.
11- Because Markdown can express bulleted lists, so your file remains **valid**
12 Markdown.
13 - Your documentation still be readable when viewed with sourcehut or Github.
14
15That is, this way of writing tables involves **no** new syntax. It's not a
16Markdown language extension.
17
18<div id="toc">
19</div>
20
21## Simple Example
22
23Suppose you want to make this table:
24
25<style>
26table {
27 margin: 0 auto;
28}
29td {
30 padding: 5px;
31}
32</style>
33
34<table>
35
36- thead
37 - Shell
38 - Version
39- tr
40 - [bash]($xref)
41 - 5.2
42- tr
43 - [OSH]($xref)
44 - 0.25.0
45
46</table>
47
48With `ul-table`, you type a **two-level Markdown list**, inside `<table>` tags:
49
50 <table>
51
52 - thead
53 - Shell
54 - Version
55 - tr
56 - [bash]($xref)
57 - 5.2
58 - tr
59 - [OSH]($xref)
60 - 0.25.0
61
62 </table>
63
64(This format looks similar to [tables in
65reStructuredText](https://sublime-and-sphinx-guide.readthedocs.io/en/latest/tables.html)).
66
67The conversion takes two steps:
68
691. Any Markdown translator will produce a
70 `<table> <ul> <li> ... </li> </ul> </table>` structure.
711. **Our** `ul-table` plugin transforms that into a
72 `<table> <tr> <td> </td> </tr> </table>` structure, which is a normal HTML
73 table.
74
75### Pure Markdown Requires Tedious HTML
76
77The bulleted lists are easier to **read and write**! Here's the equivalent in
78CommonMark:
79
80 <table>
81 <thead>
82 <tr>
83 <td>Shell</td>
84 <td>Version</td>
85 </tr>
86 </thead>
87 <tr>
88 <td>
89
90 [bash]($xref)
91
92 </td>
93 <td>5.2</td>
94 </tr>
95 <tr>
96 <td>
97
98 [OSH]($xref)
99
100 </td>
101 <td>0.25.0</td>
102 </tr>
103
104 </table>
105
106It uses the rule where you can embed HTML inside markdown, and then markdown
107inside HTML.
108
109With `ul-table`, we **remove** this kind of mutual nesting (at least, one level
110of it.)
111
112---
113
114Note that HTML inside CommonMark results in an extra `<p>` element:
115
116 <td>
117 <p>OSH</p>
118 </td>
119
120In contrast, `ul-table` can produce:
121
122 <td>
123 OSH
124 </td>
125
126### Stylesheet
127
128To make the table look nice, I use `<style>` tags inside Markdown:
129
130 <style>
131 table {
132 margin: 0 auto;
133 }
134 td {
135 padding: 5px;
136 }
137 </style>
138
139### The Untranslated Markdown
140
141By the way, if you omit the `<table>` tags, then the bulleted list looks like
142this:
143
144- thead
145 - Shell
146 - Version
147- tr
148 - [bash]($xref)
149 - 5.2
150- tr
151 - [OSH]($xref)
152 - 0.25.0
153
154This is how your tables will appear on sourcehut or Github &mdash; the contents
155are still readable. Remember, `ul-table` is **not** an extension to Markdown
156syntax.
157
158## More Complex Example
159
160View the source code of this table: [doc/ul-table.md]($oils-src)
161
162[bash]: $xref
163
164<table id="foo">
165
166- thead
167 - Shell
168 - Version
169 - Example Code
170- tr
171 - [bash][]
172 - 5.2
173 - ```
174 echo sh=$bash
175 ls /tmp | wc -l
176 echo
177 ```
178- tr
179 - [dash]($xref)
180 - 1.5
181 - <em>Inline HTML</em>
182- tr
183 - [mksh]($xref)
184 - 4.0
185 - <table>
186 <tr>
187 <td>HTML table</td>
188 <td>inside</td>
189 </tr>
190 <tr>
191 <td>this table</td>
192 <td>no way to re-enter inline markdown though?</td>
193 </tr>
194 </table>
195- tr
196 - [zsh]($xref)
197 - 3.6
198 - Unordered List
199 - one
200 - two
201- tr
202 - [yash]($xref)
203 - 1.0
204 - Ordered List
205 1. one
206 1. two
207- tr
208 - [ksh]($xref)
209 - This is
210 paragraph one.
211
212 This is
213 paragraph two
214 - Another cell with ...
215
216 ... multiple paragraphs.
217
218</table>
219
220## Real Examples in Oils
221
222TODO
223
224- [Guide to Procs and Funcs]($oils-doc:proc-func.html)
225 - interior/exterior?
226- blog
227 - What Oils Looks Like in 2024
228 - Line Counts
229 - Narrow waist? diagrams
230
231- TODO: Wiki pages could use conversion
232 - [Alternative Shells]($wiki)
233 - [Alternative Regex Syntax]($wiki)
234 - [Survey of Config Languages]($wiki)
235 - [Polyglot Language Understanding]($wiki)
236 - [The Biggest Shell Programs in the World]($wiki)
237
238## `ul-table` Features
239
240### Works Well with both Markdown and inline HTML
241
242- Any markdown can be in a cell
243 - paragraphs, code blocks with backticks, nested lists
244 - Markdown supports arbitrary HTML, so arbitrary HTML can be in a cell
245 - no new rules to learn!
246- You can mix `ul-table` and inline HTML
247 - e.g. the header can use `ul-table`, but other rows use raw `<tr>`
248
249### Attributes for Cells, Columns, and Rows
250
251- Cells: put `<td-attrs class=foo />` in a `tr` section
252- Columns: put `<td-attrs class=foo />` in the `thead` section
253- Rows: `tr <tr-attrs class=foo />`
254
255Note: should have a custom rule of aligning numbers to right, and text to left?
256I think `web/table/` has that rule.
257
258## Quirks
259
260### CommonMark
261
262(1) CommonMark doesn't seem to allow empty list items:
263
264 - thead
265 -
266 - above is not rendered as a list item
267
268A workaround is to use a comment or invisible character:
269
270 - tr
271 - <!-- empty -->
272 - above is OK
273 - tr
274 - &nbsp;
275 - also OK
276
277- [Related CommonMark thread](https://talk.commonmark.org/t/clarify-following-empty-list-items-in-0-31-2/4599)
278
279As similar issue is that line breaks affect backtick expansion to `<code>`:
280
281 - tr
282 - <td-attrs /> <!-- we need something on this line -->
283 ... More `proc` features ...
284
285I think this is also because `<td-attrs />` doesn't "count" as text, so the
286list item is considered empty.
287
288(2) Likewise, a cell with a literal hyphen may need a comment in front of it:
289
290 - tr
291 - <!-- hyphen --> -
292 - <!-- hyphen --> -
293
294
295### HTML
296
297- `<th>` is like `<td>`, but it belongs in `<thead><tr>`. Browsers make it
298 bold and centered.
299- You can't put `class=` on `<colgroup>` and `<col>` and align columns left and
300 right.
301 - You have to put `class=` on *every* `<td>` cell instead.
302 - `ul-table` solves this with "inherited" `<td-attrs />` in the `thead`
303 section.
304
305## FAQ
306
307(1) Why do row with attributes look like `tr <tr-attrs />`? The first `tr`
308looks redundant.
309
310This is because of the CommonMark quirk above: a list item without **text** is
311treated as **empty**. So we require the extra `tr` text.
312
313It's also consistent with plain rows, without attributes.
314
315## Appendix
316
317### Related Docs
318
319- [How We Build Oils Documentation](doc-toolchain.html)
320- [Examples of HTML Plugins](doc-plugins.html)
321
322### Our Style is Nicer Than Github's
323
324Github-flavored Markdown has an non-standard extension for tables:
325
326- [Github: Organizing Information With Tables](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables)
327
328This style is hard to read and write, especially with large tables:
329
330```
331| Command | Description |
332| --- | --- |
333| git status | List all new or modified files |
334| git diff | Show file differences that haven't been staged |
335```
336
337Our style is less noisy and more easily editable:
338
339```
340- thead
341 - Command
342 - Description
343- tr
344 - git status
345 - List all new or modified files
346- tr
347 - git diff
348 - Show file differences that haven't been staged
349```
350
351### CommonMark
352
353- 2014 discussion: [Tables in pure Markdown](https://talk.commonmark.org/t/tables-in-pure-markdown/81)
354- 2022 discussion: [Obvious Markdown syntax for Tables](https://talk.commonmark.org/t/obvious-markdown-syntax-for-tables/4143/9)
355
356
357### Implemention
358
359- [doctools/ul_table.py]($oils-src) - less than 400 lines
360- [lazylex/html.py]($oils-src) - about 400 lines
361
362TODO:
363
364- Make it run under Python 3, including unit tests
365- De-couple it from cmark.so
366 - Use Unix pipes, with a demo in `doctools/ul-table.sh`