フォーマット一括クリア機能の追加

basecamp/lexxy

フォーマットドロップダウンに「Clear formatting」ボタンが追加されました。選択範囲内のテキスト装飾・リンク・ブロックスタイルをまとめて除去できます。

背景

これまで lexxy エディタでは、太字・斜体・リンクといった書式を個別のボタンで一つずつ解除する必要がありました。コピー&ペーストで持ち込まれた複合的な書式や、複数の装飾が重なったテキストを素のパラグラフに戻すには、複数の操作を繰り返す必要がありました。本PRはその煩雑さを一操作で解決します。

技術的な変更

clearFormatting() メソッドが src/editor/contents.js に実装され、選択範囲に対して以下の順序でフォーマットを除去します:

  • テキストノード単位のインライン書式(太字・斜体・下線・取り消し線)とスタイル(ハイライトなど)
  • リンク
  • ブロッククォートのアンラップ
  • ブロックタイプのパラグラフへのリセット(コードブロック・リストを含む)

実装の核心は、Lexical の $forEachSelectedTextNode を使って各テキストノードに setFormat(0)setStyle("") を適用する点です。format はビットフラグで管理されており、0 を渡すことで全フラグを一括クリアできます。

clearFormatting() {
  const selection = $getSelection()
  if (!$isRangeSelection(selection)) return

  $forEachSelectedTextNode(node => {
    node.setFormat(0)
    node.setStyle("")
  })

  $toggleLink(null)

  this.#topLevelElementsInSelection(selection).filter($isQuoteNode).forEach(node => this.#unwrap(node))

  $setBlocksType(selection, () => $createParagraphNode())
}

ブロッククォートの除去には既存の #unwrap() ヘルパーを流用し、$setBlocksType でコードブロックやリストもパラグラフへ変換します。PR Descriptionで明記されている通り、テーブル自体の構造は維持し、内部のテキスト書式のみをクリアする仕様となっています。

UIレイヤーでは、src/elements/toolbar.js に区切り線(lexxy-editor__toolbar-separator)と「Clear formatting」ボタンが追加され、src/elements/toolbar_icons.js に消しゴム形のSVGアイコン(clearFormatting)が追加されました。コマンドの配線は src/editor/command_dispatcher.jsCOMMANDS 配列への "clearFormatting" の追加と、対応する dispatchClearFormatting() メソッドの実装によって完結しています。

設計判断

インライン書式・リンク・ブロックスタイルの除去を単一メソッド内で順序立てて行う設計が採用されています。それぞれ異なるLexical APIを使う必要があるため(テキストノードへの直接操作、$toggleLink$setBlocksType)、責務を一か所にまとめることで呼び出し側をシンプルに保っています。

PR Descriptionで明記されている通り、テーブルはクリア対象外とされており、テーブル内部のテキスト書式のみが除去されます。ブロック構造の変換と内部書式のクリアを明示的に区別することで、仕様の境界が明確に定義されています。

ブラウザテストは test/browser/tests/formatting/clear_formatting.test.js に独立したファイルとして追加され、太字・斜体・下線・取り消し線・リンク・カラーハイライトなど書式の種類ごとに個別のテストケースが用意されています。

まとめ

$forEachSelectedTextNode によるビットフラグのゼロクリアと既存ヘルパーの組み合わせにより、最小限のコード追加で多様な書式を一括除去できる機能が実現されました。各書式除去APIを正しい順序で呼ぶだけで完結する実装は、Lexicalの設計に沿ったシンプルな拡張といえます。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
0c4ffea2

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

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

リード文(総論)→背景・技術詳細(各論)→まとめ(結論)の3部構成が明確に適用されており、必須要素もすべて満たしています。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きシンタックスハイライト(```javascript:src/editor/contents.js)とGitHubのPRリンク記法([PR #943](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

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

LexicalフレームワークのAPIやビットフラグといった専門用語を前提としており、対象読者であるエンジニアに適した技術レベルで書かれています。

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

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

各セクションが「総論→各論」で構成され、各段落がトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られており、非常に読みやすいです。

Diff内容との照合 ✓ PASS

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

記事内のコードブロックは `src/editor/contents.js` のDiff内容と完全に一致しています。また、他のファイル(toolbar.js, command_dispatcher.jsなど)への言及もDiffと整合性が取れています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「ビットフラグ」「$forEachSelectedTextNode」など、PRの内容と文脈に即した技術用語が正確に使用されています。

説明の技術的正確性 ✓ PASS

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

`setFormat(0)`がビットフラグをクリアする挙動であるという説明など、コードの動作に関する技術的な説明が正確かつ論理的です。

事実の突合 ✓ PASS

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

記事内のすべての主張(機能の仕様、UIの変更、テストファイルの追加など)は、PRのDescriptionやDiffの内容によって裏付けられており、ハルシネーションは検出されませんでした。

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

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

PR番号(#943)や、コード内で参照されているファイルパス、メソッド名がすべて正確です。

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

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

記事のタイトル「フォーマット一括クリア機能の追加」は、PRのタイトル「Clear formatting」の内容を的確に反映しています。

外部知識の正確性 ✓ PASS

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

PRに記載のないバージョン情報やリリース日程などの外部知識の持ち込みはありません。Lexicalの「ビットフラグ」に関する言及は、コードを説明するための妥当な補足情報です。

時間表現の正確性 ✓ PASS

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

「〜が追加されました」といった完了形の表現が使われており、PRで実装された内容を報告する記事として時間表現は正確です。