From cfade95e97fadec1eba4e80b2b59870b133b1a95 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Tue, 3 Jun 2025 23:09:33 +0800 Subject: [PATCH] feat: md preview --- package.json | 6 +-- pnpm-lock.yaml | 46 +++++++++++++------ src/apps/preview/md.tsx | 44 ++++++++++++++++++ src/components/html/md/Preview.tsx | 41 ++++++++++++++++- .../{06-01-summary.md => 25-06-01-summary.md} | 25 +++++----- .../blogs/logger-life/25-06-03-扩展屏幕.md | 12 +++++ src/pages/docs/summary/index.astro | 2 +- src/pages/preview/md.astro | 18 ++++++++ 8 files changed, 162 insertions(+), 32 deletions(-) create mode 100644 src/apps/preview/md.tsx rename src/data/blogs/kevisual/{06-01-summary.md => 25-06-01-summary.md} (67%) create mode 100644 src/data/blogs/logger-life/25-06-03-扩展屏幕.md create mode 100644 src/pages/preview/md.astro diff --git a/package.json b/package.json index 386f921..20a2457 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "react-dom": "^19.1.0", "react-draggable": "^4.4.6", "react-dropzone": "^14.3.8", - "react-hook-form": "^7.56.4", + "react-hook-form": "^7.57.0", "react-i18next": "^15.5.2", "react-resizable-panels": "^3.0.2", "react-sortablejs": "^6.1.4", @@ -69,7 +69,7 @@ "devDependencies": { "@excalidraw/excalidraw": "^0.18.0", "@kevisual/markdown-editor": "workspace:*", - "@kevisual/query": "^0.0.20", + "@kevisual/query": "^0.0.25", "@kevisual/query-awesome": "^0.0.2", "@kevisual/router": "^0.0.21", "@kevisual/store": "^0.0.9", @@ -89,5 +89,5 @@ "tw-animate-css": "^1.3.3", "vite-plugin-remote-assets": "^2.0.0" }, - "packageManager": "pnpm@10.11.0" + "packageManager": "pnpm@10.11.1" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ca8979..46acb78 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: version: 0.0.12 '@kevisual/query-login': specifier: ^0.0.6 - version: 0.0.6(@kevisual/query@0.0.20(ws@8.18.2)(zod@3.24.3))(rollup@4.40.1)(tslib@2.8.1)(typescript@5.8.3) + version: 0.0.6(@kevisual/query@0.0.25(ws@8.18.2)(zod@3.24.3))(rollup@4.40.1)(tslib@2.8.1)(typescript@5.8.3) '@kevisual/registry': specifier: ^0.0.1 version: 0.0.1(typescript@5.8.3) @@ -120,8 +120,8 @@ importers: specifier: ^14.3.8 version: 14.3.8(react@19.1.0) react-hook-form: - specifier: ^7.56.4 - version: 7.56.4(react@19.1.0) + specifier: ^7.57.0 + version: 7.57.0(react@19.1.0) react-i18next: specifier: ^15.5.2 version: 15.5.2(i18next@25.2.1(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3) @@ -151,8 +151,8 @@ importers: specifier: workspace:* version: link:packages/markdown-editor '@kevisual/query': - specifier: ^0.0.20 - version: 0.0.20(ws@8.18.2)(zod@3.24.3) + specifier: ^0.0.25 + version: 0.0.25(ws@8.18.2)(zod@3.24.3) '@kevisual/query-awesome': specifier: ^0.0.2 version: 0.0.2 @@ -838,8 +838,8 @@ packages: '@kevisual/query@0.0.15': resolution: {integrity: sha512-DK41qvyOiJMmlj70QyVP/48M0gszA39DdnBLtgU94YwAe6OqKrr9tYXHLjZrOROmUVMezIIBQuWMLedSAvb54A==} - '@kevisual/query@0.0.20': - resolution: {integrity: sha512-IpkQd1Pz50namxDNytLJpyR2CRLJWKTkmk68Fiw6CEkTXQDkdyBh2kIOIf7+Geu8quai/J9io3KjWzt17AeYdg==} + '@kevisual/query@0.0.25': + resolution: {integrity: sha512-pQjIKnZt36UeCuX2W9SEh5elyoS+jhsdLHg7sPIbJuuNSJegup5CeHoimKqkGgXRy4aFH2HLl8B9SGjKzYEakg==} '@kevisual/registry@0.0.1': resolution: {integrity: sha512-//OHu9m4JDrMjgP8o8dcjZd3D3IAUkRVlkTSviouZEH7r5m7mccA3Hvzw0XJ/lelx6exC6LWsyv6c4uV0Dp+gw==} @@ -3559,6 +3559,18 @@ packages: zod: optional: true + openai@5.0.2: + resolution: {integrity: sha512-NN7LAAImgBmd4RIe6WyRpLmwCbn+HQ1iaXeIG7K9DM3Auy/G2waKFhrDfRgaEeY0UUPnm6nohaCsqcS+zO8+2g==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + orderedmap@2.1.1: resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} @@ -3762,8 +3774,8 @@ packages: peerDependencies: react: '>= 16.8 || 18.0.0' - react-hook-form@7.56.4: - resolution: {integrity: sha512-Rob7Ftz2vyZ/ZGsQZPaRdIefkgOSrQSPXfqBdvOPwJfoGnjwRJUs7EM7Kc1mcoDv3NOtqBzPGbcMB8CGn9CKgw==} + react-hook-form@7.57.0: + resolution: {integrity: sha512-RbEks3+cbvTP84l/VXGUZ+JMrKOS8ykQCRYdm5aYsxnDquL0vspsyNhGRO7pcH6hsZqWlPOjLye7rJqdtdAmlg==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -5098,10 +5110,10 @@ snapshots: '@kevisual/query-awesome@0.0.2': {} - '@kevisual/query-login@0.0.6(@kevisual/query@0.0.20(ws@8.18.2)(zod@3.24.3))(rollup@4.40.1)(tslib@2.8.1)(typescript@5.8.3)': + '@kevisual/query-login@0.0.6(@kevisual/query@0.0.25(ws@8.18.2)(zod@3.24.3))(rollup@4.40.1)(tslib@2.8.1)(typescript@5.8.3)': dependencies: '@kevisual/cache': 0.0.2(rollup@4.40.1)(tslib@2.8.1)(typescript@5.8.3) - '@kevisual/query': 0.0.20(ws@8.18.2)(zod@3.24.3) + '@kevisual/query': 0.0.25(ws@8.18.2)(zod@3.24.3) dotenv: 16.5.0 transitivePeerDependencies: - rollup @@ -5116,11 +5128,10 @@ snapshots: - ws - zod - '@kevisual/query@0.0.20(ws@8.18.2)(zod@3.24.3)': + '@kevisual/query@0.0.25(ws@8.18.2)(zod@3.24.3)': dependencies: - openai: 4.100.0(ws@8.18.2)(zod@3.24.3) + openai: 5.0.2(ws@8.18.2)(zod@3.24.3) transitivePeerDependencies: - - encoding - ws - zod @@ -8344,6 +8355,11 @@ snapshots: transitivePeerDependencies: - encoding + openai@5.0.2(ws@8.18.2)(zod@3.24.3): + optionalDependencies: + ws: 8.18.2 + zod: 3.24.3 + orderedmap@2.1.1: {} p-limit@6.2.0: @@ -8590,7 +8606,7 @@ snapshots: prop-types: 15.8.1 react: 19.1.0 - react-hook-form@7.56.4(react@19.1.0): + react-hook-form@7.57.0(react@19.1.0): dependencies: react: 19.1.0 diff --git a/src/apps/preview/md.tsx b/src/apps/preview/md.tsx new file mode 100644 index 0000000..b7f8145 --- /dev/null +++ b/src/apps/preview/md.tsx @@ -0,0 +1,44 @@ +import { ToastProvider } from '@/modules/toast/Provider'; +import { query } from '@/modules/query'; + +import { useEffect, useState } from 'react'; +import { MarkdownPreview } from '@/components/html/md/Preview'; + +export const App = () => { + return ( + +
+ + ); +}; +const Main = () => { + const [mdUrl, setMdUrl] = useState(''); + const [markdown, setMarkdown] = useState(''); + useEffect(() => { + const url = new URL(window.location.href); + const md = url.searchParams.get('md'); + if (md) { + setMdUrl(md); + } + }, []); + useEffect(() => { + if (!mdUrl) return; + getMdContent(mdUrl); + }, [mdUrl]); + const getMdContent = async (url: string) => { + console.log('url', url); + const res = await query.fetchText({ + url: url, + }); + if (res.code === 200) { + console.log('Markdown content fetched:', res.data); + setMarkdown(res.data); + } + }; + + return ( +
+ +
+ ); +}; diff --git a/src/components/html/md/Preview.tsx b/src/components/html/md/Preview.tsx index 2d55c61..1ebaeeb 100644 --- a/src/components/html/md/Preview.tsx +++ b/src/components/html/md/Preview.tsx @@ -1,16 +1,53 @@ import { cn } from '@/lib/utils'; +import { useEffect, useState } from 'react'; // import './Preview.css'; +import { md2html } from '@kevisual/markdown-editor/tiptap/index.ts'; +export const clearMeta = (markdown?: string) => { + if (!markdown) return ''; + // Remove YAML front matter if present + const yamlRegex = /^---\n[\s\S]*?\n---\n/; + return markdown.replace(yamlRegex, ''); +}; type Props = { children?: React.ReactNode; className?: string; style?: React.CSSProperties; + content?: string; // Optional content prop for markdown text [key: string]: any; // Allow any additional props }; export const MarkdownPreview = (props: Props) => { return ( -
- {props.children} +
+ {props.children ? {props.children} : }
); }; + +export const WrapperText = (props: { children?: React.ReactNode; html?: string }) => { + if (props.html) { + return
; + } + return
{props.children}
; +}; + +export const MarkdownPreviewWrapper = (props: Props) => { + const [html, setHtml] = useState(''); + useEffect(() => { + init(); + }, [props.content]); + const init = async () => { + if (props.content) { + const htmlContent = await md2html(props.content); + setHtml(htmlContent); + } else { + setHtml(''); + } + }; + return ; +}; diff --git a/src/data/blogs/kevisual/06-01-summary.md b/src/data/blogs/kevisual/25-06-01-summary.md similarity index 67% rename from src/data/blogs/kevisual/06-01-summary.md rename to src/data/blogs/kevisual/25-06-01-summary.md index 522ad57..a7f69ac 100644 --- a/src/data/blogs/kevisual/06-01-summary.md +++ b/src/data/blogs/kevisual/25-06-01-summary.md @@ -9,19 +9,19 @@ tags: ['kevisual', 'platform', 'assistant'] ## 目标 -软件不再是开放者的归属,而是使用者私自的后花园。AI 能够更快速的生成代码,所以用户只需要一个能把代码跑起来的平台,可视化部署,管理,动作。 +软件不再是开放者的归属,而是使用者私自的后花园。生态发展下,AI 能够更快速的生成代码,所以用户只需要一个能把代码跑起来的平台,可视化部署和管理。 -所以类似于把一个小程序的平台挂到自己的网站,电脑,私有部署。为了解决类小程序化,所以需要有一个程序框架去当作容器,代码是属于动态代码。 +所以类似于把一个小程序的平台挂到自己的网站,自己的电脑、私有部署这个平台。为了解决类小程序化,所以需要有一个程序框架去当作容器,代码是属于动态代码,这个框架我先简称为`平台`。 -什么语言能够实现这个功能呢?需要保证动态,需要保证浏览器容易执行,而且保持稳定性。**只有 js**。而在服务端同代码执行的,deno 和 bun,已经非常的优秀了。 +什么语言能够实现这个功能呢?首要条件保证动态,然后需要保证浏览器容易执行,而且保持稳定性,最后客户端的也能用。**只有 js**。而在服务端同代码执行的,已经有 deno 和 bun,已经非常的优秀了。 ## 平台搭建 -当私有化部署,可以跨平台运行,windows,linux,mac,docker。他对于用户而言,就是一个终极的**助手**,而它是属于一个代码环境,用户可以放动态的代码。 +当私有化部署,可以跨平台运行,windows,linux,mac,docker。他对于用户而言,就是一个终极的**助手**,而它更是属于一个代码运行环境,类似浏览器,用户可以放动态的代码,ts 或者 js。 ### 实现方案 -前端和后端可执行的实现方案是两个不同的难度量级,但是两者的核心都是在于动态文件管理。文件管理都基于开源的 minio,用 api 获取。 +前端和后端可执行的实现方案是两个不同的难度量级,但是两者的核心都是在于动态文件管理。而动态的文件管理,并能够通过 api 去进行维护和管理的,有一个开源工具,minio。文件基于 minio 进行封装,存储的核心即解决了。 #### 前端的动态 @@ -29,14 +29,13 @@ tags: ['kevisual', 'platform', 'assistant'] 所以我开发了一个`page-proxy`,功能只有一个,页面代理,以及 api 的代理。 -对于不同的用户,拥有的不同的应用,因为平台是包函多样性的,同一个用户可以有不同的身份。所以定位问题就属于定位到用户的程序,也就是路径`/username/appKey/`, 往下一层级的路由,假如文件不存在,转到`/username/appKey/`,类似于`try_files`的模式(解决了单页面应用 `browser history` 路由问题)。对于 `api` 而言,比较特殊,就像是`/api/v1/`, `api` 这个用户的 `v1` 应用(属于 rest api),特殊的适配。 - +对于不同的用户,拥有的不同的应用,因为平台是包函多样性的,同一个用户可以有不同的身份。所以定位问题就属于定位到用户的程序,也就是路径`/username/appKey/`, 往下一层级的路由,假如文件不存在,转到`/username/appKey/`,类似于`try_files`的模式(解决了单页面应用 `browser history` 路由问题)。对于 `api` 而言,比较特殊,就像是`/api/v1/`, `api` 这个用户的 `v1` 应用(等于 rest api),需要特殊的适配。 **最后解决了,任何用户都能够上传自己的前端代码,然后都能够在对应的自己名下去找到那一个应用进行访问。** -所以 ai 生成的简单页面,能够最简方式去运行。 +所以 ai 生成的简单页面,能够最简方式去运行。前端开发者,开发的页面也能轻松的部署。 -为了平台的可用性,添加用户级的访问权限,可以配置公共或则私有。 +为了保证应用的私有性,添加用户级的访问权限,可以配置公共或则私有。 #### 后端的动态 @@ -58,6 +57,10 @@ tags: ['kevisual', 'platform', 'assistant'] 当核心助手模块完善后,就能够用 AI 来实现一些其他的东西了。 +[center](https://git.xiongxiao.me/kevisual/code-center) +[page-proxy](https://git.xiongxiao.me/kevisual/page-proxy) +[assistant](https://git.xiongxiao.me/kevisual/envision-cli) + ## AI doing @@ -70,6 +73,6 @@ doing #### 本地的应用 -### AI的知识库的搭建 +### AI 的知识库的搭建 -### 知识库的运用 \ No newline at end of file +### 知识库的运用 diff --git a/src/data/blogs/logger-life/25-06-03-扩展屏幕.md b/src/data/blogs/logger-life/25-06-03-扩展屏幕.md new file mode 100644 index 0000000..694e84f --- /dev/null +++ b/src/data/blogs/logger-life/25-06-03-扩展屏幕.md @@ -0,0 +1,12 @@ +# 作为一个助手的外接副屏 + +时刻在动态变化的内容,个人大屏幕。 + +时刻获取录制的声音转文字, + +获取对话ai对话的任务,返回对应的内容。 + +实时的操作,比如跳转到某一个地方的功能操作。 + + + diff --git a/src/pages/docs/summary/index.astro b/src/pages/docs/summary/index.astro index df6e03f..7f7ba6e 100644 --- a/src/pages/docs/summary/index.astro +++ b/src/pages/docs/summary/index.astro @@ -2,7 +2,7 @@ import '@/styles/theme.css'; import '@/styles/global.css'; import Blank from '@/components/html/blank.astro'; -import Readme from '@/data/blogs/kevisual/06-01-summary.md'; +import Readme from '@/data/blogs/kevisual/25-06-01-summary.md'; import { MarkdownPreview } from '@/components/html/md/Preview'; --- diff --git a/src/pages/preview/md.astro b/src/pages/preview/md.astro new file mode 100644 index 0000000..e01fd6d --- /dev/null +++ b/src/pages/preview/md.astro @@ -0,0 +1,18 @@ +--- +import '@/styles/theme.css'; +import '@/styles/global.css'; +import Blank from '@/components/html/blank.astro'; +import { App } from '@/apps/preview/md.tsx'; +--- + + + + + +