chore: syntax highlighting optimizations
1e573bc0
8 file(s) · +91 −76
| 1 | 1 | import { defineConfig } from "astro/config"; |
|
| 2 | 2 | import rehypeExternalLinks from "rehype-external-links"; |
|
| 3 | + | import rehypeShikiFromHighlighter from "@shikijs/rehype/core"; |
|
| 3 | 4 | import cloudflare from "@astrojs/cloudflare"; |
|
| 4 | 5 | import mdx from "@astrojs/mdx"; |
|
| 5 | 6 | import tailwindcss from "@tailwindcss/vite"; |
|
| 6 | 7 | import sitemap from "@astrojs/sitemap"; |
|
| 7 | 8 | import { fileURLToPath } from "url"; |
|
| 8 | 9 | import path from "path"; |
|
| 9 | - | import darkmatter from "./darkmatter.json"; |
|
| 10 | + | import { createDarkmatterHighlighter, THEME_NAME } from "./shiki-setup.mjs"; |
|
| 11 | + | ||
| 12 | + | const highlighter = createDarkmatterHighlighter(); |
|
| 13 | + | ||
| 14 | + | const root = path.dirname(fileURLToPath(import.meta.url)); |
|
| 15 | + | const emptyShikiTheme = path.resolve(root, "./empty-shiki-theme.mjs"); |
|
| 10 | 16 | ||
| 11 | 17 | // https://astro.build/config |
|
| 12 | 18 | export default defineConfig({ |
|
| 14 | 20 | outDir: "dist", |
|
| 15 | 21 | compressHTML: true, |
|
| 16 | 22 | markdown: { |
|
| 17 | - | shikiConfig: { |
|
| 18 | - | theme: darkmatter, |
|
| 19 | - | wrap: false, |
|
| 20 | - | }, |
|
| 23 | + | syntaxHighlight: false, |
|
| 21 | 24 | rehypePlugins: [ |
|
| 25 | + | [(opts) => rehypeShikiFromHighlighter(highlighter, opts), { theme: THEME_NAME, defaultLanguage: "text", fallbackLanguage: "text", addLanguageClass: true }], |
|
| 22 | 26 | [rehypeExternalLinks, { target: "_blank", rel: ["noopener", "noreferrer"] }], |
|
| 23 | 27 | ], |
|
| 24 | 28 | }, |
|
| 27 | 31 | vite: { |
|
| 28 | 32 | plugins: [tailwindcss()], |
|
| 29 | 33 | resolve: { |
|
| 30 | - | alias: { |
|
| 31 | - | "@/components": path.resolve( |
|
| 32 | - | path.dirname(fileURLToPath(import.meta.url)), |
|
| 33 | - | "./src/components", |
|
| 34 | - | ), |
|
| 35 | - | "@/layouts": path.resolve( |
|
| 36 | - | path.dirname(fileURLToPath(import.meta.url)), |
|
| 37 | - | "./src/layouts", |
|
| 38 | - | ), |
|
| 39 | - | "@/utils": path.resolve( |
|
| 40 | - | path.dirname(fileURLToPath(import.meta.url)), |
|
| 41 | - | "./src/utils/index.ts", |
|
| 42 | - | ), |
|
| 43 | - | "@/stores": path.resolve( |
|
| 44 | - | path.dirname(fileURLToPath(import.meta.url)), |
|
| 45 | - | "./src/stores", |
|
| 46 | - | ), |
|
| 47 | - | "@/data": path.resolve( |
|
| 48 | - | path.dirname(fileURLToPath(import.meta.url)), |
|
| 49 | - | "./src/data", |
|
| 50 | - | ), |
|
| 51 | - | }, |
|
| 34 | + | alias: [ |
|
| 35 | + | { find: /^@shikijs\/themes\/[^/]+$/, replacement: emptyShikiTheme }, |
|
| 36 | + | { find: /^@shikijs\/themes\/dist\/.+\.mjs$/, replacement: emptyShikiTheme }, |
|
| 37 | + | { find: "@/components", replacement: path.resolve(root, "./src/components") }, |
|
| 38 | + | { find: "@/layouts", replacement: path.resolve(root, "./src/layouts") }, |
|
| 39 | + | { find: "@/utils", replacement: path.resolve(root, "./src/utils/index.ts") }, |
|
| 40 | + | { find: "@/stores", replacement: path.resolve(root, "./src/stores") }, |
|
| 41 | + | { find: "@/data", replacement: path.resolve(root, "./src/data") }, |
|
| 42 | + | ], |
|
| 52 | 43 | extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".astro"], |
|
| 53 | 44 | }, |
|
| 54 | 45 | ssr: { |
|
| 9 | 9 | "@astrojs/rss": "4.0.14", |
|
| 10 | 10 | "@astrojs/ts-plugin": "1.10.6", |
|
| 11 | 11 | "astro": "5.16.7", |
|
| 12 | - | "markdown-it": "^14.1.0", |
|
| 12 | + | "markdown-it": "^14.1.1", |
|
| 13 | 13 | "rehype-external-links": "^3.0.0", |
|
| 14 | - | "sanitize-html": "^2.17.0", |
|
| 15 | - | "sharp": "^0.33.1", |
|
| 14 | + | "sanitize-html": "^2.17.3", |
|
| 15 | + | "sharp": "^0.33.5", |
|
| 16 | 16 | "shiki": "^4.0.2", |
|
| 17 | 17 | }, |
|
| 18 | 18 | "devDependencies": { |
|
| 19 | 19 | "@astrojs/mdx": "4.3.13", |
|
| 20 | 20 | "@astrojs/sitemap": "3.6.1", |
|
| 21 | 21 | "@biomejs/biome": "2.1.1", |
|
| 22 | - | "@tailwindcss/typography": "^0.5.15", |
|
| 23 | - | "@tailwindcss/vite": "^4.1.7", |
|
| 24 | - | "@types/bun": "^1.3.6", |
|
| 22 | + | "@shikijs/rehype": "^4.0.2", |
|
| 23 | + | "@tailwindcss/typography": "^0.5.19", |
|
| 24 | + | "@tailwindcss/vite": "^4.2.4", |
|
| 25 | + | "@types/bun": "^1.3.13", |
|
| 25 | 26 | "@types/markdown-it": "^14.1.2", |
|
| 26 | - | "@types/sanitize-html": "^2.16.0", |
|
| 27 | - | "tailwindcss": "^4.1.7", |
|
| 28 | - | "typescript": "^5.6.2", |
|
| 29 | - | "wrangler": "^4.58.0", |
|
| 27 | + | "@types/sanitize-html": "^2.16.1", |
|
| 28 | + | "tailwindcss": "^4.2.4", |
|
| 29 | + | "typescript": "^5.9.3", |
|
| 30 | + | "wrangler": "^4.87.0", |
|
| 30 | 31 | }, |
|
| 31 | 32 | }, |
|
| 32 | 33 | }, |
|
| 288 | 289 | "@shikijs/langs": ["@shikijs/langs@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2" } }, "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg=="], |
|
| 289 | 290 | ||
| 290 | 291 | "@shikijs/primitive": ["@shikijs/primitive@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw=="], |
|
| 292 | + | ||
| 293 | + | "@shikijs/rehype": ["@shikijs/rehype@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@types/hast": "^3.0.4", "hast-util-to-string": "^3.0.1", "shiki": "4.0.2", "unified": "^11.0.5", "unist-util-visit": "^5.1.0" } }, "sha512-cmPlKLD8JeojasNFoY64162ScpEdEdQUMuVodPCrv1nx1z3bjmGwoKWDruQWa/ejSznImlaeB0Ty6Q3zPaVQAA=="], |
|
| 291 | 294 | ||
| 292 | 295 | "@shikijs/themes": ["@shikijs/themes@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2" } }, "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA=="], |
|
| 293 | 296 | ||
| 578 | 581 | "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="], |
|
| 579 | 582 | ||
| 580 | 583 | "hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="], |
|
| 584 | + | ||
| 585 | + | "hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="], |
|
| 581 | 586 | ||
| 582 | 587 | "hast-util-to-text": ["hast-util-to-text@4.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "hast-util-is-element": "^3.0.0", "unist-util-find-after": "^5.0.0" } }, "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A=="], |
|
| 583 | 588 | ||
| 1 | + | export default {}; |
| 16 | 16 | "@astrojs/mdx": "4.3.13", |
|
| 17 | 17 | "@astrojs/sitemap": "3.6.1", |
|
| 18 | 18 | "@biomejs/biome": "2.1.1", |
|
| 19 | + | "@shikijs/rehype": "^4.0.2", |
|
| 19 | 20 | "@tailwindcss/typography": "^0.5.19", |
|
| 20 | 21 | "@tailwindcss/vite": "^4.2.4", |
|
| 21 | 22 | "@types/bun": "^1.3.13", |
| 1 | + | import { createHighlighterCoreSync } from "shiki/core"; |
|
| 2 | + | import { createJavaScriptRegexEngine } from "shiki/engine/javascript"; |
|
| 3 | + | import javascript from "@shikijs/langs/javascript"; |
|
| 4 | + | import typescript from "@shikijs/langs/typescript"; |
|
| 5 | + | import jsx from "@shikijs/langs/jsx"; |
|
| 6 | + | import tsx from "@shikijs/langs/tsx"; |
|
| 7 | + | import python from "@shikijs/langs/python"; |
|
| 8 | + | import bash from "@shikijs/langs/bash"; |
|
| 9 | + | import shellscript from "@shikijs/langs/shellscript"; |
|
| 10 | + | import json from "@shikijs/langs/json"; |
|
| 11 | + | import html from "@shikijs/langs/html"; |
|
| 12 | + | import css from "@shikijs/langs/css"; |
|
| 13 | + | import rust from "@shikijs/langs/rust"; |
|
| 14 | + | import go from "@shikijs/langs/go"; |
|
| 15 | + | import markdown from "@shikijs/langs/markdown"; |
|
| 16 | + | import yaml from "@shikijs/langs/yaml"; |
|
| 17 | + | import toml from "@shikijs/langs/toml"; |
|
| 18 | + | import lua from "@shikijs/langs/lua"; |
|
| 19 | + | import darkmatter from "./darkmatter.json" with { type: "json" }; |
|
| 20 | + | ||
| 21 | + | export const LANGS = [ |
|
| 22 | + | javascript, |
|
| 23 | + | typescript, |
|
| 24 | + | jsx, |
|
| 25 | + | tsx, |
|
| 26 | + | python, |
|
| 27 | + | bash, |
|
| 28 | + | shellscript, |
|
| 29 | + | json, |
|
| 30 | + | html, |
|
| 31 | + | css, |
|
| 32 | + | rust, |
|
| 33 | + | go, |
|
| 34 | + | markdown, |
|
| 35 | + | yaml, |
|
| 36 | + | toml, |
|
| 37 | + | lua, |
|
| 38 | + | ]; |
|
| 39 | + | ||
| 40 | + | export const THEME = darkmatter; |
|
| 41 | + | export const THEME_NAME = "Darkmatter"; |
|
| 42 | + | ||
| 43 | + | export function createDarkmatterHighlighter() { |
|
| 44 | + | return createHighlighterCoreSync({ |
|
| 45 | + | themes: [darkmatter], |
|
| 46 | + | langs: LANGS, |
|
| 47 | + | engine: createJavaScriptRegexEngine(), |
|
| 48 | + | }); |
|
| 49 | + | } |
| 1 | 1 | --- |
|
| 2 | 2 | import PageLayout from "@/layouts/Base.astro"; |
|
| 3 | - | import { createHighlighterCore, type ThemeRegistrationRaw } from "shiki/core"; |
|
| 4 | - | import { createJavaScriptRegexEngine } from "shiki/engine/javascript"; |
|
| 5 | - | import bash from "@shikijs/langs/bash"; |
|
| 6 | - | import darkmatter from "../../darkmatter.json"; |
|
| 3 | + | import { createDarkmatterHighlighter, THEME_NAME } from "../../shiki-setup.mjs"; |
|
| 7 | 4 | ||
| 8 | 5 | const meta = { |
|
| 9 | 6 | title: "Git", |
|
| 10 | 7 | description: "Access the open source repos I'm working on", |
|
| 11 | 8 | }; |
|
| 12 | 9 | ||
| 13 | - | const highlighter = await createHighlighterCore({ |
|
| 14 | - | themes: [darkmatter as unknown as ThemeRegistrationRaw], |
|
| 15 | - | langs: [bash], |
|
| 16 | - | engine: createJavaScriptRegexEngine(), |
|
| 17 | - | }); |
|
| 10 | + | const highlighter = createDarkmatterHighlighter(); |
|
| 18 | 11 | ||
| 19 | 12 | const codeHtml = highlighter.codeToHtml("ssh git.stevedylan.dev", { |
|
| 20 | 13 | lang: "bash", |
|
| 21 | - | theme: "Darkmatter", |
|
| 14 | + | theme: THEME_NAME, |
|
| 22 | 15 | }); |
|
| 23 | 16 | --- |
|
| 24 | 17 |
| 132 | 132 | .prose :where(strong):not(:where([class~="not-prose"], [class~="not-prose"] *)) { |
|
| 133 | 133 | font-weight: 700; |
|
| 134 | 134 | } |
|
| 135 | - | .prose :where(code):not(:where([class~="not-prose"], [class~="not-prose"] *)) { |
|
| 135 | + | .prose :where(code):not(:where(pre code, [class~="not-prose"], [class~="not-prose"] *)) { |
|
| 136 | 136 | border: 1px dotted #666; |
|
| 137 | 137 | border-radius: 2px; |
|
| 138 | 138 | } |
| 1 | 1 | import MarkdownIt from "markdown-it"; |
|
| 2 | - | import { createHighlighterCore, type ThemeRegistrationRaw } from "shiki/core"; |
|
| 3 | - | import { createJavaScriptRegexEngine } from "shiki/engine/javascript"; |
|
| 4 | - | import darkmatter from "../../darkmatter.json"; |
|
| 5 | - | ||
| 6 | - | const LANGS = [ |
|
| 7 | - | import("@shikijs/langs/javascript"), |
|
| 8 | - | import("@shikijs/langs/typescript"), |
|
| 9 | - | import("@shikijs/langs/jsx"), |
|
| 10 | - | import("@shikijs/langs/tsx"), |
|
| 11 | - | import("@shikijs/langs/python"), |
|
| 12 | - | import("@shikijs/langs/bash"), |
|
| 13 | - | import("@shikijs/langs/shellscript"), |
|
| 14 | - | import("@shikijs/langs/json"), |
|
| 15 | - | import("@shikijs/langs/html"), |
|
| 16 | - | import("@shikijs/langs/css"), |
|
| 17 | - | import("@shikijs/langs/rust"), |
|
| 18 | - | import("@shikijs/langs/go"), |
|
| 19 | - | import("@shikijs/langs/markdown"), |
|
| 20 | - | import("@shikijs/langs/yaml"), |
|
| 21 | - | import("@shikijs/langs/toml"), |
|
| 22 | - | import("@shikijs/langs/lua"), |
|
| 23 | - | ]; |
|
| 2 | + | import { createDarkmatterHighlighter, THEME_NAME } from "../../shiki-setup.mjs"; |
|
| 24 | 3 | ||
| 25 | 4 | export async function createMarkdownRenderer(): Promise<MarkdownIt> { |
|
| 26 | - | const highlighter = await createHighlighterCore({ |
|
| 27 | - | themes: [darkmatter as unknown as ThemeRegistrationRaw], |
|
| 28 | - | langs: LANGS, |
|
| 29 | - | engine: createJavaScriptRegexEngine(), |
|
| 30 | - | }); |
|
| 5 | + | const highlighter = createDarkmatterHighlighter(); |
|
| 31 | 6 | ||
| 32 | 7 | let md: MarkdownIt; |
|
| 33 | 8 | ||
| 42 | 17 | try { |
|
| 43 | 18 | return highlighter.codeToHtml(code, { |
|
| 44 | 19 | lang: resolvedLang, |
|
| 45 | - | theme: "Darkmatter", |
|
| 20 | + | theme: THEME_NAME, |
|
| 46 | 21 | }); |
|
| 47 | 22 | } catch { |
|
| 48 | 23 | return `<pre><code>${md.utils.escapeHtml(code)}</code></pre>`; |
|