diff --git a/src/app/(home)/page.tsx b/src/app/(home)/page.tsx
index 65bb548..6e01b76 100644
--- a/src/app/(home)/page.tsx
+++ b/src/app/(home)/page.tsx
@@ -1,8 +1,7 @@
"use client";
-import MorphText from "@/components/Morph";
-import { Card } from "fumadocs-ui/components/card";
-import { BookOpenIcon, NewspaperIcon, RocketIcon } from "lucide-react";
+import MorphCode from "@/components/Morph";
+import { NewspaperIcon, RocketIcon } from "lucide-react";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
@@ -152,11 +151,9 @@ export default function HomePage() {
return (
diff --git a/src/components/Morph.tsx b/src/components/Morph.tsx
index 95e7f1f..788ba5d 100644
--- a/src/components/Morph.tsx
+++ b/src/components/Morph.tsx
@@ -1,60 +1,70 @@
-import { motion, AnimatePresence } from "framer-motion";
+"use client";
-interface MorphTextProps {
- text: string;
+import { BundledLanguage, codeToTokens } from "shiki";
+import { motion, AnimatePresence } from "framer-motion";
+import { useEffect, useState } from "react";
+
+interface Props {
+ code: string;
+ lang?: BundledLanguage;
}
-const tokenize = (str: string) => {
- const counts: Record
= {};
- return str.split("").map((char) => {
- const displayChar = char === " " ? "\u00A0" : char;
- counts[char] = (counts[char] || 0) + 1;
- return { char: displayChar, id: `${char}-${counts[char]}` };
- });
-};
+export default function MorphCode({ code, lang = "rust" }: Props) {
+ const [lines, setLines] = useState([]);
-export default function MorphText({ text }: MorphTextProps) {
- const lines = text.split("\n"); // 👈 split by newline
+ useEffect(() => {
+ async function run() {
+ const result = await codeToTokens(code, {
+ lang,
+ theme: "github-dark",
+ });
+
+ const rawLines = code.split("\n");
+
+ const fixed = rawLines.map((_, i) => {
+ return (
+ result.tokens[i] ?? [
+ {
+ content: "\n",
+ color: undefined,
+ },
+ ]
+ );
+ });
+
+ setLines(fixed);
+ }
+
+ run();
+ }, [code, lang]);
return (
-
-
- {lines.map((line, lineIndex) => {
- const tokens = tokenize(line);
-
- // 👇 empty line = real vertical space
- if (line === "") {
- return (
-
- );
- }
-
- return (
-
- {tokens.map(({ char, id }) => (
+
+
+
+ {lines.map((line, lineIndex) => (
+
+ {line.map((token, tokenIndex) => (
- {char}
+ {token.content}
))}
- );
- })}
-
-
+ ))}
+
+
+
);
}