diff options
author | Paul Duncan <pabs@pablotron.org> | 2021-10-20 18:40:26 -0400 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2021-10-20 18:40:26 -0400 |
commit | e67c7b9ab722beb884b81a51ca74fe3d9605f410 (patch) | |
tree | ebc614a847b29a21dd8e32aa79c5822b00e2f060 /themes | |
parent | 58e1e21b6e20df6b29bd7af2f1aac3c9fc8e91a7 (diff) | |
download | pablotron.org-e67c7b9ab722beb884b81a51ca74fe3d9605f410.tar.bz2 pablotron.org-e67c7b9ab722beb884b81a51ca74fe3d9605f410.zip |
hugo-pt2021: add table shortcode
Diffstat (limited to 'themes')
-rw-r--r-- | themes/hugo-pt2021/layouts/shortcodes/table.html | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/themes/hugo-pt2021/layouts/shortcodes/table.html b/themes/hugo-pt2021/layouts/shortcodes/table.html new file mode 100644 index 0000000..4f7c337 --- /dev/null +++ b/themes/hugo-pt2021/layouts/shortcodes/table.html @@ -0,0 +1,299 @@ +{{/* +Custom Hugo table shortcode which renders tables by: + +1. Reads table definition and data from a structured (JSON, TOML, or + YAML) data file in the site data directory. +2. Renders the table using CSS classes rather than inline styles. + +Why does this shortcode exist? + +1. The default Markdown table markup in Hugo is horrible for anything + more than rudimentary tables. +2. The default Markdown table renderer in Hugo does not give you a way + to set cell alignment without using inline styles, which means + enabling `unsafe-inline` in your `Content-Security-Policy` header. +3. I prever specifying table contents in an external structured file + rather than inline. + +Features: + +* Sets reasonable default `title` and `aria-label` attributes on + table, column headers, and cells. +* Annotates column headers and cells with coordinate and column ID data + attributes for easy styling. +* Add an optional table caption. +* Add optional table, header, row, and cell IDs. +* Specify cell alignment on a per-column or per-cell basis, +* Specify custom table, row, and cell CSS classes. +* Use a custom `data-` attribute prefix to prevent collisions. +* Render cell values as markup or raw HTML. + +By default this shortcode renders using Bulma classes, but that can be +changed by setting individual CSS classes in the `params.table_shortcode` +section of the site's `config.toml`. + +... TODO: move documentation to README.md, document all options ... +Notes: +* IDs keys that begin with "_" should not be used, because we use + them to set some option. +* document `params.table_shortcode` TOML options +* document cell values as literal or as dict (latter allows custom + alignment, id, colspan, and rowspan, class) +* row tooltip with _row and id with _id + +Example: + + {{< table "favorite-fruits" "fruits" >}} + +And the corresponding `data/favorite-fruits/fruits.yaml`: + + --- + # table name (required) + name: "Favorite Fruits" + + # column list (required) + cols: + - id: "name" + name: "Name" + - id: "color" + name: "Color" + - id: "description" + name: "Description" + + # table rows (required) + rows: + - name: "Apple" + color: "Red or Green" + description: "Sweet if red, or sour if green." + - name: "Banana" + color: "Yellow" + description: "Skin is slipping hazard on floor." + - name: "Orange" + color: "Orange" + description: "Citrus bonanza." + - name: "Peach" + color: "Orange" + description: "Don't eat the core!" + +This shortcode will render the following table: + + <table class='table' title='Favorite Fruits' aria-label='Favorite Fruits'> + <caption>My favorite fruits.</caption> + + <thead> + <tr> + <th title='Name' aria-label='Name' data-th_x='0' data-col_id='name'> + Name + </th> + + <th title='Color' aria-label='Color' data-th_x='1' data-col_id='color'> + Color + </th> + + <th title='Description' aria-label='Description' data-th_x='2' data-col_id='description'> + Description + </th> + </tr> + </thead> + + <tbody> + <tr data-tr_y='0'> + <td title='Name' aria-label='Name' data-td_x='0' data-col_id='name'> + Apple + </td> + + <td title='Color' aria-label='Color' data-td_x='1' data-col_id='color'> + Red or Green + </td> + + <td title='Description' aria-label='Description' data-td_x='2' data-col_id='description'> + Sweet if red, or sour if green. + </td> + </tr> + + ... (other rows omitted for brevity) ... + </tbody> + </table> + +You can also configure alignment on a per-column or per-cell basis, and +you can override the `class` attribute for individual cells. +*/}} + +{{/* get config from site params (default to bulma) */}} +{{- $config := default (dict "data_prefix" "" "table_base_css" "table" "cell_align_left" "has-text-left" "cell_align_center" "has-text-centered" "cell_align_justified" "has-text-justified" "cell_align_right" "has-text-right") $.Site.Params.table_shortcode -}} + +{{/* get data prefix */}} +{{- $dp := $config.data_prefix | safeHTMLAttr -}} + +{{/* get table data */}} +{{- $table := (index .Site.Data.tables (.Get 0) (.Get 1)) -}} + +<table + {{/* emit table ID */}} + {{- if $table.id -}}id='{{- $table.id -}}'{{- end -}} + + {{/* base (e.g. "table" in bulma) and custom CSS class for table */}} + class='{{- $config.table_base_css }} {{ default "" $table.css -}}' + + {{/* table tooltip and ARIA label */}} + title='{{- default $table.name $table.tip -}}' + arial-label='{{- default $table.name $table.tip -}}' +> + {{- if $table.caption -}} + {{/* render caption */}} + <caption>{{- $table.caption -}}</caption> + {{- end -}} + + {{/* render table headers */}} + <thead> + <tr> + {{- range $x, $col := $table.cols -}} + <th + title='{{- default $col.tip $col.name -}}' + aria-label='{{- default $col.tip $col.name -}}' + data-{{- $dp -}}th_x='{{- $x -}}' + data-{{- $dp -}}='{{- $col.id -}}' + > + {{- $col.name -}} + </th> + {{- end -}} + </tr> + </thead> + + {{- if $table.rows -}} + <tbody> + {{/* render rows */}} + {{- range $y, $row := $table.rows -}} + <tr + {{/* emit row ID */}} + {{- if $row._id -}} + id='{{- $row._id -}}' + {{- end -}} + + {{- if $row._tip -}} + {{/* emit row tooltip */}} + title='{{- $row._tip -}}' + aria-label='{{- $row._tip -}}' + {{- end -}} + + {{- if $row._css -}} + {{/* emit row css */}} + class='{{- $row._css -}}' + {{- end -}} + + {{/* row position */}} + data-{{- $dp -}}tr_y='{{- $y -}}' + > + {{- range $x, $col := $table.cols -}} + {{/* get cell */}} + {{- $cell := index $row $col.id -}} + {{- $is_map := reflect.IsMap $cell -}} + + {{/* get cell value */}} + {{- $val := "" -}} + {{- if $is_map -}} + {{- $val = index $cell "val" -}} + {{- else -}} + {{- $val = $cell -}} + {{- end -}} + + {{/* get cell ID */}} + {{- $cell_id := "" -}} + {{- if $is_map -}} + {{- if index $cell "id" -}} + {{- $cell_id = $cell.id -}} + {{- end -}} + {{- end -}} + + {{/* get cell tip */}} + {{- $tip := (default $col.tip $col.name) -}} + {{- if $is_map -}} + {{- if index $cell "tip" -}} + {{- $tip = index $cell "tip" -}} + {{- end -}} + {{- end -}} + + {{/* get cell alignment */}} + {{- $align := $col.align -}} + {{- if and $is_map -}} + {{- if (index $cell "align") -}} + {{- $align = index $cell "align" -}} + {{- end -}} + {{- end -}} + + {{/* get default cell css */}} + {{- $css := "" -}} + {{- if eq $align "left" -}} + {{- $css = $config.cell_align_left -}} + {{- else if eq $align "center" -}} + {{- $css = $config.cell_align_center -}} + {{- else if eq $align "justified" -}} + {{- $css = $config.cell_align_justified -}} + {{- else if eq $align "right" -}} + {{- $css = $config.cell_align_right -}} + {{- end -}} + + {{/* get cell css override */}} + {{- if $is_map -}} + {{- if index $cell "css" -}} + {{- $css = $cell.css -}} + {{- end -}} + {{- end -}} + + {{/* get colspan */}} + {{- $colspan := 1 -}} + {{- if $is_map -}} + {{- if index $cell "colspan" -}} + {{- $colspan = $cell.colspan -}} + {{- end -}} + {{- end -}} + + {{/* get rowspan */}} + {{- $rowspan := 1 -}} + {{- if $is_map -}} + {{- if index $cell "rowspan" -}} + {{- $rowspan = $cell.rowspan -}} + {{- end -}} + {{- end -}} + + {{/* emit cell */}} + <td + {{/* emit cell ID */}} + {{- if $cell_id -}} + id='{{- $cell_id -}}' + {{- end -}} + + title='{{- $tip -}}' + aria-label='{{- $tip -}}' + class='{{- $css -}}' + + data-{{- $dp -}}td_x='{{- $x -}}' + data-{{- $dp -}}col_id='{{- $col.id -}}' + + {{- if gt $colspan 1 -}} + colspan='{{- $colspan -}}' + {{- end -}} + + {{- if gt $rowspan 1 -}} + rowspan='{{- $rowspan -}}' + {{- end -}} + > + {{- if $is_map -}} + {{- if $cell.html -}} + {{/* render as raw HTML */}} + {{- $val | safeHTML -}} + {{- else -}} + {{/* render as markup */}} + {{- $val | $.Page.RenderString -}} + {{- end -}} + {{- else -}} + {{/* render as markup */}} + {{- $val | $.Page.RenderString -}} + {{- end -}} + </td> + {{- end -}} + </tr> + {{- end -}} + </tbody> + {{- end -}} +</table> |