rehype プラグイン
@love-rox/tcy-rehype
`unified` の HAST パイプラインに組み込んで、build 時に縦中横を適用する rehype プラグイン。Markdown / MDX / 静的 HTML — どこでも、クライアントランタイムなしで動きます。
v0.3.0MITbuild-time
インストール
@love-rox/tcy-core は依存として自動的に引き込まれます。unified ベースのビルド(remark / rehype / Astro / eleventy など)で使えます。Astro 専用に最適化された API が必要な場合は [Astro 版](./astro) を使ってください。
bun
bun add @love-rox/tcy-rehypepnpm
pnpm add @love-rox/tcy-rehypenpm
npm i @love-rox/tcy-rehypeyarn
yarn add @love-rox/tcy-rehypeMarkdown パイプラインに組み込む
remark-rehype のあと、HAST が確定したタイミングで rehypeTcy を挟むだけです。HTML として出力される時点で、縦中横ラッピングは済んでいます。
Markdown → HTMLts
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import rehypeTcy from "@love-rox/tcy-rehype";
const html = String(
await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeTcy)
.use(rehypeStringify)
.process("第1章 2026年4月"),
);
// <p>第<span class="tcy">1</span>章 <span class="tcy">2026</span>年<span class="tcy">4</span>月</p>HTML だけのパイプライン
Markdown を介さず、HTML in / HTML out なら同じ要領で:
HTML → HTMLts
import { unified } from "unified";
import rehypeParse from "rehype-parse";
import rehypeStringify from "rehype-stringify";
import rehypeTcy from "@love-rox/tcy-rehype";
const html = String(
await unified()
.use(rehypeParse, { fragment: true })
.use(rehypeTcy)
.use(rehypeStringify)
.process("<p>第1章 2026年4月</p>"),
);オプション
共通オプション(target / combine / include / exclude / maxLength / excludeWords)はすべて React / Vue / Astro と同じ意味で動きます。
共通オプション
| オプション | 型 | 既定値 | 説明 |
|---|---|---|---|
| target | 'alphanumeric' | 'alpha' | 'digit' | 'ascii' | RegExp | 'alphanumeric' | 縦中横対象として扱う文字種。alphanumeric は [0-9A-Za-z]、ascii は印字可能な ASCII 全般。任意の RegExp も指定可能。 |
| combine | boolean | true | 連続した対象文字を1つのスパンにまとめるか。false にすると1文字ずつ別々のスパンで包みます。 |
| include | string | string[] | undefined | target に含まれなくても対象として扱う追加の文字。 |
| exclude | string | string[] | undefined | 対象から外したい文字。include より優先されます。 |
| maxLength | number | undefined | 縦中横セグメントの最大文字数。これを超える長さの英数字 run はプレーンテキストに戻ります。たとえば maxLength: 2 にすると 2026 のような4桁年は寝かせ、1 や 19 の短い run のみを縦中横にできます。 |
| excludeWords | string[] | undefined | 縦中横にしたくない語を完全一致で指定(部分一致ではなくセグメント値全体のマッチ)。URL API のような固有の略号や、特定の年号だけを横倒しのまま残したいときに便利。 |
rehype プラグイン専用オプション
| オプション | 型 | 既定値 | 説明 |
|---|---|---|---|
| tagName | string | 'span' | ラップに使用するタグ名。 |
| className | string | string[] | 'tcy' | ラップ要素に付与するクラス名(配列で複数指定可)。 |
| skipTags | string[] | ['code', 'pre', 'script', 'style'] | 走査をスキップするタグ。<code> <pre> などコード表示中のテキストはデフォルトで処理されません。 |
挙動の注記
- 冪等です。同じ HAST に2回プラグインを適用しても、出力は1回適用したときと同じ。span が二重になったりはしません。
skipTagsのデフォルト(code/pre/script/style)が、コードサンプルや埋め込み JSON が縦中横化されるのを防ぎます。<em>12</em>34のように要素境界をまたぐ文字列は連結されず、別々のスパンになります。maxLength/excludeWordsで対象外になった run はプレーンテキストに戻り、隣接するテキストと自動的にマージされます。
Astro を使っているなら
Astro 4+ で .md / .mdx / .astro を扱うなら、Markdown パイプラインへの登録と <Tcy> コンポーネントが同梱された [Astro インテグレーション](./astro) のほうが手数が少なく済みます。