remark-directiveでMDから好きなHTMLを生成

2 min read読了の目安(約1900字

MDから任意のHTMLを作りたいが、MDXを書くのは面倒。 もっと楽に好き勝手を生成したい。

remark-directiveでできるじゃん

Generic directives proposalという構文がCommonMarkで議論されている。

https://talk.commonmark.org/t/generic-directives-plugins-syntax/444/158

例えば、


:::main
あああ
:::

が、

<main><p>あああ</p></main>

になる。


Lorem:br
ipsum.

::hr{.red}

が、

<p>Lorem<br>ipsum.</p>
<hr class="red">

になる。結構便利そう。

これをremarkで使えるようにしたのが、以下のパッケージ。

https://github.com/remarkjs/remark-directive

react-remark で使う

例としてNext.js + react-remarkで使ってみる。

必要なもの

使用例


import { Remark } from 'react-remark'
import Link from 'next/link'
const directive = require('remark-directive')
const visit = require('unist-util-visit')
const h = require('hastscript')

interface RenderProps {
  source: string
}

function htmlDirectives() {
  return transform

  function transform(tree:any) {
    visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], ondirective)
  }

  function ondirective(node:any) {
    var data = node.data || (node.data = {})
    var hast = h(node.name, node.attributes)

    data.hName = hast.tagName
    data.hProperties = hast.properties
  }
}

function UnifiedMd(props: RenderProps) {

  return (
    <Remark
        remarkPlugins={[directive,htmlDirectives]}
        rehypeReactOptions={{
          components: {
            p: (props: any) =>
              <p className="someClass" {...props} />
          },
        }}
      >
        {`ここにMarkdown`}
      </Remark>
    )

}

export default UnifiedMd

htmlDirectivesは上記パッケージのReadmeから拝借した。

まずMDが変換された後、unist-util-visithastscriptでhastのツリーを参照して、remark-directiveに渡すことで、要素を生成しているらしい。

これが最適解かわからないが、rehypeReactOptionsを使えば任意のReactコンポーネントに変換できるので、はてな記法的な独自の記法を開発できるかもしれない。