ブラウザ互換性の強化:browserslist導入、`checkVisibility`ポリフィル、Lexical v0.44更新
Lexxyにブラウザ互換性の仕組みが整備されました。browserslistの定義、ESLintによる非対応APIの静的検出、Safari向けのcheckVisibilityポリフィルを組み合わせることで、サポートブラウザ範囲を明示しつつ実行時の互換性を保証する体制が確立されています。
背景
これまでLexxyはサポートブラウザの範囲を明示的に定義しておらず、ブラウザ固有のAPIを使用する際も互換性の検証は開発者の裁量に委ねられていました。Element.checkVisibility()のようにChrome・Firefoxでは利用可能でも古いSafariでは未実装のAPIが、検出されないまま利用されていたのが典型例です。
Railsの:modern設定と同等のブラウザ定義を採用することで、フレームワーク側の互換性基準との一致も図られています。
技術的な変更
browserslistとESLintによる静的検証の導入
サポートブラウザの定義と非対応APIの検出が、それぞれpackage.jsonとESLint設定によって自動化されました。
package.jsonに追加された browserslist の定義は以下のとおりです:
"browserslist": [
"Safari >= 17.2", "iOS >= 17.2",
"Chrome >= 120", "ChromeAndroid >= 120",
"Firefox >= 121",
"not dead"
]
eslint.config.jsは eslint-plugin-compat と @eslint/css を追加し、defineConfigベースの構成に刷新されました。JavaScriptファイルに対してはcompatプラグインがbrowserslistを参照して非対応APIの使用を警告します。CSSファイルに対してはcss/use-baselineルールが2023年ベースラインを基準に未対応プロパティを検出し、css/no-invalid-propertiesルールが無効なプロパティをエラーとして検出します。
{
files: ["src/**/*.js"],
plugins: { js, compat },
extends: ["js/recommended"],
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: globals.browser
}
},
{
files: ["app/**/*.css"],
language: "css/css",
plugins: { css },
extends: ["css/recommended"],
rules: {
"css/use-baseline": ["warn", { available: 2023 }],
"css/no-invalid-properties": ["error", { allowUnknownVariables: true }]
}
}
CIのJavaScriptリントステップも「Lint JavaScript code for consistent style and browser support」と名称が更新され、ブラウザ互換性チェックが正式にCIパイプラインに組み込まれています。
Element.checkVisibility()のポリフィル
Safari 17.2ではElement.checkVisibility()が未実装であるため、src/helpers/html_helper.jsにポリフィルが追加されました。
変更前:
export function isActiveAndVisible(element) {
return element && !element.disabled && element.checkVisibility()
}
変更後:
export function isActiveAndVisible(element) {
return element && !element.disabled && checkVisibility(element)
}
// no `checkVisibility` in Safari < 17.4
// https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility#browser_compatibility
function checkVisibility(element, options) {
if (element.checkVisibility) {
return element.checkVisibility(options)
} else {
if (options) throw new Error("Polyfilled checkVisibility does not support options")
// Will not work for body or a fixed position element child of the body
// which is OK since that doesn't apply in the toolbar where this is used
return Boolean(element.offsetParent)
}
}
フォールバック実装はelement.offsetParentの非null性で可視性を判定しています。コメントにも明記されているとおり、bodyやposition: fixedな要素では正確に動作しませんが、このポリフィルが使われるツールバーのユースケースでは問題が生じません。
Lexical v0.44へのアップデートとネストリスト修正
Lexicalが0.43から0.44に更新され、@lexical/listなどすべての関連パッケージが新バージョンに追従しています。v0.44にはfacebook/lexical#8313で修正されたネストリストのHTML出力バグが含まれています。
修正前は、ネストされたリストを$generateHtmlFromNodesでHTMLに変換する際、子リストが独立した<li>に包まれて出力されていました。修正後は、子リストが親<li>の内側に配置されます。この変更に合わせて、テスト期待値が以下のように更新されています:
変更前(block_formatting.test.js):
'<ol><li value="1">First</li><li value="2" class="lexxy-nested-listitem"><ol><li value="1">Nested</li></ol></li><li value="2">Second</li></ol>'
変更後:
'<ol><li value="1">First<ol><li value="1">Nested</li></ol></li><li value="2">Second</li></ol>'
class="lexxy-nested-listitem"を持つ独立した<li>が除去され、ネストリストが親<li>内に直接配置された形式が期待値となりました。同様の修正がtest/browser/tests/formatting/list_indentation.test.jsにも適用されています。
CSSの調整
app/assets/stylesheets/lexxy-editor.cssでは、ESLintのCSSチェックで検出された箇所に/* eslint-disable-next-line css/no-invalid-properties */コメントが追加されています。また、フォントプレビューの::after擬似要素がdisplay: inline-blockからdisplay: flexに変更され、センタリングにalign-self: centerではなくalign-items: centerとjustify-content: centerが使用されるようになりました。
設計判断
ポリフィルをライブラリ側で内包する方針が採られており、利用側アプリケーションへの変更を不要にしています。checkVisibilityのフォールバックをoffsetParentベースで実装したことは、完全な仕様準拠ではなく実用上の制約を明示したうえでの実装です。コメントで「このポリフィルはツールバーのユースケースでは問題ない」と注記されていることで、将来の保守者が制約を把握できます。
ESLintによるブラウザ互換性チェックについては「HTMLElementのメンバーには対応が難しい」とPRに注記されており、静的解析の限界を認識したうえでの導入です。完全な自動検出ではなく、静的検証と手動ポリフィルを組み合わせるアプローチが取られています。また、browserslistには具体的なブラウザバージョンを列挙する形式を採用し、ESLintのCSSルールにはbaseline 2023という異なる基準を使用するという、ツールごとに適した表現形式を使い分けている点も注目されます。
まとめ
browserslistによる対象ブラウザの明示、ESLintによる静的検出、個別ポリフィルの実装という三層構造で、Lexxyのブラウザ互換性保証の仕組みが整備されました。Lexical v0.44へのアップデートによるネストリストバグの解消とあわせて、エディタの出力品質も改善されています。