|
|
@@ -4,8 +4,8 @@ import { useEffect, useState } from "react";
|
|
|
import { createHighlighter, type Highlighter } from "shiki";
|
|
|
import { CopyButton } from "./copy-button";
|
|
|
|
|
|
-const vercelTheme = {
|
|
|
- name: "vercel",
|
|
|
+const vercelDarkTheme = {
|
|
|
+ name: "vercel-dark",
|
|
|
type: "dark" as const,
|
|
|
colors: {
|
|
|
"editor.background": "transparent",
|
|
|
@@ -63,13 +63,72 @@ const vercelTheme = {
|
|
|
],
|
|
|
};
|
|
|
|
|
|
+const vercelLightTheme = {
|
|
|
+ name: "vercel-light",
|
|
|
+ type: "light" as const,
|
|
|
+ colors: {
|
|
|
+ "editor.background": "transparent",
|
|
|
+ "editor.foreground": "#171717",
|
|
|
+ },
|
|
|
+ settings: [
|
|
|
+ {
|
|
|
+ scope: ["comment", "punctuation.definition.comment"],
|
|
|
+ settings: { foreground: "#6b7280" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["string", "string.quoted", "string.template"],
|
|
|
+ settings: { foreground: "#067a6e" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["constant.numeric", "constant.language.boolean", "constant.language.null"],
|
|
|
+ settings: { foreground: "#067a6e" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["keyword", "storage.type", "storage.modifier"],
|
|
|
+ settings: { foreground: "#d6409f" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["keyword.operator", "keyword.control"],
|
|
|
+ settings: { foreground: "#d6409f" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["entity.name.function", "support.function", "meta.function-call"],
|
|
|
+ settings: { foreground: "#6e56cf" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["variable", "variable.other", "variable.parameter"],
|
|
|
+ settings: { foreground: "#171717" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["entity.name.tag", "support.class.component", "entity.name.type"],
|
|
|
+ settings: { foreground: "#d6409f" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["punctuation", "meta.brace", "meta.bracket"],
|
|
|
+ settings: { foreground: "#6b7280" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["support.type.property-name", "entity.name.tag.json", "meta.object-literal.key"],
|
|
|
+ settings: { foreground: "#171717" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["entity.other.attribute-name"],
|
|
|
+ settings: { foreground: "#067a6e" },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ scope: ["support.type.primitive", "entity.name.type.primitive"],
|
|
|
+ settings: { foreground: "#067a6e" },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+};
|
|
|
+
|
|
|
// Preload highlighter on module load
|
|
|
let highlighterPromise: Promise<Highlighter> | null = null;
|
|
|
|
|
|
function getHighlighter() {
|
|
|
if (!highlighterPromise) {
|
|
|
highlighterPromise = createHighlighter({
|
|
|
- themes: [vercelTheme],
|
|
|
+ themes: [vercelLightTheme, vercelDarkTheme],
|
|
|
langs: ["json", "tsx", "typescript"],
|
|
|
});
|
|
|
}
|
|
|
@@ -91,7 +150,14 @@ export function CodeBlock({ code, lang }: CodeBlockProps) {
|
|
|
|
|
|
useEffect(() => {
|
|
|
getHighlighter().then((highlighter) => {
|
|
|
- setHtml(highlighter.codeToHtml(code, { lang, theme: "vercel" }));
|
|
|
+ setHtml(highlighter.codeToHtml(code, {
|
|
|
+ lang,
|
|
|
+ themes: {
|
|
|
+ light: "vercel-light",
|
|
|
+ dark: "vercel-dark",
|
|
|
+ },
|
|
|
+ defaultColor: false,
|
|
|
+ }));
|
|
|
});
|
|
|
}, [code, lang]);
|
|
|
|
|
|
@@ -104,7 +170,7 @@ export function CodeBlock({ code, lang }: CodeBlockProps) {
|
|
|
<div className="sticky top-0 float-right z-10">
|
|
|
<CopyButton
|
|
|
text={code}
|
|
|
- className="opacity-0 group-hover:opacity-100 text-muted-foreground bg-card"
|
|
|
+ className="opacity-0 group-hover:opacity-100 text-neutral-400"
|
|
|
/>
|
|
|
</div>
|
|
|
<div
|