unist specによるAST生成を導入する
Closed this issue · 5 comments
sounisi5011 commented
概要
AST等の生成にunistを導入する。
詳細
開発中の #13 において、SVGを生成するために独自実装した仮想ノードを変換している。これを、驚くような大手のプロジェクトでも採用されているらしいunistを使用したものに切り替える。
メリット
- デファクトスタンダード(?)な仕様に従うことで、有志のライブラリを再利用できる
- 今後
vec-draw
のデベロッパーツール等を制作する際の助けになる- コード上の位置を表現する型
Position
などもシッカリ含まれている。
- コード上の位置を表現する型
- JSONと完全互換のツリー
デメリット
- 学習コスト
- ライブラリの複雑化
- 開発に遅れが生じる
備考
unistに対応したHTMLを表現する仕様hastのツリーをhyperscript(h()
関数)形式で生成できるライブラリにhastscriptなるものが存在する。
sounisi5011 commented
知った経緯をメモしておこうか。
- 「PEGを書きやすくする拡張構文の調査(構文ルール編) - Qiita」を読んで、PEG.jsの機能不足さに危機感を抱く。
- 特に、中置演算子の定義の複雑さはどうにかして解決したくなった。
- PEG.js以外のPEGライブラリを探して「js peg」と検索。
- 「PEG.js で機械的に構文を定義したい時に ejs 使ったら便利だった - カラクリスタ・ノート」という記事を発見
- 記事内にて言及されていた「HAST」なるものに興味を抱く。
- ようこそ、unifiedの世界へ。
sounisi5011 commented
sounisi5011 commented
使い方はこのようなものを想定。
import fs from 'fs';
import util from 'util';
import unified from 'unified';
import createStream from 'unified-stream';
import rehypeStringify from 'rehype-stringify';
import { parse, ast2rehype } from '@sounisi5011/vec-draw';
const readFileAsync = util.promisify(fs.readFile);
const writeFileAsync = util.promisify(fs.writeFile);
(async () => {
const inputDSLText = await readFileAsync('input.vec-draw', 'utf-8');
const outputSVGText = await unified()
.use(parse)
.use(ast2rehype)
.use(rehypeStringify)
.process(inputDSLText);
await writeFileAsync('output.svg', outputSVGText);
const processor = unified()
.use(parse)
.use(ast2rehype)
.use(rehypeStringify);
const src = fs.createReadStream('src.vec-draw', 'utf8');
const dest = fs.createWriteStream('dest.svg', 'utf8');
src.pipe(createStream(processor)).pipe(dest);
})();
parse
は以下のような感じで定義。
export function parse(options) {
this.Parser = file => {
const fileText = String(file);
const ast = /* fileTextをASTオブジェクトに変換する処理 */;
return ast;
};
}
sounisi5011 commented
#24 で作業を開始したのでこっちも再度open。
sounisi5011 commented
#24 が完了したので、closeする。