---
title: CJK Language Support
description: Full support for Chinese, Japanese, and Korean text with proper emphasis formatting.
type: reference
summary: Proper line breaking, emphasis marks, and character spacing for CJK languages.
prerequisites:
  - /docs/getting-started
related:
  - /docs/typography
---

# CJK Language Support



Streamdown includes built-in support for CJK (Chinese, Japanese, Korean) languages, ensuring that emphasis markers like bold and italic work correctly with ideographic punctuation. This is particularly important for AI-generated content, where language models naturally place emphasis markers around phrases that include or end with punctuation.

## The Problem

The CommonMark/GFM specification has a [limitation](https://github.com/commonmark/commonmark-spec/issues/650) where emphasis markers (`**` or `*`) adjacent to ideographic punctuation marks occasionally fail to be recognized. This causes formatting to break in CJK text:

```markdown
**この文は太字になりません（This won't be bolded）。**この文のせいで（It is due to this sentence）。
```

Without CJK-friendly parsing, the text above would render as plain text instead of bold because the closing `**` appears next to the Japanese period.

## The Solution

Streamdown uses the [remark-cjk-friendly](https://www.npmjs.com/package/remark-cjk-friendly) and [remark-cjk-friendly-gfm-strikethrough](https://www.npmjs.com/package/remark-cjk-friendly-gfm-strikethrough) plugins to handle CJK text properly. This plugin implements an improved parsing approach that correctly recognizes emphasis markers adjacent to ideographic punctuation.

## Supported Features

### Bold Text with Punctuation

Works correctly with all ideographic punctuation marks:

```markdown
**日本語の文章（括弧付き）。**この文が後に続いても大丈夫です。
**中文文本（带括号）。**这句子继续也没问题。
**한국어 구문(괄호 포함)**을 강조.
```

{/* The following lang="..." is crucial to ensure proper han character rendering */}

Japanese: <span lang="ja"><strong>日本語の文章（括弧付き）。</strong>この文が後に続いても大丈夫です。</span>

Chinese: <span lang="zh-Hans"><strong>中文文本（带括号）。</strong>这句子继续也没问题。</span>

Korean: <span lang="ko"><strong>한국어 구문(괄호 포함)</strong>을 강조.</span>

### Italic Text with Punctuation

```markdown
*これは斜体のテキストです（括弧付き）。*この文が後に続いても大丈夫です。
*这是斜体文字（带括号）。*这句子继续也没问题。
*이 텍스트(괄호 포함)*는 기울임꼴입니다.
```

Japanese: <span lang="ja"><em>これは斜体のテキストです（括弧付き）。</em>この文が後に続いても大丈夫です。</span>

Chinese: <span lang="zh-Hans"><em>这是斜体文字（带括号）。</em>这句子继续也没问题。</span>

Korean: <span lang="ko"><em>이 텍스트(괄호 포함)</em>는 기울임꼴입니다.</span>

### Strikethrough with Punctuation

Streamdown includes `remark-cjk-friendly-gfm-strikethrough` for proper strikethrough support:

```markdown
~~削除されたテキスト（括弧付き）。~~この文は正しいです。
~~删除的文字（带括号）。~~这个句子是正确的。
~~이 텍스트(괄호 포함)~~를 삭제합니다.
```

Japanese: <span lang="ja"><del>削除されたテキスト（括弧付き）。</del>この文は正しいです。</span>

Chinese: <span lang="zh-Hans"><del>删除的文字（带括号）。</del>这个句子是正确的。</span>

Korean: <span lang="ko"><del>이 텍스트(괄호 포함)</del>를 삭제합니다。</span>

### Mixed Content

CJK and English text work seamlessly together:

```markdown
**重要提示（Important Notice）：**请注意。
```

Result: <span lang="zh-Hans"><strong>重要提示（Important Notice）：</strong>请注意。</span>

## Supported Punctuation

The plugin handles all common ideographic punctuation marks:

* Parentheses: `（）`
* Brackets: `【】「」〈〉`
* Periods: `。．`
* Commas: `，、`
* Questions: `？`
* Exclamations: `！`
* Colons: `：`

## Why This Matters for AI

Language models generate markdown naturally, often placing emphasis markers around phrases that include punctuation. Without CJK-friendly parsing, AI-generated content in Chinese, Japanese, or Korean would have broken formatting.

<dl>
  <dt>
    ❌ Without CJK support:
  </dt>

  <dd>
    * The model writes:{" "}
      <span lang="ja">`**この用語（読み方など）**について説明します。`</span>- The
      user sees: <span lang="ja">
      \*\*この用語（読み方など）\*\*について説明します。
      </span> (not bold!)
  </dd>

  <dt>
    ✅ With CJK support:
  </dt>

  <dd>
    * The model writes:{" "}
      <span lang="ja">`**この用語（読み方など）**について説明します。`</span>- The
      user sees: <span lang="ja">
      <strong>この用語（読み方など）</strong>について説明します。
      </span> (properly bolded!)
  </dd>
</dl>

## Enabling CJK Support

CJK support requires the CJK plugin. Install it:

<CodeBlockTabs defaultValue="npm">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npm install @streamdown/cjk
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm add @streamdown/cjk
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn add @streamdown/cjk
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun add @streamdown/cjk
    ```
  </CodeBlockTab>
</CodeBlockTabs>

Then import and pass the plugin to Streamdown:

```tsx title="app/page.tsx"
import { Streamdown } from "streamdown";
import { cjk } from "@streamdown/cjk";

export default function Page() {
  return (
    <Streamdown plugins={{ cjk: cjk }}>
      {markdown}
    </Streamdown>
  );
}
```

Without the CJK plugin, emphasis markers adjacent to ideographic punctuation may not render correctly.

## Autolink Boundary Handling

The CJK plugin also prevents autolinks from swallowing trailing CJK punctuation. When a URL ends with CJK punctuation characters, the plugin splits the link so the punctuation appears as regular text.

**Example:**

```markdown
Check out https://example.com。这是一个链接。
```

Without CJK support, the trailing `。` would be included in the URL. With the plugin, the link ends at `https://example.com` and the period is rendered as text.

**Supported boundary characters:**

`。．，、？！：；（）【】「」『』〈〉《》`

## Plugin Configuration

### Using the Factory Function

For advanced configuration, use `createCjkPlugin`:

```tsx title="app/page.tsx"
import { Streamdown } from "streamdown";
import { createCjkPlugin } from "@streamdown/cjk";

const cjk = createCjkPlugin();

export default function Page() {
  return (
    <Streamdown plugins={{ cjk }}>
      {markdown}
    </Streamdown>
  );
}
```

### Plugin API

The CJK plugin provides remark plugins in a specific order for proper integration:

```tsx
interface CjkPlugin {
  // Plugins that run BEFORE remarkGfm (e.g., remark-cjk-friendly)
  remarkPluginsBefore: Pluggable[];

  // Plugins that run AFTER remarkGfm (e.g., autolink boundary, strikethrough)
  remarkPluginsAfter: Pluggable[];

  // @deprecated - Use remarkPluginsBefore and remarkPluginsAfter instead
  remarkPlugins: Pluggable[];
}
```

Streamdown automatically handles the plugin ordering. If integrating manually, ensure:

1. `remarkPluginsBefore` runs before `remarkGfm` (modifies emphasis handling)
2. `remarkPluginsAfter` runs after `remarkGfm` (enhances autolinks and strikethrough)
