Files
PaperClipAI/ui/package.json
scotttongandClaude Opus 5 27897e754e feat(markdown): add syntax colors to rendered code blocks
The block follows the theme now, but every token in it is one color.
Add syntax highlighting, using the palette from the approved design.

Render: add rehype-highlight and pass it to react-markdown. The plugin
array sits at module scope, because react-markdown remounts the rendered
tree when the array identity changes. That is the same hazard the
remarkPlugins memo already guards against.

Detection: `detect` is on, because most agent-authored fences carry no
language tag and would never highlight without it. `subset` restricts
detection to the languages agents actually post. highlight.js guesses
badly on short snippets, and a wrong guess colors the whole block wrongly.

Palette: eight `--code-syntax-*` aliases carry the roles. Each one points
at a token that already exists and already has a `.dark` override, so a
custom property resolves per mode at its use site and one definition
covers both themes.

The mapping is BORROWED, and this is the part to review. Paperclip has no
syntax palette. `--status-task-icon-*` and `--chip-match-title-fg` name
task-status and search-chip concerns. They were used because they are the
only hues that carry a real per-mode value; the fixed `--status-task-*`
hues go dim on the dark code surface. The coupling is confined to the
alias block. Repointing those eight lines moves the whole palette, and no
rule changes. A test asserts that the syntax rules never reference the
borrowed tokens directly.

Verified in both themes on a real task. Light resolves keyword #7c3aed,
identifier oklch(0.145 0 0), function oklch(0.4 0.13 265), comment
oklch(0.556 0 0). Dark resolves #9474f0, oklch(0.985 0 0),
oklch(0.78 0.1 265), oklch(0.708 0 0).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 21:49:57 -07:00

89 lines
3.0 KiB
JSON

{
"name": "@paperclipai/ui",
"version": "0.3.1",
"description": "Prebuilt Paperclip board UI assets.",
"license": "MIT",
"homepage": "https://github.com/paperclipai/paperclip",
"bugs": {
"url": "https://github.com/paperclipai/paperclip/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/paperclipai/paperclip",
"directory": "ui"
},
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"storybook": "storybook dev -p 6006 -c storybook/.storybook",
"build-storybook": "storybook build -c storybook/.storybook -o storybook-static",
"preview": "vite preview",
"typecheck": "tsc -b",
"clean": "rm -rf dist storybook-static tsconfig.tsbuildinfo",
"prepack": "rm -f package.dev.json && cp package.json package.dev.json && node ../scripts/generate-ui-package-json.mjs",
"postpack": "if [ -f package.dev.json ]; then mv package.dev.json package.json; fi"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@assistant-ui/react": "0.14.14",
"@base-ui/react": "^1.6.0",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@lexical/link": "0.49.0",
"@mdxeditor/editor": "^3.55.0",
"@paperclipai/adapter-claude-local": "workspace:*",
"@paperclipai/adapter-codex-local": "workspace:*",
"@paperclipai/adapter-cursor-cloud": "workspace:*",
"@paperclipai/adapter-cursor-local": "workspace:*",
"@paperclipai/adapter-gemini-local": "workspace:*",
"@paperclipai/adapter-grok-local": "workspace:*",
"@paperclipai/adapter-openclaw-gateway": "workspace:*",
"@paperclipai/adapter-opencode-local": "workspace:*",
"@paperclipai/adapter-pi-local": "workspace:*",
"@paperclipai/adapter-utils": "workspace:*",
"@paperclipai/hermes-paperclip-adapter": "workspace:*",
"@paperclipai/shared": "workspace:*",
"@radix-ui/react-slot": "^1.3.0",
"@tailwindcss/typography": "^0.5.20",
"@tanstack/react-query": "^5.101.4",
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"i18next": "^26.3.6",
"lexical": "0.49.0",
"lucide-react": "^0.577.0",
"mermaid": "^11.16.1",
"radix-ui": "^1.6.4",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-i18next": "^17.0.10",
"react-markdown": "^10.1.0",
"react-resizable-panels": "^4.12.2",
"react-router-dom": "^7.18.1",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1",
"tailwind-merge": "^3.6.0"
},
"devDependencies": {
"@storybook/addon-a11y": "10.5.4",
"@storybook/addon-docs": "10.5.0",
"@storybook/react-vite": "10.5.0",
"@tailwindcss/vite": "^4.3.3",
"@types/node": "^22.20.1",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^4.3.4",
"storybook": "10.5.5",
"tailwindcss": "^4.3.2",
"typescript": "^5.7.3",
"vite": "^6.4.3",
"vitest": "^4.1.10"
}
}