カスタムタグを含むHTMLの読み込みエラーを修正
LexxyでAction Textのアタッチメントタグ名をカスタマイズした際、HTMLが正しく読み込まれない問題が解消されました。これにより、Lexxy.configure でタグ名を変更しても、エディタの初期化が正常に動作するようになります。
背景
Lexxyは Lexxy.configure を通じて attachmentTagName などのグローバル設定をカスタマイズできる仕組みを提供しています。しかし、カスタム要素の登録とグローバル設定の適用の間に競合状態が存在し、設定が初期化より後に適用されてしまう問題がありました。
#564 で報告されたように、attachmentTagName を action-text-attachment から bc-attachment に変更しても、エディタが古いタグ名で初期化されてしまい、カスタムタグを含むHTMLの読み込みに失敗していました。これは、インポート時に即座にカスタム要素が登録されるため、その後の Lexxy.configure 呼び出しが間に合わないという問題でした。
技術的な変更
カスタム要素の登録タイミングを遅延させることで、設定の適用を確実に先行させる実装に変更されました。
変更前:
各要素ファイルの末尾で即座に customElements.define を実行:
export default class LexicalEditorElement extends HTMLElement {
// ...
}
customElements.define("lexxy-editor", LexicalEditorElement)
変更後:
要素定義を src/elements/index.js に集約し、setTimeout で遅延実行:
export function defineElements() {
const elements = {
"lexxy-toolbar": Toolbar,
"lexxy-editor": Editor,
"lexxy-link-dropdown": DropdownLink,
"lexxy-highlight-dropdown": DropdownHighlight,
"lexxy-prompt": Prompt,
"lexxy-code-language-picker": CodeLanguagePicker,
"lexxy-table-tools": TableTools,
}
Object.entries(elements).forEach(([name, element]) => {
customElements.define(name, element)
})
}
import { defineElements } from "./elements/index"
import Lexxy from "./config/lexxy"
// Pushing elements definition to after the current call stack to allow global configuration to take place first
setTimeout(defineElements, 0)
setTimeout(defineElements, 0) により、現在のコールスタックが完了した後にカスタム要素が登録されます。これにより、ユーザーコードで Lexxy.configure を同期的に呼び出せば、要素の初期化前に確実に設定が反映されます。
テストでは、カスタムタグ bc-attachment を含むHTMLの読み込みが正常に動作することが確認されています:
test "load attachment with custom tag" do
visit new_post_path(attachment_tag_name: "bc-attachment")
person = people(:james)
find_editor.value = <<~HTML
<div>Hello World <bc-attachment sgid="#{person.attachable_sgid}" content-type="#{person.content_type}" content=""#{person.name}""></bc-attachment></div>
HTML
assert_editor_html do
assert_selector "bc-attachment"
end
end
設計判断
setTimeout による遅延実行 が採用されました。JavaScriptのイベントループの仕組みを活用し、マクロタスクキューに要素登録を配置することで、同期的なコールスタック(インポート文とその直後の Lexxy.configure 呼び出し)が完了してから初期化が実行されます。
この判断により、ユーザーは以下のような直感的な記述で設定をカスタマイズできます:
import Lexxy from "lexxy"
Lexxy.configure({
attachmentTagName: "bc-attachment"
})
docs/configuration.md には、この制約が明記されました。Lexxy.configure はインポート文の直後に呼び出す必要があることが強調されています。遅延時間を0msに設定することで、実用上の影響を最小限に抑えながら、確実な初期化順序を保証しています。
本PRは、JavaScriptモジュールのロードタイミングとカスタム要素の登録タイミングの競合を、イベントループの制御によって解決した変更です。setTimeout による遅延実行という最小限の変更で、設定のカスタマイズ性と後方互換性の両立を実現しています。