diff --git a/ui/src/components/markdown-parser.ts b/ui/src/components/markdown-parser.ts
index 3a603673a45b..75af77b68a3b 100644
--- a/ui/src/components/markdown-parser.ts
+++ b/ui/src/components/markdown-parser.ts
@@ -1,5 +1,6 @@
import { asOptionalRecord } from "@openclaw/normalization-core/record-coerce";
import MarkdownIt, { type MarkdownIt as MarkdownItParser, type Token } from "markdown-it";
+import markdownItCjkFriendly from "markdown-it-cjk-friendly";
import markdownItTaskLists from "markdown-it-task-lists";
import { t } from "../i18n/index.ts";
import { fileKindForPath, shortestFileLabels } from "./file-kind.ts";
@@ -147,6 +148,7 @@ export function createMarkdownParser(): MarkdownItParser {
breaks: true,
linkify: true,
});
+ markdownParser.use(markdownItCjkFriendly);
const defaultCodeInlineRenderer = markdownParser.renderer.rules.code_inline!;
// Enable GFM strikethrough (~~text~~) to match original marked.js behavior.
diff --git a/ui/src/e2e/chat-markdown-alignment.e2e.test.ts b/ui/src/e2e/chat-markdown-alignment.e2e.test.ts
index b1978794a5be..f91efc181a20 100644
--- a/ui/src/e2e/chat-markdown-alignment.e2e.test.ts
+++ b/ui/src/e2e/chat-markdown-alignment.e2e.test.ts
@@ -26,6 +26,10 @@ suite.define(() => {
text: [
"## Alignment check",
"",
+ "これは**(注記)**です",
+ "",
+ 'safe
break and unsafe
markup',
+ "",
"- Bullet item",
"",
"1. Numbered item",
@@ -56,6 +60,9 @@ suite.define(() => {
hasText: "Alignment check",
});
await markdown.waitFor();
+ expect(await markdown.locator("strong", { hasText: "(注記)" }).count()).toBe(1);
+ expect(await markdown.locator("br").count()).toBe(1);
+ expect(await markdown.textContent()).toContain('unsafe
markup');
const geometry = await markdown.evaluate((root) => {
const textRect = (selector: string) => {