rehype plugin
new@love-rox/ptpt-rehype
A rehype plugin + client hydrator that turns marked Markdown / HTML into split-flap boards. It emits readable text with data-ptpt-* at build time; hydrate animates it in the browser. No JS, you still see the text.
Install
Install
@love-rox/ptpt-core is a peer dependency (used by the client hydrator). Use this on any unified-based build (remark / rehype / Astro / eleventy / …). For Astro ergonomics, the Astro adapter is purpose-built.
bun
bun add @love-rox/ptpt-rehypepnpm
pnpm add @love-rox/ptpt-rehypenpm
npm i @love-rox/ptpt-rehypeyarn
yarn add @love-rox/ptpt-rehypeUsage
Markdown pipeline
Add rehypePtpt to your rehypePlugins. It recognizes two input forms: an inline element with the marker class (<span class="patapata">HELLO</span>) and a fenced code block tagged `patapata (one board row per line). Then hydrate() animates everything it finds.
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeRaw from "rehype-raw";
import rehypeStringify from "rehype-stringify";
import rehypePtpt from "@love-rox/ptpt-rehype";
// Markdown marks a board with the marker class (or a ```patapata fence):
const md = '<span class="patapata" data-preset="alphanumeric">TOKYO</span>';
const html = String(
await unified()
.use(remarkParse)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeRaw)
.use(rehypePtpt)
.use(rehypeStringify)
.process(md),
);
// <span class="ptpt" data-ptpt-targets="TOKYO" data-ptpt-preset="alphanumeric">TOKYO</span>Hydrate on the client
The plugin only emits static markup. Call hydrate once in the browser to animate every [data-ptpt-targets] it produced:
// Browser entry — animate everything the plugin emitted.
import { hydrate } from "@love-rox/ptpt-rehype/client";
import "@love-rox/ptpt-core/styles.css";
// scans the document for [data-ptpt-targets] and flips them into boards
hydrate();Options
Options
The plugin takes className, fenceLanguage, and defaultPreset. The shared cell options below are read per board from data-ptpt-* attributes and behave exactly as they do in the React, Vue, and Astro adapters.
Shared cell options (via data-ptpt-*)
| Option | Type | Default | Description |
|---|---|---|---|
| preset | PresetDefinition | string | defaultPreset | The flap set. Pass a PresetDefinition (its recommendedDuration / locale become defaults) or a string of characters whose order is the flap order. Mutually exclusive with frames. |
| frames | FrameInput[] | undefined | An explicit frame set — text, images, or arbitrary elements. Mutually exclusive with preset. |
| durationPerFlap | number | preset's recommendation, else 200 | Milliseconds for one flap. Overrides the preset's recommendedDuration. |
| direction | 'forward' | 'shortest' | 'forward' | Direction taken through the frame ring. shortest may reverse to reach a nearer flap. |
| reducedMotion | 'instant' | 'minimal' | 'ignore' | 'instant' | Behaviour when the OS prefers reduced motion. instant snaps to the target without animating. |
rehype plugin options
| Option | Type | Default | Description |
|---|---|---|---|
| className | string | 'patapata' | Class that marks an inline element for conversion into a board. |
| fenceLanguage | string | 'patapata' | Code-fence language that marks a fenced block for conversion. |
| defaultPreset | string | undefined | Preset name applied when an element / block specifies none. |
Behaviour
Behavior notes
- Progressive. The build emits plain, readable text; without JS the content is still there —
hydrateonly adds the animation. - Inline markers become
<span class="ptpt" data-ptpt-targets="…">;`patapatablocks become one row per line. data-preset/data-duration/data-directionon a marker carry through todata-ptpt-*on the output.- The chosen preset must contain every character in the target, or that board is left blank — pick
default/alphanumericfor mixed text.
Related
If you're on Astro
If you're on Astro 4+ and dealing with .md / .mdx / .astro, the Astro integration registers this plugin, injects the stylesheet, and runs the hydrator for you — and ships <Patapata> components for .astro files.