Why Sponsor Oils? | source | all docs for version 0.32.0 | all versions | oils.pub
ul-table is an HTML processor that lets you write tables as bulleted
lists, in Markdown.
It's a short program I wrote because I got tired of reading and writing <tr>
and <td> and </td> and </tr>. And I got tired of aligning numbers by
writing <td class="num"> for every cell.
Let's see how it works. How do you make this table?
| Shell | Version |
|---|---|
| bash | 5.2 |
| OSH | 0.25.0 |
With ul-table, you create a two-level Markdown list, inside <table>
tags:
<table>
- thead
- Shell
- Version
- tr
- [bash](https://www.gnu.org/software/bash/)
- 5.2
- tr
- [OSH](https://oils.pub/)
- 0.25.0
</table>
The header and data rows are at the top level, and the cells are indented under them.
The conversion takes 2 steps: it's Markdown → HTML → HTML.
First, any Markdown processor will produce this list structure, with <ul> and
<li>:
Second, our ul-table plugin parses and transforms that into a table, with
<tr> and <td>:
| Shell | Version |
|---|---|
| bash | 5.2 |
| OSH | 0.25.0 |
So ul-table is an HTML processor, not a Markdown processor. But it's
meant to be used with Markdown.
Compared to other table markup formats, ul-table is shorter, less noisy, and
easier to edit:
Recall that a ul-table is a two-level Markdown list, between <table>
tags. The top level list contains either:
thead |
zero or one, at the beginning |
tr |
zero or more, after thead |
The second level contains the contents of cells, but you don't write td
or <td>.
To make the table look nice, I add a <style> tag, inside Markdown:
<style>
table {
margin: 0 auto;
}
td {
padding-left: 1em;
padding-right: 1em;
}
</style>
HTML attributes like <tr class=foo> and <td id=bar> let you format and
style your table.
You can add attributes to cells, columns, and rows.
| Name | Age |
|---|---|
| Alice | 42 |
| Bob | 9 |
Add cell attributes with a cell-attrs tag after the cell contents:
- thead
- Name
- Age
- tr
- Alice
- 42 <cell-attrs class=hi />
- tr
- Bob
- 9
You must use a self-closing tag:
<cell-attrs /> # Yes
<cell-attrs> # No: this is an opening tag
Notice that ul-table takes the attributes from the <cell-attrs /> tag, and
puts it on the generated <td> tag.
| Name | Age |
|---|---|
| Alice | 42 |
| Bob | 9 |
To add attributes to every cell in a column, put <cell-attrs /> in the
thead section:
- thead
- Name
- Age <cell-attrs class=num />
- tr
- Alice
- 42 <!-- this cell gets class=num -->
- tr
- Bob
- 9 <!-- this cells gets class=num -->
Then every <td> in the column will "inherit" those attributes. This is
useful for aligning numbers to the right:
<style>
.num {
align: right;
}
</style>
If the same attribute appears in a column in both thead and tr, the values
are concatenated, with a space. Example:
<td class="from-thead from-tr">
| Name | Age |
|---|---|
| Alice | 42 |
| Bob | 9 |
To add row attributes, put <row-attrs /> after the - tr:
- thead
- Name
- Age
- tr
- Alice
- 42
- tr <row-attrs class="special-row" />
- Bob
- 9
This example uses more features, like Markdown and HTML inside cells. You may want to view the source text for this table: doc/ul-table.md.
| Shell | Version | Example Code | ||||
|---|---|---|---|---|---|---|
| bash | 5.2 |
|
||||
| dash | 1.5 | Inline HTML | ||||
| mksh | 4.0 |
|
||||
| zsh | 3.6 | Unordered List
|
||||
| yash | 1.0 | Ordered List
|
||||
|
This is paragraph one. This is paragraph two |
Another cell with ... ... multiple paragraphs. |
Another table:
| OSH | YSH |
|---|---|
|
|
| x | y |
Here are some quirks I ran into when using ul-table.
(1) CommonMark doesn't allow empty list items:
- thead
-
- above is not rendered as a list item
You can work around this by using a comment, or invisible character:
- tr
- <!-- empty -->
- above is OK
- tr
-
- also OK
(2) Similarly, a cell with a literal hyphen may need a comment or space in front of it:
- tr
- <!-- hyphen --> -
- -
ul-table is a nice way of writing and maintaining HTML tables. The appendix
has links and details.
TODO: I would like someone to produce a DOM-based implementation!
Our implementation is pretty low-level. It's meant to avoid the "big load anti-pattern" (allocating too much), so it's a necessarily more verbose.
A DOM-based implementation should be much less than 1000 lines.
ul-table.
Source: doc/proc-func.md${x@a}I converted the tables in these September posts to ul-table:
The markup was much shorter and simpler after conversion!
TODO:
<th> is like <td>, but it belongs in <thead><tr>. Browsers make it
bold and centered.<colgroup> and <col> often do do what I want.
class= columns and align them to the
right or left. You have to put class= on every <td> cell instead.tfoot?tbody?We could help users edit well-formed tables with enforced column names:
- thead
- <cell-attrs ult-name=name /> Name
- <cell-attrs ult-name=age /> Age
- tr
- <cell-attrs ult-name=name /> Hi
- <cell-attrs ult-name=age /> 5
This is a bit verbose, but may be worth it for large tables.
Less verbose syntax idea:
- thead
- <ult col=NAME /> <cell-attrs class=foo /> Name
- <ult col=AGE /> Age
- tr
- <ult col=NAME /> Hi
- <ult col=AGE /> 5
Even less verbose:
- thead
- {NAME} Name
- {AGE} Age
- tr
- {NAME} Hi
- {AGE} 5
The obvious problem is that we might want the literal text {NAME} in the
header. It's unlikely, but possible.