🥱
なるべくコードを書かずに「.md」ファイルを HTML に変換 / Marked.js + Prism.js + Mermaid.js
はじめに
CDN で公開されているものを組み合わせて、マークダウン記法で書けるサイトができたらと考えた。今回は JavaScript から MD ファイルを読み込んで DOM を生成する。
使用したライブラリ
- github-markdown-css
- Marked.js
- Prism.js
- Mermaid.js
各ファイルの中身
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="content-security-policy" content="script-src 'self' *.cloudflare.com *.jsdelivr.net">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/themes/prism-okaidia.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/plugins/line-numbers/prism-line-numbers.min.css">
<link rel="stylesheet" href="main.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/16.2.0/lib/marked.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/components/prism-typescript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mermaid-js/tiny@11.10.0/dist/mermaid.tiny.min.js"></script>
</head>
<body class="markdown-body">
<div>
<header>
<h1>header</h1>
</header>
<main id="main"></main>
<footer>
<hr>
<p>footer</p>
</footer>
</div>
<script src="main.js"></script>
</body>
</html>
main.css
.markdown-body {
font-family: 'Noto Sans JP', 'Hiragino Sans', sans-serif;
}
.markdown-body > div {
max-width: 1000px;
width: 100%;
margin: 0 auto;
padding: 0 16px;
box-sizing: border-box;
}
main.js
/**
* MAIN
* @returns {Promise<void>}
*/
async function main() {
const mainContents = document.getElementById('main');
const df = await makeDocumentFragment();
mainContents.appendChild(df);
Prism.highlightAll();
mermaid.initialize({ securityLevel: 'loose', theme: 'neutral' });
mermaid.init(undefined, document.getElementsByClassName('language-mermaid'));
}
main().catch(console.error);
/* ################################################################ */
/**
* メインコンテンツの DocumentFragment を生成
* @returns {Promise<DocumentFragment>}
*/
async function makeDocumentFragment() {
const df = document.createDocumentFragment();
const text = await importTextFile('main.md');
const doc = document.createElement('div');
marked.use({ renderer: { code: appendClass } });
marked.setOptions({ breaks: true });
doc.innerHTML = marked.parse(text);
df.appendChild(doc);
return df;
}
/**
* テキストファイルをインポート
* @param filename ファイル名
* @returns {Promise<string>} テキスト
*/
async function importTextFile(filename) {
const file = await fetch(filename);
return await file.text();
}
/**
* コードエリアへ Class を追加
* @param code コードの種類
* @returns {string} 変換後の HTML
*/
function appendClass(code) {
if (code.lang === 'mermaid' || code.lang === 'Mermaid') {
return '<pre class="language-mermaid">' + code.text + '</pre>';
} else {
return '<pre><code class="language-' + code.lang + ' line-numbers">' + code.text + '</code></pre>';
}
}
結果
若干、色がちぐはぐですが、よいのではないでしょうか。
ダークモード

ライトモード

おわりに
Marked.js + Prism.js + Mermaid.js のサンプルが見つからなかったので書いた。これをベースに日記を作りたい (願望)。
参考リンク
- Using mermaid with marked.js · Issue #2972 · mermaid-js/mermaid
- yusukebe/workers-blog: PoC
Discussion