/** * What a fence says about itself, read without a browser. * * Deliberately separable from the renderer: everything here decides what to * hand a highlighter, and none of it needs one — which is the whole reason * these functions are not in the component that calls them. */ import { describe, expect, it } from "bun:test"; import { DIFF_LANGUAGE, MERMAID_LANGUAGE } from "@chopin/dialect"; import { fileNameOf, kindOf, LANGUAGES, repaired, titled, titleOf } from "./code"; describe("what a fence is", () => { it("tells the two rendered languages apart from ordinary code", () => { expect(kindOf(MERMAID_LANGUAGE)).toBe("mermaid"); expect(kindOf(DIFF_LANGUAGE)).toBe("diff"); expect(kindOf("typescript")).toBe("code"); }); /** * A fence nobody named renders nothing. Colouring uncoloured text beside * the same uncoloured text is two of the same thing, and an invitation to * edit the copy that is not the document. */ it("has nothing to draw for a fence with no language", () => { expect(kindOf("")).toBe("plain"); }); /** One spelling, so the agent cannot copy a second one back at us. */ it("does not accept another spelling of diff", () => { expect(kindOf("patch")).toBe("code"); expect(kindOf("udiff")).toBe("code"); }); }); describe("a fence's title", () => { it("reads the two spellings a generator is likely to have written", () => { expect(titleOf('title="a.js"')).toBe("a.js"); expect(titleOf('filename="a.js"')).toBe("a.js"); expect(titleOf("title='a.js'")).toBe("a.js"); }); it("finds one among the rest of the info string", () => { expect(titleOf('collapsed title="apps/server/src/main.ts" {1,3}')) .toBe("apps/server/src/main.ts"); }); /** * Quotes are required. An unquoted value cannot contain a space, so * half-supporting it would mean a path with one in it silently losing its * tail — and a plan is full of paths somebody typed. */ it("refuses a value it would have to guess the end of", () => { expect(titleOf("title=a.js")).toBeUndefined(); expect(titleOf("title=my file.js")).toBeUndefined(); }); it("is not fooled by a word ending in title", () => { expect(titleOf('subtitle="a.js"')).toBeUndefined(); }); it("has nothing to say about an empty info string", () => { expect(titleOf("")).toBeUndefined(); expect(titled("")).toBe(false); expect(titled('title="a.js"')).toBe(true); }); }); describe("the name handed to the renderer", () => { /** * The renderer works in files: it shows the name, and falls back to it * when nothing else says what the language is. A fence usually has no * name, so one is invented — invented rather than omitted, because an * empty header reads as a missing file rather than as a snippet. */ it("invents one from the language when the fence has no title", () => { expect(fileNameOf("ts", "")).toBe("snippet.ts"); expect(fileNameOf("", "")).toBe("snippet.txt"); }); it("prefers what the author wrote", () => { expect(fileNameOf("ts", 'title="apps/web/src/main.tsx"')).toBe("apps/web/src/main.tsx"); }); }); describe("the languages on offer", () => { it("offers both of the fences that render as something else", () => { let ids = LANGUAGES.map(([id]) => id); expect(ids).toContain(MERMAID_LANGUAGE); expect(ids).toContain(DIFF_LANGUAGE); }); /** * The list is written out by hand, and a duplicate in it is a `