diff --git a/surfsense_backend/app/tasks/background_tasks.py b/surfsense_backend/app/tasks/background_tasks.py
index 1d278f7..2e5e361 100644
--- a/surfsense_backend/app/tasks/background_tasks.py
+++ b/surfsense_backend/app/tasks/background_tasks.py
@@ -419,7 +419,7 @@ async def add_youtube_video_document(
content=chunk.text,
embedding=config.embedding_model_instance.embed(chunk.text),
)
- for chunk in config.chunker_instance.chunk(transcript_text)
+ for chunk in config.chunker_instance.chunk(combined_document_string)
]
# Create document
diff --git a/surfsense_web/app/dashboard/[search_space_id]/researcher/[chat_id]/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/researcher/[chat_id]/page.tsx
index 78239e2..80f98c8 100644
--- a/surfsense_web/app/dashboard/[search_space_id]/researcher/[chat_id]/page.tsx
+++ b/surfsense_web/app/dashboard/[search_space_id]/researcher/[chat_id]/page.tsx
@@ -48,7 +48,6 @@ import {
researcherOptions
} from '@/components/chat';
import { MarkdownViewer } from '@/components/markdown-viewer';
-import { connectorSourcesMenu as defaultConnectorSourcesMenu } from '@/components/chat/connector-sources';
import { Logo } from '@/components/Logo';
import { useSearchSourceConnectors } from '@/hooks';
diff --git a/surfsense_web/app/globals.css b/surfsense_web/app/globals.css
index 98e4411..5dbd332 100644
--- a/surfsense_web/app/globals.css
+++ b/surfsense_web/app/globals.css
@@ -45,6 +45,7 @@
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
+ --syntax-bg: #f5f5f5;
}
.dark {
@@ -80,6 +81,7 @@
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
+ --syntax-bg: #1e1e1e;
}
@theme inline {
diff --git a/surfsense_web/components/markdown-viewer.tsx b/surfsense_web/components/markdown-viewer.tsx
index 1df6501..f4bebf9 100644
--- a/surfsense_web/components/markdown-viewer.tsx
+++ b/surfsense_web/components/markdown-viewer.tsx
@@ -1,4 +1,4 @@
-import React, { useMemo } from "react";
+import React, { useMemo, useState, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
@@ -6,6 +6,10 @@ import remarkGfm from "remark-gfm";
import { cn } from "@/lib/utils";
import { Citation } from "./chat/Citation";
import { Source } from "./chat/types";
+import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
+import { oneLight, oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
+import { Check, Copy } from "lucide-react";
+import { useTheme } from "next-themes";
interface MarkdownViewerProps {
content: string;
@@ -75,16 +79,19 @@ export function MarkdownViewer({ content, className, getCitationSource }: Markdo
td: ({node, ...props}: any) =>
| ,
code: ({node, className, children, ...props}: any) => {
const match = /language-(\w+)/.exec(className || '');
+ const language = match ? match[1] : '';
const isInline = !match;
- return isInline
- ? {children}
- : (
-
- );
+
+ if (isInline) {
+ return {children}
;
+ }
+
+ // For code blocks, add syntax highlighting and copy functionality
+ return (
+
+ {String(children).replace(/\n$/, '')}
+
+ );
}
};
}, [getCitationSource]);
@@ -102,6 +109,102 @@ export function MarkdownViewer({ content, className, getCitationSource }: Markdo
);
}
+// Code block component with syntax highlighting and copy functionality
+const CodeBlock = ({ children, language }: { children: string, language: string }) => {
+ const [copied, setCopied] = useState(false);
+ const { resolvedTheme, theme } = useTheme();
+ const [mounted, setMounted] = useState(false);
+
+ // Prevent hydration issues
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ const handleCopy = async () => {
+ await navigator.clipboard.writeText(children);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ };
+
+ // Choose theme based on current system/user preference
+ const isDarkTheme = mounted && (resolvedTheme === 'dark' || theme === 'dark');
+ const syntaxTheme = isDarkTheme ? oneDark : oneLight;
+
+ return (
+
+
+
+
+ {mounted ? (
+
+ {children}
+
+ ) : (
+
+ )}
+
+ );
+};
+
// Helper function to process citations within React children
const processCitationsInReactChildren = (children: React.ReactNode, getCitationSource: (id: number) => Source | null): React.ReactNode => {
// If children is not an array or string, just return it
diff --git a/surfsense_web/package.json b/surfsense_web/package.json
index a5ec4d8..2899a2a 100644
--- a/surfsense_web/package.json
+++ b/surfsense_web/package.json
@@ -35,6 +35,7 @@
"@tabler/icons-react": "^3.30.0",
"@tanstack/react-table": "^8.21.2",
"@types/mdx": "^2.0.13",
+ "@types/react-syntax-highlighter": "^15.5.13",
"ai": "^4.1.54",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -55,6 +56,7 @@
"react-json-view": "^1.21.3",
"react-json-view-lite": "^2.4.0",
"react-markdown": "^10.0.1",
+ "react-syntax-highlighter": "^15.6.1",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^4.0.1",
diff --git a/surfsense_web/pnpm-lock.yaml b/surfsense_web/pnpm-lock.yaml
index 1d8653f..e7ab3e9 100644
--- a/surfsense_web/pnpm-lock.yaml
+++ b/surfsense_web/pnpm-lock.yaml
@@ -68,6 +68,9 @@ importers:
'@types/mdx':
specifier: ^2.0.13
version: 2.0.13
+ '@types/react-syntax-highlighter':
+ specifier: ^15.5.13
+ version: 15.5.13
ai:
specifier: ^4.1.54
version: 4.1.54(react@19.0.0)(zod@3.24.2)
@@ -128,6 +131,9 @@ importers:
react-markdown:
specifier: ^10.0.1
version: 10.0.1(@types/react@19.0.10)(react@19.0.0)
+ react-syntax-highlighter:
+ specifier: ^15.6.1
+ version: 15.6.1(react@19.0.0)
rehype-raw:
specifier: ^7.0.0
version: 7.0.0
@@ -2047,6 +2053,9 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+ '@types/hast@2.3.10':
+ resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==}
+
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
@@ -2073,6 +2082,9 @@ packages:
peerDependencies:
'@types/react': ^19.0.0
+ '@types/react-syntax-highlighter@15.5.13':
+ resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==}
+
'@types/react@19.0.10':
resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==}
@@ -2334,12 +2346,21 @@ packages:
character-entities-html4@2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+ character-entities-legacy@1.1.4:
+ resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==}
+
character-entities-legacy@3.0.0:
resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+ character-entities@1.2.4:
+ resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==}
+
character-entities@2.0.2:
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+ character-reference-invalid@1.1.4:
+ resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
+
character-reference-invalid@2.0.1:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
@@ -2384,6 +2405,9 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'}
+ comma-separated-tokens@1.0.8:
+ resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==}
+
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@@ -2762,6 +2786,9 @@ packages:
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+ fault@1.0.4:
+ resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==}
+
fbemitter@3.0.0:
resolution: {integrity: sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==}
@@ -2815,6 +2842,10 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
+ format@0.2.2:
+ resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
+ engines: {node: '>=0.4.x'}
+
framer-motion@12.4.7:
resolution: {integrity: sha512-VhrcbtcAMXfxlrjeHPpWVu2+mkcoR31e02aNSR7OUS/hZAciKa8q6o3YN2mA1h+jjscRsSyKvX6E1CiY/7OLMw==}
peerDependencies:
@@ -2985,6 +3016,9 @@ packages:
hast-util-from-parse5@8.0.3:
resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
+ hast-util-parse-selector@2.2.5:
+ resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==}
+
hast-util-parse-selector@4.0.0:
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
@@ -3012,9 +3046,18 @@ packages:
hast-util-whitespace@3.0.0:
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+ hastscript@6.0.0:
+ resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==}
+
hastscript@9.0.1:
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
+ highlight.js@10.7.3:
+ resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
+
+ highlightjs-vue@1.0.0:
+ resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==}
+
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
@@ -3049,9 +3092,15 @@ packages:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
+ is-alphabetical@1.0.4:
+ resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
+
is-alphabetical@2.0.1:
resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+ is-alphanumerical@1.0.4:
+ resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==}
+
is-alphanumerical@2.0.1:
resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
@@ -3097,6 +3146,9 @@ packages:
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
+ is-decimal@1.0.4:
+ resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==}
+
is-decimal@2.0.1:
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
@@ -3124,6 +3176,9 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
+ is-hexadecimal@1.0.4:
+ resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
+
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
@@ -3362,6 +3417,9 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
+ lowlight@1.20.0:
+ resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==}
+
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@@ -3716,6 +3774,9 @@ packages:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
+ parse-entities@2.0.0:
+ resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==}
+
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
@@ -3792,12 +3853,23 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ prismjs@1.27.0:
+ resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==}
+ engines: {node: '>=6'}
+
+ prismjs@1.30.0:
+ resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
+ engines: {node: '>=6'}
+
promise@7.3.1:
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ property-information@5.6.0:
+ resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==}
+
property-information@6.5.0:
resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
@@ -3921,6 +3993,11 @@ packages:
'@types/react':
optional: true
+ react-syntax-highlighter@15.6.1:
+ resolution: {integrity: sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==}
+ peerDependencies:
+ react: '>= 0.14.0'
+
react-textarea-autosize@8.5.7:
resolution: {integrity: sha512-2MqJ3p0Jh69yt9ktFIaZmORHXw4c4bxSIhCeWiFwmJ9EYKgLmuNII3e9c9b2UO+ijl4StnpZdqpxNIhTdHvqtQ==}
engines: {node: '>=10'}
@@ -3955,6 +4032,9 @@ packages:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
+ refractor@3.6.0:
+ resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==}
+
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
@@ -4142,6 +4222,9 @@ packages:
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
engines: {node: '>= 8'}
+ space-separated-tokens@1.1.5:
+ resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==}
+
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@@ -4256,6 +4339,9 @@ packages:
tailwind-merge@3.2.0:
resolution: {integrity: sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA==}
+ tailwind-merge@3.3.0:
+ resolution: {integrity: sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==}
+
tailwindcss-animate@1.0.7:
resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
peerDependencies:
@@ -4509,6 +4595,10 @@ packages:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
+ xtend@4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
+
yaml@1.10.2:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
@@ -6253,6 +6343,10 @@ snapshots:
'@types/estree@1.0.6': {}
+ '@types/hast@2.3.10':
+ dependencies:
+ '@types/unist': 2.0.11
+
'@types/hast@3.0.4':
dependencies:
'@types/unist': 3.0.3
@@ -6277,6 +6371,10 @@ snapshots:
dependencies:
'@types/react': 19.0.10
+ '@types/react-syntax-highlighter@15.5.13':
+ dependencies:
+ '@types/react': 19.0.10
+
'@types/react@19.0.10':
dependencies:
csstype: 3.1.3
@@ -6568,10 +6666,16 @@ snapshots:
character-entities-html4@2.1.0: {}
+ character-entities-legacy@1.1.4: {}
+
character-entities-legacy@3.0.0: {}
+ character-entities@1.2.4: {}
+
character-entities@2.0.2: {}
+ character-reference-invalid@1.1.4: {}
+
character-reference-invalid@2.0.1: {}
chokidar@3.6.0:
@@ -6626,6 +6730,8 @@ snapshots:
color-string: 1.9.1
optional: true
+ comma-separated-tokens@1.0.8: {}
+
comma-separated-tokens@2.0.3: {}
commander@4.1.1: {}
@@ -6744,7 +6850,7 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
react-easy-sort: 1.6.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- tailwind-merge: 3.2.0
+ tailwind-merge: 3.3.0
tsup: 6.7.0(postcss@8.5.3)(typescript@5.8.2)
transitivePeerDependencies:
- '@swc/core'
@@ -7218,6 +7324,10 @@ snapshots:
dependencies:
reusify: 1.1.0
+ fault@1.0.4:
+ dependencies:
+ format: 0.2.2
+
fbemitter@3.0.0:
dependencies:
fbjs: 3.0.5
@@ -7283,6 +7393,8 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
+ format@0.2.2: {}
+
framer-motion@12.4.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
motion-dom: 12.4.5
@@ -7501,6 +7613,8 @@ snapshots:
vfile-location: 5.0.3
web-namespaces: 2.0.1
+ hast-util-parse-selector@2.2.5: {}
+
hast-util-parse-selector@4.0.0:
dependencies:
'@types/hast': 3.0.4
@@ -7600,6 +7714,14 @@ snapshots:
dependencies:
'@types/hast': 3.0.4
+ hastscript@6.0.0:
+ dependencies:
+ '@types/hast': 2.3.10
+ comma-separated-tokens: 1.0.8
+ hast-util-parse-selector: 2.2.5
+ property-information: 5.6.0
+ space-separated-tokens: 1.1.5
+
hastscript@9.0.1:
dependencies:
'@types/hast': 3.0.4
@@ -7608,6 +7730,10 @@ snapshots:
property-information: 7.0.0
space-separated-tokens: 2.0.2
+ highlight.js@10.7.3: {}
+
+ highlightjs-vue@1.0.0: {}
+
html-url-attributes@3.0.1: {}
html-void-elements@3.0.0: {}
@@ -7633,8 +7759,15 @@ snapshots:
hasown: 2.0.2
side-channel: 1.1.0
+ is-alphabetical@1.0.4: {}
+
is-alphabetical@2.0.1: {}
+ is-alphanumerical@1.0.4:
+ dependencies:
+ is-alphabetical: 1.0.4
+ is-decimal: 1.0.4
+
is-alphanumerical@2.0.1:
dependencies:
is-alphabetical: 2.0.1
@@ -7691,6 +7824,8 @@ snapshots:
call-bound: 1.0.3
has-tostringtag: 1.0.2
+ is-decimal@1.0.4: {}
+
is-decimal@2.0.1: {}
is-extendable@0.1.1: {}
@@ -7714,6 +7849,8 @@ snapshots:
dependencies:
is-extglob: 2.1.1
+ is-hexadecimal@1.0.4: {}
+
is-hexadecimal@2.0.1: {}
is-map@2.0.3: {}
@@ -7917,6 +8054,11 @@ snapshots:
dependencies:
js-tokens: 4.0.0
+ lowlight@1.20.0:
+ dependencies:
+ fault: 1.0.4
+ highlight.js: 10.7.3
+
lru-cache@10.4.3: {}
lru-cache@11.1.0: {}
@@ -8536,6 +8678,15 @@ snapshots:
dependencies:
callsites: 3.1.0
+ parse-entities@2.0.0:
+ dependencies:
+ character-entities: 1.2.4
+ character-entities-legacy: 1.1.4
+ character-reference-invalid: 1.1.4
+ is-alphanumerical: 1.0.4
+ is-decimal: 1.0.4
+ is-hexadecimal: 1.0.4
+
parse-entities@4.0.2:
dependencies:
'@types/unist': 2.0.11
@@ -8604,6 +8755,10 @@ snapshots:
prelude-ls@1.2.1: {}
+ prismjs@1.27.0: {}
+
+ prismjs@1.30.0: {}
+
promise@7.3.1:
dependencies:
asap: 2.0.6
@@ -8614,6 +8769,10 @@ snapshots:
object-assign: 4.1.1
react-is: 16.13.1
+ property-information@5.6.0:
+ dependencies:
+ xtend: 4.0.2
+
property-information@6.5.0: {}
property-information@7.0.0: {}
@@ -8746,6 +8905,16 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.10
+ react-syntax-highlighter@15.6.1(react@19.0.0):
+ dependencies:
+ '@babel/runtime': 7.26.9
+ highlight.js: 10.7.3
+ highlightjs-vue: 1.0.0
+ lowlight: 1.20.0
+ prismjs: 1.30.0
+ react: 19.0.0
+ refractor: 3.6.0
+
react-textarea-autosize@8.5.7(@types/react@19.0.10)(react@19.0.0):
dependencies:
'@babel/runtime': 7.26.9
@@ -8804,6 +8973,12 @@ snapshots:
get-proto: 1.0.1
which-builtin-type: 1.2.1
+ refractor@3.6.0:
+ dependencies:
+ hastscript: 6.0.0
+ parse-entities: 2.0.0
+ prismjs: 1.27.0
+
regenerator-runtime@0.14.1: {}
regex-recursion@6.0.2:
@@ -9078,6 +9253,8 @@ snapshots:
dependencies:
whatwg-url: 7.1.0
+ space-separated-tokens@1.1.5: {}
+
space-separated-tokens@2.0.2: {}
sprintf-js@1.0.3: {}
@@ -9208,6 +9385,8 @@ snapshots:
tailwind-merge@3.2.0: {}
+ tailwind-merge@3.3.0: {}
+
tailwindcss-animate@1.0.7(tailwindcss@4.0.9):
dependencies:
tailwindcss: 4.0.9
@@ -9508,6 +9687,8 @@ snapshots:
string-width: 5.1.2
strip-ansi: 7.1.0
+ xtend@4.0.2: {}
+
yaml@1.10.2: {}
yocto-queue@0.1.0: {}