-
Notifications
You must be signed in to change notification settings - Fork 125
/
Copy pathcode_block_theme.ts
105 lines (93 loc) · 3.47 KB
/
code_block_theme.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
* @module
*
* Manages the server-side functionality of the code blocks feature, mostly for obtaining the available themes for syntax highlighting.
*/
import fs from "fs";
import themeNames from "./code_block_theme_names.json" with { type: "json" };
import { t } from "i18next";
import { join } from "path";
import { isDev, isElectron, getResourceDir } from "./utils.js";
/**
* Represents a color scheme for the code block syntax highlight.
*/
interface ColorTheme {
/** The ID of the color scheme which should be stored in the options. */
val: string;
/** A user-friendly name of the theme. The name is already localized. */
title: string;
}
/**
* Returns all the supported syntax highlighting themes for code blocks, in groups.
*
* The return value is an object where the keys represent groups in their human-readable name (e.g. "Light theme")
* and the values are an array containing the information about every theme. There is also a special group with no
* title (empty string) which should be displayed at the top of the listing pages, without a group.
*
* @returns the supported themes, grouped.
*/
export function listSyntaxHighlightingThemes() {
const path = join(getResourceDir(), getStylesDirectory());
const systemThemes = readThemesFromFileSystem(path);
return {
"": [
{
val: "none",
title: t("code_block.theme_none")
}
],
...groupThemesByLightOrDark(systemThemes)
};
}
export function getStylesDirectory() {
if (isElectron && !isDev) {
return "styles";
}
return "node_modules/@highlightjs/cdn-assets/styles";
}
/**
* Reads all the predefined themes by listing all minified CSSes from a given directory.
*
* The theme names are mapped against a known list in order to provide more descriptive names such as "Visual Studio 2015 (Dark)" instead of "vs2015".
*
* @param path the path to read from. Usually this is the highlight.js `styles` directory.
* @returns the list of themes.
*/
export function readThemesFromFileSystem(path: string): ColorTheme[] {
return fs
.readdirSync(path)
.filter((el) => el.endsWith(".min.css"))
.map((name) => {
const nameWithoutExtension = name.replace(".min.css", "");
let title = nameWithoutExtension.replace(/-/g, " ");
if (title in themeNames) {
title = (themeNames as Record<string, string>)[title];
}
return {
val: `default:${nameWithoutExtension}`,
title: title
};
});
}
/**
* Groups a list of themes by dark or light themes. This is done simply by checking whether "Dark" is present in the given theme, otherwise it's considered a light theme.
* This generally only works if the theme has a known human-readable name (see {@link #readThemesFromFileSystem()})
*
* @param listOfThemes the list of themes to be grouped.
* @returns the grouped themes by light or dark.
*/
function groupThemesByLightOrDark(listOfThemes: ColorTheme[]) {
const darkThemes = [];
const lightThemes = [];
for (const theme of listOfThemes) {
if (theme.title.includes("Dark")) {
darkThemes.push(theme);
} else {
lightThemes.push(theme);
}
}
const output: Record<string, ColorTheme[]> = {};
output[t("code_block.theme_group_light")] = lightThemes;
output[t("code_block.theme_group_dark")] = darkThemes;
return output;
}