Add highlight.js and rehype-highlight for enhanced code syntax highlighting in markdown. Update globals.css for styling and modify MarkdownBlock component to utilize new highlighting features.
Browse files- frontend/app/globals.css +6 -0
- frontend/components/markdown-block.tsx +2 -0
- frontend/package-lock.json +86 -0
- frontend/package.json +2 -0
frontend/app/globals.css
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
@import "tailwindcss";
|
|
|
|
| 2 |
|
| 3 |
:root {
|
| 4 |
--font-sans:
|
|
@@ -367,6 +368,11 @@ textarea {
|
|
| 367 |
color: inherit;
|
| 368 |
}
|
| 369 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
.markdown-block blockquote {
|
| 371 |
border-left: 3px solid rgba(11, 136, 238, 0.32);
|
| 372 |
padding-left: 0.9rem;
|
|
|
|
| 1 |
@import "tailwindcss";
|
| 2 |
+
@import "highlight.js/styles/atom-one-dark.css";
|
| 3 |
|
| 4 |
:root {
|
| 5 |
--font-sans:
|
|
|
|
| 368 |
color: inherit;
|
| 369 |
}
|
| 370 |
|
| 371 |
+
.markdown-block pre code.hljs {
|
| 372 |
+
background: transparent;
|
| 373 |
+
padding: 0;
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
.markdown-block blockquote {
|
| 377 |
border-left: 3px solid rgba(11, 136, 238, 0.32);
|
| 378 |
padding-left: 0.9rem;
|
frontend/components/markdown-block.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import ReactMarkdown from "react-markdown";
|
|
|
|
| 2 |
import remarkGfm from "remark-gfm";
|
| 3 |
|
| 4 |
type MarkdownBlockProps = {
|
|
@@ -14,6 +15,7 @@ export function MarkdownBlock({
|
|
| 14 |
<div className={`markdown-block ${className}`.trim()}>
|
| 15 |
<ReactMarkdown
|
| 16 |
remarkPlugins={[remarkGfm]}
|
|
|
|
| 17 |
components={{
|
| 18 |
a: ({ ...props }) => (
|
| 19 |
<a
|
|
|
|
| 1 |
import ReactMarkdown from "react-markdown";
|
| 2 |
+
import rehypeHighlight from "rehype-highlight";
|
| 3 |
import remarkGfm from "remark-gfm";
|
| 4 |
|
| 5 |
type MarkdownBlockProps = {
|
|
|
|
| 15 |
<div className={`markdown-block ${className}`.trim()}>
|
| 16 |
<ReactMarkdown
|
| 17 |
remarkPlugins={[remarkGfm]}
|
| 18 |
+
rehypePlugins={[[rehypeHighlight, { detect: true, ignoreMissing: true }]]}
|
| 19 |
components={{
|
| 20 |
a: ({ ...props }) => (
|
| 21 |
<a
|
frontend/package-lock.json
CHANGED
|
@@ -11,11 +11,13 @@
|
|
| 11 |
"@ai-sdk/react": "^3.0.164",
|
| 12 |
"ai": "^6.0.162",
|
| 13 |
"clsx": "^2.1.1",
|
|
|
|
| 14 |
"lucide-react": "^0.511.0",
|
| 15 |
"next": "^16.2.3",
|
| 16 |
"react": "^19.2.0",
|
| 17 |
"react-dom": "^19.2.0",
|
| 18 |
"react-markdown": "^10.1.0",
|
|
|
|
| 19 |
"remark-gfm": "^4.0.1"
|
| 20 |
},
|
| 21 |
"devDependencies": {
|
|
@@ -4282,6 +4284,19 @@
|
|
| 4282 |
"node": ">= 0.4"
|
| 4283 |
}
|
| 4284 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4285 |
"node_modules/hast-util-to-jsx-runtime": {
|
| 4286 |
"version": "2.3.6",
|
| 4287 |
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
|
@@ -4309,6 +4324,22 @@
|
|
| 4309 |
"url": "https://opencollective.com/unified"
|
| 4310 |
}
|
| 4311 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4312 |
"node_modules/hast-util-whitespace": {
|
| 4313 |
"version": "3.0.0",
|
| 4314 |
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
|
|
@@ -4339,6 +4370,15 @@
|
|
| 4339 |
"hermes-estree": "0.25.1"
|
| 4340 |
}
|
| 4341 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4342 |
"node_modules/html-url-attributes": {
|
| 4343 |
"version": "3.0.1",
|
| 4344 |
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
|
@@ -5372,6 +5412,21 @@
|
|
| 5372 |
"loose-envify": "cli.js"
|
| 5373 |
}
|
| 5374 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5375 |
"node_modules/lru-cache": {
|
| 5376 |
"version": "5.1.1",
|
| 5377 |
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
|
@@ -6943,6 +6998,23 @@
|
|
| 6943 |
"url": "https://github.com/sponsors/ljharb"
|
| 6944 |
}
|
| 6945 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6946 |
"node_modules/remark-gfm": {
|
| 6947 |
"version": "4.0.1",
|
| 6948 |
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
|
|
@@ -7968,6 +8040,20 @@
|
|
| 7968 |
"url": "https://opencollective.com/unified"
|
| 7969 |
}
|
| 7970 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7971 |
"node_modules/unist-util-is": {
|
| 7972 |
"version": "6.0.1",
|
| 7973 |
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
|
|
|
|
| 11 |
"@ai-sdk/react": "^3.0.164",
|
| 12 |
"ai": "^6.0.162",
|
| 13 |
"clsx": "^2.1.1",
|
| 14 |
+
"highlight.js": "^11.11.1",
|
| 15 |
"lucide-react": "^0.511.0",
|
| 16 |
"next": "^16.2.3",
|
| 17 |
"react": "^19.2.0",
|
| 18 |
"react-dom": "^19.2.0",
|
| 19 |
"react-markdown": "^10.1.0",
|
| 20 |
+
"rehype-highlight": "^7.0.2",
|
| 21 |
"remark-gfm": "^4.0.1"
|
| 22 |
},
|
| 23 |
"devDependencies": {
|
|
|
|
| 4284 |
"node": ">= 0.4"
|
| 4285 |
}
|
| 4286 |
},
|
| 4287 |
+
"node_modules/hast-util-is-element": {
|
| 4288 |
+
"version": "3.0.0",
|
| 4289 |
+
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz",
|
| 4290 |
+
"integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==",
|
| 4291 |
+
"license": "MIT",
|
| 4292 |
+
"dependencies": {
|
| 4293 |
+
"@types/hast": "^3.0.0"
|
| 4294 |
+
},
|
| 4295 |
+
"funding": {
|
| 4296 |
+
"type": "opencollective",
|
| 4297 |
+
"url": "https://opencollective.com/unified"
|
| 4298 |
+
}
|
| 4299 |
+
},
|
| 4300 |
"node_modules/hast-util-to-jsx-runtime": {
|
| 4301 |
"version": "2.3.6",
|
| 4302 |
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
|
|
|
| 4324 |
"url": "https://opencollective.com/unified"
|
| 4325 |
}
|
| 4326 |
},
|
| 4327 |
+
"node_modules/hast-util-to-text": {
|
| 4328 |
+
"version": "4.0.2",
|
| 4329 |
+
"resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
|
| 4330 |
+
"integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==",
|
| 4331 |
+
"license": "MIT",
|
| 4332 |
+
"dependencies": {
|
| 4333 |
+
"@types/hast": "^3.0.0",
|
| 4334 |
+
"@types/unist": "^3.0.0",
|
| 4335 |
+
"hast-util-is-element": "^3.0.0",
|
| 4336 |
+
"unist-util-find-after": "^5.0.0"
|
| 4337 |
+
},
|
| 4338 |
+
"funding": {
|
| 4339 |
+
"type": "opencollective",
|
| 4340 |
+
"url": "https://opencollective.com/unified"
|
| 4341 |
+
}
|
| 4342 |
+
},
|
| 4343 |
"node_modules/hast-util-whitespace": {
|
| 4344 |
"version": "3.0.0",
|
| 4345 |
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
|
|
|
|
| 4370 |
"hermes-estree": "0.25.1"
|
| 4371 |
}
|
| 4372 |
},
|
| 4373 |
+
"node_modules/highlight.js": {
|
| 4374 |
+
"version": "11.11.1",
|
| 4375 |
+
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
|
| 4376 |
+
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
| 4377 |
+
"license": "BSD-3-Clause",
|
| 4378 |
+
"engines": {
|
| 4379 |
+
"node": ">=12.0.0"
|
| 4380 |
+
}
|
| 4381 |
+
},
|
| 4382 |
"node_modules/html-url-attributes": {
|
| 4383 |
"version": "3.0.1",
|
| 4384 |
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
|
|
|
| 5412 |
"loose-envify": "cli.js"
|
| 5413 |
}
|
| 5414 |
},
|
| 5415 |
+
"node_modules/lowlight": {
|
| 5416 |
+
"version": "3.3.0",
|
| 5417 |
+
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz",
|
| 5418 |
+
"integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==",
|
| 5419 |
+
"license": "MIT",
|
| 5420 |
+
"dependencies": {
|
| 5421 |
+
"@types/hast": "^3.0.0",
|
| 5422 |
+
"devlop": "^1.0.0",
|
| 5423 |
+
"highlight.js": "~11.11.0"
|
| 5424 |
+
},
|
| 5425 |
+
"funding": {
|
| 5426 |
+
"type": "github",
|
| 5427 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 5428 |
+
}
|
| 5429 |
+
},
|
| 5430 |
"node_modules/lru-cache": {
|
| 5431 |
"version": "5.1.1",
|
| 5432 |
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
|
|
|
| 6998 |
"url": "https://github.com/sponsors/ljharb"
|
| 6999 |
}
|
| 7000 |
},
|
| 7001 |
+
"node_modules/rehype-highlight": {
|
| 7002 |
+
"version": "7.0.2",
|
| 7003 |
+
"resolved": "https://registry.npmjs.org/rehype-highlight/-/rehype-highlight-7.0.2.tgz",
|
| 7004 |
+
"integrity": "sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==",
|
| 7005 |
+
"license": "MIT",
|
| 7006 |
+
"dependencies": {
|
| 7007 |
+
"@types/hast": "^3.0.0",
|
| 7008 |
+
"hast-util-to-text": "^4.0.0",
|
| 7009 |
+
"lowlight": "^3.0.0",
|
| 7010 |
+
"unist-util-visit": "^5.0.0",
|
| 7011 |
+
"vfile": "^6.0.0"
|
| 7012 |
+
},
|
| 7013 |
+
"funding": {
|
| 7014 |
+
"type": "opencollective",
|
| 7015 |
+
"url": "https://opencollective.com/unified"
|
| 7016 |
+
}
|
| 7017 |
+
},
|
| 7018 |
"node_modules/remark-gfm": {
|
| 7019 |
"version": "4.0.1",
|
| 7020 |
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
|
|
|
|
| 8040 |
"url": "https://opencollective.com/unified"
|
| 8041 |
}
|
| 8042 |
},
|
| 8043 |
+
"node_modules/unist-util-find-after": {
|
| 8044 |
+
"version": "5.0.0",
|
| 8045 |
+
"resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
|
| 8046 |
+
"integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==",
|
| 8047 |
+
"license": "MIT",
|
| 8048 |
+
"dependencies": {
|
| 8049 |
+
"@types/unist": "^3.0.0",
|
| 8050 |
+
"unist-util-is": "^6.0.0"
|
| 8051 |
+
},
|
| 8052 |
+
"funding": {
|
| 8053 |
+
"type": "opencollective",
|
| 8054 |
+
"url": "https://opencollective.com/unified"
|
| 8055 |
+
}
|
| 8056 |
+
},
|
| 8057 |
"node_modules/unist-util-is": {
|
| 8058 |
"version": "6.0.1",
|
| 8059 |
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
|
frontend/package.json
CHANGED
|
@@ -13,11 +13,13 @@
|
|
| 13 |
"@ai-sdk/react": "^3.0.164",
|
| 14 |
"ai": "^6.0.162",
|
| 15 |
"clsx": "^2.1.1",
|
|
|
|
| 16 |
"lucide-react": "^0.511.0",
|
| 17 |
"next": "^16.2.3",
|
| 18 |
"react": "^19.2.0",
|
| 19 |
"react-dom": "^19.2.0",
|
| 20 |
"react-markdown": "^10.1.0",
|
|
|
|
| 21 |
"remark-gfm": "^4.0.1"
|
| 22 |
},
|
| 23 |
"devDependencies": {
|
|
|
|
| 13 |
"@ai-sdk/react": "^3.0.164",
|
| 14 |
"ai": "^6.0.162",
|
| 15 |
"clsx": "^2.1.1",
|
| 16 |
+
"highlight.js": "^11.11.1",
|
| 17 |
"lucide-react": "^0.511.0",
|
| 18 |
"next": "^16.2.3",
|
| 19 |
"react": "^19.2.0",
|
| 20 |
"react-dom": "^19.2.0",
|
| 21 |
"react-markdown": "^10.1.0",
|
| 22 |
+
"rehype-highlight": "^7.0.2",
|
| 23 |
"remark-gfm": "^4.0.1"
|
| 24 |
},
|
| 25 |
"devDependencies": {
|