マルチ行テキスト貼り付け時のバックスラッシュが失われる問題を修正

basecamp/lexxy

Lexxy で Windows/UNC パスを複数行にまたがって貼り付けると先頭のバックスラッシュが消失していた問題を、プレーンテキスト判定を拡張し、改行も含めてそのまま挿入するように修正した。

背景

Lexxy のプレーンテキスト貼り付け処理は Markdown 変換経路を通すため、空白の縮小やバックスラッシュのアンエスケープが起き、特に Windows/UNC パス \\server\share\server\share に変形していた。この現象は、パスがコピー元で改行で折り返され、貼り付け時に <br> タグを含む単一段落としてレンダリングされたときに発生した。シングルラインの貼り付けは正しく処理されていたが、マルチラインの場合は Markdown 構造と判定され、従来の「テキストのみ」チェックを通過できなかった。したがって、Markdown 構造が存在しなくても改行付きテキストを正しく扱う判定ロジックが必要だった。

技術的な変更

src/editor/clipboard.js の判定メソッド #isPlainTextWithoutMarkdown が拡張され、子ノードに BR 要素が含まれていてもプレーンテキストとみなすようになった。

-      && Array.from(paragraph.childNodes).every((node) => node.nodeType === Node.TEXT_NODE)
+      && Array.from(paragraph.childNodes).every((node) => node.nodeType === Node.TEXT_NODE || node.nodeName === "BR")

この条件緩和により、改行 (<br>) を含む段落でも true を返し、以降の貼り付けロジックで原文をそのまま挿入できる。src/editor/contents.jsinsertText も改行文字で分割し、行ごとに LineBreakNodeTextNode を生成して挿入するように実装が変更された:

-      const paragraph = $createParagraphNode().append($createTextNode(text))
+      const paragraph = $createParagraphNode()
+      text.split("\n").forEach((line, index) => {
+        if (index > 0) paragraph.append($createLineBreakNode())
+        paragraph.append($createTextNode(line))
+      })

これにより、マルチ行の UNC パスが \\server\share の形で保持され、Markdown 変換による破損が防止された。

設計判断

プレーンテキスト判定を「テキストノードのみ」から「テキストノード+改行ノード」へ拡張する選択は、Markdown 構造の有無を判定する既存ロジックを最小限の変更で対応したものだ。このアプローチは、既存のリッチテキスト処理や真正な Markdown 入力を影響させず、純粋なテキスト貼り付けのみを対象にすることで後方互換性を保っている。代替案としては新たなフラグや別メソッドを導入する案も考えられたが、コードパスの増大とテスト負荷が懸念されたため採用されなかった。結果として、Lexxy の貼り付け処理は「テキストかつ改行を含む」ケースでも安全に動作し、ユーザーが期待するファイルパス表現を忠実に保持できるようになった。

まとめ

マルチ行にまたがるプレーンテキスト貼り付けで失われていた先頭バックスラッシュを、#isPlainTextWithoutMarkdown の判定拡張と insertText の改行対応により復元した。本修正は最小限のロジック変更で既存機能との互換性を保ちつつ、UNC パスなど重要な文字列の正確性を向上させ、エディタの信頼性を高めた。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
ef2090c6

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的変更、設計判断(任意)とまとめが明確に配置されており、総論→各論→結論の流れが保たれています。

カスタムMarkdown構文 ⚠ WARNING

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックは diff 形式のみで、ファイル名付きハイライトは使用されていませんが問題はありません。一方、PR リンクのテキストが「PR #1162」になっており、要求された「[#1162](URL)」形式と完全に一致していないため警告とします。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

エンジニア向けの専門的な用語と実装詳細が中心で、初心者向けの過度な説明はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論パラグラフ→各論パラグラフ→結論パラグラフで構成され、段落は1文で要点が示され、1段落1トピック、長すぎる段落はなく、空行で区切られています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事中の diff スニペットは提供された PR の diff と完全に一致しており、ファイル名やコード内容も正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「プレーンテキスト」「UNC パス」「バックスラッシュ」「Markdown」などの用語は PR と整合し、誤用はありません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

技術的な説明は PR の記述と一致し、因果関係も正しく示されています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事の全ての主張は PR のタイトル・説明・diff に裏付けられており、根拠のない推測はありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #1162 以外の数値や固有名詞は記載されておらず、誤りはありません。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

日本語タイトルは PR の「Preserve backslashes in plain text pasted across multiple lines」の内容を正確に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事内にバージョンサポートやリリース日程など PR 以外の外部知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現は使用されておらず、PR の記述と矛盾はありません。