Skip to content

Add configurable code blocks and inline code - #1193

Open
anquinn wants to merge 3 commits into
basecamp:mainfrom
anquinn:configurable-code
Open

Add configurable code blocks and inline code#1193
anquinn wants to merge 3 commits into
basecamp:mainfrom
anquinn:configurable-code

Conversation

@anquinn

@anquinn anquinn commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Adds codeBlocks and inlineCode options to Lexxy.configure. They are configurable separately via preset or element attribute. Both default true, default behaviour is unchanged.

Lexxy's configuration and is breadth of formatting options is great, however, I have some applications where I don't need or can't use features such as code blocks. This allows for optionally disabling code them.

This follows the API and structure laid out in #1169 (configurable headers) and the existing richText / markdown / attachments options. It uses the same Lexxy.configure boolean-option shape, per-editor element attributes, data-* + CSS toolbar hiding, and load-time stripping to plain text. This extends that established pattern to code blocks and inline code. It solves part of #1097.

What

Adds two options (both default true), configurable separately via preset or element attribute:

// all editors
Lexxy.configure({ 
  default: { 
    codeBlocks: false, 
    inlineCode: false 
  }
})
<!-- per editor -->
<lexxy-editor code-blocks="false"></lexxy-editor>
<lexxy-editor inline-code="false"></lexxy-editor>

How it works when disabled

Code blocks and inline code share one toolbar button (name="code"), which routes to inline code when text is selected on a single line and to a code block otherwise. Making them independently disablable splits that routing rather than just hiding the button:

  • Insertion - the shared button routes to whichever feature is still enabled, and is hidden (via a data-code-blocks / data-inline-code compound CSS rule) only when both are off. The CODE / INLINE_CODE Markdown transformers are filtered out per feature.
  • Load / paste stripping - existing content is reduced to plain text: a CodeNode transform rewrites code blocks to paragraphs, and a TextNode transform clears the inline code format. The code nodes stay registered because the highlight, format-escape, and Trix-conversion extensions register transforms against them for every rich-text editor. Unregistering them breaks bootstrap.

Testing

  • JS unit (test/javascript/unit/editor/code_configuration.test.js) config resolution across default / preset / attribute override, mirroring the headings config test.
  • Playwright (test/browser/tests/formatting/code_disabled.test.js) button visibility, routing, Markdown suppression, and load-stripping for each of the three states (code blocks off, inline off, both off).
  • System (test/system/code_disabled_test.rb) Action Text round-trip (load → strip → save → render → re-edit) for both features.

Docs updated to match (home/docs/configuration.md).

Adds `codeBlocks` and `inlineCode` options (both default `true`),
configurable separately via preset or element attribute, following the
same shape as the existing `richText` / `markdown` / `attachments`
options.

When disabled:
- Insertion is removed from the toolbar and Markdown. The shared code
  button routes to whichever feature is still enabled and is hidden
  only when both are off.
- Existing code blocks and inline code are reduced to plain text on load
  and paste via node transforms. The code nodes stay registered so the
  highlight, format-escape, and Trix conversion extensions keep working.

Documented in home/docs/configuration.md. Covered by JS unit, Playwright,
and Capybara round-trip tests.
@anquinn
anquinn marked this pull request as ready for review July 13, 2026 00:24
Copilot AI review requested due to automatic review settings July 13, 2026 00:24

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds per-editor and preset-level configuration switches for code blocks and inline code in Lexxy, preserving current defaults while allowing apps to disable either feature (including load/paste stripping and Markdown shortcut suppression).

Changes:

  • Add codeBlocks and inlineCode configuration options (default true) with element-attribute overrides.
  • Adjust code insertion routing, Markdown transformers, and import/paste/load behavior to strip disabled code formats.
  • Add unit, Playwright, and system tests plus fixtures/docs/CSS updates for the new options.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/elements/editor.js Adds support flags, transformer filtering, and stripping transforms; passes feature state to toolbar via data attributes.
