diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index e039d3691f6a..965cd037629c 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -20,6 +20,19 @@ module.exports = { colorMode: { respectPrefersColorScheme: true, }, + prism: { + additionalLanguages: [ + "bash", + "c", + "cmake", + "ini", + "linker-script", + "log", + "powershell", + ], + theme: require("./src/theme/prism/themes/oceanic-next"), + darkTheme: require("./src/theme/prism/themes/oceanic-next"), + }, // sidebarCollapsible: false, navbar: { title: "ZMK Firmware", diff --git a/docs/src/theme/prism-include-languages.js b/docs/src/theme/prism-include-languages.js new file mode 100644 index 000000000000..c073923b92a4 --- /dev/null +++ b/docs/src/theme/prism-include-languages.js @@ -0,0 +1,23 @@ +import siteConfig from "@generated/docusaurus.config"; +export default function prismIncludeLanguages(PrismObject) { + const { + themeConfig: { prism }, + } = siteConfig; + const { additionalLanguages } = prism; + // Prism components work on the Prism instance on the window, while prism- + // react-renderer uses its own Prism instance. We temporarily mount the + // instance onto window, import components to enhance it, then remove it to + // avoid polluting global namespace. + // You can mutate PrismObject: registering plugins, deleting languages... As + // long as you don't re-assign it + globalThis.Prism = PrismObject; + additionalLanguages.forEach((lang) => { + // eslint-disable-next-line global-require + require(`prismjs/components/prism-${lang}`); + }); + + require("./prism/components/prism-devicetree.js"); + require("./prism/components/prism-kconfig.js"); + + delete globalThis.Prism; +} diff --git a/docs/src/theme/prism/components/prism-devicetree.js b/docs/src/theme/prism/components/prism-devicetree.js new file mode 100644 index 000000000000..3f2f90b8750d --- /dev/null +++ b/docs/src/theme/prism/components/prism-devicetree.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +/* eslint-disable no-undef */ + +Prism.languages.devicetree = { + comment: Prism.languages.c["comment"], + string: Prism.languages.c["string"], + keyword: + /\/(?:bits|delete-node|delete-property|dts-v1|incbin|include|memreserve|omit-if-no-ref|plugin)\//, + label: { + pattern: /\b(?:[a-z_]\w*):/i, + alias: "tag", + }, + reference: { + pattern: /&(?:[a-z_]\w*|\{[\w,.+*#?@/-]*\})/i, + alias: "variable", + }, + node: { + pattern: /(?:\/|\b[\w,.+\-@]+)(?=\s*\{)/, + alias: "function", + inside: { + // Node address + number: { + pattern: /(@)[0-9a-f,]/i, + lookbehind: true, + }, + }, + }, + function: Prism.languages.c["function"], + "attr-name": /\\?[\w,.+*#?@-]+(?=\s*[=;])/, + number: [/\b[0-9a-f]{2}\b/i, /\b(?:0[xX][0-9a-fA-F]+|\d+)(?:ULL|UL|LL|U|L)?/], + constant: { + pattern: /\b[A-Z_]+\b/, + alias: "number", + }, + macro: Prism.languages.c["macro"], + operator: /<<|>>|[<>]=?|[!=]=?|&&?|\|\|?|[+\-*/%~?^]/, + punctuation: /[{}[\];(),.]/, +}; + +Prism.languages.dts = Prism.languages.devicetree; diff --git a/docs/src/theme/prism/components/prism-kconfig.js b/docs/src/theme/prism/components/prism-kconfig.js new file mode 100644 index 000000000000..f911d6e32be1 --- /dev/null +++ b/docs/src/theme/prism/components/prism-kconfig.js @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +/* eslint-disable no-undef */ + +Prism.languages.kconfig = { + comment: { + pattern: /(^|[^\\])#.*/, + lookbehind: true, + greedy: true, + }, + string: /"(?:\\.|[^\\\r\n"])*"/, + helptext: { + // help text ends at the first line at a lower level of indentation than the + // first line of text. + pattern: /(^\s*)(?:help|---help---)\s*^(\s+)(?:.+)(?:\s*^\2[^\n]*)*/m, + lookbehind: true, + alias: "string", + inside: { + keyword: /^(?:help|---help---)/, + }, + }, + keyword: + /\b(?:allnoconfig_y|bool|boolean|choice|comment|config|def_bool|def_hex|def_int|def_string|def_tristate|default|defconfig_list|depends|endchoice|endif|endmenu|env|hex|if|imply|int|mainmenu|menu|menuconfig|modules|on|option|optional|orsource|osource|prompt|range|rsource|select|source|string|tristate|visible)\b/, + expansion: { + pattern: /\$\([\s\S]+\)/, + alias: "variable", + inside: { + function: /\$\(|\)/, + punctuation: /,/, + }, + }, + number: /\b(?:0[xX][0-9a-fA-F]+|\d+)/, + boolean: { + pattern: /\b(?:y|n|m)\b/, + alias: "number", + }, + variable: /\b[A-Z_]+\b/, + operator: /[<>]=?|[!=]=?|&&|\|\|/, + punctuation: /[()]/, +}; diff --git a/docs/src/theme/prism/themes/oceanic-next.js b/docs/src/theme/prism/themes/oceanic-next.js new file mode 100644 index 000000000000..1b0eae1ab54d --- /dev/null +++ b/docs/src/theme/prism/themes/oceanic-next.js @@ -0,0 +1,31 @@ +/** @type {import("prism-react-renderer").PrismTheme} */ +const baseTheme = require("prism-react-renderer/themes/oceanicNext"); + +/** @type {import("prism-react-renderer").PrismTheme} */ +const theme = { + plain: baseTheme.plain, + styles: [ + ...baseTheme.styles, + { + types: ["directive", "directive-hash"], + style: { + color: "#c5a5c5", + }, + }, + // Default colors for diffs are unintuitive. Switch to red and green. + { + types: ["deleted"], + style: { + color: "#fc929e", + }, + }, + { + types: ["inserted"], + style: { + color: "#8dc891", + }, + }, + ], +}; + +module.exports = theme;