Astro integration

NEW

@love-rox/tcy-astro

Astro 4+ only. Auto-registers the rehype plugin on Astro's Markdown / MDX pipeline, and ships a `<Tcy>` component for `.astro` files.

v0.3.0MITastro >= 4

Install

Peer dependency: astro >= 4. @love-rox/tcy-core and @love-rox/tcy-rehype are pulled in automatically.

bun

bun add @love-rox/tcy-astro

pnpm

pnpm add @love-rox/tcy-astro

npm

npm i @love-rox/tcy-astro

yarn

yarn add @love-rox/tcy-astro

Two pieces

tcy() integration

Registers @love-rox/tcy-rehype on Astro's Markdown / MDX pipeline so half-width alphanumerics in your .md and .mdx content are wrapped automatically at build time.

<Tcy> component

An Astro component to wrap a slot inside .astro files explicitly — useful for body content authored directly in .astro, outside the Markdown pipeline.

Usage

Register the integration in astro.config.mjs. That alone makes Markdown / MDX content tate-chu-yoko-aware.

astro.config.mjsts
// astro.config.mjs
import { defineConfig } from "astro/config";
import tcy from "@love-rox/tcy-astro";

export default defineConfig({
  integrations: [tcy()],
});

With options

Forward any rehype-tcy options through the integration call.

astro.config.mjs (with options)ts
// astro.config.mjs
import { defineConfig } from "astro/config";
import tcy from "@love-rox/tcy-astro";

export default defineConfig({
  integrations: [
    tcy({
      maxLength: 2,
      excludeWords: ["URL", "API", "2026"],
    }),
  ],
});

Inside an `.astro` file

For body content authored directly in .astro (no Markdown in the picture), use the <Tcy> component.

src/pages/example.astroastro
---
import Tcy from "@love-rox/tcy-astro/Tcy.astro";
---

<p style="writing-mode: vertical-rl">
  <Tcy>第1章 2026年4月、Webの縦書きは進化した。</Tcy>
</p>

Options

The shared options behave exactly as they do in the React / Vue / rehype adapters. There's just one integration-only knob.

Shared options + rehype passthrough

OptionTypeDefaultDescription
target'alphanumeric' | 'alpha' | 'digit' | 'ascii' | RegExp'alphanumeric'What counts as a tate-chu-yoko target. alphanumeric matches [0-9A-Za-z]; ascii covers printable ASCII. A custom RegExp is accepted.
combinebooleantrueMerge consecutive target characters into a single span. Set to false to wrap each character individually.
includestring | string[]undefinedExtra characters to treat as targets regardless of target.
excludestring | string[]undefinedCharacters to exclude. Takes precedence over include.
maxLengthnumberundefinedMaximum length for a tcy segment. Runs longer than this are demoted back to plain text — for example maxLength: 2 keeps single digits and pairs uprighted while leaving four-digit years like 2026 lying on their side.
excludeWordsstring[]undefinedExact words to exclude from tcy wrapping. Matched against the whole segment value (not a substring) — useful for keeping acronyms like URL / API or specific years out of the upright treatment.
tagNamestring'span'Tag name used for wrapping.
classNamestring | string[]'tcy'Class name(s) applied to the wrapping element. Pass an array for multiple classes.
skipTagsstring[]['code', 'pre', 'script', 'style']Tags whose subtrees are left untouched. Code/pre/script/style content is skipped by default.

Integration-only

OptionTypeDefaultDescription
markdownbooleantrueWhether to register rehype-tcy on the Markdown / MDX pipeline. Set to false to opt out (e.g. if you only want the <Tcy> component).

Behavior notes

  • Astro is SSG-first, so both pieces run at build time — there's no client-side cost.
  • Text inside <code> / <pre> / <script> / <style> is skipped by default (configurable via skipTags).
  • Idempotent. Rebuild the same Markdown as many times as you want; the output HTML doesn't drift.
  • The <Tcy> component delegates to the same tcy-rehype underneath, so Markdown content and .astro-authored content behave identically.

Other adapters

Not using Astro? Drop the [rehype plugin](./rehype) directly into your unified pipeline. Need runtime wrapping in the app? Use the [React](./react) or [Vue](./vue) component.