Skip to content

fix(admin): make the declarative Tabulator layer apply its attributes - #20457

Merged
miketheman merged 2 commits into
pypi:mainfrom
miketheman:miketheman/tabulator-fix
Aug 28, 2026
Merged

fix(admin): make the declarative Tabulator layer apply its attributes#20457
miketheman merged 2 commits into
pypi:mainfrom
miketheman:miketheman/tabulator-fix

Conversation

@miketheman

Copy link
Copy Markdown
Member

A tabulator-* attribute could be spelled right and still do nothing. Tabulator parses them in HtmlTableImport, which initializes after the core modules, so any option read during a module's initialize() (layout, groupBy) kept its default. Table options are read here now and handed to the constructor, with the attributes removed once read so the later parse cannot put the string back. The lookup uses hasOwn, since HTML lowercases attribute names and a plain lookup answers for constructor, and each table mounts in its own try/catch so one bad attribute cannot flatten every table after it.

Cell values arrive as innerHTML, already escaped by the template, and the default formatter escaped them a second time, so a project or status holding &, < or > rendered as a visible entity. Re-injecting the same markup round-trips it exactly and covers the link and badge columns that carried tabulator-formatter="html". A new test asserts the rule this rests on: a data-tabulator cell may only hold Jinja-autoescaped output.

Since values are markup, sorting and filtering were comparing hrefs and class names, so both read the text out first, memoized because a sort asks for the same value many times. Blanks sort last either way, and columns cap their initial width and wrap at the cap rather than clipping, since Tabulator sizes to the widest cell and a payload or caveat blob is what the admin came to read.

data-tabulator-column-menu and data-tabulator-download bring back the DataTables column menu, copy and CSV over Tabulator's own Download and Clipboard modules. Exports read cell text, and the menu tracks what the admin asked for rather than isVisible(), which is also false for a column the responsive layout has folded away. A collapsing table gets the handle that opens the folded block, which no attribute can ask for.

Adds the first tests for admin JS. Jest could not load Tabulator at all, since the published CJS bundle is a browser UMD that exports nothing to require, so it maps the package to the ESM build webpack ships, with the flag that enables that quoted so the shell expands it.

A `tabulator-*` attribute could be spelled right and still do nothing.
Tabulator parses them in HtmlTableImport, which initializes after the core
modules, so any option read during a module's `initialize()` (`layout`,
`groupBy`) kept its default. Table options are read here now and handed to the
constructor, with the attributes removed once read so the later parse cannot
put the string back. The lookup uses `hasOwn`, since HTML lowercases attribute
names and a plain lookup answers for `constructor`, and each table mounts in
its own try/catch so one bad attribute cannot flatten every table after it.

Cell values arrive as innerHTML, already escaped by the template, and the
default formatter escaped them a second time, so a project or status holding
`&`, `<` or `>` rendered as a visible entity. Re-injecting the same markup
round-trips it exactly and covers the link and badge columns that carried
`tabulator-formatter="html"`. A new test asserts the rule this rests on: a
`data-tabulator` cell may only hold Jinja-autoescaped output.

Since values are markup, sorting and filtering were comparing hrefs and class
names, so both read the text out first, memoized because a sort asks for the
same value many times. Blanks sort last either way, and columns cap their
initial width and wrap at the cap rather than clipping, since Tabulator sizes
to the widest cell and a payload or caveat blob is what the admin came to
read.

`data-tabulator-column-menu` and `data-tabulator-download` bring back the
DataTables column menu, copy and CSV over Tabulator's own Download and
Clipboard modules. Exports read cell text, and the menu tracks what the admin
asked for rather than `isVisible()`, which is also false for a column the
responsive layout has folded away. A collapsing table gets the handle that
opens the folded block, which no attribute can ask for.

Adds the first tests for admin JS. Jest could not load Tabulator at all, since
the published CJS bundle is a browser UMD that exports nothing to require, so
it maps the package to the ESM build webpack ships, with the flag that enables
that quoted so the shell expands it.

Signed-off-by: Mike Fiedler <miketheman@gmail.com>
@miketheman miketheman added the javascript requires change to JavaScript files label Aug 28, 2026
@miketheman
miketheman requested review from a team as code owners August 28, 2026 13:53
@miketheman miketheman added admin Features needed for the Admin UI (people running the site) core-team labels Aug 28, 2026
@miketheman
miketheman enabled auto-merge (squash) August 28, 2026 15:35
@miketheman
miketheman merged commit e531d36 into pypi:main Aug 28, 2026
21 checks passed
@miketheman
miketheman deleted the miketheman/tabulator-fix branch August 28, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

admin Features needed for the Admin UI (people running the site) core-team javascript requires change to JavaScript files

2 participants