marked.jsを利用してMarkdownをHTMLに変換

Markdownで書かれた内容をHTMLに変換してみます。ライブラリとして「marked.js」を利用します。シンタックスハイライト、独自クラスの追加、目次の生成などについても取り上げます。

MarkdownをHTMLに変換

markedをインストール

npm install marked

ソース

const marked = require('marked')

const markdown = '# heading\n' +
  '## list\n' +
  '- list1\n' +
  '- list2\n\n' +
  '## code\n' +
  '```js\n' +
  'let x = 1;\n' +
  '```\n' +
  '## table\n' +
  '| col1 | col2 |\n' +
  '---|---\n' +
  'abc|123\n' +
  'xyz|456';

console.log(marked(markdown))

実行結果

以下のように、HTMLに変換されました。

$ node app.js 
<h1 id="heading">heading</h1>
<h2 id="list">list</h2>
<ul>
<li>list1</li>
<li>list2</li>
</ul>
<h2 id="code">code</h2>
<pre><code class="language-js">let x = 1;</code></pre>
<h2 id="table">table</h2>
<table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
</tr>
</thead>
<tbody><tr>
<td>abc</td>
<td>123</td>
</tr>
<tr>
<td>xyz</td>
<td>456</td>
</tr>
</tbody></table>

オプション|setOptions

オプションで marked.js の動作を変更できます。利用可能なオプションは以下ページで確認できます。
https://marked.js.org/#/USING_ADVANCED.md#options

シンタックスハイライト

highlight.jsをインストール

npm install highlight.js

ソース

const marked = require('marked')
const highlight = require('highlight.js')

marked.setOptions({
  highlight: code => {
    return highlight.highlightAuto(code).value
  }
})

const markdown = '## code\n' +
  '```js\n' +
  'let x = 1;\n' +
  '```'

console.log(marked(markdown))

実行結果

highlight.js によって hljs-attribute のクラスが追加されました。

$ node app.js 
<h2 id="code">code</h2>
<pre><code class="language-js"><span class="hljs-attribute">let x</span> = 1;</code></pre>

対応するスタイルは、node_modules/highlight.js/stylesディレクトリ 配下に存在します。

拡張|独自クラスの追加

テーブルタグに独自のClassを追加するよう拡張してみます。

オリジナルの処理を探す

https://github.com/markedjs/marked/blob/master/lib/marked.js にて Renderer.prototype.table で検索すると以下処理が見つかりました。

Renderer.prototype.table = function(header, body) {
  if (body) body = '<tbody>' + body + '</tbody>';

  return '<table>\n'
    + '<thead>\n'
    + header
    + '</thead>\n'
    + body
    + '</table>\n';
};

ソース

先ほど見つけたtableタグの処理を拡張してみます。

const marked = require('marked')

const renderer = new marked.Renderer()
renderer.table = (header, body) => {
  if (body) body = '<tbody>' + body + '</tbody>'

  return '<table class="wakuwaku">\n'
    + '<thead>\n'
    + header
    + '</thead>\n'
    + body
    + '</table>\n'
}
marked.setOptions({ renderer: renderer })

const markdown = '## table\n' +
  '| col1 | col2 |\n' +
  '---|---\n' +
  'abc|123\n' +
  'xyz|456'

console.log(marked(markdown))

実行結果

tableタグclass="wakuwaku" が追加されました。

$ node app.js 
<h2 id="table">table</h2>
<table class="wakuwaku">
<thead>
<tr>
<th>col1</th>
<th>col2</th>
</tr>
</thead>
<tbody><tr>
<td>abc</td>
<td>123</td>
</tr>
<tr>
<td>xyz</td>
<td>456</td>
</tr>
</tbody></table>

拡張|目次(toc)の生成

目次(table of contents)用のリストを生成してみます。

ソース

toc変数 に目次データを格納します。

const marked = require('marked')
const toc = []

const renderer = new marked.Renderer()
renderer.heading = (text, level) => {
  const slug = encodeURI(text.toLowerCase())
  toc.push({
    level: level,
    slug: slug,
    title: text
  })
  return '<h'
    + level
    + ' id="'
    + slug
    + '">'
    + text
    + '</h'
    + level
    + '>\n'
}
marked.setOptions({ renderer: renderer })

