pangu.js: one space between CJK and Latin, and a model that reads the exception
Opinionated paranoid text spacing in JavaScript, with on-device AI semantic judgment
At a glance
- What is it?
- pangu inserts whitespace between CJK characters and Latin letters, digits or symbols, ships a CLI whose check mode exits non-zero, and its Chrome extension asks Gemini Nano on the device when a plus or minus sign is genuinely ambiguous. Version 10.4.1, MIT licensed, with Markdown explicitly out of scope.
- Who is it for?
- pangu fits a Chinese, Japanese or Korean site whose HTML mixes scripts, and a team that wants the spacing enforced in review rather than by eye, since the CLI check mode turns the rule into a build failure.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 21 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- vinta/pangu.js4,861 ★ · +35
| Repository | 2026-09-16 | 2026-11-13 |
|---|---|---|
| vinta/pangu.js | 4.8k | 4.9k |
35 Stars in the last 58 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The rule is CJK next to ANS, and nothing else
The library states its own definition in one line: it automatically inserts whitespace between CJK, meaning Chinese, Japanese and Korean, and ANS, meaning alphabetical letters, numerical digits and symbols. That is the entire scope, and the word used for it is opinionated, which is the author's way of saying the spacing is a preference rather than a standard. The name comes from the same tradition: sinologists call the blank character 盤古之白, after the myth of a creator who split the chaos between full-width and half-width characters. The file follows that etymology with a paragraph of invented statistics about marriage and happiness, which is a joke about leaving whitespace in writing as well as in life, not a study. The implementation detail that matters is the pair of character classes: anything outside those two groups is left untouched.
A plus sign can mean two things, so the extension asks a model
The Chrome extension adds a feature called AI Spacing, and the reason given is that regular expressions cannot distinguish semantic nuances. Two examples make the problem concrete. In `這裡沒有18+的內容` the plus means or more, and the spaced form is `這裡沒有 18+ 的內容`. In `Switch 2+瑪利歐賽車世界同捆組` the same character joins two things, and the spaced form becomes `Switch 2 + 瑪利歐賽車世界同捆組`. A minus has the same ambiguity: `女朋友今天的氣溫是-273.15度` is a negative number, while `博客來-4% 法則` is a separator. The extension resolves this by asking a language model through Chrome's built-in Prompt API, which runs Gemini Nano on the device, so the judgment stays local and nothing leaves the machine.
The prompts are written by a model and judged on a real one
How the AI spacing prompts get better is described with unusual specificity. A model called GPT-6 Astra writes the prompts, and it works through a skill file at .agents/skills/prompt-experiments/SKILL.md rather than by hand. The loop it runs has four steps: propose a change, test it against the real Gemini Nano running in Chrome, interview Gemini Nano for clues when a case fails, and search online for new approaches to test when progress stalls. The file summarises the arrangement in one line, prompts for a model, tuned by a bigger model, judged on real data.
Bundlers need pangu/browser, not the Node entry
In a browser build the file is emphatic about the import path. You should import from `pangu/browser` in ESM, because that is the DOM-aware build exposing spaceNode() and autoSpacePage(), it ships matching TypeScript types, and it resolves correctly across bundlers. Two alternatives sit beside it for people without a bundler: `pangu/browser/standalone`, described as one self-contained file, and a UMD script tag from a CDN, which sets window.pangu. The usage itself is three calls. spaceText returns a spaced string, spaceNode walks a DOM node you pass it, and autoSpacePage handles the page once it is ready, guarded by a check on document.readyState.
Every CDN path ships the same two files
Three CDNs are listed, and each one offers the same pair of builds, which is the detail worth copying. jsDelivr and unpkg both serve a UMD file at dist/browser/pangu.umd.js and a self-contained ESM file at dist/browser/pangu.js under the package version in the path. cdnjs serves the minified equivalents, browser/pangu.umd.min.js and browser/pangu.min.js. In every case the version segment is written as x.y.z, and the file tells you to replace it with the version you want, which is the same advice as installing with an exact version. Two consequences follow for a production site: you can pin the CDN copy to the same version as your package.json, and you have to choose deliberately between the UMD build that pollutes the global scope and the ESM build that does not.
Node usage is one import, and spaceFile is asynchronous
On the server the entry point is the package root, and installation is one command:
npm install pangu --save-exactIt is imported as `import pangu from 'pangu'`, with a CommonJS require shown as the alternative for projects that have not moved yet:
import pangu from 'pangu';
// or
// const pangu = require('pangu'); // use this if you're still using CommonJS
const content = await pangu.spaceFile('/path/to/text.txt');The same spaceText call works as in the browser, and there is one extra method, spaceFile, which takes a path and returns content asynchronously, so it must be awaited. The file is blunt about the wrong use case: you SHOULD NOT use this library to space Markdown documents, because it is designed for HTML web pages and plain text with no markup language, and it points at issue #127 for the discussion.
The CLI check mode turns the rule into a build failure
The command line tool is where the rule becomes enforceable:
$ echo "他們在release的前一天爆炸" | pangu
他們在 release 的前一天爆炸
$ pangu -c "盤古新聞網:工程師會議中默不作聲,PM恐成最大贏家"; echo $?
Corrected: 盤古新聞網:工程師會議中默不作聲,PM 恐成最大贏家
1Piping text in works, and so does passing it as an argument. Two flags handle the mode: -f reads a file path, and -t is shown with a longer sentence about commits and code review, spaced word by word. The one to know is -c. In the example it prints a line beginning with Corrected, and the shell then reports an exit code of 1. That is what makes the tool usable in a pipeline, since a check that always exits zero can only report, while this one fails the run.
Two bin names, dual types, and a false flag for tree shaking
The manifest shows how much care went into the packaging. The package is type module with sideEffects false, which lets a bundler drop the whole library when nothing calls it, and it still ships a CommonJS main at ./dist/node/index.cjs. The exports map is built per condition: importing gets types from index.d.ts and code from index.js, requiring gets types from index.d.cts and code from index.cjs, so both module systems get accurate declarations. Separate entries exist for pangu/browser, pangu/browser/standalone and pangu/shared. Two binary names are installed, pangu and pangu-js, both pointing at the same cli.js, so scripts written against either name keep working. Around the package sit a fixtures directory, a Playwright config and a set of verify scripts under examples.
Editorial conclusion
pangu fits a Chinese, Japanese or Korean site whose HTML mixes scripts, and a team that wants the spacing enforced in review rather than by eye, since the CLI check mode turns the rule into a build failure. It does not fit Markdown, which the file rules out by name and points at an issue for, and it does not fit a project that needs semantic judgment on symbols, because the rule set is regex based and the only semantic layer lives in the Chrome extension through Gemini Nano on your own machine. Before you adopt it, check four things: that your content really is HTML or plain text rather than a templating language, that the exact version is pinned since the install command asks for --save-exact, that your bundler resolves the pangu/browser entry point rather than the Node one, and whether adding a space inside a string literal, a code sample or a URL is something your templates can survive.
Frequently asked questions
What does pangu.js actually do?
It inserts whitespace between CJK characters, meaning Chinese, Japanese and Korean, and ANS characters, meaning alphabetical letters, numerical digits and symbols. The file calls the practice opinionated and names the blank character 盤古之白, after the myth of splitting full-width and half-width characters apart.
How do I install pangu?
For the library, run `npm install pangu --save-exact`. The author also maintains official implementations for Python, Go and Java, plus a website with an HTTP API at pangu.space, and the Chrome extension is the install path for people who only want to read web pages with the spacing applied.
Can pangu.js space Markdown documents?
The file says you SHOULD NOT use it on Markdown. The library is designed for HTML web pages and plain text without any markup language, and the file links issue #127 for the discussion.
What does the AI Spacing feature in the pangu Chrome extension do?
It asks a language model when a symbol is ambiguous, such as a plus that means or more in one phrase and joins two things in another, or a minus that is either a negative number or a separator. It uses Chrome's built-in Prompt API running Gemini Nano on the device, so the file states it is fully offline and nothing leaves your machine.
Does the pangu command line tool fail when it changes text?
With the -c flag it does. The example prints a line starting with Corrected and the shell then reports an exit code of 1, which makes the flag usable as a check in a pipeline. Other forms are -f for a file path, -t for text, and plain arguments or piped input for one-off spacing.
Which import path should a bundler use for pangu?
`pangu/browser` in ESM, which is the DOM-aware build with spaceNode() and autoSpacePage() and matching TypeScript types, and which the file says resolves correctly across bundlers. Without a bundler, `pangu/browser/standalone` is one self-contained file, and a UMD script from a CDN sets window.pangu instead.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/vinta-pangu-js)Star history chart for your README
[](https://hysenlabs.com/projects/vinta-pangu-js)Was this useful?