Skip to content

Derive semantic Markdown changes - #9047

Draft
hweihwang wants to merge 1 commit into
mainfrom
review/structured-markdown-comparison-model
Draft

Derive semantic Markdown changes#9047
hweihwang wants to merge 1 commit into
mainfrom
review/structured-markdown-comparison-model

Conversation

@hweihwang

@hweihwang hweihwang commented Aug 14, 2026

Copy link
Copy Markdown

Version comparison for Collectives pages has been requested in #599 for a long time. The core gap lives in Text: nothing could tell you what actually changed between two Markdown revisions. A byte diff says edits happened. It does not say that a paragraph was inserted, a link target changed, or a table row moved.

This PR adds the model that answers that: two Markdown documents in, a typed list of changes out. It is the foundation only, so there is no UI yet and no screenshot. The next three PRs build the views on top of it.

What's in this PR

  • A comparison model built on ProseMirror ChangeSet
  • Every change classified as text, formatting, attribute, structure, or unknown
  • Conservative move detection and position mapping between the two revisions
  • An explicit complexity limit: the caller gets a limited result, never a silent partial list

Design notes

  • Both editors share one schema instance. ProseMirror compares node types by identity. Two separate schemas would produce a wrong result, not a slow one. Tests pin this.
  • Moves under-report on purpose. Only exact moves are detected. Anything ambiguous becomes a remove plus an insert. A missed move is noise; a wrong move claims edited content is unchanged.
  • Attributes and formatting stay separate, so hiding formatting-only changes can never hide a changed link target.

Stack

First of six, followed by #9048, #9049 and #9050 in this repo (each based on the one before), then nextcloud/collectives#2699 and #2700.

Verification

ts:check and lint pass. The complete suite passes at this tip: 1,768/1,768, re-run on 2026-08-14. I also re-checked SyncService.spec.ts in isolation at a clean checkout of base fd0155f6be: it passes there too. Zero drift against upstream main, clean merge-tree, clean diff --check, clean worktree, backup refs match.

Related

Happy to answer any questions in review.

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>
@hweihwang

Copy link
Copy Markdown
Author

Note on CI: the static-psalm-analysis failure is at lib/Migration/Version030201Date20201116110353.php, a 2020 migration this stack does not touch — the diff is limited to src/ and tests. Upstream main's last static-analysis run passed on 2026-08-04; this looks like psalm-version drift flagging an untouched file. Nothing in this PR's diff is involved; happy to look into it upstream if maintainers want a separate fix.

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