const markdown =
  '# 見出し1\n' +
  '## 見出し1-1\n' +
  '### 見出し1-1-1\n' +
  '### 見出し1-1-2\n' +
  '## 見出し1-2\n' +
  '## 見出し1-3\n' +
  '# 見出し2\n' +
  '## 見出し2-1\n' +
  '## 見出し2-2\n' +
  '# 見出し3'

console.log(marked(markdown))
console.log(toc)

実行結果

$ node app.js
<h1 id="%E8%A6%8B%E5%87%BA%E3%81%971">見出し1</h1>
<h2 id="%E8%A6%8B%E5%87%BA%E3%81%971-1">見出し1-1</h2>
<h3 id="%E8%A6%8B%E5%87%BA%E3%81%971-1-1">見出し1-1-1</h3>
<h3 id="%E8%A6%8B%E5%87%BA%E3%81%971-1-2">見出し1-1-2</h3>
<h2 id="%E8%A6%8B%E5%87%BA%E3%81%971-2">見出し1-2</h2>
<h2 id="%E8%A6%8B%E5%87%BA%E3%81%971-3">見出し1-3</h2>
<h1 id="%E8%A6%8B%E5%87%BA%E3%81%972">見出し2</h1>
<h2 id="%E8%A6%8B%E5%87%BA%E3%81%972-1">見出し2-1</h2>
<h2 id="%E8%A6%8B%E5%87%BA%E3%81%972-2">見出し2-2</h2>
<h1 id="%E8%A6%8B%E5%87%BA%E3%81%973">見出し3</h1>

[ { level: 1, slug: '%E8%A6%8B%E5%87%BA%E3%81%971', title: '見出し1' },
  { level: 2, slug: '%E8%A6%8B%E5%87%BA%E3%81%971-1', title: '見出し1-1' },
  { level: 3, slug: '%E8%A6%8B%E5%87%BA%E3%81%971-1-1', title: '見出し1-1-1' },
  { level: 3, slug: '%E8%A6%8B%E5%87%BA%E3%81%971-1-2', title: '見出し1-1-2' },
  { level: 2, slug: '%E8%A6%8B%E5%87%BA%E3%81%971-2', title: '見出し1-2' },
  { level: 2, slug: '%E8%A6%8B%E5%87%BA%E3%81%971-3', title: '見出し1-3' },
  { level: 1, slug: '%E8%A6%8B%E5%87%BA%E3%81%972', title: '見出し2' },
  { level: 2, slug: '%E8%A6%8B%E5%87%BA%E3%81%972-1', title: '見出し2-1' },
  { level: 2, slug: '%E8%A6%8B%E5%87%BA%E3%81%972-2', title: '見出し2-2' },
  { level: 1, slug: '%E8%A6%8B%E5%87%BA%E3%81%973', title: '見出し3' } ]

参考・関連

【エンジニア向け】仕事を見つける方法

転職する

転職エージェントを活用する

転職サイトの場合、自身でサイト上から企業を探す必要があります。 一方「レバテックキャリア」 などの転職エージェントの場合、エージェントが企業を紹介してくれます。エージェントが間に入ることにより、日程調整や、条件交渉などもサポートしてくれます。

転職ドラフトを活用する

転職ドラフト」は、 企業がITエンジニアをドラフトという形で指名するサービスです。年収が最初に提示されるなどのメリットがあります。 ただ、初回登録時にレジュメ作成が必要で、すでにエンジニア経験が豊富にあるエンジニア向けのサービスかと思います。 レジュメ作成が手間ですが、自身のキャリアを見直す機会になり、他の仕事探しにも役立つはずです。

エンジニア転職保証のあるスクールを活用する

ある程度、開発経験のあるかたであれば、独学で必要なスキルを身につけることができるはずです。ただ、別業種からエンジニアに転職したい場合など、1から独学で学ぶのはハードルが高いです。そういった方は、スクールの活用を検討しても良いと思います。 「TechAcademy」は、エンジニア転職保証コースを提供しています。給付金制度の対象講座として認定されているため、金銭面の負担も抑えることができます。

フリーランスとして活動する

レバテックフリーランス」「ITプロパートナーズ」「ギークスジョブ」は、フリーランスエージェントサービスです。 エージェントによって、支払いサイトなど細かい違いはありますが、まずは良い案件を見つけることが重要です。 登録自体は無料なので、複数エージェントに登録して、より多くの案件を紹介してもらうのがおすすめです。

logo
わくわくBank.
技術系の記事を中心に、役に立つと思ったこと、整理したい情報などを掲載しています。