MarkedとDOMPurifyでMarkdownライブプレビュー:HTMLの無害化を体験

プログラミング・Web開発カテゴリを表すパンダのイラスト プログラミング・Web開発

この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。架空のデータとブラウザの操作を使って、MarkedとDOMPurifyの用途、仕組み、失敗時の観察ポイントを学びます。実在のサービスや個人情報へのアクセスは行いません。

検証ステータス: 2026-10-30に公式資料とGitHub固定コミットのHTML/JavaScriptを照合しました。実ブラウザ操作・CDN取得・描画/音声出力は未実行で、本文の結果はコードからの期待値です。

項目内容
対象Chrome/Edge/Firefox等の現代的なブラウザ(実機互換性は未確認)
使用ライブラリMarkedとDOMPurify(教材内バージョン: Marked 16.3.0 / DOMPurify 3.4.17)
費用デモのソース自体に有料APIは不要。通信料金や利用条件は環境に依存
データページ内の架空データ。認証情報・位置情報・企業データ不要
学習操作Markdownを入力すると安全化したHTMLプレビューを表示する

なぜこの技術を試すのか

ブログを書いているとき、Markdownをプレビューできれば見出しや箇条書きの形を確認しやすくなります。しかしMarkdownからHTMLを作る処理は、それだけで安全なHTMLを作れることを意味しません。MarkedはMarkdownをHTMLへ解析する役割、DOMPurifyはHTMLから危険な要素・属性を取り除く役割です。両者を組み合わせると、便利さと安全性の境界を小さなデモで学べます。実際の公開用CMSの認証や保存機能を代替するものではありません。

動くサンプルを作るときは、見た目が動いたという事実だけで終わらず、「どの入力がどの変数を変え、どの処理が描画を更新したか」を区別する必要があります。今回の教材では、その変化を画面に明示します。実際のサービスへ取り込むときには、認証や保存の処理を別途設計してください。

まず試す:ライブデモと期待する結果

最初に「星空メモ」の見出しと太字・斜体のMarkdownを表示し、更新ボタンを押します。見出しと箇条書きがHTMLの構造として反映されるか確認してください。次に架空の文字列へ書き換え、プレビューが変更されるか観察します。動作の観察をするときは、Markdownを変換する前の文字列と、DOMへ反映した結果を分けて考えます。画面下のSUCCESSは処理が例外なく終わった意味であり、あらゆる攻撃に対する安全性の保証ではありません。

操作の前に確認すること

  1. 自分のPCがJavaScriptを実行できることを確認します。管理者権限は必要ありません。

  2. ブラウザの開発者ツールを開き、Consoleでエラー、NetworkでCDN取得失敗がないか見る準備をします。

  3. デモが実際に公開されていない場合は、Daily Code側のindex.htmlとapp.jsを同じフォルダに保存して、ローカルHTTPサーバーで開きます。moduleを使う場合、file://での直接実行は動作保証されません。

  4. 結果を操作前後で比べます。期待値と異なる場合は「何が表示されなかったか」を先に記録します。

仕組みの全体図

flowchart LR
    A["入力やクリック"] --> B["イベントを受ける"]
    B --> C["MarkedとDOMPurify のAPI"]
    C --> D["状態と描画を更新"]
    D --> E["見た目と文字で確認"]

この図は学習用の概念図で、ブラウザ内部の実装やネットワーク通信の詳細を表したものではありません。ライブラリが何でも「操作がどの変数へ届くか」を追いかけることは共通です。

公開デモが使えない場合のローカル確認

固定コミットのHTML本体とJavaScript本体をGitHubのRaw表示から、それぞれindex.htmlとapp.jsとして同じ新規フォルダに保存します。READMEだけでは動作しません。WindowsではそのフォルダでPowerShellを開きpy -3 -m http.server 8000 --bind 127.0.0.1、Linux/macOSではpython3 -m http.server 8000 --bind 127.0.0.1を実行し、同じPCのhttp://127.0.0.1:8000/を開きます。終了はターミナルでCtrl+Cです。ブラウザがライブラリ本体を外部CDNから取得するため、接続できない場合はConsoleとNetworkのエラーを確認します。この手順は再現案内であり、本記事のブラウザ実測報告ではありません。

どう動いているのか:APIを読み解く

MarkedのparseはMarkdownテキストからHTML文字列を生成します。Markdown自体にHTMLを含められるため、解析結果へonerrorなどのイベント属性が混ざることもあります。MarkedはそのHTMLの無害化を行いません。ブラウザで生成結果をinnerHTMLへ渡す前にDOMPurify.sanitizeで安全な要素へ制限します。今回のデモでは画像・iframe・style・scriptをさらに禁止し、外部リンクもクリック不可にします。これは教材用の制限であり、用途によって許す要素を明確に設計する必要があります。

