mirror of
https://git.aramjonghu.dev/AramJonghu/aramjonghu-site.git
synced 2026-09-12 09:23:30 +02:00
feat(codeblocks): codeblocks now have proper theming with highlighting
This commit is contained in:
@@ -18,6 +18,8 @@
|
|||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"rehype-sanitize": "^6.0.0",
|
"rehype-sanitize": "^6.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
|
"shiki": "^4.3.1",
|
||||||
|
"@shikijs/rehype": "^4.3.1",
|
||||||
"tailwindcss": "^4.2.2"
|
"tailwindcss": "^4.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -58,3 +58,15 @@
|
|||||||
.stream-frame iframe {
|
.stream-frame iframe {
|
||||||
@apply w-full h-full border-0;
|
@apply w-full h-full border-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shiki,
|
||||||
|
.shiki .line span {
|
||||||
|
color: var(--shiki-light);
|
||||||
|
background-color: var(--shiki-light-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.macchiato .shiki,
|
||||||
|
.macchiato .shiki .line span {
|
||||||
|
color: var(--shiki-dark);
|
||||||
|
background-color: var(--shiki-dark-bg);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import ReactMarkdown from "react-markdown";
|
|||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import rehypeRaw from "rehype-raw";
|
import rehypeRaw from "rehype-raw";
|
||||||
import rehypeSanitize from "rehype-sanitize";
|
import rehypeSanitize from "rehype-sanitize";
|
||||||
|
import highlighter from "../utils/highlighter";
|
||||||
|
|
||||||
const toRawUrl = (repoUrl: string): string => {
|
const toRawUrl = (repoUrl: string): string => {
|
||||||
if (!repoUrl) return repoUrl;
|
if (!repoUrl) return repoUrl;
|
||||||
@@ -136,10 +137,7 @@ export default function MdProcessor({
|
|||||||
|
|
||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
return (
|
return (
|
||||||
<code
|
<code className="text-sm" {...props}>
|
||||||
className={`${className || ""} text-sm block overflow-x-auto`}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</code>
|
</code>
|
||||||
);
|
);
|
||||||
@@ -157,13 +155,67 @@ export default function MdProcessor({
|
|||||||
|
|
||||||
pre({
|
pre({
|
||||||
children,
|
children,
|
||||||
...props
|
|
||||||
}: ComponentPropsWithoutRef<"pre">): ReactElement {
|
}: ComponentPropsWithoutRef<"pre">): ReactElement {
|
||||||
|
const codeChild = Array.isArray(children)
|
||||||
|
? children[0]
|
||||||
|
: children;
|
||||||
|
|
||||||
|
let lang = "";
|
||||||
|
let code = "";
|
||||||
|
|
||||||
|
if (
|
||||||
|
codeChild &&
|
||||||
|
typeof codeChild === "object" &&
|
||||||
|
"props" in codeChild
|
||||||
|
) {
|
||||||
|
const el = codeChild as {
|
||||||
|
props: {
|
||||||
|
className?: string;
|
||||||
|
children?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const cls = el.props?.className;
|
||||||
|
const match = cls?.match(/language-(\w+)/);
|
||||||
|
if (match) lang = match[1];
|
||||||
|
if (
|
||||||
|
typeof el.props?.children === "string"
|
||||||
|
) {
|
||||||
|
code = el.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlighted =
|
||||||
|
lang && code
|
||||||
|
? highlighter.codeToHtml(code, {
|
||||||
|
lang,
|
||||||
|
themes: {
|
||||||
|
dark: "catppuccin-macchiato",
|
||||||
|
light: "catppuccin-latte",
|
||||||
|
},
|
||||||
|
defaultColor: false,
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (highlighted) {
|
||||||
|
return (
|
||||||
|
<div className="relative border-2 border-ctp-text/50 rounded-md overflow-hidden my-6 bg-ctp-base">
|
||||||
|
{lang && (
|
||||||
|
<span className="absolute top-0 left-0 px-2 py-1 text-xs font-mono text-ctp-mauve">
|
||||||
|
{lang}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={`overflow-x-auto text-sm p-4 ${lang ? "pt-7" : ""}`}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: highlighted,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<pre
|
<pre className="overflow-x-auto text-sm p-4 bg-ctp-mantle m-0 border-2 border-ctp-lavender/60 rounded-md my-6">
|
||||||
className="bg-ctp-mantle p-4 rounded-lg overflow-x-auto text-sm my-4"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</pre>
|
</pre>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { createHighlighter } from "shiki";
|
||||||
|
|
||||||
|
export default await createHighlighter({
|
||||||
|
themes: ["catppuccin-macchiato", "catppuccin-latte"],
|
||||||
|
langs: [
|
||||||
|
"javascript",
|
||||||
|
"typescript",
|
||||||
|
"jsx",
|
||||||
|
"tsx",
|
||||||
|
"css",
|
||||||
|
"html",
|
||||||
|
"json",
|
||||||
|
"bash",
|
||||||
|
"shellscript",
|
||||||
|
"python",
|
||||||
|
"markdown",
|
||||||
|
"yaml",
|
||||||
|
"toml",
|
||||||
|
"rust",
|
||||||
|
"sql",
|
||||||
|
"diff",
|
||||||
|
"docker",
|
||||||
|
"graphql",
|
||||||
|
"go",
|
||||||
|
"java",
|
||||||
|
"kotlin",
|
||||||
|
"swift",
|
||||||
|
"c",
|
||||||
|
"cpp",
|
||||||
|
"odin",
|
||||||
|
"csharp",
|
||||||
|
"php",
|
||||||
|
"ruby",
|
||||||
|
"perl",
|
||||||
|
"lua",
|
||||||
|
"haskell",
|
||||||
|
"scala",
|
||||||
|
"elixir",
|
||||||
|
"erlang",
|
||||||
|
"r",
|
||||||
|
"matlab",
|
||||||
|
"sass",
|
||||||
|
"scss",
|
||||||
|
"less",
|
||||||
|
"vue",
|
||||||
|
"svelte",
|
||||||
|
"astro",
|
||||||
|
"solidity",
|
||||||
|
"nix",
|
||||||
|
"zig",
|
||||||
|
"ocaml",
|
||||||
|
"coq",
|
||||||
|
"lean",
|
||||||
|
"purescript",
|
||||||
|
"racket",
|
||||||
|
"scheme",
|
||||||
|
"clojure",
|
||||||
|
"common-lisp",
|
||||||
|
"makefile",
|
||||||
|
"cmake",
|
||||||
|
"powershell",
|
||||||
|
"proto",
|
||||||
|
"prisma",
|
||||||
|
"terraform",
|
||||||
|
"hcl",
|
||||||
|
"nginx",
|
||||||
|
"apache",
|
||||||
|
"latex",
|
||||||
|
"tex",
|
||||||
|
],
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user