HTMLの空白行を削除するスクリプト

<!-- markdown-mode-on --> ## **概要** 今まで、気の向くままにブログを書いてきて、表題(h2, h3など)の前後に気分で空白行を入れたり、入れなかったりしていた。 その空白行の入れ方にも、`<br/>`タグであったり、`<p>`タグや`<div>`タグであったり、まちまちのやり方をしていた。 それを統一感のあるものにしようと考えた。 <a name="more"></a> ## 現状把握(空白行の書き方) 記事のHTMLにある空白行を削除するには、空白行の書き方を把握することが重要だ。それを列記してみる。 ### 空白行の一般的な書き方 1. **`<br/>` タグの使用** ```html <p>これは本文です。</p> <br/> <p>これは次の段落です。</p> ``` → `<br/>` タグを削除すれば、空白行がなくなります。 2. **`<p>` タグの余白によるもの** ```html <p>これは本文です。</p> <p>これは次の段落です。</p> ``` → 余分な `<p>` タグを削除したり、CSSで `margin` の調整をすることで改善できます。 3. **空白スペースや改行 (` `) の使用** ```html <p>これは本文です。</p> <p> </p> <p>これは次の段落です。</p> ``` → ` ` のある `<p>` タグを削除するか、CSSで `display: none;` にすればOK。 4. **空白の `div` タグの使用** ```html <div style="height: 20px;"></div> ``` → 不要な `div` タグを削除するか、CSS で `display: none;` を適用。 5. **CSSによる `margin` 設定** ```css p { margin-bottom: 20px; } ``` → `margin-bottom` の値を小さくするか `margin: 0;` に変更すると空白行が減ります。 ## 空白行の削除方針 ### 方法 1. **HTMLの整理(書き換え)** → 上記の不要なタグ (`<br/>`、余分な `<p>`、` ` など) を削除 1. **CSSの調整** → `margin` や `padding` の値を適切に設定する 1. **JavaScriptで動的に削除**(大量の空白を削除したい場合) ```javascript document.querySelectorAll('p:empty, div:empty').forEach(el => el.remove()); ``` これにより、空の `<p>` や `<div>` を削除できる。 ### 方針 前項のやり方で空白行の削除ができるが、個々の記事HTMLから空白行を見つけ出し、それを削除したHTMLに更新するとなると、1記事ごとにやるにしろ一括でやるにしろ、大変な作業となる。 そこで、 1. **テーマxml**に空白削除スクリプトを追加し、**DOM (Document Object Model) 上での削除**(※下記注釈)をおこなう。 1. **テーマxml**で、見出しの前後に適切な空白行をつけるCSS調整をおこなう。 DOM 上の削除とは? - 実際の HTML ファイルのコードには影響を与えず、ブラウザが読み込んだ後のページ上で br や空の要素を削除する。 - 記事HTML ファイル自体は変更されない。 - 開発者ツール (F12 キー) で動作を確認すると、DOM から要素が消えているのがわかる。 ## スクリプト 削除したい空白行の書き方と、除外事例を挙げて、<svg aria-label="i-copilot" class="blog-logo" height="24" width="24"><use href="#i-copilot"></use></svg><span style="font-size:12px;"> </span> Copilot にスクリプトを書いてもらった。一発では決まらず、何度か修正を繰り返している。 今、気づいている範囲での最終形である。 ```javascript <script> /*<![CDATA[*/ document.addEventListener("DOMContentLoaded", function () { console.log("? 空白削除スクリプト開始"); // ① 改行目的の <br> タグを削除(ただし #dark-header, #dark-toggler, .item-control, .quick-edit, .blogcard, .katex 内の要素, `<table>` の内部は削除しない) document.querySelectorAll("br").forEach(el => { if (!el.closest("#dark-header") && !el.closest("#dark-toggler") && !el.closest(".item-control") && !el.closest(".quick-edit") && !el.closest(".blogcard") && !el.closest(".katex") && (!el.closest("table")) { el.remove(); } }); console.log("? 不要な <br> の削除完了"); // ② 空の <p> や <div> の削除(#dark-header, #dark-toggler, .item-control, .quick-edit, .blogcard, .katex は削除しない) document.querySelectorAll("p, div").forEach(el => { if (!el.textContent.trim() && !el.closest("#dark-header") && !el.closest("#dark-toggler") && !el.closest(".item-control") && !el.closest(".quick-edit") && !el.closest(".blogcard") && !el.closest(".katex")) { console.log(`削除: ${el.tagName}`); el.remove(); } }); console.log("? 空の <p> や <div> の削除完了"); // ③ span要素の削除を制限(ただし #dark-header, #dark-toggler, .item-control, .quick-edit, .blogcard, .katex 内のものは削除しない) document.querySelectorAll("span").forEach(el => { if (!el.textContent.trim() && !el.closest("#dark-header") && !el.closest("#dark-toggler") && !el.closest(".item-control") && !el.closest(".quick-edit") && !el.closest(".blogcard") && !el.closest(".katex")) { console.log(`削除: ${el.tagName}`); el.remove(); } }); console.log("? 空の <span> の削除完了"); // ④ MutationObserver の修正(ボタンやアイコン・ブログカード・KaTeX 数式が削除されないようにする) const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.removedNodes.forEach(node => { if (node.id === "dark-toggler" || node.id === "dark-header" || node.classList.contains("item-control") || node.classList.contains("quick-edit") || node.classList.contains("blogcard") || node.classList.contains("katex")) { console.warn("?? 重要な要素が削除されたので復元します", node); document.body.appendChild(node); // 強制的に復元 } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); console.log("? MutationObserver 設定完了(ボタン・アイコン・ブログカード・数式を監視)"); }); /*]]>*/ </script> ``` ## CSS調整 ### 見出し(h1, h2, h3, h4, h5, h6) オリジナルJetthemaでの見出し前後の空白行の設定は、次のようになっている。`jettheme-v2.xml`では、590行。 ``` css .entry-text h1, .entry-text h2, .entry-text h3, .entry-text h4, .entry-text h5, .entry-text h6 { color: var(--jt-heading-color); padding-top: 1em; margin-bottom: 1rem; } ``` これを少し調整して、次のようにする。`/*Your custom CSS is here*/` に書く。デフォルトでも悪いわけでもないので、これは好みの問題である。 ```css .entry-text h1, .entry-text h2, .entry-text h3, .entry-text h4, .entry-text h5, .entry-text h6 { margin-top: 1em; margin-bottom: 1em; } ``` ### 画像 ```css /* 記事やブログカードの画像のみに適用(クイック編集アイコンには影響なし) */ .blogcard img:not(:has(+ figcaption)), .post img:not(:has(+ figcaption)) { display: block; margin-bottom: 1.8rem; } /* キャプション付きの画像には影響を与えない */ figcaption { display: block; margin-bottom: 1.8rem; } ``` ## 削除対象から除外が必要な要素 ### ✅ KaTeX の数式 (.katex) - KaTeX の数式は `<span>` や `<div>` を使って構造化されている - 数式表記の HTML に textContent.trim() の判定が影響 ### ✅ ダークモードアイコン - #dark-header,#dark-toggler の要素を削除対象から除外 ### ✅ ソース編集ボタン (.item-control) - .closest(".item-control") をチェック → item-control の子要素である `<p>` や `<div>` は削除対象から除外 - ソース編集ボタンが削除されないよう制御 → ブログのデザインを維持しながら空白削除できるはず。 ### ✅ クイック編集ボタン - .quick-editの要素を削除対象から除外 ### ✅ ブログカード (.blogcard) も影響を受けない - .closest(".blogcard") をチェックして、ブログカード内の `<span>` や `<div>` を削除しないように変更 - ブログカードの構造を維持しつつ、不要な空白行を削除できるよう調整 ### ✅ MutationObserver によって、誤削除された場合は強制復元 - nextElementSibling を確認 → 連続する `<br/><br/>` を削除 - MutationObserver を追加 → 動的に追加された `<br/>` も削除 ## 関連リンク </div></span></div></p></div></span></div></p></p></p></p></p></div></p>
Next Post Previous Post