Repository navigation
feat(muya): support same-line display math - #4935
Conversation
|
Pushed 7cf518c: the display-math rule is now a linear-time scanner instead of a regex. A downstream review of this change flagged that
Evidence:
Re-verified: the touched suites 53/53, |
Port of upstream PR marktext#4935 (closes marktext#4904 upstream). `$$...$$` now renders as display math on the same line as surrounding text, matching pandoc and GitHub, instead of showing raw markers. A linear-time scanner (execInlineDisplayMath) tokenizes non-empty single-line $$ spans ahead of the unchanged single-dollar rule; multiline fences still go through the block parser, and the token stays inline in paragraph state so markdown round-trips losslessly. The preview renders KaTeX in display mode as a full-width centered block; offsets derive from the real marker length. Deviations from the upstream PR, integrating with marktext#5004 (29d010a) which landed here first: - The inlineMath toggle gates only single-dollar math. The WYSIWYG lexer tries execInlineDisplayMath before the gated $ rule, and the marked inlineKatex extension now rejects single-dollar matches instead of being dropped wholesale — its start() scans past rejected candidates so a later $$ span on the same line is still found. Interaction specs cover both engines. - The renderer merge keeps this fork's lazy KaTeX loading; the new spec preloads KaTeX so the display assertion sees real output.
|
Could we achieve this by modifying the regular expression rather than adding a new rule ( |
…uns (marktext#5365) The trailing (\\*) group never changes an accepted match, but with no closing $ the engine tried every split of a backslash run between it and the content group, so `$` + 131,072 backslashes took ~6.6s to tokenize. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fold `$$...$$` into the `inline_math` regex instead of a scanner that runs before it in `tryChunks`. Being a regular rule, it is also part of `validateRules`, so emphasis that closes inside a `$$` span no longer takes the formula (`*note $$a*b$$`). Like `$...$`, `$$...$$` may now span a soft line break; directly adjacent formulas such as `$$a$$$$b$$` need a space. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ktext#5364) `MATH_BLOCK_REG` matched any paragraph that started with `$$`, so Enter in `$$ E=MC^2 $$`, `$$x` or `- $$a$$ b` replaced the paragraph with an empty math block and deleted its text. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
With auto-pair on, typing `$$x$$` saved `$$x$$$`: the second `$` overtypes the auto-inserted closer, so the final `$` completes the formula with the caret at its end, where the in-math check (`offset < end`) no longer applied and a closing `$` was paired. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Once the hidden wrapper became `display: block`, its zero-size `$$` marker spans were left in anonymous line boxes of their own, so a paragraph that only held `$$E=mc^2$$` was 84px tall around a 33px formula. Tag the markers of display math and take them out of flow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The hidden display wrapper is as wide as its container, but the preview kept the editor-wide `max-width`, so in `> - > - $$...$$` a long formula stuck out 150px past the quote instead of scrolling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Without KaTeX rendering (copy as HTML / rich text), the math extension wrote every inline token as `$text$`, so copying `$$ E=MC^2 $$` produced inline math `$E=MC^2$`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`getOffset` hard-coded marker widths (2 for strong/del, 1 otherwise) and special-cased `inline_math`. Inline code can be fenced by up to three backticks, so toggling code off in ``` ``word`` ``` shifted the selection by one; the token's own marker length covers every case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rewrite said only single-dollar errors stay compact, but `$$` parse errors take the same compact path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks @Renakoni, same-line Design: one
|
| Commit | Change |
|---|---|
| dd5a434 | Inline math rule no longer backtracks on backslash runs (#5365) |
| e4ea1fc | Same-line display math matched by the inline_math rule (above) |
| e32beef | Enter in a paragraph that starts with $$ (for example $$ E=MC^2 $$) replaced it with an empty math block and deleted the formula. Only a bare $$ line converts now (#5364; MATH_BLOCK_REG was /^\$\$/) |
| 9dfd439 | With auto-pair on, typing $$x$$ saved $$x$$$. The $ that closes the formula is no longer paired |
| 7b40db1 | A paragraph holding only $$E=mc^2$$ was 84px tall around a 33px formula: the zero-size hidden $$ markers each got an anonymous line box. They are taken out of flow now |
| dec70b2 | In > - > - $$<long>$$ the preview kept the editor-wide max-width and stuck out 150px past the quote. It is capped at the wrapper width now and scrolls |
| a34b0e8 | Copy as HTML / rich text wrote display math as $E=MC^2$. It keeps $$ now |
| 432ec15 | getOffset reads token.marker.length for all markered formats. This replaces the nested ternary and also fixes the selection shift when toggling off ``code`` |
| ab5f35c | Restored the inline-math error comment. $$ errors take the same compact path |
| 150d66b | sameLineDisplayMath.spec.ts restores window.MUYA_VERSION, like its sibling specs |
Not changed here
- Export parity. The marked math extension used by HTML/PDF export and the clipboard still needs whitespace before the opener and whitespace or
?!.,:after the closer, and does not cross newlines. So($$x$$),中文$$x$$中文and a$$span with a soft break render in the editor but come out raw in export.$...$has the same gap ondeveloptoday, so it belongs in a separate change. The PR description's note that export "already renders$$" holds for whitespace-delimited formulas. - Caret next to the formula. A caret at either edge of the formula reveals its source, and the paragraph reflows from the centered block to inline source. This is the same reveal-on-caret model as
$...$.
Verification
pnpm -C packages/muya test: 1692 passed.test:spec: 1347 passed.lint,lint:typesandcheck-circularare clean.- New or updated unit tests fail before each fix and pass after it: the [Bug] A
$followed by a long run of backslashes freezes the editor #5365 timing test, soft break and emphasis in the display-math spec, [Bug] Enter on a paragraph that starts with$$replaces it with an empty math block #5364 Enter at top level and in a list item,wordtoggle, and clipboard$$. - Chrome e2e (
same-line-display-math.spec.ts, 7 tests): the new$$auto-pair, blank-line and nested-overflow tests failed before their fixes and pass now. - Full local Chromium e2e suite: every failure also fails locally on
develop's source (shortcuts, format toolbar, empty-and-tiny, link punctuation). CI is running on 150d66b.
The description still says multiline $$ is left to the block parser and that $$a$$$$b$$ tokenizes as two formulas. This comment supersedes those two points.
Follow GitHub: `$$...$$` renders as display math only in a paragraph that holds nothing but such formulas, and never inside a list item. With text around it in the same paragraph, or in a heading, table cell or list item, it renders inline like `$...$`. A content renders before it is attached, so a list item re-renders its `$$` contents once its children are in place. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The marked math extension rendered every `$$...$$` in display mode. A walkTokens pass now marks it display only in a paragraph that holds nothing but `$$` formulas, outside list items, matching the editor and GitHub. The clipboard source keeps the authored marker instead of deriving it from the display mode. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Follow-up: Rule. I checked each case below against GitHub's Markdown API (
Tests: 21 editor render cases and 20 export cases. Every inline case failed on 150d66b and passes now. The e2e sentence test now checks that |
Drop the list-item exception: a paragraph that holds nothing but `$$` formulas renders them as display math wherever it sits, so the decision depends only on the paragraph's own text. That removes the post-attach re-render the ancestor check needed (contents render before they are attached) and keeps a paragraph correct when it moves in or out of a list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Match the editor: drop the list-item exception from the export rule. A tight list item's paragraph comes from marked as a block-level `text` token, so it is checked like a `paragraph`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Follow-up on the Rule now.
Why diverge from GitHub in lists. A paragraph content renders when it is created, before it is attached to its list item. Keeping the list exception meant re-rendering I also checked how GitHub renders in Chrome. Its inline
Tests: 22 editor render cases and 22 export cases, including nested and task lists and |
KaTeX positions `\tag` absolutely at the right edge of `.katex-html`, a block as wide as whatever holds it, so a formula wider than the column was drawn underneath the tag rather than beside it — the overlap reported in #4339 and still open upstream as KaTeX/KaTeX#1983. Size that box to the formula and float the tag instead: the tag then follows the formula inside the scrollable extent, and `min-width: 100%` keeps it at the right margin whenever the formula fits, which is the numbered-equation look. Same-line display math (#4935) is covered by the same rules — its popup shrinks to fit the formula, so the tag sat over the tail of even a short one. The one deliberate cost: a formula that fits is now centred in the space left of its tag, half the tag's width off the box centre. Centring the formula and flowing the tag after it cannot both hold, and the overlap is the bug. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…) (#5540) KaTeX positions `\tag` absolutely at the right edge of `.katex-html`, a block as wide as whatever holds it, so a formula wider than the column was drawn underneath the tag rather than beside it — the overlap reported in #4339 and still open upstream as KaTeX/KaTeX#1983. Size that box to the formula and float the tag instead: the tag then follows the formula inside the scrollable extent, and `min-width: 100%` keeps it at the right margin whenever the formula fits, which is the numbered-equation look. Same-line display math (#4935) is covered by the same rules — its popup shrinks to fit the formula, so the tag sat over the tail of even a short one. The one deliberate cost: a formula that fits is now centred in the space left of its tag, half the tag's width off the box centre. Centring the formula and flowing the tag after it cannot both hold, and the overlap is the bug. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
, marktext#5365) (marktext#4935) Render `$$...$$` on the same line as the surrounding text (marktext#4904). A `$$` span renders as display math when its paragraph holds nothing but such formulas, and inline otherwise — matching GitHub, except inside list items where MarkText keeps the block layout. Also fixes Enter on a paragraph starting with `$$` replacing it with an empty math block (marktext#5364), and the quadratic backtracking of the inline math rule (marktext#5365). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit bec5f47)
Closes #4904, closes #5364, closes #5365
Summary
MarkText only rendered
$$...$$display math when the$$fences were on their own lines. This PR lets$$...$$render as display math on the same line as surrounding text, matching pandoc and GitHub — so markdown copied from those sources (or from tools that emit inline$$) renders correctly on paste instead of showing raw$$.For example, both of these now render:
What this PR does
$$...$$as inline display math. A dedicated rule recognizes non-empty$$...$$spans and is tried before the (unchanged) single-dollar$...$rule. Empty$$$$, unclosed openers, and multiline$$fences are not treated as inline display math — multiline fences still go through the existing block parser, and single-dollar math is untouched (including soft line breaks inside$...$).$$stays an inline token in paragraph state; it is not promoted to amath-block. Source round-trips losslessly and paste behavior is preserved, including adjacent formulas like$$a$$$$b$$.$$spans render through KaTeX in display mode; a new.mu-display-mathclass shows the hidden preview as a full-width, centered block, while the editing state (caret inside) stays inline-block so the source is editable in place.$$) instead of a hardcoded 1, so selecting or toggling a$$x$$span targets the content correctly.Type of change
Test plan
Passing checks:
tsctype check and ESLint (0 errors), plus targetedinlineSyntax.cssstylelintNotes for reviewers
$$is deliberately an inline token, not amath-block. That is what preserves source round-trip and paste; multiline$$fences are unaffected and still go through the block parser.$$via KaTeX display mode, so no export CSS was touched.developMuya spec baseline currently has three unrelated round-trip failures, tracked separately in [Bug] Muya round-trip spec has three baseline failures on develop #4934.$$...$$in pasted content now renders as display math, which covers the rendering half of that issue's example. This PR does not change paste newline → paragraph splitting (the core of Pasted newline characters should create new paragraph blocks #3741), so that issue stays open.By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.