Skip to content

fix(muyajs): preserve nested lists of differing types (#4341) - #4354

Merged
Jocs merged 1 commit into
developfrom
fix/4341-nested-mixed-lists
Jun 3, 2026
Merged

Jocs merged 1 commit into
developfrom
fix/4341-nested-mixed-lists

Conversation

@Jocs

@Jocs Jocs commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes [Bug] Regression: nested mixed lists no longer work #4341 — a ul nested inside an ol li (and vice versa) was being silently rewritten as a paragraph by the legacy muya lexer, losing the list structure on import.
  • Root cause: the guard at packages/muyajs/lib/parser/marked/lexer.js:350-365 (introduced in the electron-vite refactor Re-Factor MarkText with electron-vite #4001, commit 85607dd2) treated any nested list whose type differed from its enclosing list as a paragraph. Sibling mixed lists are handled by a separate code path (lexer.js:419-453) and were unaffected.
  • The fix is a single-block deletion of that guard; the existing CommonMark code path then handles nested mixed lists correctly.

Tests

  • New vitest spec (packages/desktop/test/unit/specs/markdown-nested-mixed-lists.spec.ts) — round-trips ul-in-ol and ol-in-ul, plus a structural check that the imported block tree actually contains a nested ul inside the ol li (rather than a paragraph). Confirmed RED on develop, GREEN after the fix.
  • New Playwright fixture (packages/desktop/test/e2e/data/nested-mixed-lists.md + a new runFixture('nested-mixed-lists', ...) block in fixture-render.spec.ts) — loads the fixture in the Electron window and asserts .editor-component ol li ul li (and the inverse) DOM shape. Confirmed RED on develop, GREEN after the fix.
  • Lists.md fixture adjustment — the deeply-nested ordered sub-list inside a * item now has a blank line before it. This brings the input in line with the canonical loose-form serialization the exporter emits for a loose-parent context; without this, the previous test was only passing because the buggy parser was collapsing that nested list into a paragraph.

Test plan

  • pnpm -C packages/desktop run test:unit — 553 passed (10 files), incl. the new spec.
  • pnpm -C packages/desktop exec playwright test test/e2e/fixture-render.spec.ts — 10/10 passed.
  • pnpm -C packages/desktop exec playwright test test/e2e/paragraph-blocks.spec.ts test/e2e/editor-input.spec.ts — 13 passed, 2 pre-existing skips.
  • pnpm run lint — 0 errors (existing warnings unchanged).
  • pnpm run typecheck — clean.
  • Reviewer: open the new fixture in pnpm run dev, confirm the inner bullets and numbers render as nested lists (not paragraph text), and that the Lists fixture still renders the deeply-nested case correctly.

🤖 Generated with Claude Code

The legacy muya lexer rewrote any nested list whose type differed from
its parent (e.g. a ul inside an ol li, or vice versa) into a paragraph,
silently dropping the list structure on import. The guard was added in
the electron-vite refactor (#4001, commit 85607dd) and is unrelated to
sibling mixed lists, which are correctly handled by the in-loop branch
at lexer.js:419-453. Remove it so CommonMark-compliant nested mixed
lists round-trip and render correctly.

Tests:
- New vitest spec round-trips ul-in-ol and ol-in-ul and inspects the
  block tree to assert a nested ul block exists inside the ol li.
- New fixture-render Playwright spec loads a mixed-nested fixture and
  asserts `.editor-component ol li ul li` (and ul li ol li) DOM shape.
- The existing `Lists` fixture in test/unit/data/common/Lists.md now
  separates the deeply-nested ordered sub-list from its sibling text
  with a blank line, matching the canonical loose-form serialization
  the exporter produces for a loose-parent context.

Fixes #4341

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Website preview ready: https://pr-4354-marktext-website.ransixi.workers.dev

Built from f06c1d0fdd37794c16b8aeaa9d44f24289ef4f63 · Worker: marktext-website · Version: 1dda2d5f-6c8b-47dd-a0fb-9aa939ddc891 · Alias: pr-4354

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Build artifacts for PR #4354:

Run: https://github.com/marktext/marktext/actions/runs/26861390540

Artifact Size Link
marktext-windows-arm64 270.6 MB Download
marktext-linux 592.9 MB Download
marktext-windows-x64 271.9 MB Download
marktext-macos-x64 271.7 MB Download
marktext-macos-arm64 261.4 MB Download

@Jocs
Jocs merged commit d5db400 into develop Jun 3, 2026
11 checks passed
@Jocs
Jocs deleted the fix/4341-nested-mixed-lists branch June 3, 2026 04:00
thimbleberrysystems pushed a commit to thimbleberrysystems/WordBird that referenced this pull request Jun 21, 2026
The legacy muya lexer rewrote any nested list whose type differed from
its parent (e.g. a ul inside an ol li, or vice versa) into a paragraph,
silently dropping the list structure on import. The guard was added in
the electron-vite refactor (marktext#4001, commit 5729066) and is unrelated to
sibling mixed lists, which are correctly handled by the in-loop branch
at lexer.js:419-453. Remove it so CommonMark-compliant nested mixed
lists round-trip and render correctly.

Tests:
- New vitest spec round-trips ul-in-ol and ol-in-ul and inspects the
  block tree to assert a nested ul block exists inside the ol li.
- New fixture-render Playwright spec loads a mixed-nested fixture and
  asserts `.editor-component ol li ul li` (and ul li ol li) DOM shape.
- The existing `Lists` fixture in test/unit/data/common/Lists.md now
  separates the deeply-nested ordered sub-list from its sibling text
  with a blank line, matching the canonical loose-form serialization
  the exporter produces for a loose-parent context.

Fixes marktext#4341

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
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.

[Bug] Regression: nested mixed lists no longer work

1 participant