https://github.com/basecamp/lexxy
LexxyエンジンがAction Textのエディターアダプター設定を自動的に行うようになりました。これまでホストアプリ側で必要だった `config.action_text.editor = :lexxy` の手動設定が不要になり、エンジン導入時のボイラープレートが削減されます。
`@mentions` ポップオーバーが画面右端付近でビューポートからはみ出す問題を修正しました。`data-clipped-at-right` 属性のスタイルに `max-inline-size: calc(100% - 1ch)` を1行追加することで、エディタ幅を基準にポップオーバーの最大幅を制約しています。論理プロパティを一貫して使用しつつ、回帰テストも同時に追加されました。
LexxyのHTMLサニタイザーが、ハードコードされた許可リストからエクステンション駆動の動的構築方式へ移行しました。LexicalのインポートコンバーターマップとエクステンションのallowedElementsゲッターを合算して許可リストを組み立てることで、新しいエクステンションを追加するだけでサニタイザーが自動的に対応できるようになります。また、添付ファイル属性をグローバルから<attachment>タグスコープに絞るなど、最小権限の観点からも改善されています。
添付ファイルのアップロード後に `src` 属性が非同期で切り替わるタイミングで選択状態がクリアされ、ギャラリーテストが断続的に失敗していた問題を修正しました。`selectAttachment` ヘルパー関数を導入し、BlobストレージURLへの切り替え完了を待機してからクリックし、選択状態の確立をアサーションで検証することで競合状態を解消しています。
Lexxyのコードブロックで2つ目以降のハイライトが1つ目を上書きしてしまうバグを修正。ハイライト適用後にリトークナイザーが走る際、`splitText` が生成する一時的な `TextNode` を複数の関数が考慮していなかったことが原因で、文字オフセット計算・スタイル適用・ハイライト保存の3箇所を修正して解消した。
リスト先頭の空アイテムでBackspaceを押した際に、アイテムが削除されるのではなくリスト上部に空段落が挿入されるよう修正されました。`#removeEmptyListItem` の条件分岐を「前の兄弟の有無」を軸に再設計し、先頭・中間・末尾の各ケースで意図通りの挙動が得られるようになっています。
ビデオ添付ファイルに対してもキャプション編集用のtextareaが表示されるようになり、画像と同等の操作性が実現されました。`ActionTextAttachmentNode` に `isVideo` ゲッターを追加し、`createDOM()` にビデオ専用の分岐を設けることで、既存の `#createDOMForFile()` と `#createEditableCaption()` を組み合わせた最小限の変更で対応しています。
`highlightCode` ヘルパーが `prismjs` を直接インポートしていたため、グラマー定義がロードされずコードハイライトが機能しない問題を修正しました。設定ファイル `src/config/prism.js` からグラマーロード済みの `Prism` をエクスポートし、ヘルパーがそこを参照するよう変更しています。あわせて v0.7.0 以前から非推奨だった `highlightAll` エクスポートが削除されました(BREAKING CHANGE)。
Shift+Enter(ソフト改行)で区切られたテキストにリスト書式を適用すると、段落全体が単一アイテムになるバグを修正。リスト書式のディスパッチ処理を `Contents` クラスに移動し、ブロッククォートと同様に事前の段落分割処理を挿入することで、選択行のみをリストアイテムとして変換する正確な動作を実現しました。
PDFや動画などプレビュー可能な非画像ファイルのアップロード直後、サーバー側でサムネイルが非同期生成される間はファイルアイコンを表示し、バックグラウンドのポーリング(指数バックオフ、最大10回)でサムネイル取得を試みる仕組みが追加されました。レスポンス画像の寸法が150px超かどうかでプレースホルダーSVG(86×100px)と本物のサムネイルを区別し、準備ができたタイミングで自動的にプレビュー表示へ切り替えます。
エディタが再接続されるたびに拡張機能のツールバーボタンが重複追加されるバグを修正。`data-lexxy-extension` 属性によるマーキングを `initializeToolbars()` に組み込み、再初期化前に前回追加された要素を自動削除することで、個々の拡張機能側の対処なしにフレームワークレベルで冪等性を保証します。
複数行を選択してコードブロックを適用すると行ごとに別々のブロックが生成される不具合を修正しました。新たに導入した `CodeNodeInserter` により、ブロック形式の切り替えを貼り付け・挿入と同一のコードパスで処理する設計に整理され、コードブロックの適用・解除が対称的かつ一貫した動作になっています。
QuoteNode内にHTMLをペーストすると、見出しやコードブロックなどのブロック要素がblockquoteの外側に分割挿入される問題を修正。Lexicalの `selection.insertNodes()` を直接呼び出す代わりに `insertAtCursor()` に統一することで、ペースト先ノードの分割が回避されるようになりました。
Lexxyの画像アップロードで発生していたレイアウトシフトを修正したPR。アップロード完了時にActionTextAttachmentNodeへ変換する際、`URL.createObjectURL()`で生成したローカルプレビューURLを`previewSrc`として引き継ぎ、サーバーからの画像読み込み完了後にサイレントで差し替えることで点滅を解消しました。テストではActive Storageモックにレスポンス遅延制御機構を追加し、非同期タイミングの正確な検証を実現しています。
lexxyエディタのフォーマットドロップダウンに「Clear formatting」ボタンが追加されました。Lexicalの`$forEachSelectedTextNode`でビットフラグをゼロクリアし、`$toggleLink`や`$setBlocksType`を組み合わせることで、太字・斜体・リンク・ブロックスタイルなど多様な書式を一操作で一括除去できます。テーブルはPR Descriptionの仕様通り構造を維持し、内部のテキスト書式のみが除去されます。
`lexxy-editor` カスタム要素のID自動生成が、`element.id` が未設定時に `null` ではなく空文字列 `""` を返すHTML仕様のために機能していなかったバグを修正。`??=`(nullish代入)を `||=`(論理OR代入)に変更することで、falsy値である空文字列も正しく処理されるようになりました。
LexxyにStrada Bridgeを介したネイティブモバイルサポートが追加された。BrowserAdapter/NativeAdapterによるアダプタパターンで、エディタコアを変更せずにiOS/Androidツールバーとの状態同期・選択freeze/thaw・コード言語ピッカー委譲・Bridge管理の添付ファイルアップロードを実現している。
Lexicalエディタ要素の切断時に`editor.dispose()`を呼び出す仕組みを整備し、10回の再接続サイクルで+4,440件のリスナーと+12,685件のノードが蓄積していた問題をゼロにしました。CommandDispatcher・Selection・Toolbar等の各コンポーネントにdispose()を実装し、ハンドラ参照固定とCustom Elements冪等化を組み合わせてリソース管理を体系化。Chrome DevTools Protocolを使ったリークテストも追加されています。
リスト系ボタンをドロップダウンにまとめていた設計を撤回し、箇条書きと番号付きリストを再び独立したツールバーアイコンとして配置しました。テストヘルパーも `clickFormatButton` と `clickListsButton` を `clickToolbarButton` に統合し、ドロップダウン経由かどうかの判定を内部化。CSSではセパレーター描画が論理プロパティとカスタムプロパティ参照に整理されています。
ツールバーの画像ボタンに `accept="image/*,video/*"` を設定し、iOS・Androidでネイティブフォト/ビデオピッカーが起動するよう改善されました。単一だった `uploadAttachments` コマンドを `uploadImage` と `uploadFile` に分離し、共通ロジックはプライベートメソッドに集約することで後方互換性を維持しています。