Adds a dedicated HtmlSvgRenderer that turns ```html / ```svg fences in assistant messages into an inline preview with a Code/Preview tab toggle. HTML runs inside an iframe with sandbox="allow-scripts" only (no allow-same-origin, no allow-top-navigation) so JS games execute but cannot reach parent.document. SVG is sanitized through DOMPurify with the svg/svgFilters profile before being mounted via dangerouslySetInnerHTML, stripping <script>, on* handlers, javascript: URLs, and any tag that could escape the SVG sandbox. The renderer defaults to the Preview tab for completed fences and locks to the Code tab while the stream is still arriving so users see partial tokens rather than a flashing preview. The Code tab keeps the existing Streamdown syntax-highlighted view and the established copy / download chrome from CodeBlockActions. HTML previews cap at 500px and have a pop-out affordance that expands to 80vh; Esc exits the modal. Wires the renderer into the markdown pipeline via the existing StreamdownBlock fork in markdown-text.tsx, replacing the previous stacked code+preview layout. Non-HTML / non-SVG fences fall through to the original highlighted code block. Adds Vitest + jsdom + React Testing Library to the frontend dev dependencies and a vitest.config.ts. Covers: iframe sandbox attribute, SVG script + onclick stripping, Code/Preview toggle, streaming lock, DOMPurify behaviour on javascript: URLs and onload handlers, and that non-HTML/SVG fences are not routed through the renderer.
111 lines
3.3 KiB
JSON
111 lines
3.3 KiB
JSON
{
|
|
"name": "unsloth-theme",
|
|
"private": true,
|
|
"version": "0.0.0",
|
|
"type": "module",
|
|
"engines": {
|
|
"node": "^20.19.0 || >=22.12.0"
|
|
},
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "tsc -b && vite build",
|
|
"lint": "eslint .",
|
|
"preview": "vite preview",
|
|
"typecheck": "tsc -b --pretty false",
|
|
"biome:check": "biome check .",
|
|
"biome:fix": "biome check . --write",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest"
|
|
},
|
|
"dependencies": {
|
|
"@assistant-ui/core": "0.1.17",
|
|
"@assistant-ui/react": "0.12.28",
|
|
"@assistant-ui/tap": "0.5.10",
|
|
"@base-ui/react": "^1.2.0",
|
|
"@dagrejs/dagre": "^2.0.4",
|
|
"@dagrejs/graphlib": "^3.0.4",
|
|
"@fontsource-variable/figtree": "^5.2.10",
|
|
"@fontsource-variable/inter": "^5.2.8",
|
|
"@fontsource-variable/space-grotesk": "^5.2.10",
|
|
"@hugeicons/core-free-icons": "^4.1.1",
|
|
"@hugeicons/react": "^1.1.5",
|
|
"@huggingface/hub": "^2.9.0",
|
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
"@radix-ui/react-label": "^2.1.8",
|
|
"@radix-ui/react-select": "^2.2.6",
|
|
"@radix-ui/react-separator": "^1.1.8",
|
|
"@radix-ui/react-slot": "^1.2.4",
|
|
"@streamdown/code": "1.1.1",
|
|
"@streamdown/math": "1.0.2",
|
|
"@streamdown/mermaid": "1.0.2",
|
|
"@tailwindcss/vite": "^4.2.2",
|
|
"@tanstack/react-router": "1.169.2",
|
|
"@tanstack/react-table": "^8.21.3",
|
|
"@tauri-apps/api": "^2.10.1",
|
|
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
|
|
"@tauri-apps/plugin-notification": "^2.3.3",
|
|
"@tauri-apps/plugin-opener": "^2.5.3",
|
|
"@tauri-apps/plugin-process": "^2.3.1",
|
|
"@tauri-apps/plugin-updater": "^2.10.1",
|
|
"@toolwind/corner-shape": "^0.0.8-3",
|
|
"@xyflow/react": "^12.10.0",
|
|
"assistant-stream": "0.3.12",
|
|
"canvas-confetti": "^1.9.4",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"cmdk": "^1.1.1",
|
|
"dexie": "^4.3.0",
|
|
"dompurify": "^3.4.2",
|
|
"fflate": "0.8.3",
|
|
"js-yaml": "^4.1.1",
|
|
"katex": "^0.16.28",
|
|
"lucide-react": "^1.7.0",
|
|
"mammoth": "^1.11.0",
|
|
"motion": "^12.34.0",
|
|
"next-themes": "^0.4.6",
|
|
"node-forge": "^1.4.0",
|
|
"radix-ui": "^1.4.3",
|
|
"react": "^19.2.4",
|
|
"react-day-picker": "^9.13.2",
|
|
"react-dom": "^19.2.4",
|
|
"react-resizable-panels": "^4.6.4",
|
|
"recharts": "3.7.0",
|
|
"shadcn": "^4.2.0",
|
|
"sonner": "^2.0.7",
|
|
"streamdown": "2.5.0",
|
|
"tailwind-merge": "^3.4.0",
|
|
"tailwindcss": "^4.1.18",
|
|
"tw-animate-css": "^1.4.0",
|
|
"tw-shimmer": "^0.4.6",
|
|
"unpdf": "^1.4.0",
|
|
"zustand": "^5.0.11"
|
|
},
|
|
"overrides": {
|
|
"@tanstack/react-router": "1.169.2",
|
|
"@tanstack/router-core": "1.169.2",
|
|
"@tanstack/history": "1.161.6"
|
|
},
|
|
"devDependencies": {
|
|
"@biomejs/biome": "^1.9.4",
|
|
"@eslint/js": "^9.39.1",
|
|
"@types/canvas-confetti": "^1.9.0",
|
|
"@types/js-yaml": "^4.0.9",
|
|
"@types/node-forge": "^1.3.14",
|
|
"@types/node": "^25.5.2",
|
|
"@types/react": "^19.2.5",
|
|
"@types/react-dom": "^19.2.3",
|
|
"@testing-library/dom": "^10.4.1",
|
|
"@testing-library/react": "^16.3.2",
|
|
"@testing-library/user-event": "^14.6.1",
|
|
"@vitejs/plugin-react": "^6.0.1",
|
|
"eslint": "^9.39.1",
|
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
"eslint-plugin-react-refresh": "^0.5.2",
|
|
"globals": "^17.4.0",
|
|
"jsdom": "^25.0.1",
|
|
"typescript": "~5.9.3",
|
|
"typescript-eslint": "^8.55.0",
|
|
"vite": "^8.0.1",
|
|
"vitest": "^2.1.9"
|
|
}
|
|
}
|