remark-directiveでMDから好きなHTMLを生成
MDから任意のHTMLを作りたいが、MDXを書くのは面倒。 もっと楽に好き勝手を生成したい。
remark-directiveでできるじゃん
Generic directives proposal
という構文がCommonMarkで議論されている。
例えば、
:::main
あああ
:::
が、
<main><p>あああ</p></main>
になる。
Lorem:br
ipsum.
::hr{.red}
が、
<p>Lorem<br>ipsum.</p>
<hr class="red">
になる。結構便利そう。
これをremark
で使えるようにしたのが、以下のパッケージ。
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-visit
とhastscript
でhastのツリーを参照して、remark-directive
に渡すことで、要素を生成しているらしい。
これが最適解かわからないが、rehypeReactOptions
を使えば任意のReactコンポーネントに変換できるので、はてな記法的な独自の記法を開発できるかもしれない。