Repository navigation
Description
The problem
Every table in Lexxy looks the same, and there's no way to tell tables apart. That matters as soon as an app needs two kinds of table in the same content. My use-case is a borderless table (acting as columns) in a blog page that can also have normal tables.
Overriding the table CSS in the host app only works if every table should change. The editor doesn't know which table is which, so nothing in the saved content can distinguish them.
The idea
Let the host register named table styles in the Lexxy config. Each table carries at most one style, chosen from a small menu in the table tools.
Lexxy.configure({
default: {
tables: {
styles: [
{ name: "borderless", label: "No borders" },
{ name: "compact", label: "Compact" }
]
}
}
})- The chosen name is saved in the editor state JSON as
tableStyleon the table node. - In HTML, the name is saved as a
lexxy-content__table--<name>class on the<table>. It's the only channel that survives the current sanitizers without loosening them: DOMPurify restrictsstyletocolorandbackground-color, and Rails' sanitizer keepsclasson<table>. - Names that aren't registered are dropped on load and paste, so arbitrary classes can't come in through content.
- A table has at most one style. Each style is meant to be a complete, self-contained look, not a building block to combine.
Why this shape
Lexxy decides nothing about how a style looks. It ships no CSS for these names, so the feature isn't tied to "borderless" or to any other appearance:
.lexxy-content__table--borderless th,
.lexxy-content__table--borderless td {
border-color: transparent;
}entries in a list plus some CSS. The editor only provides the part an app can't build itself: telling tables apart in the editor, in the JSON state, and in the saved HTML.
It's also opt-in. With no styles configured there's no menu and no change in behavior, and existing content and JSON are unchanged.
What it looks like
Implementation
A working implementation is on my fork, as one commit: compare view.
WrappedTableNodestores the style and round-trips it through JSON and HTML.TablesExtensionadds asetTableStylecommand and a transform that drops unregistered names.- A "Style" menu in the table tools, shown only when styles are configured.
- Config names are validated up front: lowercase letters, digits and dashes, and unique.
selectionis reserved becauselexxy-content__table--selectionalready exists. - Playwright tests (set, replace, clear, undo, export and re-import, JSON, unregistered names, no menu by default), a Vitest test for the config validation, and a Capybara test for the save, render and re-edit round trip.
- Docs in
configuration.md.
Questions
- Is this something you'd want in Lexxy? I'm happy to open a PR, and to split it up if that would make review easier.
- Is
tables.stylesthe right place for the option? Add configurable tables support #1104 makestablesa boolean (tables: false). If that merges first, this would become something liketables: { enabled, styles }, or I could use a separate top-level key. I'm fine either way. - Are you happy with the
lexxy-content__table--<name>class convention for the saved HTML?
Activity
fillipeppalhares commentedon Oct 26, 2026
Hi there, @jorgemanrubia! Could you take a look a this, please?