[pull] develop from marktext:develop - #48
Merged
Merged
Conversation
…4401) * fix(muya): treat CJK as punctuation for strong/em flanking (#4307) Strong/em delimited with `**` directly against a CJK character whose inner content is punctuation-bounded did not bold in muya, e.g. `例子例子**"加粗"**例子例子`, `日本語**(強調)**日本語`, `한국어**[강조]**한국어`, and the non-BMP `𠀀𠀁**"加粗"**𠀀𠀁`. The legacy muyajs engine bolded these. CommonMark §6.2 classifies CJK ideographs / Hangul / Kana as "other" (Lo), neither whitespace nor punctuation, so a `**` run wrapped by CJK with punctuation-bounded content is not left/right-flanking and stays literal. muya has TWO inline-tokenization paths and both carry the same CJK-as- punctuation widening the legacy engine shipped: - Static / export path (marked@16): a `cjkEmStrong` tokenizer override that rebuilds marked's emStrong flanking regexes with CJK folded into the punctuation class and removed from the alphanumeric class, registered in getHighlightHtml and getClipboardHtml. Faithful copy of marked's emStrong body; rules are swapped in/out per-call so the shared tokenizer rules are never left mutated. - Live editor path (inlineRenderer): CJK widening added to canOpen/canCloseEmphasis in inlineRenderer/utils.ts, plus full code-point reading so the non-BMP CJK Ext-B surrogate-pair branch is live. CJK ranges (matching legacy CJK_REG): Hiragana+Katakana U+3040–U+30FF, CJK Ext-A U+3400–U+4DBF, CJK Unified U+4E00–U+9FFF, CJK Compatibility U+F900–U+FAFF, Hangul Syllables U+AC00–U+D7AF, Halfwidth Katakana U+FF66–U+FF9D, and CJK Ext-B U+20000–U+2A6DF (non-BMP). The widening is additive — it never bolds anything CommonMark accepts as non-emphasis — so the CommonMark 0.31 + GFM conformance suites are unchanged (1347/1347, no unexpected passes). Promotes the #4399 `it.fails` placeholders to passing `it` cases and adds live-editor-path coverage plus negative cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(muya): assert negative CJK flanking cases emit neither strong nor em The static/export-path negative cases in strongCjkFlanking.spec.ts only checked for <strong> via rendersStrong. Since #4307 widens the emphasis/strong flanking logic, a regression could surface as unexpected <em> output while still passing a <strong>-only assertion. Add a rendersEm helper mirroring rendersStrong and assert NEITHER tag is produced for the negative cases. The live editor path already covers this: tokenizesEmphasis returns true for either a strong or em token, so its negative .toBe(false) already rejects both. Only the static path needed strengthening. Addresses Copilot review on #4401. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/dompurify/printService/sourceCode/icon) (#4402) * feat(desktop): wire @muyajs/core into the desktop package Begin migrating the desktop renderer off the legacy `@marktext/muyajs` engine and onto the TypeScript rewrite published as `@muyajs/core` (packages/muya). This first step only adds the dependency and the type plumbing; the `muya` alias (→ packages/muyajs) is left intact so editor.vue keeps working while the migration proceeds file by file. - Add `@muyajs/core: workspace:*` to packages/desktop dependencies. - `@muyajs/core` ships no built `lib/types`; its package `exports` map points `.` at `./src/index.ts`, so vue-tsc would otherwise descend into the entire muya source tree and report errors that only exist because muya's own `src/types/global.d.ts` globals aren't loaded under the desktop program. Add a hand-written `src/types/muya-core.d.ts` declaring just the surface the desktop consumes, and a `paths` entry redirecting type resolution to it. Runtime resolution still goes through the package `exports` map via Vite/electron-vite (verified by build:unpack and a vitest import smoke test). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(desktop): consume @muyajs/core in markdownToHtml/pdf/sourceCode Swap the directly-equivalent muyajs imports for their `@muyajs/core` counterparts: - util/markdownToHtml.ts: `new ExportHtml(md).renderHtml()` → `new MarkdownToHtml(md).renderHtml()`. The new `renderHtml()` already wraps its output in `<article class="markdown-body">…</article>` (muyajs did not), so the desktop no longer adds the wrapper — output is byte-identical. - util/pdf.ts: `escapeHTML`/`unescapeHTML` now come from `@muyajs/core` (identical implementations). The `Slugger` import is intentionally left on muyajs: the TOC anchors built here must match the heading `id`s emitted by the muyajs export renderer (`Muya#exportStyledHTML`, still used by editor.vue), which use the SAME Slugger. Swapping to @muyajs/core's `generateGithubSlug` (a different algorithm, no dedup/unicode downcoding) would break in-document TOC links; it migrates together with the editor.vue swap. - components/editorWithTabs/sourceCode.vue: `wordCount` now comes from `@muyajs/core`. Same `{ word, paragraph, character, all }` return shape; the token-split regex differs only cosmetically (`/\s+/` vs `/[\s\n]+/`, equivalent since `\s` covers `\n`). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(desktop): vendor dompurify directly in util/dompurify Replace the `muya/lib/utils/dompurify` import (whose default export was simply `DOMPurify.sanitize`) with `dompurify` directly — already a direct desktop dependency. `@muyajs/core`'s exported `sanitize(html, opts, disableHtml)` has a different signature (it escapes HTML internally), whereas the desktop needs the RAW sanitizer that does not escape (pdf.ts escapes/unescapes around it). Behavior is identical to the legacy path. Cast through `unknown` to bridge DOMPurify's `string | TrustedHTML` overload union; both configs set `RETURN_TRUSTED_TYPE: false`, so the result is always a string. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(desktop): use @marktext/file-icons directly in sideBar/icon Drop the `muya/lib/ui/fileIcons` import in favor of the underlying `@marktext/file-icons` package (already a direct desktop dependency). The muyajs wrapper only added a `getClassByName(name)` helper around the package's `matchName(name)?.getClass(0, false)`; inline that helper in the component and import the package's CSS (`build/index.css`) directly, as the wrapper did. Add an ambient module declaration for `@marktext/file-icons` (it ships no types) to shims.d.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(desktop): document printService getImageInfo migration blocker services/printService.ts calls `getImageInfo(rawSrc: string).src` to normalise an <img>'s src attribute into a displayable URL before printing/PDF export (GH#678). `@muyajs/core` has no behaviour-equivalent string helper for this: - its `getImageInfo(image: HTMLElement)` takes a DOM element, not a string; - its `getImageSrc(src: string)` double-prefixes already-resolved `file://` URLs (`file://file://…`) and blanks `data:` URLs — and the muyajs export renderer already emits absolute `file://` srcs into the HTML this consumes, so it would regress every image. Keep the muyajs import for now and document why; it migrates once the export render path (editor.vue / Muya#exportStyledHTML) moves to @muyajs/core. No behavioral change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ore (#4404) Additive prep for the muyajs -> @muyajs/core editor engine swap. The new @muyajs/core engine reads kebab-case CSS custom properties (e.g. --editor-color, --theme-color, --h1-color), whereas legacy muyajs reads the themes' existing camelCase vars (--editorColor, --themeColor, --h1Color). This change is ADDITIVE and NON-BREAKING: each of the 32 *.theme.css files keeps all existing camelCase vars and gains a kebab-case block in its :root that mirrors the muya target set. The current editor ignores the kebab vars; once editor.vue switches engines they take effect. Authoritative target var set was taken from packages/muya/src/assets/styles/index.css. Mapping: each kebab var is set to var(--camelCaseSource) so it tracks the theme's value with no drift (--editorColor80 -> --editor-color-80, --floatBgColor -> --float-bg-color, --h1Color -> --h1-color, etc.). Two vars use muya's own defaults instead of a theme source: --button-border-focus (var(--button-border), matching muya) and --float-shadow (muya's literal multi-layer box-shadow, since the desktop --floatShadow is a single color wrapped at call sites and not a valid standalone box-shadow value). Verified: postcss parses all 32 files cleanly, all 41 muya kebab vars are declared in every theme with no dangling var() sources, build:unpack and desktop typecheck pass, and the diff is purely additive (0 deletions). Visual verification follows the separate editor.vue engine swap. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* build(muya): export TableChessboard from @muyajs/core entrypoint Export the TableChessboard UI plugin from the muya core entrypoint so the desktop editor host can register it (the quick-insert table picker). The @muyajs/core workspace dependency and the tsconfig.base.json @muyajs/core paths entry it consumes already landed on develop via #4402. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(desktop): exportStyledHTML wrapper + @muyajs/core types shim @muyajs/core exposes MarkdownToHtml(md, muya).generate() but has no equivalent of the legacy muyajs exportStyledHTML (which injects a TOC at the [TOC] marker and wraps the article in a header/footer page table for PDF/print). Add a desktop-side exportStyledHTML wrapper that reproduces that behaviour on top of the engine output so export stays equivalent. Add a hand-written @muyajs/core declaration shim (referenced by the tsconfig paths entry) so vue-tsc resolves the import at the package boundary instead of type-checking the entire muya source tree under the desktop program. Delete it once @muyajs/core ships built type declarations. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(desktop): migrate editor.vue to the @muyajs/core engine Rewire the editor host onto @muyajs/core: - Construction: build the engine with markRaw(new Muya(el, options)) + explicit init(); register the new UI plugin set (TableChessboard, ParagraphQuickInsertMenu, CodeBlockLanguageSelector, EmojiSelector, ImageEditTool, ImageResizeBar/ToolBar, InlineFormatToolbar, ParagraphFront*, PreviewToolBar, LinkTools, FootnoteTool, Table*). - Options/i18n: map the desktop language preference to the engine's bundled locale objects and pass locale on construct + on language-changed (editor.locale(...)). - Events: derive the content-change payload (markdown/wordCount/cursor/ history/TOC/blocks) from the engine's low-level json-change; adapt the new selection-change shape for the application-menu state builder and drive format state off the formats it now carries; listen for scroll on the container directly (engine has no scroll event). - Methods: setContent (replacing setMarkdown), getScrollContainer via domNode, viewport-relative caret coords for typewriter/keep-visible scrolling, copy/paste method remap (copyAsRich -> copyAsHtml), per-tab engine-history stash for in-session tab switches with a synthetic desktop-shaped history for save/dirty tracking. - Search circular-ref fix: muya's search/replace/find return the live Search instance (circular: Search -> muya -> ... -> ScrollPage) and each match carries a live block ref. The store deep-clones (JSON) its payload, which crashed; toSearchMatches() strips it to the plain { index, matches, value } the search UI needs before dispatching. - Blur the editor when the command palette opens to avoid a focus-trap vs engine-selection deadlock that froze the renderer. Documented gaps (engine does not yet surface these; editor stays fully functional): heading-copy-link hover affordance, selection affiliation chain for block-context menu toggles, and selectedTableCells in select-all. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(desktop): update e2e selectors + recipes for @muyajs/core mu- DOM Migrate the desktop e2e suite to the @muyajs/core renderer: - Swap ag-* DOM selectors for the engine's mu-* equivalents across the fixture-render, crash, issue-regression, paragraph-blocks and strong-cjk specs, and update helpers.ts (paragraph content lives in span.mu-paragraph-content; selection is committed via a synthetic keyup so the engine updates its active block). - crash-update-paragraph #2099: the quick-insert menu now triggers on '/' (not the legacy '@'); type '/', wait for the float to be shown (it is always attached but parked off-screen until positioned), then pick Header 1. - plantuml: the engine encodes via plantuml-encoder (no '~1' deflate prefix), so assert the bare plantuml-alphabet base64 src. - strong-cjk: mark the CJK + **"x"** flanking case as fixme — a documented @muyajs/core parser gap (#4307, tracked as it.fails in packages/muya/src/state/__tests__/strongCjkFlanking.spec.ts); the CJK + **plain** regression still passes. Full desktop e2e: 87 passed, 3 skipped (all documented gaps), 0 failed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The @muyajs/core engine opens the quick-insert menu with "/" (its in-editor ghost text already reads "Type / to insert"), replacing the legacy muyajs "@" trigger. Update the desktop quick-insert hint strings (type-at-to-insert / typeAtToInsert) across all nine locales and the end-user EDITING doc so nothing still references the old "@" trigger. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )