feat: md preview

This commit is contained in:
2025-06-03 23:09:33 +08:00
parent 63d21d6614
commit cfade95e97
8 changed files with 162 additions and 32 deletions

44
src/apps/preview/md.tsx Normal file
View File

@@ -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 (
<ToastProvider>
<Main />
</ToastProvider>
);
};
const Main = () => {
const [mdUrl, setMdUrl] = useState<string>('');
const [markdown, setMarkdown] = useState<string>('');
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 (
<div className='bg-white w-full h-full py-2 '>
<MarkdownPreview content={markdown} />
</div>
);
};

View File

@@ -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 (
<div className={cn('markdown-body scrollbar h-full overflow-auto px-6 py-2 max-w-[800px] border my-4 flex flex-col justify-self-center rounded-md shadow-md', props.className)} style={props.style}>
{props.children}
<div
className={cn(
'markdown-body scrollbar h-full overflow-auto w-full px-6 py-2 max-w-[800px] border my-4 flex flex-col justify-self-center rounded-md shadow-md',
props.className,
)}
style={props.style}>
{props.children ? <WrapperText>{props.children}</WrapperText> : <MarkdownPreviewWrapper content={clearMeta(props.content)} />}
</div>
);
};
export const WrapperText = (props: { children?: React.ReactNode; html?: string }) => {
if (props.html) {
return <div className='w-full' dangerouslySetInnerHTML={{ __html: props.html }} />;
}
return <div className='w-full h-full'>{props.children}</div>;
};
export const MarkdownPreviewWrapper = (props: Props) => {
const [html, setHtml] = useState<string>('');
useEffect(() => {
init();
}, [props.content]);
const init = async () => {
if (props.content) {
const htmlContent = await md2html(props.content);
setHtml(htmlContent);
} else {
setHtml('');
}
};
return <WrapperText html={html} />;
};

View File

@@ -9,19 +9,19 @@ tags: ['kevisual', 'platform', 'assistant']
## 目标
软件不再是开放者的归属而是使用者私自的后花园。AI 能够更快速的生成代码,所以用户只需要一个能把代码跑起来的平台,可视化部署管理,动作
软件不再是开放者的归属,而是使用者私自的后花园。生态发展下,AI 能够更快速的生成代码,所以用户只需要一个能把代码跑起来的平台,可视化部署管理。
所以类似于把一个小程序的平台挂到自己的网站,电脑私有部署。为了解决类小程序化,所以需要有一个程序框架去当作容器,代码是属于动态代码。
所以类似于把一个小程序的平台挂到自己的网站,自己的电脑私有部署这个平台。为了解决类小程序化,所以需要有一个程序框架去当作容器,代码是属于动态代码,这个框架我先简称为`平台`
什么语言能够实现这个功能呢?需要保证动态,需要保证浏览器容易执行,而且保持稳定性。**只有 js**。而在服务端同代码执行的deno 和 bun已经非常的优秀了。
什么语言能够实现这个功能呢?首要条件保证动态,然后需要保证浏览器容易执行,而且保持稳定性,最后客户端的也能用。**只有 js**。而在服务端同代码执行的,已经有 deno 和 bun已经非常的优秀了。
## 平台搭建
当私有化部署可以跨平台运行windowslinuxmacdocker。他对于用户而言就是一个终极的**助手**,而它是属于一个代码环境,用户可以放动态的代码。
当私有化部署可以跨平台运行windowslinuxmacdocker。他对于用户而言就是一个终极的**助手**,而它是属于一个代码运行环境,类似浏览器,用户可以放动态的代码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 的知识库的搭建
### 知识库的运用
### 知识库的运用

View File

@@ -0,0 +1,12 @@
# 作为一个助手的外接副屏
时刻在动态变化的内容,个人大屏幕。
时刻获取录制的声音转文字,
获取对话ai对话的任务返回对应的内容。
实时的操作,比如跳转到某一个地方的功能操作。

View File

@@ -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';
---

View File

@@ -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';
---
<link
rel='stylesheet'
href='https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown-light.min.css'
integrity='sha512-X175XRJAO6PHAUi8AA7GP8uUF5Wiv+w9bOi64i02CHKDQBsO1yy0jLSKaUKg/NhRCDYBmOLQCfKaTaXiyZlLrw=='
crossorigin='anonymous'
referrerpolicy='no-referrer'
/>
<Blank>
<App client:only />
</Blank>