feat: support GitLab inline diff and multiline blockquote (#954) by Jocs · Pull Request #5649 · marktext/marktext · GitHub
Skip to content

feat: support GitLab inline diff and multiline blockquote (#954) - #5649

Merged
Jocs merged 3 commits into
developfrom
feat/954-gitlab-inline-diff-multiline-blockquote
Oct 7, 2026
Merged

Jocs merged 3 commits into
developfrom
feat/954-gitlab-inline-diff-multiline-blockquote

Conversation

@Jocs

@Jocs Jocs commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Closes #954

Summary

Implements the two GitLab Flavored Markdown extensions requested in #954 that MarkText was missing, each behind an off-by-default preference, in the editor and in every export path.

  • inlineDiff — {+ … +} / [+ … +] render as additions and {- … -} / [- … -] as deletions, with GitLab's green / red wash in the editor and in the HTML / PDF / print / copy-as-HTML output.
  • multilineBlockquote — >>> … >>> fenced blockquotes, kept verbatim on save and export.

GitLab semantics are followed: the opener and closer must pair ({+ … +] is not recognised), the body is plain text, and the fence closes with >>> (the <<< in the issue text is a typo — GitLab's own BlockquoteFenceFilter is ^>>>\ *\n…\n>>>\ *$).

Type of change

  • Bug fix (non-breaking, fixes an issue)
  • New feature (non-breaking, adds functionality)
  • Breaking change (causes existing functionality to change)
  • Documentation update

Test plan

  • New tests added (or explain why not needed)
    • packages/muya/src/inlineRenderer/__tests__/inlineDiffSyntax.spec.ts
    • packages/muya/src/state/__tests__/multilineBlockquote.spec.ts
    • packages/muya/src/block/content/paragraphContent/__tests__/enterMultilineBlockquote.spec.ts
    • Engine: pnpm -C packages/muya test (281 files / 2427 tests) and test:spec (CommonMark + GFM, 1347 tests) pass; muya lint, lint:types, check-circular, desktop typecheck and lint are clean.
  • Manually tested on: macOS

Notes for reviewers [optional]

  • Pandoc has no native reader extension for either syntax, so the Pandoc export flags are unchanged, per the issue.
  • Inline diff delimiters are matched by four explicit regexes (one per valid pair) so the opener/closer pairing lives in the regex — JS has no branch-reset groups to back-reference { to }.
  • A run of > with nothing else no longer auto-promotes to a blockquote while multilineBlockquote is on, so typing >>> reaches the fence.
  • The inline-diff washes are exposed as --code-new-inline-diff-background-color / --code-old-inline-diff-background-color for themes to override.

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

Add two off-by-default preferences that read the GitLab Flavored Markdown
extensions MarkText was missing, in the editor and in every export path.

- `inlineDiff` renders `{+ … +}` / `[+ … +]` additions as `<ins>` and
  `{- … -}` / `[- … -]` deletions as `<del>`. The opener and closer must
  match, the body is plain text (no nested markdown), and the span is
  line-scoped — all matching GitLab's own diff filter.

- `multilineBlockquote` reads `>>>` … `>>>` fenced blockquotes. They reuse
  the existing block-quote block; a `meta.style = 'fenced'` flag only drives
  markdown serialization so the fence round-trips instead of collapsing to
  `>`. Typing `>>>` alone on a line and pressing Enter opens one.

Editor rules live in muya (inline tokens + a block extension); the HTML /
PDF / print and copy-as-HTML paths get matching marked extensions wired
through getHighlightHtml, getClipboardHtml, MarkdownToHtml and
renderToStaticHTML. Pandoc has no native reader extension for either
syntax, so the Pandoc export flags are unchanged.

Adds the two preferences to the schema, shipped defaults, Preferences UI,
editor option plumbing and all 12 locales, plus the markdown syntax and
preferences docs. Verified with engine unit + CommonMark/GFM spec suites.

Refs #954
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Build artifacts for PR #5649:

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

Artifact Size Link
marktext-windows-arm64 278.2 MB Download
marktext-macos-x64 296.0 MB Download
marktext-macos-arm64 285.7 MB Download
marktext-linux 635.0 MB Download
marktext-windows-x64 286.4 MB Download

- A run of `>` with nothing else no longer auto-promotes to a blockquote
  while `multilineBlockquote` is on, so typing `>>>` reaches the fence
  instead of being swallowed after the second character.
- An empty or whitespace-only diff body (`{++}`, `{+ +}`) stays literal,
  matching how `**` behaves.
- Inline diff delimiters are matched by four explicit regexes, one per
  valid opener/closer pair, instead of the hand-rolled `tryInlineDiff`
  bracket check. JS regex has no branch-reset groups, so `{` cannot be
  back-referenced to `}`; one pattern per pair keeps the pairing in the
  regex while the shared `tryChunks` pipeline handles the token.
- Inline diffs render like GitLab's `.idiff`: a green wash for additions
  and a red one for deletions (no underline / strikethrough), in the
  editor and in the exported HTML. The colours are exposed as
  `--code-new/old-inline-diff-background-color` for themes.
- Drop the added comments that only restated the code.

Refs #954
@Jocs
Jocs requested a balanced review from Copilot October 7, 2026 16:26

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.

🟡 Changes recommended

Live enabling of multiline blockquotes cannot recognize fences already parsed while the preference was disabled.

1 open finding
What changed in this PR

Adds opt-in GitLab inline-diff and fenced multiline-blockquote support across Muya, desktop preferences, exports, styling, localization, and documentation.

Changes:

  • Implements parsing, editing, serialization, and HTML rendering.
  • Adds desktop preferences, styles, and translations.
  • Adds unit coverage and end-user documentation.
File Description
packages/​website/​content/​docs/​end-user/​PREFERENCES.md Documents preferences.
packages/​website/​content/​docs/​end-user/​MARKDOWN_SYNTAX.md Documents syntax.
packages/​muya/​src/​utils/​marked/​types.ts Extends lexer types.
packages/​muya/​src/​utils/​marked/​options.ts Adds defaults.
packages/​muya/​src/​utils/​marked/​lexBlock.ts Registers blockquote extension.
packages/​muya/​src/​utils/​marked/​getHighlightHtml.ts Enables export rendering.
packages/​muya/​src/​utils/​marked/​getClipboardHtml.ts Enables clipboard rendering.
packages/​muya/​src/​utils/​marked/​extensions/​multilineBlockquote.ts Implements fenced blockquotes.
packages/​muya/​src/​utils/​marked/​extensions/​inlineDiff.ts Implements inline diffs.
packages/​muya/​src/​utils/​marked/​compatibleTaskList.ts Handles nested task lists.
packages/​muya/​src/​types.ts Extends Muya options.
packages/​muya/​src/​state/​types.ts Records fenced quote style.
packages/​muya/​src/​state/​stateToMarkdown.ts Serializes fences.
packages/​muya/​src/​state/​renderToStaticHTML.ts Exposes rendering options.
packages/​muya/​src/​state/​markdownToState.ts Builds fenced quote state.
packages/​muya/​src/​state/​markdownToHtml.ts Propagates export options.
packages/​muya/​src/​state/​index.ts Propagates parser option.
packages/​muya/​src/​state/​getTOC.ts Supports inline diffs in headings.
packages/​muya/​src/​state/​__tests__/​multilineBlockquote.spec.ts Tests quote parsing/export.
packages/​muya/​src/​muya.ts Re-parses block syntax changes.
packages/​muya/​src/​inlineRenderer/​types.ts Defines inline-diff tokens.
packages/​muya/​src/​inlineRenderer/​rules.ts Adds delimiter rules.
packages/​muya/​src/​inlineRenderer/​renderer/​inlineDiff.ts Renders inline diffs.
packages/​muya/​src/​inlineRenderer/​renderer/​index.ts Registers renderer.
packages/​muya/​src/​inlineRenderer/​lexer.ts Tokenizes inline diffs.
packages/​muya/​src/​inlineRenderer/​__tests__/​inlineDiffSyntax.spec.ts Tests inline-diff behavior.
packages/​muya/​src/​config/​index.ts Adds defaults and format type.
packages/​muya/​src/​clipboard/​paste.ts Propagates quote parsing.
packages/​muya/​src/​clipboard/​copyData.ts Propagates export options.
packages/​muya/​src/​block/​content/​paragraphContent/​index.ts Adds typed-fence conversion.
packages/​muya/​src/​block/​content/​paragraphContent/​__tests__/​enterMultilineBlockquote.spec.ts Tests fence entry behavior.
packages/​muya/​src/​block/​commonMark/​blockQuote/​index.ts Preserves quote metadata.
packages/​muya/​src/​block/​base/​format.ts Supports inline-diff editing.
packages/​muya/​src/​assets/​styles/​inlineSyntax.css Styles editor diffs.
packages/​muya/​src/​assets/​styles/​index.css Defines diff colors.
packages/​muya/​src/​assets/​styles/​exportStyle.css Styles exported diffs.
packages/​desktop/​static/​preference.json Adds persisted defaults.
packages/​desktop/​static/​locales/​zh-TW.json Adds translations.
packages/​desktop/​static/​locales/​zh-CN.json Adds translations.
packages/​desktop/​static/​locales/​tr.json Adds translations.
packages/​desktop/​static/​locales/​ru.json Adds translations.
packages/​desktop/​static/​locales/​pt.json Adds translations.
packages/​desktop/​static/​locales/​nl.json Adds translations.
packages/​desktop/​static/​locales/​ko.json Adds translations.
packages/​desktop/​static/​locales/​ja.json Adds translations.
packages/​desktop/​static/​locales/​fr.json Adds translations.
packages/​desktop/​static/​locales/​es.json Adds translations.
packages/​desktop/​static/​locales/​en.json Adds preference labels.
packages/​desktop/​static/​locales/​de.json Adds translations.
packages/​desktop/​src/​shared/​types/​preferences.ts Extends preference types.
packages/​desktop/​src/​renderer/​src/​store/​preferences.ts Adds preference state.
packages/​desktop/​src/​renderer/​src/​prefComponents/​markdown/​index.vue Adds settings controls.
packages/​desktop/​src/​renderer/​src/​components/​editorWithTabs/​editor.vue Applies preferences live.
packages/​desktop/​src/​main/​preferences/​schema.json Validates preferences.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +617 to +618
Copilot review: enabling the preference on an already-open document could
not recognise existing fences. With the option off, Marked had already
folded each fence into ordinary nested blockquote state, and re-parsing
`getMarkdown()` then emitted spaced `> > >` markers the extension could
no longer match.

The `multilineBlockquote` extension is now always registered and, while
the preference is off, returns a literal paragraph instead of a nested
blockquote. That keeps `>>>` verbatim on load, save and export — the same
"stays literal while off" behaviour as `==` under `highlightSyntax` — and
gives an off → on toggle the fence it needs to rebuild the quote. The
marked export path follows the same rule.

Only the fence shape (`>>>` alone on a line, closed by `>>>` alone on a
line) is affected; `>>> foo` and the other CommonMark blockquote spellings
are untouched.

Refs #954
@Jocs
Jocs merged commit c2a7f59 into develop Oct 7, 2026
18 checks passed
@Jocs
Jocs deleted the feat/954-gitlab-inline-diff-multiline-blockquote branch October 7, 2026 17:14
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.

GitLab Flavored Markdown

2 participants