GATE01

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-rehype

pnpm

pnpm add @love-rox/ptpt-rehype

npm

npm i @love-rox/ptpt-rehype

yarn

yarn add @love-rox/ptpt-rehype
GATE02

Usage

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.

Markdown → HTMLts
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:

client.tsts
// 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();
GATE03

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-*)

OptionTypeDefaultDescription
presetPresetDefinition | stringdefaultPresetThe 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.
framesFrameInput[]undefinedAn explicit frame set — text, images, or arbitrary elements. Mutually exclusive with preset.
durationPerFlapnumberpreset's recommendation, else 200Milliseconds 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

OptionTypeDefaultDescription
classNamestring'patapata'Class that marks an inline element for conversion into a board.
fenceLanguagestring'patapata'Code-fence language that marks a fenced block for conversion.
defaultPresetstringundefinedPreset name applied when an element / block specifies none.
GATE04

Behaviour

Behavior notes

  • Progressive. The build emits plain, readable text; without JS the content is still there — hydrate only adds the animation.
  • Inline markers become <span class="ptpt" data-ptpt-targets="…">; `patapata blocks become one row per line.
  • data-preset / data-duration / data-direction on a marker carry through to data-ptpt-* on the output.
  • The chosen preset must contain every character in the target, or that board is left blank — pick default / alphanumeric for mixed text.
GATE05

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.