UNPKG

@ryhrm-gz/xincodo-lib

Version:

Utilities for working with Xincodo body documents.

280 lines (205 loc) 8.96 kB
# xincodo-lib Xincodo body documents を TypeScript で構築、検証、移行、走査、編集、テキスト抽出するためのユーティリティです。 `Body``{ version: 1, content: BodyBlock[] }` というシンプルな構造で、本文ブロック、リッチテキスト、画像、テーブル、リンクなどを型付きで扱えます。 ## Installation ```bash pnpm add @ryhrm-gz/xincodo-lib ``` このパッケージは ESM として公開され、型定義は同梱されています。 If you use an AI agent, run `npx @tanstack/intent@latest install`. ## Quick Start ```ts import { bulletedList, callout, createBody, estimateReadingTime, heading, listItem, paragraph, text, toPlainText, } from "@ryhrm-gz/xincodo-lib"; const body = createBody([ heading(1, "Getting started", { id: "getting-started" }), paragraph( "Create structured content with ", text("typed helpers", { annotations: { bold: true } }), ".", ), bulletedList([listItem("Build documents"), listItem("Validate before saving")]), callout("Remember to add image alt text.", { icon: { type: "emoji", emoji: "!" }, color: "yellow", }), ]); const plainText = toPlainText(body); const readingTime = estimateReadingTime(body); console.log(plainText); console.log(readingTime.minutes); ``` ## Document Model `Body` は現在 `version: 1` のドキュメントです。本文は次の `BodyBlock` で表現します。 - `text`: 段落。`children` に子ブロックを持てます。 - `heading_1` から `heading_4`: 見出し。 - `bulleted_list`, `numbered_list`, `toggle_list`: リスト。各 item はリッチテキストと子ブロックを持てます。 - `callout`, `quote`: 補足や引用。`children` に子ブロックを持てます。 - `table`: 行とセルを持つテーブル。 - `divider`: 区切り線。 - `page_link`: Xincodo 内ページ ID または URL への参照。 - `image`, `gallery`: 単一画像または画像ギャラリー。 リッチテキストは `text()``lineBreak()` で作成できます。`text()` には `bold`, `italic`, `underline`, `strikethrough`, `color`, `backgroundColor`, `link` などの注釈を付けられます。 ```ts import { lineBreak, paragraph, text } from "@ryhrm-gz/xincodo-lib"; const block = paragraph( text("Docs", { annotations: { underline: true }, link: { href: "https://example.com/docs", title: "Documentation" }, }), lineBreak(), "Read more", ); ``` ## Usage Examples ### Validate Unknown Input 外部入力や保存済み JSON は `parseBody()` で安全に検証できます。 ```ts import { parseBody } from "@ryhrm-gz/xincodo-lib"; const result = parseBody(JSON.parse(serializedBody)); if (!result.success) { console.error(result.issues); throw new Error("Invalid Xincodo body"); } const body = result.output; ``` 将来のバージョン移行を見越した読み込みには `safeMigrateBody()` または `migrateBody()` を使います。 ```ts import { safeMigrateBody } from "@ryhrm-gz/xincodo-lib"; const result = safeMigrateBody(rawBody); if (result.success) { console.log(result.output); } else { console.error(result.issue.message); } ``` ### Lint Before Saving `lintBody()` は重複 ID、不正 URL、空のテーブル、見出しレベルのジャンプ、画像 alt 欠落などを検出します。 ```ts import { lintBody } from "@ryhrm-gz/xincodo-lib"; const report = lintBody(body, { maxDepth: 3, requireImageAlt: true, validateUrls: true, }); if (!report.valid) { console.log(report.errors); } ``` ### Extract Render Metadata 目次、抜粋、読了時間、画像、リンクなど、レンダリング前に必要になりやすい情報を抽出できます。 ```ts import { collectImageSources, collectLinks, createExcerpt, estimateReadingTime, extractHeadingAnchors, } from "@ryhrm-gz/xincodo-lib"; const headings = extractHeadingAnchors(body); const excerpt = createExcerpt(body, { maxLength: 120, preserveWords: true }); const readingTime = estimateReadingTime(body); const images = collectImageSources(body); const links = collectLinks(body); ``` ### Traverse And Edit Immutably 走査や編集ヘルパーは元の `Body` を変更せず、新しい `Body` を返します。 ```ts import { findBlockPathById, insertBlockAtPath, paragraph, richText, updateRichTextAtPath, } from "@ryhrm-gz/xincodo-lib"; const introPath = findBlockPathById(body, "intro"); const withNote = introPath ? insertBlockAtPath(body, introPath, paragraph("Inserted after intro"), { position: "after", }) : body; const updatedIntro = introPath ? updateRichTextAtPath(body, [...introPath, { key: "richText" }], () => richText("Updated intro")) : body; ``` ## Public API すべての API はパッケージルートから import できます。 ```ts import { createBody, parseBody, type Body } from "@ryhrm-gz/xincodo-lib"; ``` ### Builders - `createBody(content)`: `Body` を作成します。 - `text(value, options)`, `lineBreak()`, `richText(...content)`: リッチテキストを作成します。 - `paragraph()`, `heading()`, `callout()`, `quote()`: テキスト系ブロックを作成します。 - `listItem()`, `toggleListItem()`, `bulletedList()`, `numberedList()`, `toggleList()`: リストを作成します。 - `tableCell()`, `tableRow()`, `table()`: テーブルを作成します。 - `divider()`, `pageLink()`, `image()`, `galleryImage()`, `gallery()`: その他のブロックを作成します。 ### Validation And Migration - `parseBody(input)`: `bodySchema``unknown` を検証し、Valibot の safe parse result を返します。 - `bodySchema`, `bodyBlockSchema`, `bodyRichTextSchema` など: Valibot schema を直接利用できます。 - `safeMigrateBody(input)`: 移行結果を success/failure の union として返します。 - `migrateBody(input)`: 移行できない場合は `BodyMigrationError` を投げます。 ### Lint - `lintBody(input, options)`: 構造や編集上の問題を `BodyLintReport` として返します。 - `BodyLintIssue`, `BodyLintCode`, `BodyLintSeverity`: lint 結果の型です。 ### Traversal And Editing - `walkBody(input, visitor)`: block, richText, inline, listItem, tableCell, galleryImage を訪問します。 - `findBlock(input, predicate)`, `filterBlocks(input, predicate)`: 条件に合うブロックを検索します。 - `mapBody(input, mapper)`: ブロックを再帰的に変換します。 - `findBlockPathById(input, id)`, `getBlockAtPath(input, path)`: パスでブロックを参照します。 - `insertBlockAtRoot()`, `insertBlockAtPath()`, `updateBlockAtPath()`, `replaceBlockAtPath()`, `removeBlockAtPath()`, `moveBlock()`: ブロックを immutable に編集します。 - `updateRichTextAtPath()`: 指定パスのリッチテキストを immutable に編集します。 - 編集に失敗した場合は `BodyEditError` を投げます。 ### Text And Rendering Helpers - `toPlainText(input)`: `Body`, block 配列, block, rich text をプレーンテキストに変換します。 - `richTextToPlainText(richText)`: リッチテキストだけを文字列化します。 - `extractHeadings(input)`: 見出しの level, text, block, path を抽出します。 - `extractHeadingAnchors(input, options)`: 目次やアンカー用の一意な ID と href を作成します。 - `slugifyHeading(value)`: 見出し文字列を slug に変換します。 - `createExcerpt(input, options)`: 抜粋を作成します。 - `estimateReadingTime(input, options)`: 読了時間、単語数、文字数を推定します。 - `collectImageSources(input)`: image, gallery image, callout icon の画像参照を集めます。 - `collectLinks(input)`: text link と page link を集めます。 ### Constants And Types - `BODY_VERSION`: 現在の body version です。 - `BODY_BLOCK_TYPES`, `TEXT_COLORS`, `HEADING_LEVELS`: サポートされる値の一覧です。 - `Body`, `BodyBlock`, `BodyRichText`, `BodyBlockType`, `TextAnnotations`, `TextLink`, `ImageSource`, `PageReference` などの公開型を利用できます。 ## Development Install dependencies: ```bash vp install ``` Run format, lint, type check, and tests: ```bash vp check vp test ``` Build the library: ```bash vp pack ``` ## Release Releases are published from a clean local `main` branch. Prerequisites: - Authenticate the GitHub CLI with `gh auth login`. - Authenticate npm with `npm login`. Run a release: ```bash vp run release ``` To choose the next version explicitly, pass a bumpp version argument: ```bash vp run release -- patch vp run release -- minor vp run release -- major ``` The release script checks that local `main` matches `origin/main`, runs checks and tests, bumps `package.json`, creates and pushes the release commit and `vX.Y.Z` tag, publishes GitHub release notes, then publishes the package to npm.