|
| 1 | +// Markdown Core tests cover CJK-friendly emphasis flanking. |
| 2 | +import { describe, expect, it } from "vitest"; |
| 3 | +import { markdownToIR } from "./ir.js"; |
| 4 | + |
| 5 | +function styledText(markdown: string, style: "bold" | "italic" = "bold"): string[] { |
| 6 | + const ir = markdownToIR(markdown); |
| 7 | + return ir.styles |
| 8 | + .filter((span) => span.style === style) |
| 9 | + .map((span) => ir.text.slice(span.start, span.end)); |
| 10 | +} |
| 11 | + |
| 12 | +describe("markdownToIR CJK emphasis flanking", () => { |
| 13 | + it("closes strong emphasis before adjacent Chinese text", () => { |
| 14 | + expect(styledText("前**加粗:**后")).toEqual(["加粗:"]); |
| 15 | + }); |
| 16 | + |
| 17 | + it("closes strong emphasis before adjacent Japanese text", () => { |
| 18 | + expect(styledText("これは**強調。**です")).toEqual(["強調。"]); |
| 19 | + }); |
| 20 | + |
| 21 | + it("closes strong emphasis before adjacent Korean text", () => { |
| 22 | + expect(styledText("이것은 **강조:**입니다")).toEqual(["강조:"]); |
| 23 | + }); |
| 24 | + |
| 25 | + it("handles supplementary CJK and variation selectors at emphasis boundaries", () => { |
| 26 | + expect(styledText("𰻞𰻞**(ビャンビャン)**麺")).toEqual(["(ビャンビャン)"]); |
| 27 | + expect(styledText("葛󠄀**(こちらが正式表記)**城市")).toEqual(["(こちらが正式表記)"]); |
| 28 | + }); |
| 29 | + |
| 30 | + it("supports CJK-friendly underscore flanking without enabling Latin intraword emphasis", () => { |
| 31 | + expect(styledText("__注意__:注意事項")).toEqual(["注意"]); |
| 32 | + expect(styledText("foo_bar_baz", "italic")).toEqual([]); |
| 33 | + }); |
| 34 | + |
| 35 | + it("keeps ASCII CommonMark emphasis behavior", () => { |
| 36 | + expect(styledText("**bold** text")).toEqual(["bold"]); |
| 37 | + expect(styledText("foo**bar**baz")).toEqual(["bar"]); |
| 38 | + }); |
| 39 | + |
| 40 | + it("treats ideographic space (U+3000) as whitespace, not a flanking CJK char", () => { |
| 41 | + // Opening delimiter followed by U+3000 must not be forced open. |
| 42 | + expect(styledText("前**\u3000加粗**后")).toEqual([]); |
| 43 | + // U+3000-separated emphasis keeps normal CommonMark behavior. |
| 44 | + expect(styledText("前\u3000**加粗**\u3000后")).toEqual(["加粗"]); |
| 45 | + }); |
| 46 | + |
| 47 | + it("treats Unicode thin space (U+2009) as whitespace in delimiter scanning", () => { |
| 48 | + // Opening delimiter followed by U+2009 must not be forced open. |
| 49 | + expect(styledText("前**\u2009加粗**后")).toEqual([]); |
| 50 | + // Closing delimiter after CJK punctuation still closes when followed by U+2009. |
| 51 | + expect(styledText("前**加粗:**\u2009后")).toEqual(["加粗:"]); |
| 52 | + }); |
| 53 | + |
| 54 | + it("leaves code spans and links on their existing paths", () => { |
| 55 | + const code = markdownToIR("`前**加粗:**后`"); |
| 56 | + expect(code.text).toBe("前**加粗:**后"); |
| 57 | + expect(code.styles.map((span) => span.style)).toEqual(["code"]); |
| 58 | + |
| 59 | + const linked = markdownToIR("[前**加粗:**后](https://example.com)"); |
| 60 | + expect(linked.text).toBe("前加粗:后"); |
| 61 | + expect(linked.links).toEqual([ |
| 62 | + { start: 0, end: linked.text.length, href: "https://example.com" }, |
| 63 | + ]); |
| 64 | + expect(linked.styles.filter((span) => span.style === "bold")).toEqual([ |
| 65 | + { start: 1, end: 4, style: "bold" }, |
| 66 | + ]); |
| 67 | + }); |
| 68 | +}); |
0 commit comments