Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions __tests__/lib/prismGrammars.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Prism } from "prism-react-renderer";
import "@/lib/prism-grammars";

function tokenTypes(language: string, code: string): string[] {
const grammar = Prism.languages[language];
expect(grammar).toBeTruthy();
const tokens = Prism.tokenize(code, grammar);
const types = new Set<string>();
const walk = (items: typeof tokens) => {
for (const item of items) {
if (typeof item === "string") {
types.add("text");
continue;
}
types.add(item.type);
if (Array.isArray(item.content)) {
walk(item.content as typeof tokens);
}
}
};
walk(tokens);
return [...types];
}

describe("prism-grammars", () => {
it("registers csharp and aliases cs/dotnet with multiple token types", () => {
const code =
'public class App { public string Name { get; set; } = "Northwind"; }';
const csharpTypes = tokenTypes("csharp", code);
expect(csharpTypes.length).toBeGreaterThan(1);
expect(csharpTypes).toEqual(
expect.arrayContaining(["keyword", "class-name", "string"]),
);
expect(Prism.languages.cs).toBe(Prism.languages.csharp);
expect(Prism.languages.dotnet).toBe(Prism.languages.csharp);
expect(tokenTypes("cs", code).length).toBeGreaterThan(1);
expect(tokenTypes("dotnet", code).length).toBeGreaterThan(1);
});

it("registers bash and aliases sh/shell", () => {
const code = "dotnet run --project ./AppHost";
expect(tokenTypes("bash", code).length).toBeGreaterThan(1);
expect(Prism.languages.sh).toBe(Prism.languages.bash);
expect(Prism.languages.shell).toBe(Prism.languages.bash);
expect(tokenTypes("sh", code).length).toBeGreaterThan(1);
expect(tokenTypes("shell", code).length).toBeGreaterThan(1);
});

it("registers powershell from upstream prismjs", () => {
const code = 'Write-Host "hello"';
expect(tokenTypes("powershell", code).length).toBeGreaterThan(1);
});

it("registers http from upstream prismjs", () => {
expect(
tokenTypes("http", "POST /webhooks HTTP/1.1\nHost: example.com").length,
).toBeGreaterThan(1);
});
});
1 change: 1 addition & 0 deletions components/typography-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Link as LinkIcon } from "lucide-react";
import Link from "next/link";
import React from "react";
import { Prism } from "tinacms/dist/rich-text/prism";
import "@/lib/prism-grammars";
import { CustomLink } from "@/components/customLink";
import MermaidElement from "@/components/mermaid/MermaidElement";
import { toSlug } from "@/lib/utils";
Expand Down
28 changes: 28 additions & 0 deletions lib/prism-grammars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Register extra Prism grammars into prism-react-renderer.
*
* TinaCMS's rich-text Prism wrapper uses prism-react-renderer, whose bundled
* language set omits csharp, bash, powershell and http. Hundreds of SSW Rules
* are tagged with those languages and otherwise render monochrome.
*
* Uses prism-react-renderer's documented custom-language approach: assign the
* vendored Prism to globalThis, then load upstream prismjs/components so they
* register onto that same instance. No custom grammars.
*
* Side-effect import this module once from the typography components so the
* shared Prism registry gains the grammars before any code_block renders.
*/
import { Prism } from "prism-react-renderer";

const root = globalThis as typeof globalThis & { Prism?: typeof Prism };
root.Prism = Prism;

require("prismjs/components/prism-csharp");
require("prismjs/components/prism-bash");
require("prismjs/components/prism-powershell");
require("prismjs/components/prism-http");

Prism.languages.cs = Prism.languages.csharp;
Prism.languages.dotnet = Prism.languages.csharp;
Prism.languages.sh = Prism.languages.bash;
Prism.languages.shell = Prism.languages.bash;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@types/js-cookie": "^3.0.6",
"@types/mssql": "^12.3.0",
"@types/node": "^25.6.0",
"@types/prismjs": "1.26.6",
"@types/react": "^19",
"@types/styled-components": "^5.1.36",
"autoprefixer": "^10.5.0",
Expand Down Expand Up @@ -80,6 +81,8 @@
"next": "16.2.4",
"next-sitemap": "^4.2.3",
"next-themes": "^0.4.6",
"prism-react-renderer": "2.4.1",
"prismjs": "1.30.0",
"prop-types": "^15.8.1",
"react": "19.2.5",
"react-country-flag": "^3.1.0",
Expand Down
15 changes: 15 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading