Repository navigation
fix: preserve whitespace-only plain text paste - #4706
Conversation
|
Thanks for the fix! I verified it locally by driving the real paste path in a headless Chromium (the muya e2e harness: TL;DR: the fix engages only when the clipboard carries Pasting two spaces at
Root cause. // utils/paste.ts
if (pasteType === PasteType.NORMAL)
return html && text ? 'html' : getTextType(text)For two spaces, Why CI stays green. The regression test feeds Suggested fix. Base the decision on the intent ("a plain inline-whitespace paste"), not on const isPlainInlineWhitespace
= text.length > 0
&& text.trim().length === 0
&& !text.includes('\n')
if (isLiteralAnchor || isPlainInlineWhitespace)
applyLiteralPaste(clipboard, ctx, isPlainInlineWhitespace ? text : markdown)
else
applyParsedPaste(clipboard, ctx, markdown)Adding a regression test that sets both Minor, while here: |
|
Thanks, this review was right. I rechecked the real paste path and the previous fix was too narrow. Root cause:
Updated fix: The special case now checks the original plain text payload instead of const isPlainInlineSpaces = /^ +$/.test(text);When that is true, the paste uses literal insertion with the original Tests added:
Validation: pnpm --filter @muyajs/core test -- src/clipboard/__tests__
pnpm --filter @muyajs/core lint:types
pnpm --filter @muyajs/core lint
pnpm --filter muya-e2e e2e:chromium -- tests/editing/clipboard.spec.ts
pnpm --filter @muyajs/core exec vitest run --testTimeout 20000
pnpm typecheck
git diff --check |
upstream が持ち込んだ主なもの: - list serialization 刷新(空項目保持 marktext#4696/marktext#4697、markerOverride/_isLooseParentList) - code fence 長の保持 marktext#4755、ソースモード undo/redo、math/diagram スクロール - flush()/_flushOperationCache() による pending-edit 同期 marktext#2938 - plain-inline-spaces 保持の paste marktext#4706、大規模依存アップグレード marktext#4597 ほか 採用/保持の判断: - フォーク保持: CLAUDE.md、setWrapCodeBlocks、PDF 描画 - 両立: fence info(フォーク) + fenceLength(upstream)、whole-line paste(フォーク) + plain-inline-spaces(upstream)、@tauri-apps/cli 保持 + upstream バージョンアップ採用 - upstream 採用: flush 機構(フォークの flushPendingChanges / _commitOperationCache / _rafHandle / _isGoing を除去、呼び出し側 editor.vue を flush() に更新) 波及修正: - フォークの空 paragraph 往復保持を top-level (_listType 空) に限定し、upstream の 空リスト項目処理と両立(muya unit 10件の回帰を解消) - pnpm-lock.yaml をマージ後 package.json から再生成 検証(全緑): muya lint:types / check-circular / unit 1397 / conformance 1347、 desktop typecheck / unit 695、build:tauri 成功・実機動作確認 OK Co-Authored-By: Claude Opus 4.8 <[email protected]>
Closes #4701
Summary
Preserve non-empty whitespace-only
text/plainpaste content when pasting inline into a paragraph.Previously, a clipboard payload such as two ordinary spaces (
U+0020 U+0020) was classified as text, then routed through the parsed Markdown paste path. That path intentionally treats empty or whitespace-only Markdown as a no-op to avoid creating empty block churn. As a result, pasting two spaces betweenAandBleft the document unchanged:This PR keeps the existing parser guard for empty or block-like whitespace pastes, but routes non-empty inline whitespace from
text/plainthrough literal insertion. Pasting two spaces atA|Bnow produces:The fix is intentionally scoped to plain text, non-empty, no-newline whitespace so normal Markdown parsing for headings, lists, tables, HTML, and multiline paste remains unchanged.
Type of change
Test plan
The following checks passed:
Notes for reviewers [optional]
The root cause is in
packages/muya/src/clipboard/paste.ts.applyParsedPaste()intentionally returns early for whitespace-only Markdown:That guard is still needed for parsed/block paste behavior, but it also caught non-empty inline plain text consisting only of spaces. The new branch detects this narrower case before parsing:
When true, the paste uses the existing literal insertion path. This preserves spaces and keeps the caret at the expected offset without changing parsed Markdown behavior for other paste types.
Regression coverage adds a paste-handler test for
ABwith the cursor betweenAandB, pasting two plain spaces and expectingA B.By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.