Chris Tate пре 5 месеци
родитељ
комит
ea62ae126f
3 измењених фајлова са 27 додато и 15 уклоњено
  1. 23 10
      apps/web/components/code-block.tsx
  2. 2 4
      apps/web/components/demo.tsx
  3. 2 1
      package.json

+ 23 - 10
apps/web/components/code-block.tsx

@@ -1,7 +1,7 @@
 "use client";
 
 import { useEffect, useState } from "react";
-import { codeToHtml } from "shiki";
+import { createHighlighter, type Highlighter } from "shiki";
 
 const vercelTheme = {
   name: "vercel",
@@ -62,6 +62,24 @@ const vercelTheme = {
   ],
 };
 
+// Preload highlighter on module load
+let highlighterPromise: Promise<Highlighter> | null = null;
+
+function getHighlighter() {
+  if (!highlighterPromise) {
+    highlighterPromise = createHighlighter({
+      themes: [vercelTheme],
+      langs: ["json", "tsx", "typescript"],
+    });
+  }
+  return highlighterPromise;
+}
+
+// Start loading immediately when module is imported
+if (typeof window !== "undefined") {
+  getHighlighter();
+}
+
 interface CodeBlockProps {
   code: string;
   lang: "json" | "tsx" | "typescript";
@@ -71,18 +89,13 @@ export function CodeBlock({ code, lang }: CodeBlockProps) {
   const [html, setHtml] = useState<string>("");
 
   useEffect(() => {
-    codeToHtml(code, {
-      lang,
-      theme: vercelTheme,
-    }).then(setHtml);
+    getHighlighter().then((highlighter) => {
+      setHtml(highlighter.codeToHtml(code, { lang, theme: "vercel" }));
+    });
   }, [code, lang]);
 
   if (!html) {
-    return (
-      <pre className="text-muted-foreground">
-        <code>{code}</code>
-      </pre>
-    );
+    return null;
   }
 
   return (

+ 2 - 4
apps/web/components/demo.tsx

@@ -65,7 +65,7 @@ export function Demo() {
   const [typedPrompt, setTypedPrompt] = useState("");
   const [stageIndex, setStageIndex] = useState(-1);
   const [streamLines, setStreamLines] = useState<string[]>([]);
-  const [activeTab, setActiveTab] = useState<Tab>("stream");
+  const [activeTab, setActiveTab] = useState<Tab>("json");
   const [actionFired, setActionFired] = useState(false);
 
   const currentStage = stageIndex >= 0 ? STAGES[stageIndex] : null;
@@ -75,7 +75,6 @@ export function Demo() {
     setTypedPrompt("");
     setStageIndex(-1);
     setStreamLines([]);
-    setActiveTab("stream");
     setActionFired(false);
   }, []);
 
@@ -115,7 +114,6 @@ export function Demo() {
         clearInterval(interval);
         setTimeout(() => {
           setPhase("complete");
-          setActiveTab("json");
         }, 500);
       }
     }, 600);
@@ -226,7 +224,7 @@ export function Demo() {
         {/* Tabbed code/stream/json panel */}
         <div>
           <div className="flex gap-4 mb-2">
-            {(["stream", "json", "code"] as const).map((tab) => (
+            {(["json", "stream", "code"] as const).map((tab) => (
               <button
                 key={tab}
                 onClick={() => setActiveTab(tab)}

+ 2 - 1
package.json

@@ -5,7 +5,8 @@
     "build": "turbo run build",
     "dev": "turbo run dev --concurrency 15",
     "lint": "turbo run lint",
-    "format": "prettier --write \"**/*.{ts,tsx,md}\"",
+    "format": "prettier --write \"**/*.{ts,tsx}\"",
+    "type-check": "turbo run check-types",
     "check-types": "turbo run check-types"
   },
   "devDependencies": {