Bloggerテーマの作成(5) シンタックスハイライターPrismJSの導入

2022-01-08

Bloggerカスタマイズ

t f B! P L

Blogger.comにPrism.jsをCDNで導入する-p--qをMarkdown-itで使えるようにします。まずはMarkdown-itのライブデモのコードの部分で生成されるHTMLをみてみます。

 シンタックスハイライター設定前のHTML

 Chromeで「ページのソースを表示」を選択するとHTMLではなくマークダウンが表示されてちょっと驚きました。仕方ないので「検証」から要素を一つずつ選択してコピペしました。

<h2>Code</h2>
<p>Inline <code>code</code></p>
<p>Indented code</p>
<pre><code>// Some comments
line 1 of code
line 2 of code
line 3 of code
</code></pre>
<p>Block code “fences”</p>
<pre><code>Sample text here...
</code></pre>
<p>Syntax highlighting</p>
<pre><code class="language-js">var foo = function (bar) {
  return bar++;
};

console.log(foo(5));
</code></pre>

 フェンスドコードブロック(CommonMark Spec)ではcodeタグに言語名のクラスがつきますけど、インラインコードやインデンテッドコードのタグには何も属性がつかないので PrismJSではシンタックスハイライトが効きません。

インデンテッドコードはフェンスドコードブロックを使えば足りるのでインラインコードのタグにクラス属性をつけることとフェンスドコードブロックのpreタグにPrismJSの設定のための属性を付ける方法を考えないといけません。

 PrismJSでシンタックスハイライトするためのHTMLタグ

<pre class="line-numbers" data-start="1" style="white-space: pre-wrap;"><code class="language-shell-session">// 行番号あり改行あり</code></pre>

<pre class="line-numbers" data-line="1" data-start="1" style="white-space: pre-wrap;"><code class="language-shell-session">// 行番号あり改行あり行ハイライトあり</code></pre>

<pre class="line-numbers" data-start="1"><code class="language-shell-session">// 行番号あり改行なし</code></pre>

<pre><code class="language-shell-session">// 行番号なし</code></pre>

<code class="language-shell-session">//インライン</code> 

この5パターンのうちデフォルトMarkdown-itのまま変換できるのは「行番号なし」だけです。

やらないといけないことはpreタグにクラス属性を付けることとインラインコードでcodeタグにクラス属性をつけることです。

フェンスドコードブロックでpreタグに属性をつける


markdown-it 12.3.0 API documentationには載っているのは探せないのですが、renderer.jsのoptions.highlight関数の引数をみるとREADME.mdの解説にはない3番目の引数があってそこで属性が受け取れます。

highlight: (str, lang, attrs) => `<pre ${attrs.replace(".line-numbers", "class=line-numbers")}><code class="language-${lang}">${md.utils.escapeHtml(str)}</code></pre>`

これでフェンスドコードブロックのpreタグに属性をつけることができます。

``` js .line-numbers data-line=2,3 data-start=1 style="white-space: pre-wrap"
var foo = function (bar) {
  return bar++;
};

console.log(foo(5));
```

フェンスドコードブロックをPrismJSでシンタックスハイライトするにはこういうふうに書けばよくなりました。

 markdown-it-attrsの導入

 

 インラインコードのタグにクラス属性をつけるためにプラグインを導入します。

 GitHub - arve0/markdown-it-attrs: Add classes, identifiers and attributes to your markdown with {} curly brackets, similar to pandoc's header attributes

 このmarkdown-it-attrsプラグインを使うとマークダウンからHTMLタグに属性を追加できるようになります。


 markdown-it-attrs CDN by jsDelivr - A CDN for npm and GitHubからmarkdown-it-attrs.browser.jsを選択しました。

 md.use(markdownItAttrs);でプラグインを有効にすれば`code`{.language-shell-session}とかけばインラインコードもシンタックスハイライトできるようになります。

PrismJSのスクリプトの取得


prismjs CDN by jsDelivr - A CDN for npm and GitHubからPrismJS関連のスクリプトを選択します。 


JavaScriptの下の7つとCSSの下4つがPrismJSのものです。

それぞれ一番上のcombineのもののコードを取得します。ただしBlogger.comにPrism.jsをCDNで導入する-p--qに書いてあるようにautoloaderだけは別に読み込むようにします。

<link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/npm/github-markdown-css@5,npm/prismjs@1/themes/prism.min.css,npm/prismjs@1/plugins/toolbar/prism-toolbar.min.css,npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.css,npm/prismjs@1/plugins/line-highlight/prism-line-highlight.min.css" />
<script src="https://cdn.jsdelivr.net/combine/npm/markdown-it@12/dist/markdown-it.min.js,npm/markdown-it-sub@1/dist/markdown-it-sub.min.js,npm/markdown-it-sup@1/dist/markdown-it-sup.min.js,npm/markdown-it-ins@3/dist/markdown-it-ins.min.js,npm/markdown-it-footnote@3/dist/markdown-it-footnote.min.js,npm/markdown-it-container@3/dist/markdown-it-container.min.js,npm/markdown-it-attrs@4/markdown-it-attrs.browser.min.js,npm/prismjs@1/components/prism-core.min.js,npm/prismjs@1/plugins/toolbar/prism-toolbar.min.js,npm/prismjs@1/plugins/show-language/prism-show-language.min.js,npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.js,npm/prismjs@1/plugins/line-highlight/prism-line-highlight.min.js,npm/prismjs@1/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
<script>
const options = {
  linkify: true,
  typographer: true,
  highlight: (str, lang, attrs) => `<pre ${attrs.replace(".line-numbers", "class=line-numbers")}><code class="language-${lang}">${md.utils.escapeHtml(str)}</code></pre>`
};
const md = window.markdownit(options)
  .use(window.markdownitSub)
  .use(window.markdownitSup)
  .use(window.markdownitIns)
  .use(window.markdownitFootnote)
  .use(window.markdownitContainer, "warning")
  .use(markdownItAttrs);
let post_elems = document.querySelectorAll("div.post-body");
post_elems.forEach(e => {
  e.innerHTML = md.render(e.textContent);
  e.classList.add("markdown-body");
});
</script>

これでマークダウンからシンタックスハイライトまでができました。

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