記法の拡張


@cosense-toolbox/parser/extensions から拡張用の型と既製の拡張を読み込めます。拡張を使わない場合、このサブパスを import する必要はありません。

拡張の種類


InlineConstruct は行の任意の位置から始まる記法を追加します。BracketRule は [...] の中身の解釈を追加します。Extension はそれらをまとめ、parse に渡す単位です。

記法を追加する


拡張関数は記法が成立しない位置で null を返します。成立した場合はノードと消費した文字数を返します。位置情報はパーサーが付けます。

TypeScript
import { parse } from "@cosense-toolbox/parser"
import type { Extension, InlineConstruct } from "@cosense-toolbox/parser/extensions"
const mention: InlineConstruct = (source, index) => {
if (source[index] !== "@") return null
const match = source.slice(index + 1).match(/^[A-Za-z0-9_-]+/)
if (!match) return null
return {
node: { type: "internalLink", label: `@${match[0]}`, target: match[0] },
length: match[0].length + 1,
}
}
const mentions: Extension = { constructs: [mention] }
parse("メモ\n@qaynam に確認する", { extensions: [mentions] })

拡張は既定のルールより先に試されます。既定の記法と同じ形を受け取る拡張を追加すると、その解釈を上書きできます。

テーブルセルの記法


テーブルセルでは既定でリンク記法だけを解析します。tableCellNotation() を extensions に加えると、装飾などを含めてセル内の記法を解析できます。

特定のノードだけをセルに残すには、拡張の keepInTableCell で判定します。セル内の文字列を <br> に置き換える描画拡張 tableCellLineBreaks() は HTML への変換 を参照してください。

独自の埋め込み


Cosense Web が埋め込まないサービスも、BracketRule から独自の provider の embed ノードを返せば埋め込みとして扱えます。Apple Music、Instagram、地図を OpenStreetMap にする例は メディアと埋め込み にあります。

独自ノード型


既存のノード型に当てはまらない記法は、InlineNodeMap を declaration merging で拡張します。独自の type が走査や描画の型にも反映されます。

TypeScript
import type { Position } from "@cosense-toolbox/parser"
declare module "@cosense-toolbox/parser" {
interface InlineNodeMap {
mention: { type: "mention"; user: string; position: Position }
}
}

描画時は toHtml の handlers にそのノード型を追加します。独自ノードを追加したのにハンドラーがない場合、子ノードがあればその内容が出力されます。

AST を検証する


@cosense-toolbox/parser/schema の decodePage は、Worker や postMessage など外部から受け取った値が Page の形かを検証します。通常の parse は必ず AST を返すため、外部データを扱う場合に使います。

TypeScript
import { decodePage } from "@cosense-toolbox/parser/schema"
import { Either } from "effect"
const result = decodePage(JSON.parse(input))
if (Either.isRight(result)) {
const page = result.right
}

不具合や記法の不足を見つけた場合は GitHub の Issue で報告できます。