# markdown-cjk-friendly exists because ** does not bold CJK text

> tats-u/markdown-cjk-friendly is a CommonMark next specification draft that makes double-asterisk emphasis work when a Chinese, Japanese or Korean character sits inside the markers. It ships as a pnpm workspace of nine published packages covering markdown-it, remark, micromark, mdast and marked, plus ports for Comrak, Markdig, a Ruby gem and goldmark.

**tats-u/markdown-cjk-friendly** — Make CommonMark more friendly for Japanese/Chinese/Korean (CommonMark next specification draft)—plugins & patched packages

- Repository: https://github.com/tats-u/markdown-cjk-friendly
- Website: https://tats-u.github.io/markdown-cjk-friendly/
- Stars: 172 · Forks: 4
- Language: TypeScript
- License: MIT
- Published: 2026-08-22 · Updated: 2026-08-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/tats-u-markdown-cjk-friendly

## The double asterisks stay literal when a CJK character sits inside them

The bug is small and it is everywhere in CJK prose. Write two asterisks, put Japanese, Chinese or Korean text inside them, and CommonMark does not treat them as emphasis at all. A Japanese sentence such as `**この文は強調されません。**この文のせいで。` comes out of the parser with both markers still attached, and the same is true of the Chinese and Korean examples the project shows. The characters render exactly as typed, so the failure is visible in the output rather than hidden as a subtle style difference. The cause is the character immediately inside the markers, not the punctuation around them. English text bolds correctly with the same two characters in the same position, which is what makes the failure easy to miss in a mostly-English codebase and obvious the first time a Japanese sentence arrives in a pull request.

## Nine packages cover the JavaScript parser stack, and one is retired

The repository is a pnpm workspace over `packages/*`, and the surface is deliberately broad because no single JavaScript markdown parser has an extension point that covers this. The markdown-it entry point is `markdown-it-cjk-friendly`. The remark line has `remark-cjk-friendly` with a GFM strikethrough variant, and beneath it the micromark layer with `micromark-extension-cjk-friendly`, its util package and a strikethrough variant, followed by the mdast serializer `mdast-util-to-markdown-cjk-friendly` and its own strikethrough variant. `marked-cjk-friendly` covers the other popular renderer. A tenth name, `markdown-it-cj-friendly`, is struck through in the list and marked deprecated with a pointer to switch to `markdown-it-cjk-friendly`, so an install following an old tutorial will pull a package its author has retired.

## The spec carries its own LICENSE-spec, separate from the code licence

Two licence files sit at the top of the repository: `LICENSE` and `LICENSE-spec`. That split is the one piece of structure worth reading before you copy anything. The MIT licence covers the implementation, while the specification document is licensed on its own terms, so the prose describing the proposed CommonMark change and the code implementing it are not the same grant. The specification itself is `specification.md`, written in English, with two companion documents for people writing their own implementation: `implementers-tips.md` and `ranges.md`, the latter covering the code point ranges the rule applies to. The repository also ships an `AGENTS.md`, a `CONTRIBUTING.md` and a `SECURITY.md`, so there is a stated process for contributing and a stated place to report problems, which is more than most specification drafts bother with.

## The ports are extension plugins, and goldmark is the only first-party one

Outside JavaScript, the project lists what other implementations have done with the rule. Comrak takes it as an extension and commonmarker, the Rust CommonMark implementation, is listed under Comrak, as is the GitLab Flavored Markdown Ruby gem with its dingus rewrite layer. Markdig, the .NET implementation, is listed as taking the extension too. The only port described as official belongs to tats-u as well: goldmark-cjk-friendly, for the Go goldmark parser. The practical shape of this is that a Go team has a maintained package with a maintainer attached, while a C# or Ruby team has a third-party implementation whose update cadence nobody in this repository controls. Both planned items on the list, tweaking the specifications and porting for non-JavaScript implementations, are still listed as planned, so neither has shipped.

## A pnpm workspace means one test command and one benchmark command

Everything is driven from the root `package.json`, and the package manager is pinned with `packageManager` set to `pnpm@12.7.0`, so a clone with the wrong pnpm major will refuse to install. Because the workspace fans out over `packages/*`, the recursive scripts cover every package at once:

```bash
pnpm -r test
pnpm -r build
```

Linting is a two-stage pipeline, `biome check` before the build and a type check after it, which is why the root `lint` script runs `lint:prebuild` and then `lint:postbuild` in sequence. Benchmarks go through `vitest bench` with a CodSpeed plugin, and a separate `print-ranges` script runs `scripts/cjk-ranges.ts` through node's type stripping, which is the tool that regenerates the ranges the rule depends on. Releases go through changesets, with separate scripts for versioning and publishing, and the published tags follow the package name, so a single repository produces nine independently versioned npm packages.

## This is a draft proposal, so the rule can still change under you

The framing matters more than any single package. The project describes itself as making CommonMark more friendly for CJK as a CommonMark next specification draft, and the planned list still contains tweaking the specifications. A draft is a proposal with a moving target, and a parser that implements it today may implement a slightly different rule once the text settles. That risk is not hypothetical for a documentation site, because a change in how emphasis is parsed shows up in rendered output rather than in a build error. The safe posture is to pin the package version you tested against, keep a copy of the test cases in your own repository, and re-run them when you bump. The repository ships a `testcases/` directory and a `demos/` directory, so both the inputs and the expected rendering are available to diff against.

## Conclusion

markdown-cjk-friendly fits a team whose documents are written in CJK and whose renderer is one of the supported JavaScript parsers, since swapping the emphasis rule is the entire point. It does not fit a Go, Rust or .NET codebase, where the extension lists stop and only goldmark has an official port today. Before adopting it, check whether your renderer already implements the CommonMark next draft, because then you would be shipping a parser change to fix something your stack resolved upstream.

## FAQ

### Which markdown-cjk-friendly package should I install for remark?

The remark entry point is `remark-cjk-friendly`, with `remark-cjk-friendly-gfm-strikethrough` as its GFM strikethrough variant. Beneath it in the stack sit `micromark-extension-cjk-friendly` and `mdast-util-to-markdown-cjk-friendly`.

### Why is markdown-it-cj-friendly deprecated?

It is struck through in the package list and marked deprecated, with a note to switch to `markdown-it-cjk-friendly`. The rename inserted the k, and the old name is kept listed only so existing installs can find the replacement.

### Does markdown-cjk-friendly exist outside JavaScript?

As ports and extensions, yes. Comrak and the commonmarker Rust implementation, the GitLab Flavored Markdown Ruby gem with dingus, and Markdig are listed, and goldmark-cjk-friendly is described as the official port for the Go goldmark parser. Porting for further non-JavaScript implementations is still on the planned list.

### How do I build and test markdown-cjk-friendly from source?

The root package is a pnpm workspace over packages/* with pnpm@12.7.0 pinned as the package manager. `pnpm -r test` and `pnpm -r build` cover every package, linting runs biome check before the build and a type check after it, and benchmarks run through `vitest bench`.

### What breaks in CJK markdown that markdown-cjk-friendly fixes?

Double-asterisk emphasis is not recognized when a Chinese, Japanese or Korean character sits immediately inside the markers, so the asterisks are displayed literally. The cause is the character just inside the markers rather than the surrounding punctuation.

## Sources

- [Official documentation](https://tats-u.github.io/markdown-cjk-friendly/)
- [Official README](https://github.com/tats-u/markdown-cjk-friendly#readme)
- [Project repository](https://github.com/tats-u/markdown-cjk-friendly)
- [Release notes](https://github.com/tats-u/markdown-cjk-friendly/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/tats-u-markdown-cjk-friendly
