FetLife configurable editor + /sandbox/fetlife - #4
Draft
shved270189 wants to merge 12 commits into
Draft
Conversation
Make code blocks and inline code disablable via Lexxy.configure (code: false) or a code element attribute. The default stays true, preserving current behavior. When disabled: CodeNode/CodeHighlightNode are not registered, the code toolbar button and the CODE/INLINE_CODE markdown shortcuts are removed, insertCodeBlock no-ops, and the code/pre HTML conversions are dropped so code markup is reduced to plain text on every import path. Guards the CodeNode replacement in FormatEscapeExtension and the code-coupled registrations in HighlightExtension to avoid build-time crashes.
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.
Make color highlighting disablable via Lexxy.configure (highlight: { enabled: false }) or a highlight element attribute. The default stays enabled, preserving current behavior. Both the object form { enabled: false } and a bare highlight: false are accepted.
When disabled: the HighlightExtension (toggle/remove commands, the <mark> import converter, paste canonicalizers) is not registered, the toolbar highlight dropdown is hidden via a data-highlight attribute, the dropdown setup is guarded, and highlight markup is reduced to plain text on import — both <mark> (by dropping the conversion) and legacy Trix styled elements (em/strong/span/del keep their bold/italic/strikethrough but lose the highlight color).
Make the inline marks (bold, italic, strikethrough, underline) configurable via Lexxy.configure or a `marks` element attribute, as an allow-list. The default enables all four, preserving current behavior. Accepts a JSON array (marks='["bold","italic"]') or a whitespace-separated string (marks="bold italic"); pass [] to disable every mark. A disabled mark is inert everywhere, not just hidden from the toolbar: its FORMAT_TEXT_COMMAND is swallowed by a high-priority interceptor (covering the toolbar button, programmatic dispatch, and the native Cmd+B/I/U shortcuts), its Markdown shortcut transformers are filtered out, its toolbar button is hidden via a data-disabled-marks attribute, and its semantic tags are dropped from the HTML import conversions so saved markup is reduced to plain text on load and paste. A TextNode transform additionally clears any disabled-mark format bit restored from pasted Lexical clipboard data.
# Conflicts: # app/assets/stylesheets/lexxy-editor.css # docs/configuration.md # src/elements/editor.js # test/dummy/app/views/posts/_form.html.erb
# Conflicts: # src/config/lexxy.js # src/elements/editor.js # test/dummy/app/views/posts/_form.html.erb
# Conflicts: # app/assets/stylesheets/lexxy-editor.css # src/config/lexxy.js # src/elements/editor.js
New sandbox template that mirrors /sandbox/empty but disables the features FetLife does not use: code, highlight, and tables, and restricts inline marks to bold, italic, and strikethrough (no underline).
Integrates the headings configuration option (basecamp#754) and wires it into the editor, which the PR left unimplemented. A new headings.js holds the canonical heading levels; the toolbar's format menu, active-state, and the native editor-initialized event are driven by the configured "headings" array. Adds an H1 ("Huge") heading level: toolbar button, icon, and the setFormatHeadingHuge command. Defaults remain h2/h3/h4 so existing behavior is unchanged. Markdown heading shortcuts stay unrestricted.
Copying between Lexxy editors carries an application/x-lexical-editor payload whose styled text nodes are deserialized directly, bypassing the <mark> import conversion that strips highlight from HTML. A disabled-highlight editor then rendered the pasted color. Add a TextNode transform (registered only when highlight is disabled) that clears color/background-color styles and the highlight format bit, mirroring the disabled-mark stripper.
There was a problem hiding this comment.
Pull request overview
This PR adds per-feature configurability (tables, highlight, code, marks, headings) to the Lexxy editor, introduces an H1 (“Huge”) heading option, and adds a FetLife-specific sandbox preset/page that disables most rich-text features while ensuring disabled markup is stripped on all import paths (including cross-editor Lexical clipboard paste).
Changes:
- Add feature flags/allowlists (
tables,code,highlight.enabled,marks,headings) and wire them through editor initialization, toolbar rendering, commands, markdown transformers, and import/paste canonicalization. - Add an H1 heading level (“Huge”) and make toolbar heading levels configurable via
headings. - Add
/sandbox/fetlifein the dummy app plus extensive system + Playwright coverage for disabled-feature behavior and regression cases.
Reviewed changes
Copilot reviewed 36 out of 38 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/system/tables_disabled_test.rb | System coverage for tables disabled (toolbar + import/round-trip stripping). |
| test/system/marks_disabled_test.rb | System coverage for marks allowlist stripping on load + round-trip. |
| test/system/highlight_disabled_test.rb | System coverage for highlight disabled stripping for <mark> + legacy styled elements. |
| test/system/code_disabled_test.rb | System coverage for code disabled (markdown fence + import/round-trip stripping). |
| test/javascript/unit/editor/headings_configuration.test.js | Unit tests for headings configuration resolution (default/preset/attribute). |
| test/javascript/native/attributes_change.test.js | Updates attributes-change expectations (adds underline). |
| test/dummy/app/views/sandbox/show.html.erb | Adds FetLife sandbox link and supports per-template editor options. |
| test/dummy/app/views/sandbox/_fetlife.html.erb | FetLife sandbox partial (template target). |
| test/dummy/app/views/posts/_form.html.erb | Wires query params into editor attributes for disabled-feature demos/tests. |
| test/dummy/app/controllers/sandbox_controller.rb | Adds fetlife template and per-template editor option overrides. |
| test/browser/tests/tables/disabled.test.js | Playwright coverage for tables disabled (UI, commands, import stripping). |
| test/browser/tests/formatting/marks_disabled.test.js | Playwright coverage for marks allowlist (UI, commands/hotkeys, markdown, import, lexical paste). |
| test/browser/tests/formatting/highlight_disabled.test.js | Playwright coverage for highlight disabled (UI, commands, import, lexical paste). |
| test/browser/tests/formatting/code_disabled.test.js | Playwright coverage for code disabled (UI, markdown shortcuts, import stripping). |
| test/browser/fixtures/tables-false.html | Fixture editor with tables="false". |
| test/browser/fixtures/marks-true.html | Fixture for non-list marks="true" (fail-open). |
| test/browser/fixtures/marks-string.html | Fixture for whitespace marks string parsing. |
| test/browser/fixtures/marks-none.html | Fixture for marks='[]' (all marks disabled). |
| test/browser/fixtures/marks-limited.html | Fixture for marks='["bold","italic"]'. |
| test/browser/fixtures/marks-empty.html | Fixture for empty/bare marks attribute (fail-open). |
| test/browser/fixtures/highlight-false.html | Fixture for highlight='{"enabled":false}'. |
| test/browser/fixtures/highlight-false-bare.html | Fixture for highlight="false" shorthand. |
| test/browser/fixtures/code-disabled.html | Fixture for code="false". |
| src/extensions/trix_content_extension.js | Adjusts legacy Trix highlight import behavior when highlight is disabled. |
| src/extensions/tables_extension.js | Gates table extension by supportsTables. |
| src/extensions/highlight_extension.js | Gates code-dependent highlight wiring and <pre> conversion by supportsCode. |
| src/extensions/format_escape_extension.js | Avoids replacing CodeNode when code support is disabled. |
| src/elements/toolbar.js | Uses canonical HEADING_LEVELS for heading pressed-state; adds H1 menu entry. |
| src/elements/toolbar_icons.js | Adds an H1 icon. |
| src/elements/editor.js | Centralizes feature gating, strips disabled conversions, and adds lexical-paste stripping transforms. |
| src/elements/dropdown/highlight.js | Guards highlight dropdown setup when highlight is disabled / buttons missing. |
| src/editor/marks.js | Introduces mark constants + markdown transformer filtering helper. |
| src/editor/headings.js | Introduces canonical heading level metadata used across toolbar/editor. |
| src/editor/command_dispatcher.js | Adds H1 command, gates code/table insertion, and intercepts disabled marks at high priority. |
| src/config/lexxy.js | Adds default preset options for tables/code/marks/headings and highlight.enabled. |
| docs/highlighting.md | Documents disabling highlighting and boolean shorthand. |
| docs/configuration.md | Documents new options (marks/tables/highlight/headings). |
| app/assets/stylesheets/lexxy-editor.css | Hides toolbar controls via data-* attributes for disabled features/marks. |
Files not reviewed (1)
- src/elements/toolbar_icons.js: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+885
to
891
| bold: { active: format.isBold, enabled: this.enabledMarks.includes("bold") }, | ||
| italic: { active: format.isItalic, enabled: this.enabledMarks.includes("italic") }, | ||
| strikethrough: { active: format.isStrikethrough, enabled: this.enabledMarks.includes("strikethrough") }, | ||
| underline: { active: format.isUnderline, enabled: this.enabledMarks.includes("underline") }, | ||
| code: { active: format.isInCode, enabled: true }, | ||
| highlight: { active: format.isHighlight, enabled: true }, | ||
| highlight: { active: this.supportsHighlight && format.isHighlight, enabled: this.supportsHighlight }, | ||
| link: { active: format.isInLink, enabled: true }, |
Comment on lines
53
to
+56
| - `richText`: Pass `false` to disable rich text editing. | ||
| - `tables`: Pass `false` to disable tables entirely. Table insertion is removed, and any existing `<table>` markup is reduced to plain text (cell text preserved) when loaded. By default, tables are enabled. | ||
| - `highlight`: Color highlighting configuration. Pass `{ enabled: false }` (or simply `false`) to disable highlighting entirely (it is enabled by default). See [Highlighting](highlighting.md) for configuring the available colors. | ||
| - `headings`: Choose which heading levels the toolbar offers, as an array of heading tags. Defaults to `["h2", "h3", "h4"]`. Any of `h1`–`h4` listed gets a button in the format dropdown; levels left out are hidden. Pass `[]` to remove every heading button. Markdown shortcuts (`#`…`######`) still produce headings regardless of this setting. Example: `<lexxy-editor headings='["h1", "h2", "h3"]'></lexxy-editor>`. |
shved270189
marked this pull request as draft
June 11, 2026 09:30
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.
What this is
A FetLife-tailored Lexxy integration branch that combines the configurable-feature work with a FetLife editor preset and a dedicated sandbox page.
Included
Brings together the configurable feature branches:
tablesoption (Add configurable tables support basecamp/lexxy#1104)highlight.enabledoption (Add configurable highlight support #2), including a fix that strips highlight on theapplication/x-lexical-editorpaste path when disabled (copying between editors previously kept the color in the editor)codeoption (Add configurable code support #1)marksallowlist (Add configurable marks support #3)headingsoption (integrates feat: enable headings to be configurable basecamp/lexxy#754, which was plumbing-only) wired into the toolbar, plus a new H1 ("Huge") heading level. Defaults remainh2/h3/h4; Markdown heading shortcuts stay unrestricted.FetLife editor preset
New
/sandbox/fetlifepage (modeled on/sandbox/empty) configured with:code: disabledhighlight: disabledtables: disabledmarks: bold, italic, strikethrough (no underline)headings: h1, h2, h3, h4 (H1 enabled)Disabled features are removed from the toolbar and reduced to plain text on every import path (initial value,
setValue, HTML paste, and cross-editor Lexical-clipboard paste).Testing
/sandbox/fetlife