@cosense-toolbox/parser
v0.1.0-beta.7
Published
Cosense (Scrapbox) notation parser — every node carries its source position. Zero runtime deps except effect.
Maintainers
Readme
@cosense-toolbox/parser
Cosense (旧 Scrapbox) の記法を、位置情報つきの AST に変換する。
ドキュメント → https://cosense-toolbox.qaynam.dev/parser/
- 依存は
effectだけ。DOM も Node の API も使わないので、ブラウザでも Node でも Workers でも動く - どのノードも元のテキストの何行目の何文字目から始まるかを持つので、エディタの色付けやカーソル位置の判定に使える
- AST はメソッドを持たないただのオブジェクト。
JSON.stringifyして保存しておき、あとで読み直せる - 記法そのものを増やせる。プロジェクト固有の書きかたも元からある記法と同じように扱える
- パースだけなら gzip 約 10 KB。HTML 変換や走査は別の import 元なので、使わなければバンドルに入らない
beta:公開 API はまだ変わりうる。安定するまではバージョンを固定して使うほうが安全。
0.1.0-beta.7 の変更
- 動画・音声・埋め込みのノードを足した。どれも Cosense Web がパースの段階で読み分けているもので、今までは外部リンクになっていた。
video:[https://…/a.mp4](拡張子は mp4 / webm / mov)。[[…]]で大きい動画 (large)、 URL を 2 つ並べるとリンク付き動画 (link) になる。単独の動画 URL にはクエリを付けられない。audio:[https://…/a.mp3](拡張子は wav / mp3 / weba / ogg / aac)。前後に文字を書くと、その文字がlabelになる。embed: YouTube / Vimeo / Spotify / anchor.fm の URL。providerと、サービスの中でのid(とkind) を持つ。<iframe>に入れる URL はasEmbedSrcで作る。
toHtml/toHastは、動画を<video>、音声を<audio>、埋め込みを<iframe>にする。 class 名はclassNamesのvideo/audio/embedで変えられる。- 地図のノード
locationを足した。[N35.68,E139.76](ズームは,Z14) で、座標の前後に書いた文字がlabelになる。 緯度と経度は数値で、南緯と西経は負の数になる。Google マップの URL はasMapUrlで作り、toHtmlはそこへのリンクを出す (class 名はclassNamesのlocation)。 - Cosense Web が埋め込まないサービスは、拡張の
bracketRulesから独自のproviderのembedを返せば足せる。 既定のtoHtmlはプレーヤーの URL を知らない埋め込みを外部リンクとして出すので、見た目はhandlersかextensionsで決める。
0.1.0-beta.6 の変更
- インラインコードが始まる括弧を、記法として読まないようにした。Cosense Web はコードを括弧より先に読むので、
[* 太字の `code` です]は装飾にならず、括弧はそのままの文字、`code`はインラインコードになる。 数式 ([$ …]) も同じで、[$ a] `` は数式にならない。閉じないバッククォートは括弧を妨げない。 - コマンドの行を Cosense Web に合わせた。字下げの後が
$か%と空白で、その後に何かある行だけがコマンドになる (monospace: true)。コマンドの行は記法を読まず、childrenは書いたままの文字のtext1 つになる。$aaのように空白が無い行と、引用の行 (> $ x) はコマンドにならない。toHtml/toHastは、Cosense Web と同じくコマンドの行を記号・空白・コマンドの要素に分けて出す (<span class="prefix">$</span><span class="space"> </span><span class="command">ls</span>)。 class 名はclassNamesのcommandPrefix/commandSpace/commandで変えられる。
0.1.0-beta.5 の変更
- タイトル行の記法を読まないようにした。Cosense Web と同じく、
[x]も#tagも書いたままの文字になる。TitleBlockの形は変わらず、childrenが書いたままの文字のtext1 つになる。
0.1.0-beta.3 の変更
- Cosense の文字装飾の記号
!"#%&'()*+,-./{|}<>_~=からなる並びを、拡張なしですべて装飾として読むようにした。 Cosense Web と同じ読み方で、[! 注意]は内部リンクではなくmarkers: ['!']の装飾になる。 見た目 (bold などのフラグ) が付くのは今までどおり* / - _だけ。ほかの記号の見た目は CSS で付ける。 customDecorationsを削除した。集合の中の記号は既定で読むので、この拡張で足せるのは Cosense Web が装飾にしない記号だけになり、Web 版と違う AST を作るため。渡していた箇所は消すだけでよい。
0.1.0-beta.2 の変更
- 記法の拡張 (
InlineConstruct/BracketRule) は、成立しなければnullを返す普通の関数になった。 これまでは effect のOptionを返す必要があり、拡張を書くのに effect が要った。Option.none()はnullに、Option.some(x)はxに書き換える。 - 拡張のルールに渡る文脈から
bracketRulesを外した。拡張から使う場面が無く、中の型が漏れていたため。
0.1.0-beta.1 の変更
beta.0 から上げるときは次の 2 点に注意。
- サブパス
./pluginを./extensionsに改名した。渡すものがExtensionで オプション名もextensionsなのに、置き場所だけ別の語彙だったため。 コンパイラを書くための型 (NodeHandlers等) は./compileにある。 decorationノードにmarkersを足した (必須)。書かれた装飾記号が 出現順・重複なしで入る。toHtmlはこれをdeco-*のような class として出す。 装飾ノードを自分で組み立てている拡張は追随が要る。
インストール
npm i @cosense-toolbox/parser既定の見た目が要るなら @cosense-toolbox/style を別途入れる。
使ってみる
import { parse } from "@cosense-toolbox/parser"
import { collectLinks } from "@cosense-toolbox/parser/utils"
import { toHtml } from "@cosense-toolbox/parser/html"
const page = parse(`今日のメモ
[プロジェクトA] の進捗を確認する
#あとで読む`)
collectLinks(page) // → ['プロジェクトA', 'あとで読む']
toHtml(page) // → '<div class="page"><h1 class="title">今日のメモ</h1>…'API
モジュールごとに export が分かれている。使うものだけ import すればよい。
| モジュール | 役割 | API |
| :----------------------------------- | :-------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- |
| @cosense-toolbox/parser | テキストを AST にする | parse parseLine tokenizeInline createParser asImageSrc asEmbedSrc asMapUrl normalizeLineEndings |
| @cosense-toolbox/parser/utils | ヘルパー。AST から取り出す | visit find collect collectLinks firstImage rawTextOf |
| @cosense-toolbox/parser/html | AST を HTML 系の出力 (hast と HTML の文字列) にする | toHast toHtml codeLineNumbers tableCellLineBreaks |
| @cosense-toolbox/parser/compile | AST を HTML 以外の形式にする | toPlainText createCompiler |
| @cosense-toolbox/parser/extensions | 記法を足す | Extension InlineConstruct BracketRule tableCellNotation |
| @cosense-toolbox/parser/schema | 外から来た値を検証する | decodePage |
parse はページ全体を読む。1 行目はタイトルで、Cosense Web と同じく記法を読まない。
記法を読みたい文字列がページでないなら、本文の 1 行は parseLine、文章の断片は tokenizeInline で読む。
各 API の詳細はドキュメントにある。
| ページ | 内容 |
| :--------------------------------------------------------------------- | :-------------------------------------------------------- |
| 概要 | インストールと、どの API を使うかの早見表 |
| 例 | 記法をひととおり変換した結果とコード |
| パース | parse / parseLine / tokenizeInline / createParser |
| AST と位置情報 | ノードの構造と position の意味 |
| ヘルパー | visit / find / collect など |
| HTML への変換 | toHast / toHtml と 8 つのオプション |
| 独自形式への変換 | toPlainText / createCompiler |
| 記法の拡張 | Extension と独自のノード型 |
互換性の方針
| 変更 | バージョン |
| :------------------------------------------- | :--------- |
| 新しいノード type の追加 | minor |
| 既存ノードへの optional フィールド追加 | minor |
| オプションへの optional フィールド追加 | minor |
| 既存ノードのフィールドの削除、型変更、必須化 | major |
| position の意味論の変更 | major |
| ノード type 文字列のリネーム | major |
ノード型は minor で増えうるので、switch (node.type) には default を置いておく。
開発
規約は CLAUDE.md にある。
bun install
bun run test
bun run buildライセンス
MIT。
このパッケージは Cosense (Scrapbox) の記法を解釈する非公式の実装である。 開発元である Helpfeel 社とは関係がなく、公認も受けていない。
