From d0e8f0750a636e0aafc93f32e73c903c7ab24479 Mon Sep 17 00:00:00 2001 From: Akemi Izuko Date: Tue, 26 Dec 2023 03:45:47 -0700 Subject: [PATCH] Markdown: add code highlighting --- astro.config.mjs | 36 ++- package-lock.json | 102 +++++- package.json | 2 + public/themes/github_light.json | 555 ++++++++++++++++++++++++++++++++ 4 files changed, 689 insertions(+), 6 deletions(-) create mode 100644 public/themes/github_light.json diff --git a/astro.config.mjs b/astro.config.mjs index 3a49f94..706853a 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -4,8 +4,29 @@ import sitemap from '@astrojs/sitemap'; //import cloudflare from "@astrojs/cloudflare"; import remarkGfm from "remark-gfm"; import remarkRehype from "remark-rehype"; +import rehypePrettyCode from "rehype-pretty-code"; +import json from "./public/github_light.json" assert { type: "json" }; import tailwind from "@astrojs/tailwind"; +const options = { + // Specify the theme to use or a custom theme json, in our case + // it will be a moonlight-II theme from + // https://github.com/atomiks/moonlight-vscode-theme/blob/master/src/moonlight-ii.json + theme: json, + // Callbacks to customize the output of the nodes + onVisitLine(node) { + // Prevent lines from collapsing in `display: grid` mode, and + // allow empty lines to be copy/pasted + if (node.children.length === 0) { + node.children = [{type: 'text', value: ' '}]; + } + }, + onVisitHighlightedLine(node) { + // Adding a class to the highlighted line + node.properties.className.push('highlighted'); + }, +}; + // https://astro.build/config export default defineConfig({ site: 'https://dev.noway.moe', @@ -17,10 +38,23 @@ export default defineConfig({ inlineStylesheets: "auto", }, markdown: { + gfm: true, + syntaxHighlight: false, remarkPlugins: [ remarkGfm, [remarkRehype, { clobberPrefix: "" }], + [rehypePrettyCode, options], ], - gfm: true, + //shikiConfig: { + // // Choose from Shiki's built-in themes (or add your own) + // // https://github.com/shikijs/shiki/blob/main/docs/themes.md + // theme: 'dracula', + // // Add custom languages + // // Note: Shiki has countless langs built-in, including .astro! + // // https://github.com/shikijs/shiki/blob/main/docs/languages.md + // langs: ["c", "ssh-config"], + // // Enable word wrap to prevent horizontal scrolling + // wrap: true, + //}, } }); diff --git a/package-lock.json b/package-lock.json index 0bf4b97..339e6c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,11 @@ "@astrojs/sitemap": "^3.0.3", "@astrojs/tailwind": "^5.0.4", "astro": "^4.0.7", + "rehype-pretty-code": "^0.12.3", "remark-gfm": "^4.0.0", "remark-rehype": "^11.0.0", "sharp": "^0.33.1", + "shiki": "^0.14.7", "tailwindcss": "^3.4.0" }, "devDependencies": { @@ -76,6 +78,14 @@ "vfile": "^6.0.1" } }, + "node_modules/@astrojs/markdown-remark/node_modules/shikiji": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz", + "integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==", + "dependencies": { + "hast-util-to-html": "^9.0.0" + } + }, "node_modules/@astrojs/mdx": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-2.0.2.tgz", @@ -1906,6 +1916,11 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==" + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -2071,6 +2086,14 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/astro/node_modules/shikiji": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz", + "integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==", + "dependencies": { + "hast-util-to-html": "^9.0.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.16", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", @@ -3479,6 +3502,18 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -3886,6 +3921,11 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -5484,6 +5524,11 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, "node_modules/parse5": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", @@ -6062,6 +6107,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-pretty-code": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.12.3.tgz", + "integrity": "sha512-6NbIit8A3hLrkKBEbNs862jVnTLeIOM2AmM0VZ/MtyHb+OuNMeCa6UZSx6UG4zrobm5tY9efTwhih1exsGYsiw==", + "dependencies": { + "@types/hast": "^3.0.3", + "hast-util-to-string": "^3.0.0", + "parse-numeric-range": "^1.3.0", + "rehype-parse": "^9.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "shikiji": "^0.7.0 || ^0.8.0 || ^0.9.0" + } + }, "node_modules/rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -6896,14 +6960,32 @@ "node": ">=8" } }, - "node_modules/shikiji": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz", - "integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==", + "node_modules/shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dependencies": { - "hast-util-to-html": "^9.0.0" + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" } }, + "node_modules/shikiji": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.9.12.tgz", + "integrity": "sha512-jYbulSGcPKYKu2uFZOSg4lgrF7s9s8/ITFzRvczE6633wypMjnnTcRnG/mCFe6v1Dbov7bRCMsXVINBUD2FV9w==", + "peer": true, + "dependencies": { + "shikiji-core": "0.9.12" + } + }, + "node_modules/shikiji-core": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/shikiji-core/-/shikiji-core-0.9.12.tgz", + "integrity": "sha512-AYsAtsbZuq0FPT3mdskNMa+yxD5VwXrFC2sH7R2ELmncVGNYvSzR6Zlfq8iEzINq7/kKL5prtt81UFzFWTTbxQ==", + "peer": true + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -7812,6 +7894,16 @@ } } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", diff --git a/package.json b/package.json index 69f4c4f..809b418 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,11 @@ "@astrojs/sitemap": "^3.0.3", "@astrojs/tailwind": "^5.0.4", "astro": "^4.0.7", + "rehype-pretty-code": "^0.12.3", "remark-gfm": "^4.0.0", "remark-rehype": "^11.0.0", "sharp": "^0.33.1", + "shiki": "^0.14.7", "tailwindcss": "^3.4.0" }, "devDependencies": { diff --git a/public/themes/github_light.json b/public/themes/github_light.json new file mode 100644 index 0000000..1c3f962 --- /dev/null +++ b/public/themes/github_light.json @@ -0,0 +1,555 @@ +{ + "name": "Github Light Theme", + "type": "light", + "colors": { + "focusBorder": "#ffffff00", + "foreground": "#000000", + "editor.background": "#f6f6f6", + "editor.foreground": "#000000", + "scrollbar.shadow": "#ffffff", + "activityBar.border": "#ffffff", + "activityBar.background": "#ffffff", + "activityBar.foreground": "#000000", + "activityBarBadge.background": "#d73a49", + "statusBar.border": "#ffffff", + "statusBar.background": "#ffffff", + "statusBar.foreground": "#000000", + "statusBar.noFolderBackground": "#ffffff", + "statusBar.noFolderForeground": "#000000", + "statusBar.debuggingBackground": "#ffffff", + "statusBar.debuggingForeground": "#000000", + "editorGroup.border": "#ffffff", + "editorGroupHeader.tabsBackground": "#ffffff", + "editorGroupHeader.noTabsBackground": "#ffffff", + "editorGroupHeader.tabsBorder": "#ffffff", + "tab.activeBackground": "#ffffff", + "tab.inactiveBackground": "#ffffff", + "tab.border": "#ffffff", + "tab.activeBorder": "#d73a49", + "sideBar.border": "#ffffff", + "sideBar.background": "#ffffff", + "sideBar.foreground": "#000000", + "sideBarSectionHeader.background": "#ffffff", + "list.highlightForeground": "#d73a49", + "list.activeSelectionBackground": "#eeeeee", + "list.activeSelectionForeground": "#d73a49", + "list.inactiveSelectionBackground": "#eeeeee", + "list.inactiveSelectionForeground": "#d73a49", + "list.hoverBackground": "#eeeeee", + "list.hoverForeground": "#d73a49", + "list.focusBackground": "#eeeeee", + "list.focusForeground": "#d73a49", + "editor.lineHighlightBackground": "#fffbdf", + "editor.lineHighlightBorder": "#fffbdf", + "editorLineNumber.foreground": "#babbbc", + "editorLineNumber.activeForeground": "#000000", + "editor.selectionBackground": "#fed442", + "input.border": "#b2b2b2", + "input.background": "#ffffff", + "inputOption.activeBorder": "#000000", + "inputOption.activeForeground": "#000000", + "dropdown.border": "#b2b2b2", + "dropdown.background": "#ffffff", + "dropdown.listBackground": "#ffffff", + "notificationCenter.border": "#ffffff", + "notificationCenterHeader.background": "#ffffff", + "notificationToast.border": "#ffffff", + "notifications.background": "#ffffff", + "notifications.border": "#ffffff", + "button.background": "#d73a49", + "button.foreground": "#ffffff", + "titleBar.border": "#ffffff", + "titleBar.activeBackground": "#ffffff", + "titleBar.activeForeground": "#000000", + "titleBar.inactiveBackground": "#ffffff", + "titleBar.inactiveForeground": "#000000", + "editorWidget.background": "#eee", + "editorWidget.border": "#000000", + "editorSuggestWidget.highlightForeground": "#d73a49", + "editorSuggestWidget.selectedBackground": "#f0f0f0", + "panel.border": "#d73a49" + }, + "tokenColors": [ + { + "scope": [ + "comment", + "punctuation.definition.comment", + "string.comment" + ], + "settings": { + "foreground": "#6a737d" + }, + "name": "Comment" + }, + { + "scope": [ + "constant", + "entity.name.constant", + "variable.other.constant", + "variable.language" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "Constant" + }, + { + "scope": [ + "keyword.operator.symbole", + "keyword.other.mark" + ], + "name": "Clojure workaround; don't highlight these separately from their enclosing scope", + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "entity", + "entity.name" + ], + "settings": { + "foreground": "#6f42c1" + }, + "name": "Entity" + }, + { + "scope": [ + "variable.parameter.function" + ], + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "entity.name.tag" + ], + "settings": { + "foreground": "#22863a" + } + }, + { + "scope": [ + "keyword" + ], + "settings": { + "foreground": "#d73a49" + }, + "name": "Keyword" + }, + { + "scope": [ + "storage", + "storage.type" + ], + "settings": { + "foreground": "#d73a49" + }, + "name": "Storage" + }, + { + "scope": [ + "storage.modifier.package", + "storage.modifier.import", + "storage.type.java" + ], + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "string", + "punctuation.definition.string", + "string punctuation.section.embedded source" + ], + "settings": { + "foreground": "#032f62" + }, + "name": "String" + }, + { + "name": "Ada workaround; don't highlight imports as strings", + "scope": [ + "string.unquoted.import.ada" + ], + "settings": {} + }, + { + "scope": [ + "support" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "Support" + }, + { + "scope": [ + "meta.property-name" + ], + "settings": { + "foreground": "#005cc5" + } + }, + { + "scope": [ + "variable" + ], + "settings": { + "foreground": "#e36209" + }, + "name": "Variable" + }, + { + "scope": [ + "variable.other" + ], + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "invalid.broken" + ], + "settings": { + "fontStyle": "bold italic underline", + "foreground": "#b31d28" + }, + "name": "Invalid - Broken" + }, + { + "scope": [ + "invalid.deprecated" + ], + "settings": { + "fontStyle": "bold italic underline", + "foreground": "#b31d28" + }, + "name": "Invalid – Deprecated" + }, + { + "scope": [ + "invalid.illegal" + ], + "settings": { + "fontStyle": "italic underline", + "foreground": "#b31d28" + }, + "name": "Invalid – Illegal" + }, + { + "scope": [ + "carriage-return" + ], + "settings": { + "fontStyle": "italic underline", + "foreground": "#d73a49" + }, + "name": "Carriage Return" + }, + { + "scope": [ + "invalid.unimplemented" + ], + "settings": { + "fontStyle": "bold italic underline", + "foreground": "#b31d28" + }, + "name": "Invalid - Unimplemented" + }, + { + "scope": [ + "message.error" + ], + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": [ + "string source" + ], + "settings": { + "foreground": "#000000" + }, + "name": "String embedded-source" + }, + { + "scope": [ + "string variable" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "String variable" + }, + { + "scope": [ + "source.regexp", + "string.regexp" + ], + "settings": { + "foreground": "#032f62" + }, + "name": "String.regexp" + }, + { + "scope": [ + "string.regexp.character-class", + "string.regexp constant.character.escape", + "string.regexp source.ruby.embedded", + "string.regexp string.regexp.arbitrary-repitition" + ], + "settings": { + "foreground": "#032f62" + }, + "name": "String.regexp.special" + }, + { + "scope": [ + "string.regexp constant.character.escape" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#22863a" + }, + "name": "String.regexp constant.character.escape" + }, + { + "scope": [ + "support.constant" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "Support.constant" + }, + { + "scope": [ + "support.variable" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "Support.variable" + }, + { + "scope": [ + "meta.module-reference" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "meta module-reference" + }, + { + "scope": [ + "markup.list" + ], + "settings": { + "foreground": "#735c0f" + }, + "name": "Markup.list" + }, + { + "scope": [ + "markup.heading", + "markup.heading entity.name" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#005cc5" + }, + "name": "Markup.heading" + }, + { + "scope": [ + "markup.quote" + ], + "settings": { + "foreground": "#22863a" + }, + "name": "Markup.quote" + }, + { + "scope": [ + "markup.italic" + ], + "settings": { + "fontStyle": "italic", + "foreground": "#000000" + }, + "name": "Markup.italic" + }, + { + "scope": [ + "markup.bold" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#000000" + }, + "name": "Markup.bold" + }, + { + "scope": [ + "markup.raw" + ], + "settings": { + "foreground": "#005cc5" + }, + "name": "Markup.raw" + }, + { + "scope": [ + "markup.deleted", + "meta.diff.header.from-file", + "punctuation.definition.deleted" + ], + "settings": { + "foreground": "#b31d28" + }, + "name": "Markup.deleted" + }, + { + "scope": [ + "markup.inserted", + "meta.diff.header.to-file", + "punctuation.definition.inserted" + ], + "settings": { + "foreground": "#22863a" + }, + "name": "Markup.inserted" + }, + { + "scope": [ + "markup.changed", + "punctuation.definition.changed" + ], + "settings": { + "foreground": "#e36209" + } + }, + { + "scope": [ + "markup.ignored", + "markup.untracked" + ], + "settings": { + "foreground": "#005cc5" + } + }, + { + "scope": [ + "meta.diff.range" + ], + "settings": { + "foreground": "#6f42c1", + "fontStyle": "bold" + } + }, + { + "scope": [ + "meta.diff.header" + ], + "settings": { + "foreground": "#005cc5" + } + }, + { + "scope": [ + "meta.separator" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#005cc5" + }, + "name": "Meta.separator" + }, + { + "name": "Output", + "scope": [ + "meta.output" + ], + "settings": { + "foreground": "#005cc5" + } + }, + { + "scope": [ + "brackethighlighter.tag", + "brackethighlighter.curly", + "brackethighlighter.round", + "brackethighlighter.square", + "brackethighlighter.angle", + "brackethighlighter.quote" + ], + "settings": { + "foreground": "#586069" + } + }, + { + "scope": [ + "brackethighlighter.unmatched" + ], + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": [ + "sublimelinter.mark.error" + ], + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": [ + "sublimelinter.mark.warning" + ], + "settings": { + "foreground": "#e36209" + } + }, + { + "scope": [ + "sublimelinter.gutter-mark" + ], + "settings": { + "foreground": "#959da5" + } + }, + { + "scope": [ + "constant.other.reference.link", + "string.other.link" + ], + "settings": { + "foreground": "#032f62", + "fontStyle": "underline" + } + }, + { + "scope": [ + "meta.function-call support.function", + "meta.function-call entity.name.function" + ], + "settings": { + "foreground": "#005cc5" + } + }, + { + "scope": [ + "keyword.operator" + ], + "settings": { + "foreground": "#000000" + } + } + ] +}