Edited at

そのページ自身をダウンロードする関数の実装

普通あまりやらないと思うけれど、以下の関数でそのページの HTML がダウンロードできる。

React などを使っている場合でも実際の DOM にレンダリングされた要素はレンダリングされた状態で出力される。

CSS も有効にしたいなら style-loader などで最初から <style> に挿入するなりインライン化するなりしておくのが楽。

const download: () => void = () => {

const doc = document.documentElement.cloneNode(true) as HTMLElement;
const script = doc.getElementsByTagName("script")[0];
doc.getElementsByTagName("body")[0].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> を残していいなら以下のようにしてもよい。

const html = `<!DOCTYPE html>\n${document.documentElement.outerHTML}`;


解説

まずは document.documentElement<html> 要素を取得する。

ここから <body><script> を取り除くが、document.body から <script>removeChild() すると、最初の実行でそのコード自体も消えてしまうため初回しか動作しない。

これを防ぐために cloneNode(true)document.documentElement を深くコピーし、これに対して removeChild(script) をしている。

あとは outerHTML<html> 要素の文字列表現を取り出し、リンクを作って <a> 要素の href にこれを指定する。

最後の行は Chrome だと a.click(); でも動くが、Firefox では動かないため横着せず dispatchEvent() で疑似的にイベントを発火させる。

クリックイベントの起こし方は MDNに例がある のでこれを参考に書いた。


参考URL