src/editor/command_dispatcher.js Routes the shared “code” action based on which code features are enabled.
src/config/lexxy.js Introduces default preset values for codeBlocks/inlineCode.
app/assets/stylesheets/lexxy-editor.css Hides the shared code toolbar button only when both features are disabled.
home/docs/configuration.md Documents codeBlocks and inlineCode options and behavior when disabled.
test/javascript/unit/editor/code_configuration.test.js Unit tests for config resolution (default/preset/attribute overrides).
test/browser/tests/formatting/code_disabled.test.js Playwright coverage for toolbar visibility/routing, Markdown suppression, and load stripping.
test/browser/fixtures/code-blocks-false.html Fixture for code-blocks="false" state.
test/browser/fixtures/inline-code-false.html Fixture for inline-code="false" state.
test/browser/fixtures/code-all-false.html Fixture for both code features disabled.
test/system/code_disabled_test.rb System test for Action Text round-trip stripping (load → save → render → re-edit).
test/dummy/app/views/posts/_form.html.erb Adds query-param driven attributes to exercise disabled states in the dummy app.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/elements/editor.js
Comment on lines 783 to 789
#createDefaultToolbar() {
const toolbar = createElement("lexxy-toolbar")
toolbar.innerHTML = LexicalToolbar.defaultTemplate
toolbar.setAttribute("data-attachments", this.supportsAttachments) // Drives toolbar CSS styles
toolbar.setAttribute("data-code-blocks", this.supportsCodeBlocks)
toolbar.setAttribute("data-inline-code", this.supportsInlineCode)
toolbar.configure(this.config.get("toolbar"))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, and technically correct. But this is a pre-existing limitation, not one introduced here: data-attachments (set on the same line, #createDefaultToolbar) has the exact same behaviour. It's only applied to toolbars Lexxy creates, never to external toolbars referenced by ID. The data-code-blocks/data-inline-code attributes follow that established pattern deliberately, so the PR stays internally consistent.

Fixing external-toolbar support here would mean moving all three attributes into #attachToolbar, which (a) expands this PR's scope to the unrelated attachments feature, and (b) makes Lexxy start writing attributes onto a user-owned element. A multi-editor setup gets more complicated at that point. I'd argue it's a separate, deliberate change and out of scope here.

Copilot AI review requested due to automatic review settings July 14, 2026 00:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment on lines +67 to +69
await expect.poll(() => editor.value()).toContain("<pre")
expect(await editor.value()).not.toContain("<code")
})
Comment thread src/elements/editor.js
Comment on lines +655 to +657
// Inline code is a text format rather than a node, so strip the format from
// any imported or pasted content. Runs on load and paste; a no-op for
// unformatted text.
Comment thread home/docs/configuration.md Outdated
Comment on lines +49 to +50
- `codeBlocks`: Pass `false` to disable code blocks. Insertion via the toolbar and Markdown is removed, and any existing `<pre>` code is reduced to plain text when loaded. By default, code blocks are enabled.
- `inlineCode`: Pass `false` to disable inline `code`. Insertion via the toolbar and Markdown is removed, and any existing inline `<code>` is reduced to plain text when loaded. By default, inline code is enabled.
Copilot AI review requested due to automatic review settings July 14, 2026 00:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Comment thread src/elements/editor.js
Comment on lines +655 to +657
// Inline code is a text format rather than a node, so strip the format from
// any imported or pasted content. Runs on load and paste; a no-op for
// unformatted text.
Comment thread src/elements/editor.js
Comment on lines +650 to +652
paragraphs.forEach((paragraph) => node.insertBefore(paragraph))
node.remove()
})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think editing another tool would be out of scope of this PR

@anquinn

anquinn commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@jorgemanrubia I saw your recent tweet on making Lexxy configurable and extensible. I totally I agree. Can you please take a look at this PR and let me know if this is along the lines you're looking for?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants