[basecamp/lexxy] テーブルをfigure要素でラップしてoverflow-xに対応
背景
HTMLのテーブル要素は、コンテンツが親要素の幅を超える場合、max-width: 100% を指定しても親コンテナからはみ出してしまうという特性があります。これを解決するには、テーブルを overflow-x: auto を持つラッパー要素で囲む必要がありました。
Lexxyエディタでは、エディタ内では setScrollableTablesActive(this.editor, true) でテーブルをラップできましたが、出力されるHTMLには反映されていませんでした。当初はレンダリング側で処理することを想定していましたが、Lexxyの出力をそのまま使えるようにするため、テーブル出力時に自動的にラッパーを含めることになりました。
実装の詳細
WrappedTableNodeの追加
Lexicalの TableNode を継承した WrappedTableNode クラスを新規作成しました。このノードは exportDOM メソッドをオーバーライドし、テーブル要素を <figure class="lexxy-content__table-wrapper"> で囲んだHTMLを出力します。
import { TableNode } from "@lexical/table"
import { createElement } from "../helpers/html_helper"
export class WrappedTableNode extends TableNode {
static clone(node) {
return new WrappedTableNode(node.__key)
}
exportDOM(editor) {
const superExport = super.exportDOM(editor)
return {
...superExport,
after: (tableElement) => {
if (superExport.after) {
tableElement = superExport.after(tableElement)
}
const clonedTable = tableElement.cloneNode(true)
const wrappedTable = createElement("figure", { className: "lexxy-content__table-wrapper" }, clonedTable.outerHTML)
return wrappedTable
}
}
}
}
ポイントは after フックを使って、親クラスの処理後にテーブルをクローンし、figure要素でラップして返すことです。superExport.after が存在する場合は先に実行してから、ラッピング処理を行います。
エディタ設定での置き換え
エディタの初期化時に、標準の TableNode を WrappedTableNode に置き換える設定を追加しました。
import { WrappedTableNode } from "../nodes/wrapped_table_node"
// ノード登録部分
nodes: [
// ...
{
replace: TableNode,
with: () => { return new WrappedTableNode() }
},
TableCellNode,
TableRowNode,
]
この設定により、既存の TableNode が WrappedTableNode に自動的に置き換えられます。
CSSの調整
ラッパー要素のスタイルには margin: 0 を追加し、デフォルトのfigure要素のマージンをリセットしました。
.lexxy-content__table-wrapper {
margin: 0;
margin-block: 1ch;
overflow-x: auto;
}
テストの追加
出力HTMLに正しくfigure要素が含まれることを確認するテストを追加しました。
test "table is wrapped in figure.table-wrapper" do
find_editor.toggle_command("insertTable")
html = find_editor.value
assert_match(/<figure class="lexxy-content__table-wrapper">/, html, "Exported HTML should have figure. table-wrapper")
assert_match(/<figure class="lexxy-content__table-wrapper">.*?<table>.*?<\/table>.*?<\/figure>/m, html, "Table with content should be nested inside the figure wrapper")
end
また、既存のテストヘルパーで引数の順序(cols, rows)を修正し、テストの一貫性を保ちました。
影響範囲
この変更により、Lexxyエディタから出力される全てのテーブルが自動的に <figure class="lexxy-content__table-wrapper"> で囲まれるようになります。レンダリング側で個別にラッパーを追加する必要がなくなり、Lexxyの出力をそのまま使用できるようになりました。