Add configurable tables support#1104
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a tables configuration option to disable table functionality end-to-end (UI, extensions, commands), with supporting docs and automated tests.
Changes:
- Introduces
tablesconfig (default enabled) andsupportsTablesgating to prevent table components/commands when disabled. - Hides the table toolbar button via a
data-tablesattribute and CSS when tables are disabled. - Adds Ruby system tests + Playwright tests + fixture to validate disabled behavior and table stripping.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/system/tables_disabled_test.rb | System-level regression coverage for “tables disabled” behavior in the dummy app |
| test/dummy/app/views/posts/_form.html.erb | Wires tables="false" attribute based on params flag |
| test/browser/tests/tables/disabled.test.js | Playwright coverage for UI + command + load-stripping behaviors when tables are disabled |
| test/browser/fixtures/tables-false.html | Fixture page for running the editor with tables="false" |
| src/extensions/tables_extension.js | Gates the tables extension on supportsTables instead of supportsRichText |
| src/elements/editor.js | Adds supportsTables, conditionally registers table components, and tags toolbar with data-tables |
| src/editor/command_dispatcher.js | Prevents dispatchInsertTable() when tables are disabled |
| src/config/lexxy.js | Adds tables: true default to configuration presets |
| docs/configuration.md | Documents the new tables option |
| app/assets/stylesheets/lexxy-editor.css | Hides the table toolbar button when data-tables="false" |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| await editor.click() | ||
| await editor.locator.evaluate((el) => el.editor.update(() => el.editor.dispatchCommand("insertTable"))) | ||
|
|
||
| await expect(editor.content.locator("table")).toHaveCount(0) | ||
| await expect.poll(() => valueOf(editor)).not.toContain("<table") |
There was a problem hiding this comment.
"insertTable" is a registered Lexxy command — it is exactly what the toolbar button dispatches via data-command="insertTable" (see toolbar.js and the COMMANDS list in command_dispatcher.js), and it routes to INSERT_TABLE_COMMAND internally. So the test does exercise the real insert path. When tables are disabled the toolbar button is CSS-hidden (not removed), so dispatching that command programmatically is the appropriate mechanism here; the disabled behavior is additionally covered by the button-hidden and load-stripping tests in this file. Happy to switch the mechanism if you prefer.
| registerList(this.editor) | ||
| ) | ||
| this.#registerTableComponents() | ||
| if (this.config.get("tables")) this.#registerTableComponents() |
There was a problem hiding this comment.
Good call — done. Switched to if (this.supportsTables) for consistency with the getter used elsewhere and to avoid drift if its logic changes.
| - `multiLine`: Pass `false` to force single line editing. | ||
| - `permittedAttachmentTypes`: Restrict the editor to a specific allowlist of attachment content types. Unset (the default) permits any content type. Example: `<lexxy-editor permitted-attachment-types="application/vnd.basecamp.mention application/vnd.basecamp.opengraph-embed"></lexxy-editor>`. | ||
| - `richText`: Pass `false` to disable rich text editing. | ||
| - `tables`: Pass `false` to disable table insertion entirely. By default, tables are enabled. |
There was a problem hiding this comment.
Done. Updated the bullet to note that disabling also reduces existing <table> markup to plain text (cell text preserved) on load, not just disabling insertion.
Make table insertion disablable via Lexxy.configure (tables: false) or a tables element attribute. The default stays true, preserving current behavior. When disabled: the TablesExtension is not registered (dropping the table nodes, table commands, and the figure/tbody import allow-list), the table toolbar button is hidden via the data-tables attribute, the lexxy-table-tools controls are not created, and insertTable no-ops. Table markup is reduced to plain text on import.
0e72da2 to
b1af468
Compare
Part of #1097 — making a few editor features individually disablable via the existing
Lexxy.configuresurface, default-preserving. This is the first and smallest slice of that set (the icebreaker): if the shape looks right here, I'll follow with the others —code,highlight, and configurablemarks— as separate focused PRs. (Heading levels are already covered by #754.)What
Adds a
tablesoption (defaulttrue) to disable table insertion entirely, configurable via preset or element attribute — the same shape asmarkdown/attachments/richText:Default behavior is unchanged.
How it works when disabled
Disabling happens at the editor level, not just by hiding the toolbar button:
TablesExtension.enabledreturnsfalse, so the table nodes, the table plugin/commands, and thefigure/tbodyimport allow-list are never registered — table markup is reduced to plain text on every import path (paste /setValue/ initial value).lexxy-table-toolscontrols are not created.insertTableno-ops.data-tablesattribute + CSS, mirroring the existingdata-attachmentsmechanism.Testing
test/browser/tests/tables/disabled.test.js): button hidden,insertTableinert, nolexxy-table-tools, pasted/loaded tables stripped to plain text (cell content preserved), no console errors. Default behavior covered by a regression baseline plus the existing tables specs.test/system/tables_disabled_test.rb): Action Text round-trip (load → strip → save → render → re-edit) confirming no table is persisted while cell text survives.docs/configuration.md).