From 14b91ed7558ec718aa82a23912a0ff3078c23c7f Mon Sep 17 00:00:00 2001 From: Simon Farshid Date: Sat, 6 Jul 2024 22:58:47 -0700 Subject: [PATCH] feat: syntax highlighter package (#418) --- apps/www/components/shadcn/Shadcn.tsx | 9 +-- apps/www/package.json | 2 + packages/cli/package.json | 2 +- packages/react-ai-sdk/package.json | 4 +- packages/react-hook-form/package.json | 8 +-- packages/react-markdown/package.json | 7 +-- .../react-syntax-highlighter/.eslintrc.json | 3 + packages/react-syntax-highlighter/README.md | 3 + .../react-syntax-highlighter/package.json | 62 +++++++++++++++++++ .../react-syntax-highlighter/src/index.ts | 9 +++ .../src/react-syntax-highlighter.tsx | 57 +++++++++++++++++ .../react-syntax-highlighter/tsconfig.json | 11 ++++ .../src/components/{code => }/code-header.tsx | 6 +- .../code/react-syntax-highlighter.tsx | 25 -------- packages/react-ui/src/components/index.ts | 4 +- .../react-ui/src/components/markdown-text.tsx | 2 +- packages/react-ui/tsconfig.json | 9 +-- packages/react/package.json | 2 +- pnpm-lock.yaml | 58 +++++++++++++---- 19 files changed, 213 insertions(+), 70 deletions(-) create mode 100644 packages/react-syntax-highlighter/.eslintrc.json create mode 100644 packages/react-syntax-highlighter/README.md create mode 100644 packages/react-syntax-highlighter/package.json create mode 100644 packages/react-syntax-highlighter/src/index.ts create mode 100644 packages/react-syntax-highlighter/src/react-syntax-highlighter.tsx create mode 100644 packages/react-syntax-highlighter/tsconfig.json rename packages/react-ui/src/components/{code => }/code-header.tsx (83%) delete mode 100644 packages/react-ui/src/components/code/react-syntax-highlighter.tsx diff --git a/apps/www/components/shadcn/Shadcn.tsx b/apps/www/components/shadcn/Shadcn.tsx index f4747b0f40..90ba02bbd2 100644 --- a/apps/www/components/shadcn/Shadcn.tsx +++ b/apps/www/components/shadcn/Shadcn.tsx @@ -8,21 +8,18 @@ import icon from "@/public/favicon/favicon.svg"; import type { TooltipContentProps } from "@radix-ui/react-tooltip"; import Image from "next/image"; import { type FC } from "react"; -import { - makePrismSyntaxHighlighter, - makeMarkdownText, - Thread, -} from "@assistant-ui/react-ui"; +import { makeMarkdownText, Thread } from "@assistant-ui/react-ui"; import { Sheet, SheetContent, SheetTrigger } from "../ui/sheet"; import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; import { ModelPicker } from "./ModelPicker"; import { useSwitchToNewThread } from "@assistant-ui/react"; import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; +import { makePrismAsyncSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter"; const MarkdownText = makeMarkdownText({ remarkPlugins: [remarkGfm], components: { - SyntaxHighlighter: makePrismSyntaxHighlighter({ + SyntaxHighlighter: makePrismAsyncSyntaxHighlighter({ style: coldarkDark, customStyle: { margin: 0, diff --git a/apps/www/package.json b/apps/www/package.json index 86caa36190..2120e51644 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -15,6 +15,7 @@ "@ai-sdk/react": "^0.0.16", "@assistant-ui/react": "workspace:*", "@assistant-ui/react-ai-sdk": "workspace:*", + "@assistant-ui/react-syntax-highlighter": "workspace:^", "@assistant-ui/react-ui": "workspace:*", "@calcom/embed-react": "^1.5.0", "@fortawesome/fontawesome-svg-core": "^6.5.2", @@ -51,6 +52,7 @@ "@types/node": "20.14.9", "@types/react": "^18", "@types/react-dom": "^18", + "@types/react-syntax-highlighter": "^15.5.13", "@types/title": "^3.4.3", "autoprefixer": "^10.4.19", "eslint-config-next": "14.2.4", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3b6d3c3c4e..ce2ee417f1 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ ], "bin": "./dist/index.js", "scripts": { - "build": "tsup src/index.ts --format esm --sourcemap" + "build": "tsup src/index.ts --format esm --sourcemap --clean" }, "publishConfig": { "access": "public", diff --git a/packages/react-ai-sdk/package.json b/packages/react-ai-sdk/package.json index e41db65dd4..87e7eff459 100644 --- a/packages/react-ai-sdk/package.json +++ b/packages/react-ai-sdk/package.json @@ -24,7 +24,7 @@ ], "sideEffects": false, "scripts": { - "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap" + "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --clean" }, "dependencies": { "tsup": "^8.1.0", @@ -45,7 +45,7 @@ }, "devDependencies": { "@assistant-ui/tsconfig": "workspace:*", - "@types/node": "^20.14.9" + "eslint-config-next": "14.2.4" }, "publishConfig": { "access": "public", diff --git a/packages/react-hook-form/package.json b/packages/react-hook-form/package.json index 49c8d3f87c..fdddd76af0 100644 --- a/packages/react-hook-form/package.json +++ b/packages/react-hook-form/package.json @@ -24,16 +24,16 @@ ], "sideEffects": false, "scripts": { - "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap" + "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --clean" }, "dependencies": { "zod": "^3.23.8" }, "peerDependencies": { "@assistant-ui/react": "^0.3.0", - "react-hook-form": "^7.x.x", "@types/react": "*", - "react": "^18" + "react": "^18", + "react-hook-form": "^7.x.x" }, "peerDependenciesMeta": { "@types/react": { @@ -42,7 +42,7 @@ }, "devDependencies": { "@assistant-ui/tsconfig": "workspace:*", - "@types/node": "^20.14.9", + "eslint-config-next": "14.2.4", "tsup": "^8.1.0" }, "publishConfig": { diff --git a/packages/react-markdown/package.json b/packages/react-markdown/package.json index 1b557200c3..d269bf294c 100644 --- a/packages/react-markdown/package.json +++ b/packages/react-markdown/package.json @@ -24,13 +24,12 @@ ], "sideEffects": false, "scripts": { - "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap" + "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --clean" }, "dependencies": { "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-use-callback-ref": "^1.1.0", - "react-markdown": "^9.0.1", - "zod": "^3.23.8" + "react-markdown": "^9.0.1" }, "peerDependencies": { "@assistant-ui/react": "^0.3.2", @@ -44,7 +43,7 @@ }, "devDependencies": { "@assistant-ui/tsconfig": "workspace:*", - "@types/node": "^20.14.9", + "eslint-config-next": "14.2.4", "tsup": "^8.1.0" }, "publishConfig": { diff --git a/packages/react-syntax-highlighter/.eslintrc.json b/packages/react-syntax-highlighter/.eslintrc.json new file mode 100644 index 0000000000..bffb357a71 --- /dev/null +++ b/packages/react-syntax-highlighter/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/packages/react-syntax-highlighter/README.md b/packages/react-syntax-highlighter/README.md new file mode 100644 index 0000000000..f7740d3181 --- /dev/null +++ b/packages/react-syntax-highlighter/README.md @@ -0,0 +1,3 @@ +# `@assistant-ui/react-syntax-highlighter` + +`react-syntax-highlighter` integration for `@assistant-ui/react`. diff --git a/packages/react-syntax-highlighter/package.json b/packages/react-syntax-highlighter/package.json new file mode 100644 index 0000000000..88d420db98 --- /dev/null +++ b/packages/react-syntax-highlighter/package.json @@ -0,0 +1,62 @@ +{ + "name": "@assistant-ui/react-syntax-highlighter", + "version": "0.0.1", + "license": "MIT", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "source": "./src/index.ts", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist", + "README.md" + ], + "sideEffects": false, + "scripts": { + "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --clean" + }, + "peerDependencies": { + "@assistant-ui/react": "^0.3.2", + "@assistant-ui/react-markdown": "^0.0.4", + "@types/react": "*", + "@types/react-syntax-highlighter": "*", + "react": "^18", + "react-syntax-highlighter": "^15.5.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-syntax-highlighter": { + "optional": true + } + }, + "devDependencies": { + "@assistant-ui/tsconfig": "workspace:*", + "eslint-config-next": "14.2.4", + "tsup": "^8.1.0" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "homepage": "https://assistant-ui.com/", + "repository": { + "type": "git", + "url": "git+https://github.com/Yonom/assistant-ui.git" + }, + "bugs": { + "url": "https://github.com/Yonom/assistant-ui/issues" + } +} diff --git a/packages/react-syntax-highlighter/src/index.ts b/packages/react-syntax-highlighter/src/index.ts new file mode 100644 index 0000000000..53dc976b74 --- /dev/null +++ b/packages/react-syntax-highlighter/src/index.ts @@ -0,0 +1,9 @@ +export { + makeSyntaxHighlighter, + makeLightSyntaxHighlighter, + makeLightAsyncSyntaxHighlighter, + makePrismSyntaxHighlighter, + makePrismLightSyntaxHighlighter, + makePrismAsyncSyntaxHighlighter, + makePrismAsyncLightSyntaxHighlighter, +} from "./react-syntax-highlighter"; diff --git a/packages/react-syntax-highlighter/src/react-syntax-highlighter.tsx b/packages/react-syntax-highlighter/src/react-syntax-highlighter.tsx new file mode 100644 index 0000000000..247f3160da --- /dev/null +++ b/packages/react-syntax-highlighter/src/react-syntax-highlighter.tsx @@ -0,0 +1,57 @@ +"use client"; + +import { ComponentType, type FC } from "react"; +import SyntaxHighlighter, { + Prism, + PrismAsync, + PrismAsyncLight, + PrismLight, + Light, + LightAsync, + SyntaxHighlighterProps as SHP, +} from "react-syntax-highlighter"; +import type { SyntaxHighlighterProps } from "@assistant-ui/react-markdown"; + +const makeMakeSyntaxHighlighter = + (SyntaxHighlighter: ComponentType) => + (config: Omit) => { + const PrismSyntaxHighlighter: FC = ({ + components: { Pre, Code }, + language, + code, + }) => { + return ( + + {code} + + ); + }; + + PrismSyntaxHighlighter.displayName = "PrismSyntaxHighlighter"; + + return PrismSyntaxHighlighter; + }; + +export const makeSyntaxHighlighter = + makeMakeSyntaxHighlighter(SyntaxHighlighter); + +export const makePrismSyntaxHighlighter = makeMakeSyntaxHighlighter(Prism); + +export const makePrismAsyncSyntaxHighlighter = + makeMakeSyntaxHighlighter(PrismAsync); + +export const makePrismAsyncLightSyntaxHighlighter = + makeMakeSyntaxHighlighter(PrismAsyncLight); + +export const makePrismLightSyntaxHighlighter = + makeMakeSyntaxHighlighter(PrismLight); + +export const makeLightSyntaxHighlighter = makeMakeSyntaxHighlighter(Light); + +export const makeLightAsyncSyntaxHighlighter = + makeMakeSyntaxHighlighter(LightAsync); diff --git a/packages/react-syntax-highlighter/tsconfig.json b/packages/react-syntax-highlighter/tsconfig.json new file mode 100644 index 0000000000..09a74b1dc4 --- /dev/null +++ b/packages/react-syntax-highlighter/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@assistant-ui/tsconfig/base.json", + "compilerOptions": { + "paths": { + "@assistant-ui/*": ["../../packages/*/src"], + "@assistant-ui/react/*": ["../../packages/react/src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/packages/react-ui/src/components/code/code-header.tsx b/packages/react-ui/src/components/code-header.tsx similarity index 83% rename from packages/react-ui/src/components/code/code-header.tsx rename to packages/react-ui/src/components/code-header.tsx index 98d0282a0a..d012344bd0 100644 --- a/packages/react-ui/src/components/code/code-header.tsx +++ b/packages/react-ui/src/components/code-header.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; -import { useThreadConfig } from "../thread-config"; -import { useCopyToClipboard } from "../../utils/useCopyToClipboard"; -import { TooltipIconButton } from "../base"; +import { useThreadConfig } from "./thread-config"; +import { useCopyToClipboard } from "../utils/useCopyToClipboard"; +import { TooltipIconButton } from "./base"; import { CheckIcon, CopyIcon } from "lucide-react"; import type { CodeHeaderProps } from "@assistant-ui/react-markdown"; diff --git a/packages/react-ui/src/components/code/react-syntax-highlighter.tsx b/packages/react-ui/src/components/code/react-syntax-highlighter.tsx deleted file mode 100644 index 6eaca4068d..0000000000 --- a/packages/react-ui/src/components/code/react-syntax-highlighter.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; - -import { type FC } from "react"; -import { Prism, SyntaxHighlighterProps as SHP } from "react-syntax-highlighter"; -import type { SyntaxHighlighterProps } from "@assistant-ui/react-markdown"; - -export const makePrismSyntaxHighlighter = ( - config: Omit, -) => { - const PrismSyntaxHighlighter: FC = ({ - components: { Pre, Code }, - language, - code, - }) => { - return ( - - {code} - - ); - }; - - PrismSyntaxHighlighter.displayName = "PrismSyntaxHighlighter"; - - return PrismSyntaxHighlighter; -}; diff --git a/packages/react-ui/src/components/index.ts b/packages/react-ui/src/components/index.ts index 1896c1657e..cb26f0b2d6 100644 --- a/packages/react-ui/src/components/index.ts +++ b/packages/react-ui/src/components/index.ts @@ -90,9 +90,7 @@ export { export { Text } from "./text"; -export { CodeHeader } from "./code/code-header"; - -export { makePrismSyntaxHighlighter } from "./code/react-syntax-highlighter"; +export { CodeHeader } from "./code-header"; export { makeMarkdownText } from "./markdown-text"; diff --git a/packages/react-ui/src/components/markdown-text.tsx b/packages/react-ui/src/components/markdown-text.tsx index 43857b96c3..9e3c4bde4a 100644 --- a/packages/react-ui/src/components/markdown-text.tsx +++ b/packages/react-ui/src/components/markdown-text.tsx @@ -1,6 +1,6 @@ import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown"; import { TextContentPartProps } from "@assistant-ui/react"; -import { CodeHeader } from "./code/code-header"; +import { CodeHeader } from "./code-header"; import { MarkdownTextPrimitiveProps } from "@assistant-ui/react-markdown"; import { FC, memo } from "react"; diff --git a/packages/react-ui/tsconfig.json b/packages/react-ui/tsconfig.json index a2b9818948..f5a0a2ff23 100644 --- a/packages/react-ui/tsconfig.json +++ b/packages/react-ui/tsconfig.json @@ -5,13 +5,6 @@ "@assistant-ui/*": ["../../packages/*/src"] } }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - "../react-markdown/src/PreOverride.tsx", - "../react-markdown/src/CodeOverride.tsx", - "../react-markdown/src/syntax-highlighter.tsx" - ], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] } diff --git a/packages/react/package.json b/packages/react/package.json index 491cd05593..bd3ec5d772 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -53,7 +53,7 @@ ], "sideEffects": false, "scripts": { - "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap" + "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --clean" }, "dependencies": { "@radix-ui/primitive": "^1.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0b5aac75d1..7f03c2e180 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: '@assistant-ui/react-ai-sdk': specifier: workspace:* version: link:../../packages/react-ai-sdk + '@assistant-ui/react-syntax-highlighter': + specifier: workspace:^ + version: link:../../packages/react-syntax-highlighter '@assistant-ui/react-ui': specifier: workspace:* version: link:../../packages/react-ui @@ -141,6 +144,9 @@ importers: '@types/react-dom': specifier: ^18 version: 18.3.0 + '@types/react-syntax-highlighter': + specifier: ^15.5.13 + version: 15.5.13 '@types/title': specifier: ^3.4.3 version: 3.4.3 @@ -655,9 +661,9 @@ importers: '@assistant-ui/tsconfig': specifier: workspace:* version: link:../tsconfig - '@types/node': - specifier: ^20.14.9 - version: 20.14.9 + eslint-config-next: + specifier: 14.2.4 + version: 14.2.4(eslint@8.57.0)(typescript@5.5.3) packages/react-hook-form: dependencies: @@ -680,9 +686,9 @@ importers: '@assistant-ui/tsconfig': specifier: workspace:* version: link:../tsconfig - '@types/node': - specifier: ^20.14.9 - version: 20.14.9 + eslint-config-next: + specifier: 14.2.4 + version: 14.2.4(eslint@8.57.0)(typescript@5.5.3) tsup: specifier: ^8.1.0 version: 8.1.0(postcss@8.4.39)(typescript@5.5.3) @@ -707,16 +713,44 @@ importers: react-markdown: specifier: ^9.0.1 version: 9.0.1(@types/react@18.3.3)(react@18.3.1) - zod: - specifier: ^3.23.8 - version: 3.23.8 devDependencies: '@assistant-ui/tsconfig': specifier: workspace:* version: link:../tsconfig - '@types/node': - specifier: ^20.14.9 - version: 20.14.9 + eslint-config-next: + specifier: 14.2.4 + version: 14.2.4(eslint@8.57.0)(typescript@5.5.3) + tsup: + specifier: ^8.1.0 + version: 8.1.0(postcss@8.4.39)(typescript@5.5.3) + + packages/react-syntax-highlighter: + dependencies: + '@assistant-ui/react': + specifier: ^0.3.2 + version: link:../react + '@assistant-ui/react-markdown': + specifier: ^0.0.4 + version: link:../react-markdown + '@types/react': + specifier: '*' + version: 18.3.3 + '@types/react-syntax-highlighter': + specifier: '*' + version: 15.5.13 + react: + specifier: ^18 + version: 18.3.1 + react-syntax-highlighter: + specifier: ^15.5.0 + version: 15.5.0(react@18.3.1) + devDependencies: + '@assistant-ui/tsconfig': + specifier: workspace:* + version: link:../tsconfig + eslint-config-next: + specifier: 14.2.4 + version: 14.2.4(eslint@8.57.0)(typescript@5.5.3) tsup: specifier: ^8.1.0 version: 8.1.0(postcss@8.4.39)(typescript@5.5.3)