DiffDaily

Deep & Concise - OSS変更の定点観測

[basecamp/lexxy] カスタム要素のマークアップを最適化し、不要な中間DOM要素を削除

basecamp/lexxy

Context

Lexxyエディタにおいて、テーブルハンドラーとコード言語選択機能が、カスタム要素とは別に独立したDOM要素としてコントロールを持っていました。これにより、空のカスタム要素タグと実際のコントロール要素が二重に存在する冗長な構造となっていました。この変更では、カスタム要素自体がコントロールを直接保持する形に変更し、DOM構造をシンプル化しています。

Technical Detail

DOM構造の変更

変更前:

<lexxy-editor>
  ...
  <lexxy-table-handler></lexxy-table-handler>
  <lexxy-code-language-picker></lexxy-code-language-picker>
  <div class="lexxy-table-handle-buttons">[table controls]</div>
  <select class="lexxy-code-language-picker">[language select]</select>
</lexxy-editor>

変更後:

<lexxy-editor>
  ...
  <lexxy-table-handler>[table controls]</lexxy-table-handler>
  <lexxy-code-language-picker>[language select]</lexxy-code-language-picker>
</lexxy-editor>

TableHandlerの実装変更

テーブルハンドラーでは、buttonsContainerという中間要素を削除し、カスタム要素自身に直接コントロールを追加するよう変更されました。

src/elements/table_handler.js:

// 変更前
#setUpButtons() {
  this.buttonsContainer = createElement("div", {
    className: "lexxy-table-handle-buttons"
  });

  this.buttonsContainer.appendChild(this.#createRowButtonsContainer());
  this.buttonsContainer.appendChild(this.#createColumnButtonsContainer());
  this.buttonsContainer.appendChild(this.moreMenu);
  this.buttonsContainer.addEventListener("keydown", this.#handleTableHandlerKeydown);

  this.#editorElement.appendChild(this.buttonsContainer);
}

// 変更後
#setUpButtons() {
  this.appendChild(this.#createRowButtonsContainer());
  this.appendChild(this.#createColumnButtonsContainer());
  this.appendChild(this.moreMenu);
  this.addEventListener("keydown", this.#handleTableHandlerKeydown);
}

これに伴い、ボタン要素へのアクセスもthis.buttonsContainer.querySelector()からthis.querySelector()に変更され、表示制御もthis.buttonsContainer.style.displayからthis.style.displayに変更されています。

CodeLanguagePickerの実装変更

同様に、コード言語選択機能でも中間要素を削除し、カスタム要素自身に<select>要素を追加するよう変更されました。

src/elements/code_language_picker.js:

// 変更前
this.languagePickerElement.style.position = "absolute"
this.editorElement.appendChild(this.languagePickerElement)

// 変更後  
this.appendChild(this.languagePickerElement)

表示/非表示の制御も、<select>要素のhidden属性からカスタム要素自体のhidden属性へと変更されています:

// 変更前
#showLanguagePicker() {
  this.languagePickerElement.hidden = false
}

// 変更後
#showLanguagePicker() {
  this.hidden = false
}

CSSセレクタの変更

CSS側も、クラスセレクタからカスタム要素セレクタに変更されました。

app/assets/stylesheets/lexxy-editor.css:

/* 変更前 */
:where(.lexxy-table-handle-buttons) {
  --button-size: 2.5lh;
  color: var(--lexxy-color-ink-inverted);
  /* ... */
}

/* 変更後 */
:where(lexxy-table-handler) {
  --button-size: 2.5lh;
  color: var(--lexxy-color-ink-inverted);
  /* ... */
}

コード言語選択機能のスタイルも、カスタム要素とその内部の<select>要素に分離されました:

:where(lexxy-code-language-picker) {
  inset-inline-end: var(--lexxy-editor-padding);
  position: absolute;

  select {
    -webkit-appearance: none;
    appearance: none;
    /* ... */
  }
}

影響範囲

  • テスト用のヘルパーメソッドも更新され、.lexxy-table-handle-buttonsからlexxy-table-handlerへのセレクタ変更が反映されています
  • この変更により、DOMツリーがよりシンプルになり、Web Componentsの標準的な使い方に沿った実装となりました
  • 機能的な変更はなく、純粋なリファクタリングです