feat(muya): add runtime setOptions / setFont / setTabSize / setListIndentation by Jocs · Pull Request #4393 · marktext/marktext · GitHub
Skip to content

feat(muya): add runtime setOptions / setFont / setTabSize / setListIndentation - #4393

Merged
Jocs merged 2 commits into
developfrom
feat/muya-set-options
Jun 8, 2026
Merged

Jocs merged 2 commits into
developfrom
feat/muya-set-options

Conversation

@Jocs

@Jocs Jocs commented Jun 8, 2026

Copy link
Copy Markdown
Member

Background

Part of the muyajs → @muyajs/core engine migration. Every desktop
Preferences toggle (and the language-changed / theme paths) relies on editor
options updating live without recreating the editor. The legacy engine
exposed setOptions(options, needRerender) plus setFont/setTabSize/
setListIndentation; @muyajs/core had none — option changes were a no-op
after construction.

What this adds (on Muya)

  • setOptions(options, forceRender = false) — merges options into
    muya.options; reflects the container-level ones immediately (the
    spellcheck attribute, the quick-insert-hint class); and, when
    forceRender is set, fully re-renders the document from its current state
    via ScrollPage.updateState so render-affecting options take effect
    (superSubScript, footnote, disableHtml, frontmatterType,
    codeBlockLineNumbers, GitLab compatibility, …). The desktop already passes
    forceRender: true for exactly those.
  • Undo history is preserved (unlike setContent, which clears it), and
    the cursor is captured via getSelection() and restored by path across the
    re-render.
  • setFont({ fontSize, lineHeight }), setTabSize(n) — update the
    corresponding options.
  • setListIndentation(n) — routes through setOptions(..., true) so the
    layout updates.

The methods are inserted right after setContent() to stay clear of other
in-flight muya.ts additions.

Tests

New happy-dom spec src/__tests__/setOptions.spec.ts (5 cases): option merge;
forceRender preserves document content and leaves undo history intact;
spellcheck attribute reflection; setFont/setTabSize; setListIndentation.

Verification

  • pnpm -C packages/muya lint → 0 errors
  • pnpm -C packages/muya lint:types ✓
  • pnpm -C packages/muya check-circular ✓
  • pnpm -C packages/muya test → 440 passed (+5)
  • pnpm -C packages/muya test:spec → 1347 passed (conformance unchanged)

🤖 Generated with Claude Code

…dentation

Every desktop Preferences toggle needs editor options to update live; the
legacy engine exposed setOptions(options, needRerender) and the setFont/
setTabSize/setListIndentation helpers, which @muyajs/core lacked.

setOptions(options, forceRender) merges into muya.options, reflects the
container-level ones (spellcheck attribute, quick-insert hint class), and —
when forceRender is set — fully re-renders the document from its current
state via ScrollPage.updateState so render-affecting options (superSubScript,
footnote, disableHtml, frontmatterType, codeBlockLineNumbers, GitLab
compatibility, …) take effect. Unlike setContent, this preserves the undo
history; the cursor is captured and restored by path across the re-render.

setFont/setTabSize update their options; setListIndentation routes through
setOptions with a re-render. Adds happy-dom coverage.

Part of the muyajs -> @muyajs/core engine migration (stage A4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 8, 2026 06:08

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

This PR adds a runtime option-update API to packages/muya’s Muya class to support the ongoing muyajs → @muyajs/core engine migration, enabling desktop preference toggles (and related theme/language flows) to take effect live without recreating the editor.

Changes:

  • Introduces Muya#setOptions(options, forceRender) to merge options at runtime, reflect container-level attributes/classes, and optionally force a full re-render from current state.
  • Adds convenience runtime setters: setFont, setTabSize, and setListIndentation (the latter forces a re-render).
  • Adds a new happy-dom Vitest suite covering the new runtime option APIs.

Reviewed changes

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

File Description
packages/muya/src/muya.ts Adds runtime option setters and a forced re-render path intended to preserve history and selection.
packages/muya/src/tests/setOptions.spec.ts Adds tests for option merging, forced re-render behavior, container spellcheck reflection, and convenience setters.

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

Comment thread packages/muya/src/muya.ts
Comment on lines +232 to +241
const selection = this.editor.selection.getSelection();
this.editor.scrollPage?.updateState(this.getState());
if (selection) {
this.editor.selection.setSelection({
anchor: selection.anchor,
focus: selection.focus,
anchorPath: selection.anchorPath,
focusPath: selection.focusPath,
});
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed — the path-only restore was indeed broken (Selection._setCursor needs a concrete block's domNode; a bare queryBlock result isn't a Node, so the instanceof Node check failed and the caret was never set). Now resolves the block at the saved anchorPath on the rebuilt tree and calls block.setCursor(begin, end, true) directly, mirroring Editor.updateContents' same-block restore.

Comment on lines +50 to +59

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right — undo() on an empty stack is a trivial no-op. Replaced it: the test now makes an edit (insertParagraph), asserts history.canUndo() is true, then asserts it's STILL true after setOptions(..., true). Note updateState uses the 'api' source (no json-change dispatch), so a forced re-render neither clears history (unlike setContent) nor pollutes it — verified by canUndo staying true.

Address Copilot review:
- Cursor restore after forceRender was broken: passing only paths to
  Selection.setSelection doesn't work (_setCursor needs a concrete block's
  domNode; a bare queryBlock result is not a Node). Resolve the block at the
  saved path on the rebuilt tree and call block.setCursor directly, mirroring
  Editor.updateContents' same-block restore.
- The history test was trivial (undo() on an empty stack never throws). Assert
  history.canUndo() stays true across a forceRender re-render instead — and
  documents that updateState uses the 'api' source so it neither clears nor
  pollutes history.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Jocs
Jocs merged commit e67fdbe into develop Jun 8, 2026
11 checks passed
@Jocs
Jocs deleted the feat/muya-set-options branch June 8, 2026 07:00
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