Skip to content

fix: CSS specificity 強化とインラインリンクの変換除外#3

Merged
hirano00o merged 8 commits intomainfrom
fix/css-robustness-and-standalone-filter
Mar 10, 2026
Merged

fix: CSS specificity 強化とインラインリンクの変換除外#3
hirano00o merged 8 commits intomainfrom
fix/css-robustness-and-standalone-filter

Conversation

@hirano00o
Copy link
Owner

背景

はてなブログで git-code-embed を使用した際、以下の2つの問題が発生していた。

  1. ホストページのグローバル CSS(Life テーマ等)が .gce-* 要素に干渉し、意図した表示にならない
  2. 文中に含まれる GitHub URL リンクも変換されてしまう

変更内容

CSS specificity 強化 (src/styles.ts)

問題 原因 CSS ルール
各行に水平線 .entry-content table td { border: 1px solid #d2d7e5 }
パディング崩れ .entry-content table td { padding: 5px 10px }
スクロール不具合 .entry-content table { display: block; overflow: auto }
ヘッダー行間が広い グローバル line-height 継承
  • セレクタを .gce-container .gce-xxx 形式に変更し、外部テーマ CSS に勝てる specificity に引き上げ
  • .gce-container *box-sizing: border-box リセットを追加
  • display: tableborder-top/bottom/left: noneline-height 等の明示プロパティを追加

変換対象の限定 (src/index.ts)

  • isEdgeSibling() を追加: 隣接ノードが null・空白テキストノード・<BR> のいずれかなら edge と判定
  • isStandaloneAnchor() を追加: 前後のシブリングが両方 edge の <a> のみ変換対象とする
  • 文中リンク・前後にテキストのあるリンク・同行複数リンクは変換されない

テスト追加 (test/index.test.ts)

  • 既存テスト1件修正(複数アンカーを <p> でラップ)
  • 新規テスト6件追加(空白テキストノード、<br> 隣接、テキスト囲み、同行2リンク等)

手動確認ケース追加 (test-page.html)

変換されないインラインリンクのケースを3件追加。

確認

  • npm test 全59件通過
  • npm run build 成功

はてなブログ等のホストページグローバル CSS(table/td ルール)が
.gce-* 要素に干渉する問題と、文中の GitHub URL リンクが意図せず
変換される問題を修正する。

- src/styles.ts: セレクタを .gce-container .gce-xxx 形式に変更して
  specificity を引き上げ、外部テーマ CSS に勝てるようにした。
  .gce-container * の box-sizing リセット、display:table 明示、
  border/padding/line-height の明示プロパティを追加。
- src/index.ts: isStandaloneAnchor() を追加し、前後のシブリングが
  null または <BR> でない <a> タグは変換対象から除外する。
- test/index.test.ts: isStandaloneAnchor に対応した既存テスト修正
  と新規テスト 5 件を追加。
- test-page.html: 変換されないインラインリンクの手動確認ケースを追加。
実際のブログ HTML では <p> と <a> の間に改行・インデントの空白
テキストノード(nodeType === 3)が挿入される。前の実装では
テキストノードを一律 false にしていたため、以下のような
よく見られる HTML パターンで変換がスキップされていた:

  <p>
    <a href="https://github.com/...">...</a>
  </p>

textContent?.trim() === "" の空白テキストノードを edge として
扱うことで、はてなブログ等の実際の HTML 構造でも正しく動作する。
空白テキストノードを透過させる実装では、改行+インデントを挟んで
並ぶ複数の <a> タグが standalone と誤判定されて変換されてしまう
問題があった。

  <p>
    <a href="...">link1</a>
    <a href="...">link2</a>   ← 誤って変換されていた
  </p>

isEdgeSibling で空白を単純に許容するのではなく、
nonWhitespaceSibling で空白テキストノードをスキップして
実質的な隣接ノードを取得するよう実装を変更した。
nonWhitespaceSibling で空白スキップ後の隣接ノードがブロック要素
(<h1>〜<h6>, <p>, <div> 等)の場合も行境界として扱うことで、
<body> 直下や <p> の外に単独で置かれた <a> を正しく変換対象と
する。

<a> タグ同士が空白テキストノード越しに隣接するケースは、
nonWhitespaceSibling がスキップ後に <a>(非ブロック要素)を
返すため引き続き変換されない。
standalone アンカーのみを変換する仕様をユーザーが把握できるよう、
隣接ノードの判定ルール一覧と変換される/されない HTML の例を追加した。
はてなブログセクションに「単独行に置く必要がある」旨と各編集モード
での正しい書き方・誤った書き方の例を追記した。
@hirano00o hirano00o merged commit 1bba225 into main Mar 10, 2026
1 check passed
@hirano00o hirano00o deleted the fix/css-robustness-and-standalone-filter branch March 10, 2026 06:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant