JSでmarkdownからカスタマイズしたHTMLを生成する
開発チームの下田です。
普段仕事をしていて、「めんどくさい」と思ったことはありませんか?
そんなときこそプログラミングの出番です。
「めんどくさい」=単純作業であることが多く、簡単なコードを書くとサクッと解決できる可能性が高いです。
私はたった今、このブログの執筆がめんどうくさいです。
どのように面倒くさいかというと少々古めのCGMを使っているため、次のような問題が起きています。
問題点
- まともな見栄えにするには、HTMLで記述しなければならない
- コードを貼り付けるときは、エスケープする必要があり、preタグのclassに"prettyprint"を指定しなければならない
- 見出しはh2タグ、小見出しはh3タグになっている
解決方法
本来はCGMを乗り換えるべきなのですが、やんごとなき事情により実現できない場合があります。
小手先で解決するために、コンテンツはmarkdownで記述して、このブログに合わせたHTMLを作ることにしました。
JSのライブラリMarkedを使って、生成ページを作成します。
完成したコード
こちらが作成したHTMLのソースコードです。
ポイントを後述します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Marked</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style type="text/css">
textarea {
width: 40vw;
height: 40vh;
}
</style>
</head>
<body>
<textarea name="md" id="md" placeholder="markdownを書いてください"></textarea>
<textarea name="html" id="html" readonly placeholder="HTMLが出てきます"></textarea>
<script>
function escapeHtml(str) {
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''')
}
let renderer = new marked.Renderer()
renderer.code = function(text, language) {
return `<pre class="prettyprint">${escapeHtml(text)}</pre>`;
}
let md = document.querySelector('#md')
let html = document.querySelector('#html')
renderer.heading = function(text, level) {
return `<h${level + 1}>${text}</h${level + 1}>`
}
md.addEventListener('change', function() {
html.value = marked(md.value, { renderer: renderer })
})
</script>
</body>
</html>
Markedの使い方
CDNからimportして、markedを呼ぶだけです。
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
marked('# title') // return '<h1>title</h1>'
Markedのカスタマイズ
Markedのドキュメントにカスタマイズ方法が載っています。
どういうHTMLで返すかは、markedのオプションにレンダラを渡すと変更できます。
見出しを変更するにはrenderer.headingを、コードを変更するにはrenderer.codeにHTML作成用のfunctionを設定してあげます。
// HTMLのレンダラを新しく作成
let renderer = new marked.Renderer()
// 大見出しがh2、小見出しがh3になるようにする
renderer.heading = function(text, level) {
return `<h${level + 1}>${text}</h${level + 1}>`
}
marked('# title', { renderer: renderer }) // return '<h2>title</h2>'
まとめ
余計な作業であるHTMLコーディングをせずに、本来やるべき文章作成に集中できるようになりました。
めんどうくさかったブログの執筆作業がめんどうくさくなくなりました。
単純作業を減らすと時間の短縮はもちろんですが、モチベーションが向上します。
せっかくプログラミングを覚えたなら、単純作業はちょっとしたコードで自動化できる場合が多いので、「めんどくさい」と思ったら少し考えてみるといいと思います。