npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wakamejs/react-rolldown

v0.2.1

Published

SSR-safe React Rolldown plugin for inserting semantic zero-width spaces with Wakame

Downloads

733

Readme

@wakamejs/react-rolldown

React の JSX をビルド時・実行時に解析し、日本語テキストを BudouX などの意味的な単位へ分割して境界にゼロ幅スペース(U+200B)を挿入する Rolldown/Vite プラグインです。サーバー用とクライアント用のバンドルに同じ変換を適用するため、SSR の HTML と hydration の結果を一致させられます。

インストール

pnpm add @wakamejs/core @wakamejs/budoux
pnpm add -D @wakamejs/react-rolldown
# または
npm install @wakamejs/core @wakamejs/budoux
npm install -D @wakamejs/react-rolldown

トークナイザーの実装(@wakamejs/budoux など)と Rolldown または Vite も必要です。

使い方

Rolldown の設定でプラグインを登録します。

import { defineConfig } from "rolldown";
import wakameReactPlugin from "@wakamejs/react-rolldown";
import { createBudouxTokenizer } from "@wakamejs/budoux";

const tokenizer = createBudouxTokenizer({ language: "ja" });

export default defineConfig({
    // Vite でも同じくトップレベル plugins に登録できます。
    plugins: [wakameReactPlugin({ tokenizer })],
});

Vite では次のように、他の wrapper plugin を作らずトップレベルの plugins に登録します。

import { defineConfig } from "vite";
import { createBudouxTokenizer } from "@wakamejs/budoux";
import wakameReactPlugin from "@wakamejs/react-rolldown";

const tokenizer = createBudouxTokenizer({ language: "ja" });

export default defineConfig({
    plugins: [wakameReactPlugin({ tokenizer })],
});

たとえば、次の JSX はビルド時にトークン境界を含む文字列式へ変換されます。

export function Heading() {
    return <h1>自然な日本語の折り返し</h1>;
}

変換結果の例:

<h1>{"自然な\u200B日本語の\u200B折り返し"}</h1>

静的な JSX テキストと静的な文字列式はビルド時に処理され、動的な JSX 式は tokenizer の runtime descriptor から生成した同期 helper で処理されます。文字列を含む配列も再帰的に処理し、既に U+200B を含む文字列は重複処理しません。動的 JSX を使う場合は、組み込み言語モデルを持つ @wakamejs/budoux など runtime descriptor 対応 tokenizer を使用してください。

API リファレンス

wakameReactPlugin(options)(デフォルトエクスポート)

JSX/TSX モジュールを Babel の公開 AST API で変換する Rolldown プラグインを生成します。デフォルトでは node_modules と、編集可能要素・pre・code・SVG・MathML などの安全でない subtree を変換しません。カスタムコンポーネントも走査し、その直接の静的テキストと子孫の安全な要素を変換します。

変換対象は除外されていない JSX 要素の直接の JSXText と静的な文字列式です。<span> などの子要素をまたぐテキストは結合せず、各ノードを個別に処理します。動的な式は runtime helper で文字列だけを処理し、その他の ReactNode はそのまま保持されます。

オプション(ReactRolldownPluginOptions)

| オプション | 型 | デフォルト値 | 説明 | | :---------------- | :----------------------------------------- | :------------------- | :--------------------------------------------------------------- | | tokenizer | Tokenizer<string, string> | 必須 | テキストを分割するトークナイザー実装 | | dictionary | DictionaryInput | undefined | トークナイザーへ渡すカスタム辞書 | | include | string \| RegExp \| (string \| RegExp)[] | /\.[jt]sx/ | 変換対象モジュールのフィルター | | exclude | string \| RegExp \| (string \| RegExp)[] | undefined | 変換から除外するモジュールのフィルター | | ignoreAttribute | string | data-wakame-ignore | この属性を持つ要素を除外 | | ignore | readonly string[] | [] | 指定した JSX コンポーネント名とその subtree を除外 | | parserPlugins | ParserPlugin[] | [] | Babel parser に追加する構文プラグイン(例: decorators-legacy) |

include と exclude の文字列は glob として扱われます。data-wakame-ignore、contentEditable、dangerouslySetInnerHTML を持つ要素もスキップされます。

ignore には JSX 名を完全一致で指定します。識別子は PageLayout、メンバー名は Namespace.Component、名前空間名は Namespace:Component の形式です。指定したコンポーネントは直接のテキストと子孫をすべてスキップします。

JSX の子は親より先に評価されるため、親コンポーネントに付けた ignore marker で、別にレンダリングされるコンポーネント内部の文字列を後から元に戻すことはできません。確実に除外するには、直接処理する箇所に marker または ignore を指定してください。

このプラグインは自動で CSS を追加しません。必要な折り返しスタイルはアプリケーション側で指定してください。

Roadmap

  • BudouX の HTMLProcessor に合わせた inline 要素をまたぐ文脈の集約
  • <wbr> 出力を選べる optional mode

対応環境

  • Node.js: >= 20
  • Rolldown: ^1.0.0
  • React: ^18.0.0 または ^19.0.0(利用する React プロジェクト側で用意)

関連パッケージ

ライセンス

MIT