Skip to content

Commit 6c9f66c

Browse files
authored
fix: unsupported themes will use dark-plus (#7187)
* feat: create a helper function to handle theme strings * feat: add tests for kebabOfThemeStr * fix: unsupported themes are correctly using dark-plus
1 parent 4eeb349 commit 6c9f66c

3 files changed

Lines changed: 81 additions & 15 deletions

File tree

core/codeRenderer/CodeRenderer.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
Highlighter,
2121
} from "shiki";
2222
import { DiffLine } from "..";
23-
import { escapeForSVG, kebabOfStr } from "../util/text";
23+
import { escapeForSVG, kebabOfThemeStr } from "../util/text";
2424

2525
interface CodeRendererOptions {
2626
themesDir?: string;
@@ -70,28 +70,29 @@ export class CodeRenderer {
7070

7171
public async setTheme(themeName: string): Promise<void> {
7272
if (
73-
this.themeExists(kebabOfStr(themeName)) ||
73+
this.themeExists(kebabOfThemeStr(themeName)) ||
7474
themeName === "Default Dark Modern"
7575
) {
7676
this.currentTheme =
7777
themeName === "Default Dark Modern"
7878
? "dark-plus"
79-
: kebabOfStr(themeName);
80-
81-
this.highlighter = await getSingletonHighlighter({
82-
langs: ["typescript"],
83-
themes: [this.currentTheme],
84-
});
85-
86-
const th = this.highlighter.getTheme(this.currentTheme);
87-
88-
this.editorBackground = th.bg;
89-
this.editorForeground = th.fg;
90-
this.editorLineHighlight =
91-
th.colors!["editor.lineHighlightBackground"] ?? "#000000";
79+
: kebabOfThemeStr(themeName);
9280
} else {
81+
// Fallback to default theme for unsupported themes.
9382
this.currentTheme = "dark-plus";
9483
}
84+
85+
// Always initialize the highlighter with the current theme.
86+
this.highlighter = await getSingletonHighlighter({
87+
langs: ["typescript"],
88+
themes: [this.currentTheme],
89+
});
90+
91+
const th = this.highlighter.getTheme(this.currentTheme);
92+
this.editorBackground = th.bg;
93+
this.editorForeground = th.fg;
94+
this.editorLineHighlight =
95+
th.colors!["editor.lineHighlightBackground"] ?? "#000000";
9596
}
9697

9798
async init(): Promise<void> {}

core/util/text.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,10 @@ export function kebabOfStr(str: string): string {
4444
.replace(/[\s_]+/g, "-") // replace spaces and underscores with hyphens
4545
.toLowerCase();
4646
}
47+
48+
export function kebabOfThemeStr(str: string): string {
49+
return str
50+
.toLowerCase()
51+
.replace(/[\s_]+/g, "-") // replace spaces and underscores with hyphens
52+
.replace(/\(|\)/g, ""); // remove parentheses
53+
}

core/util/text.vitest.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
capitalizeFirstLetter,
44
escapeForSVG,
55
kebabOfStr,
6+
kebabOfThemeStr,
67
replaceEscapedCharacters,
78
} from "./text";
89

@@ -184,3 +185,60 @@ describe("kebabOfStr", () => {
184185
expect(kebabOfStr("MiXeD cAsE")).toBe("mi-xe-d-c-as-e");
185186
});
186187
});
188+
189+
describe("kebabOfThemeStr", () => {
190+
it("should convert spaces to hyphens", () => {
191+
expect(kebabOfThemeStr("hello world")).toBe("hello-world");
192+
expect(kebabOfThemeStr("multiple spaces")).toBe("multiple-spaces");
193+
});
194+
195+
it("should convert underscores to hyphens", () => {
196+
expect(kebabOfThemeStr("snake_case")).toBe("snake-case");
197+
expect(kebabOfThemeStr("multiple___underscores")).toBe(
198+
"multiple-underscores",
199+
);
200+
});
201+
202+
it("should convert mixed spaces and underscores", () => {
203+
expect(kebabOfThemeStr("mixed_ case")).toBe("mixed-case");
204+
expect(kebabOfThemeStr("theme name_variant")).toBe("theme-name-variant");
205+
});
206+
207+
it("should convert to lowercase", () => {
208+
expect(kebabOfThemeStr("UPPERCASE")).toBe("uppercase");
209+
expect(kebabOfThemeStr("MiXeD CaSe")).toBe("mixed-case");
210+
});
211+
212+
it("should handle already kebab-case strings", () => {
213+
expect(kebabOfThemeStr("already-kebab")).toBe("already-kebab");
214+
});
215+
216+
it("should handle empty strings", () => {
217+
expect(kebabOfThemeStr("")).toBe("");
218+
});
219+
220+
it("should handle single characters", () => {
221+
expect(kebabOfThemeStr("A")).toBe("a");
222+
expect(kebabOfThemeStr("a")).toBe("a");
223+
});
224+
225+
it("should preserve other special characters", () => {
226+
expect(kebabOfThemeStr("hello@world")).toBe("hello@world");
227+
expect(kebabOfThemeStr("test.file.name")).toBe("test.file.name");
228+
});
229+
230+
it("should not convert camelCase (unlike kebabOfStr)", () => {
231+
expect(kebabOfThemeStr("camelCase")).toBe("camelcase");
232+
expect(kebabOfThemeStr("PascalCase")).toBe("pascalcase");
233+
});
234+
235+
it("should handle strings with numbers", () => {
236+
expect(kebabOfThemeStr("theme_v2 beta")).toBe("theme-v2-beta");
237+
expect(kebabOfThemeStr("version_123_FINAL")).toBe("version-123-final");
238+
});
239+
240+
it("should handle strings with parentheses", () => {
241+
expect(kebabOfThemeStr("theme_v2 (beta)")).toBe("theme-v2-beta");
242+
expect(kebabOfThemeStr("Gruvbox Dark (Hard)")).toBe("gruvbox-dark-hard");
243+
});
244+
});

0 commit comments

Comments
 (0)