/** * highlightCode — deterministic token markup for code blocks. * * The code editor's "colorful code" regression: a code block must render * Prism token spans (`…`) for known languages so * globals.css can color them, and must return null (→ raw text, no spans) * for plaintext / unknown languages / empty input so a bad language value * never breaks rendering. */ import { describe, expect, it } from "vitest"; import { CODE_LANGUAGES, highlightCode } from "../code-highlight"; describe("highlightCode", () => { it("javascript: keywords, strings, functions and numbers become token spans", () => { const html = highlightCode('const x = "hello";\nfunction add(a, b) { return a + b; }\nlet n = 42;', "javascript"); expect(html, "expected HTML output").toBeTruthy(); expect(html).toContain('class="token keyword"'); expect(html).toContain(">const<"); expect(html).toContain('class="token string"'); expect(html).toContain("hello"); expect(html).toContain('class="token function"'); expect(html).toContain("add"); expect(html).toContain('class="token number"'); expect(html).toContain(">42<"); // Punctuation is tokenized too (the `;`, `{`, etc.). expect(html).toContain('class="token punctuation"'); }); it("typescript extends javascript (interface is a keyword)", () => { const html = highlightCode("interface Foo { x: number }", "typescript"); expect(html).toContain('class="token keyword"'); expect(html).toContain(">interface<"); }); it("python: keywords + strings + comments", () => { const html = highlightCode('# count\nx = "hi"\nif x:\n print(x)', "python"); expect(html).toContain('class="token comment"'); expect(html).toContain("count"); expect(html).toContain('class="token string"'); expect(html).toContain('class="token keyword"'); }); it("sql: keywords are uppercased-matched and quoted", () => { const html = highlightCode("SELECT id, name FROM users WHERE id = 1;", "sql"); expect(html).toContain('class="token keyword"'); expect(html).toContain("SELECT"); expect(html).toContain('class="token number"'); }); it("json: keys/strings/numbers tokenized", () => { const html = highlightCode('{ "a": 1, "b": true }', "json"); expect(html).toContain('class="token property"'); expect(html).toContain('class="token number"'); expect(html).toContain('class="token boolean"'); }); it("bash: shebang/comment + strings", () => { const html = highlightCode("#!/usr/bin/env bash\n# done\necho \"hi\"", "bash"); expect(html).toContain("token shebang"); expect(html).toContain('class="token comment"'); expect(html).toContain('class="token string"'); }); it("css: property, value and selector tokens", () => { const html = highlightCode("body { color: #ff0000; }", "css"); expect(html).toContain("token"); }); it("html (markup): tags + attributes", () => { const html = highlightCode("
x
", "html"); expect(html).toContain('class="token tag"'); expect(html).toContain('class="token attr-name"'); }); it("plaintext: null (rendered raw, never wrapped in spans)", () => { expect(highlightCode("just some text", "plaintext")).toBeNull(); }); it("unknown language: null (fallback to raw, no broken markup)", () => { expect(highlightCode("def f(): pass", "cobol")).toBeNull(); expect(highlightCode("x", "")).toBeNull(); }); it("empty input: null", () => { expect(highlightCode("", "javascript")).toBeNull(); }); it("escapes HTML special characters (no raw markup inside token output)", () => { const html = highlightCode("const s = \"&\";", "javascript"); // Prism entity-escapes `<` (and `&`) in token contents so the output // cannot open a real element inside the DOM. A bare `>` can never // start a tag, so Prism leaves it as-is — the safety property is that no // raw `` survives the highlight. expect(html).toContain("<b>"); expect(html).toContain("&"); expect(html).not.toContain(""); // raw markup must not appear }); it("CODE_LANGUAGES matches the CodeBlock dropdown exactly (plaintext + 10 languages)", () => { expect([...CODE_LANGUAGES]).toEqual([ "plaintext", "javascript", "typescript", "python", "bash", "json", "sql", "go", "rust", "css", "html", ]); }); });