generated from template/astro-template
	feat: md preview
This commit is contained in:
		@@ -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"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										46
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								src/apps/preview/md.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/apps/preview/md.tsx
									
									
									
									
									
										Normal 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>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
@@ -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} />;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
							
								
								
									
										12
									
								
								src/data/blogs/logger-life/25-06-03-扩展屏幕.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/data/blogs/logger-life/25-06-03-扩展屏幕.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
# 作为一个助手的外接副屏
 | 
			
		||||
 | 
			
		||||
时刻在动态变化的内容,个人大屏幕。
 | 
			
		||||
 | 
			
		||||
时刻获取录制的声音转文字,
 | 
			
		||||
 | 
			
		||||
获取对话ai对话的任务,返回对应的内容。
 | 
			
		||||
 | 
			
		||||
实时的操作,比如跳转到某一个地方的功能操作。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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';
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								src/pages/preview/md.astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/pages/preview/md.astro
									
									
									
									
									
										Normal 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>
 | 
			
		||||
		Reference in New Issue
	
	Block a user