最小コードの読み方

// Marked単体のHTMLをinnerHTMLへ直渡ししない
const unsafeHtml = marked.parse(markdownText);
const safeHtml = DOMPurify.sanitize(unsafeHtml);
preview.innerHTML = safeHtml;

上記はAPIの要点を取り出した抜粋です。コピーして単独実行する完成ファイルではありません。動かすためのHTMLと実装一式はDaily Code側のREADME/デモファイルで確認してください。どの関数がHTML要素を選び、どの行が数値を更新するかを追い、既知の架空値で試します。

一条件だけ変更して比較する

入力へ通常の太字を追加するとstrong要素へ変換されます。一方、画像を含むMarkdownを入力しても、デモでは画像を表示させません。これはあえて外部画像の読み込みを禁止したためです。公開CMSへ組み込む場合は必要なタグだけを許可し、URLのプロトコルとリンクの属性も確認します。Markdown構文とHTMLの許可規則を分けて変更できることが重要です。

比較の手順は、最初の値を記録し、一か所だけ変更して、結果が想定の部分に現れたかを確認することです。入力を一度にいくつも変更すると、何が影響したか分からなくなります。変更前へ戻す操作まで含めて検証してください。

失敗したときにどこを見るか

Markdownの変換ライブラリを通ったからといって「安全」と判断するのは誤りです。HTML文字列を加工した後に再び安全でないHTMLを結合すると、無害化した意味が失われます。実務ではHTML Sanitizerの更新、CSP、Trusted Typesなども検討対象です。ユーザー入力をそのまま公開する場合はブラウザだけでなくサーバー側にも適切な検証が必要です。今回のサンプルは簡単なブラウザ表示の実験であり、安全性保証やペネトレーションテストの代わりにはなりません。

観察した状態切り分ける点対応の例
画面が初期状態から変わらないスクリプト取得・初期化・イベント登録Console / Network / scriptタグを確認
表示が変わるが意味が合わない入力値・配列・単位・更新対象値を固定して一条件ずつ確認
ボタンを押せないセレクターとDOM生成順序idが一致するかHTMLを確認
一部の端末だけ動かないブラウザ機能、権限、CDN、性能端末とバージョン、再現操作を記録

ブラウザ内でのエラーと公開Webサーバーの障害は別です。前者は開発者ツールのエラー内容、後者はHTTPレスポンスやアセットの配信条件から調べます。未知の失敗を成功と表現しないことが、技術メモの信頼性を高めます。

業務・学習への応用

技術ドキュメントのプレビュー、メモ帳、軽量CMS、社内Wikiの試作などに応用できます。実際の編集権限、改訂履歴、公開フロー、ロールバック、悪意あるファイルのアップロード防止などは別の業務要件です。プレビュー用のライブラリを選ぶだけでは公開基盤全体の安全性は完成しません。

導入前に決めること

読者へ公開するとき、表示したデータがどこから来るか、誰が変更できるか、画面へ残る情報の種類、ライブラリ更新時の確認項目を決めます。今回のデモにはログインもサーバー保存もありません。そこで運用機能を追加する前に、まず「想定どおり表示される最小部分」と「実務上の信頼性・権限・バックアップが必要な部分」を区別することを勧めます。第三者CDNは外部通信のため、企業ネットワークで許されるか事前確認が必要です。

別方式と比較する

方式向く場面注意点
MarkedとDOMPurifyMarkdownを入力すると安全化したHTMLプレビューを表示するなど目的に合う場面依存ライブラリの更新・利用条件の管理が必要
ブラウザ標準API小さな機能を自前で作る仕様や互換性を自分で確認する
静的画像・表操作を必要としない説明状態の変化をその場で体験できない

ライブラリは必要なときに選ぶ道具です。何を達成したいかと学習コストを合わせて比較します。「ライブラリを入れること」を目的にしない方が、小規模なページでは保守しやすくなります。

GitHubサンプル

ブログ本文は背景や考え方、Daily Codeは実行・改造するためのコード、という役割を分けています。外部サービスへ投稿・保存するAPIは含めません。

公式情報・一次情報

資料確認範囲: 2026-10-27の編集時点で公式ドキュメントを参照。リンク先の将来の変更やすべてのCDNアセット応答まで保証するものではありません。

検証範囲の補足

GitHubに保存された固定ソースと公式API説明を照合しました。ブラウザ操作、CDNロード、各OS上での結果は未検証です。実際の動作確認時にはConsoleとNetworkを確認し、画面のSUCCESS表示だけで全条件の成功を断定しないでください。

文書情報

記事タイトル
MarkedとDOMPurifyでMarkdownライブプレビュー:HTMLの無害化を体験
作成日
更新日
Source URL
https://papanda925.com/?p=18300

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

タイトルとURLをコピーしました