feat(table): make the wrap argument work with data tables#2018
Merged
Conversation
Design to make the table `wrap` argument compatible with data tables: - Hinode renders a single table (one RenderString) for both wrap paths - Plain tables carry both layouts via responsive display utilities - Data tables get the wrapped layout from a simple-datatables tableRender hook, gated on matchMedia and re-rendered with dt.update(true) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Six tasks across hinode, mod-simple-datatables and mod-utils, each ending in an independently verifiable deliverable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exercises a plain wrapped table with striping, a wrapped data table, and a two-column wrapped table. Regression target for the wrap rework.
A workspace use directive alone does not override mod-simple-datatables, so a replacements line is needed too. Both files must be reverted before merge.
A wrapped table will render as a single table serving both widths, so the border suppression has to be scoped to the breakpoint rather than applied unconditionally, and Bootstrap's odd-row striping has to be recomputed per record pair. Safelist both wrap classes: on a data table they are only ever added by JavaScript.
A wrapped table was rendered twice - once regular, once wrapped - and both copies were emitted into the page. Render it once instead: a plain table now carries both layouts and switches with display utilities, and a data table is rendered uniformly and marked with data-table-wrap so simple-datatables can apply the wrapped layout itself. This halves the markup of a wrapped table, parses the Markdown once instead of twice, and stops Flexsearch indexing every wrapped table twice.
A wrapped data table gets its layout built in the browser, so the `d-none` that hides the wrapped column's heading is emitted by JavaScript alone. On a site whose only wrapped tables are data tables the class never reaches hugo_stats.json and PurgeCSS would strip it, leaving the heading visible below the breakpoint. It survives today only incidentally, because the navbar chrome happens to emit it. Safelist it explicitly alongside table-wrap and table-border-bottom-wrap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mod-simple-datatables declares integration = "optional", so Hinode only loads its JavaScript for pages that list it in frontmatter. Without this the fixture's data table was inert - no DataTable instance, no pager - so the wrapped data-table path was never actually exercised.
…p marker
`d-{breakpoint}-table-cell` is emitted only by render-table.html, for a plain wrapped table.
PurgeCSS is fed the previous build's hugo_stats.json whenever PostCSS is not deferred to Hugo's
post-process phase (`hugo server`, or any non-production build with style.purge enabled). A site
whose committed stats predate its first wrapped table therefore lost the rule: the wrapped
column's cells kept only `d-none` and stayed hidden at every width, while the colspan rows showed
at every width. Safelist the utility for every breakpoint infix.
Correct the group's comment while here. `d-none` is emitted by a dozen core layouts and can never
actually be purged, so it is listed only to record the dependency, not because JavaScript adds it.
The exampleSite carries its own PostCSS config and had never received the wrap safelist at all, so
apply the group there too.
`table-wrap` is an internal marker that keys the wrap-specific striping rules, but the partial
handed ownership back to the caller. `class="table-wrap"` without `wrap` striped a uniform table by
record pairs, and a `{.table-wrap}` attribute block on a sortable table made the render hook split
its rows server-side - the very layout simple-datatables must never be given. Filter the marker out
of the caller's class list, and flag a data table through the page store so the render hook ignores
the attribute there.
✅ Deploy Preview for gethinode-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Picks up the corrected wrap argument comment, which no longer claims that wrap is incompatible with data tables. The exampleSite resolves the same version through the committed workspace, so its own pin needs no change.
Collaborator
Author
|
Rebased onto the released mod-utils v6.4.2 ( |
Collaborator
Author
|
🎉 This PR is included in version 3.0.6 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
markdumay
added a commit
that referenced
this pull request
Jul 14, 2026
The wrap argument now combines with sortable, paginate and searchable. Hinode renders a wrapped data table uniformly and marks it with data-table-wrap; mod-simple-datatables v4.1.0 applies the wrapped layout below the main breakpoint through simple-datatables' tableRender hook, so sorting, searching and paging keep operating on an unmodified row model. Plain wrapped tables are now rendered once rather than twice, which halves their markup, parses the Markdown once, and stops Flexsearch indexing them twice. The work shipped across v3.0.6 and this release; see #2018 and #2020. Recorded as a feature so the changelog reflects the new capability.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The table shortcode's
wrapargument moves a wide table's last column onto a full-width row of its own below the site's main breakpoint. It could not be combined withsortable/paginate/searchable— mod-utils documented the incompatibility explicitly. This makes them work together, and rewrites the plain path to render one table instead of two.The problem
wraprendered the table twice: a regular copy shown at or above the main breakpoint, and a pre-split "wrapped" copy shown below it. Both copies carried the.data-tableclass, so simple-datatables initialised on both — and the wrapped copy's ragged DOM (N−1 header cells, alternating N−1 / 1-cell rows) cannot be represented by its uniform row model.The change
Plain wrapped table → one table carrying both layouts. The last
<th>and<td>getd-none d-{bp}-table-cell, the other cells gettable-border-bottom-wrap, and an extra<tr class="d-{bp}-none">with<td colspan="N-1">follows each data row. Still pure CSS and static HTML — it works with JavaScript disabled, which is why it stayed a render hook.Wrapped data table → rendered uniformly and marked
data-table-wrap/data-table-wrap-breakpoint. mod-simple-datatables (gethinode/mod-simple-datatables#277) then builds the wrapped layout in the browser via simple-datatables'tableRenderhook, which rewrites the virtual DOM only — so sorting, searching and paging keep operating on an unmodified row model.Beyond enabling the combination, this parses the Markdown once instead of twice, halves the markup of a wrapped table, and stops Flexsearch indexing every wrapped table twice.
Things worth knowing in review
.table-striped(tr:nth-of-type(odd), which counts hidden rows too) would stripe every record instead of alternating._table.scssnow stripes per record pair (4n + 1, plus4n + 2below the breakpoint where the second row is visible).d-{bp}-table-cellis safelisted.render-table.htmlis its only emitter in the theme, and on the eager-PostCSS path PurgeCSS reads the previous build'shugo_stats.json. Without the safelist entry the class is purged on a site's first build after upgrade, hiding the wrapped column at every width. Added to both postcss configs —exampleSite/has its own tracked copy that had drifted.xsguard. The old code emittedd-xs-none, which Bootstrap never generates.wrapis now a no-op atxs.table-wrapis an internal marker the templates own; callers can no longer inject it and misfire the striping override.Release ordering
The intermediate state is safe in both directions: with the currently vendored module, a wrapped data table simply renders as a normal unwrapped data table (
data-table-wrapis an unread attribute). mod-simple-datatables needs to ship and be re-vendored before wrapped data tables work on a real site.Verification
exampleSite/content/en/table-demo.mdis the fixture. Verified in a real browser: wrapped data tables initialise with zero console errors, the pager counts records rather than rendered rows, sorting keeps each description with its record, search still matches the wrapped column, and sort/page/search survive a breakpoint crossing. The plain path was verified with JavaScript disabled at both widths, with striping confirmed per record via computedbox-shadow.Known gap, not addressed
layouts/_shortcodes/table.htmlnever forwardsfilter/filter-colto the partial, so the category filter is unreachable from Markdown even thoughdata/structures/table.ymldeclares both. Pre-existing; worth a follow-up to wire them through or drop them.🤖 Generated with Claude Code