aboutsummaryrefslogtreecommitdiff
path: root/themes/hugo-pt2021/layouts/shortcodes
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2021-10-20 18:40:26 -0400
committerPaul Duncan <pabs@pablotron.org>2021-10-20 18:40:26 -0400
commite67c7b9ab722beb884b81a51ca74fe3d9605f410 (patch)
treeebc614a847b29a21dd8e32aa79c5822b00e2f060 /themes/hugo-pt2021/layouts/shortcodes
parent58e1e21b6e20df6b29bd7af2f1aac3c9fc8e91a7 (diff)
downloadpablotron.org-e67c7b9ab722beb884b81a51ca74fe3d9605f410.tar.bz2
pablotron.org-e67c7b9ab722beb884b81a51ca74fe3d9605f410.zip
hugo-pt2021: add table shortcode
Diffstat (limited to 'themes/hugo-pt2021/layouts/shortcodes')
-rw-r--r--themes/hugo-pt2021/layouts/shortcodes/table.html299
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>