ブラウザ互換性の強化:browserslist導入、`checkVisibility`ポリフィル、Lexical v0.44更新

basecamp/lexxy

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.jseslint-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性で可視性を判定しています。コメントにも明記されているとおり、bodyposition: 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: centerjustify-content: centerが使用されるようになりました。

設計判断

ポリフィルをライブラリ側で内包する方針が採られており、利用側アプリケーションへの変更を不要にしています。checkVisibilityのフォールバックをoffsetParentベースで実装したことは、完全な仕様準拠ではなく実用上の制約を明示したうえでの実装です。コメントで「このポリフィルはツールバーのユースケースでは問題ない」と注記されていることで、将来の保守者が制約を把握できます。

ESLintによるブラウザ互換性チェックについては「HTMLElementのメンバーには対応が難しい」とPRに注記されており、静的解析の限界を認識したうえでの導入です。完全な自動検出ではなく、静的検証と手動ポリフィルを組み合わせるアプローチが取られています。また、browserslistには具体的なブラウザバージョンを列挙する形式を採用し、ESLintのCSSルールにはbaseline 2023という異なる基準を使用するという、ツールごとに適した表現形式を使い分けている点も注目されます。

まとめ

browserslistによる対象ブラウザの明示、ESLintによる静的検出、個別ポリフィルの実装という三層構造で、Lexxyのブラウザ互換性保証の仕組みが整備されました。Lexical v0.44へのアップデートによるネストリストバグの解消とあわせて、エディタの出力品質も改善されています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
4c9a9e29

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

「総論→各論→結論」の構成が明確です。リード文、背景、技術詳細、設計判断、まとめの各要素が適切に配置され、記事全体の流れが非常に分かりやすいです。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きシンタックスハイライト(例: ```json:package.json)、PR番号のリンク記法(例: [PR #1046](URL))ともに正しく使用されています。

対象読者への適合性 ✓ PASS

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

browserslist, ESLint, ポリフィルといった具体的な技術要素に言及しており、専門知識を持つエンジニアを対象読者として適切に書かれています。

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

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

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

Diff内容との照合 ⚠ WARNING

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

`package.json`の`browserslist`の引用が、実際のDiff内容(`"baseline 2023", "not dead"`)と異なり、PR Description内の説明用コードブロックを引用しています。技術的な理解を大きく妨げるものではありませんが、厳密には不正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「ポリフィル」「browserslist」「ESLint」「ネストリスト」など、使用されている技術用語はすべて正確かつ文脈に適しています。

説明の技術的正確性 ✓ PASS

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

checkVisibilityのポリフィル実装やLexicalのネストリスト修正に関する説明は、Diff内のコード変更と完全に一致しており、技術的に正確です。

事実の突合 ✓ PASS

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

記事内の主張はすべてPRのDescriptionやDiff内のコードで裏付けられています。「Railsの`:modern`設定」や「HTMLElementのメンバーには対応が難しい」といったPR内の注記も正確に拾い上げています。

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

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

PR番号(#1046)、Lexicalのバージョン(v0.44)、ブラウザのバージョン番号など、記事に含まれる数値や固有名詞はすべて正確です。

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

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

記事のタイトルはPRの主題である「Browser compatibility」を具体的かつ正確に要約しており、内容と完全に一致しています。

外部知識の正確性 ✓ PASS

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

PR情報に含まれないLTSやEOLといった外部知識の捏造は見られません。すべての記述がPRのコンテキストに基づいています。

時間表現の正確性 ✓ PASS

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

「〜が整備されました」のように完了した変更として記述されており、時間表現の歪曲はありません。