そのページ自身をダウンロードする関数
普通やらないと思うが、以下の関数でそのページの HTML がダウンロードできる。
React などを使っている場合でも実際の DOM にレンダリングされた要素はレンダリングされた状態で出力される。
CSS も有効にしたいなら style-loader などで最初から <style> に挿入するなりインライン化するなりしておくのが楽。 code:ts
const download: () => void = () => {
const doc = document.documentElement.cloneNode(true) as HTMLElement;
const script = doc.getElementsByTagName("script")0; script.parentNode!.removeChild(script);
const html = <!DOCTYPE html>\n${doc.outerHTML};
const a = document.createElement("a");
a.href = URL.createObjectURL(new Blob(html, { type: "text/html" })); a.download = "page.html";
a.dispatchEvent(new MouseEvent("click"));
};
<script> を残していいなら以下のようにしてもよい。
code:ts
const html = <!DOCTYPE html>\n${document.documentElement.outerHTML};
doc を整形する際に <canvas> を <img> に変換するなら、こんな処理も必要。
code:ts
const img = document.createElement("img");
const canvas = doc.getElementsByTagName("canvas")0; img.src = document.getElementsByTagName("canvas")0.toDataURL(); img.className = canvas.className;
canvas.parentNode!.replaceChild(img, canvas);
解説
ここから <body> の <script> を取り除くが、document.body から <script> を removeChild() すると、最初の実行でそのコード自体も消えてしまうため初回しか動作しない。 これを防ぐために cloneNode() で document.documentElement を深くコピーし、これに対して removeChild() をする。 あとは outerHTML で <html> 要素の文字列表現を取り出し、リンクを作って <a> 要素の href にこれを指定する。 最後の行は a.click() だと Chrome では動くが Firefox では動かないため、dispatchEvent() でイベントを発火させている。 参考URL