Skip to content

Compare literal Markdown off the main thread - #9046

Closed
hweihwang wants to merge 4 commits into
nextcloud:mainfrom
hweihwang:review/structured-markdown-source-comparison
Closed

Compare literal Markdown off the main thread#9046
hweihwang wants to merge 4 commits into
nextcloud:mainfrom
hweihwang:review/structured-markdown-source-comparison

Conversation

@hweihwang

@hweihwang hweihwang commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

In one sentence: the Markdown source view that catches what rendering hides — line endings, whitespace, syntax — computed in a worker.

What and why

Two revisions can render identically and still differ: LF vs CRLF, trailing whitespace, a missing final newline, link syntax rewritten. The semantic engine works on parsed documents, so by design it cannot see these. This PR adds the view that can.

What's in this PR

  • A Markdown source view comparing the literal text, with line numbers and token-level emphasis
  • Explicit diagnostics: line-ending changes, per-line LF/CRLF badges, trailing whitespace, missing final newlines
  • All computation in a cancellable module worker with three explicit limits: 2,000,000 characters, 50,000 edits, 2,000 ms — a limit always reports itself as limited, never as "identical"

The Changes view honestly reporting zero rendered differences, with a direct button to the Markdown source view
Zero rendered changes, stated honestly — the whole reason this view exists.

Markdown source view: line numbers, −/+ gutters, token-level emphasis
The source view. Source change groups can differ from rendered ones.

Diagnostics: LF → CRLF banner, per-line badges, trailing-whitespace badge
Explicit diagnostics for what the rendered view cannot show.

Design notes

  • Source is a separate subsystem, not a mode — the semantic engine can't see what parsing discards, and that is the entire subject of this view.
  • The worker exists even for small documents: Myers complexity tracks edit distance, not size, so a size cap alone would not stop a two-second UI freeze.
  • The worker is emitted under js/ (verified: js/markdownSourceComparison.worker-Bn7Bh2ec.worker.mjs, no assets/) so the post-merge asset pipeline regenerates it. Under Vite's default assets/ it would build locally but disappear after merge.
  • diff@8.0.3 (BSD-3-Clause, kpdecker/jsdiff) is declared here only — T1–T3 don't import it.

Stack

Depends on: #9045. Last Text unit — after this, Collectives nextcloud/collectives#2697 and #2698. Opened stacked — the diff narrows as predecessors merge; I'll rebase before review.

Verification

ts:check and lint pass; complete suite 1,917/1,917. Worker ready/limited protocol responses are tested against the real module. Production build re-run at this tip: emitted js/markdownSourceComparison.worker-Bn7Bh2ec.worker.mjs, no assets/ directory.

AI assistance

Commits carry Assisted-by: Codex:gpt-5.6-sol; an independent review pass was run with Claude Opus 5. Description drafted with Hermes (deepseek-v4-pro) from my notes, then reviewed by me.

Related

Parse immutable documents, normalize their semantic structure, and emit bounded stable change descriptors. Support one shared schema for both parsed documents.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
Expose the Text comparison factory and render grouped changes by document section. Preserve every changed-only preview in multi-edit blocks with semantic deletion and insertion markup.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
Mount both immutable documents once, apply semantic decorations, support independent pane navigation, and provide an accessible single-pane layout for narrow containers.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
Add bounded source diagnostics for syntax-only and oversized rendered comparisons. Emit the cancellable worker under js so the post-merge asset job includes it.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
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.

1 participant