From c92fe3fdd4855abd727caf6169f0761584a1baf9 Mon Sep 17 00:00:00 2001 From: SunLxy <1011771396@qq.com> Date: Sat, 9 Jul 2022 11:11:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kktrc.ts | 4 +- README.md | 77 +++++++------- package.json | 9 +- website/App.tsx | 6 +- website/components/Markdown/Code.tsx | 76 ++++++++++---- website/components/Markdown/index.tsx | 146 ++++++++------------------ website/react-app-env.d.ts | 10 +- 7 files changed, 155 insertions(+), 173 deletions(-) diff --git a/.kktrc.ts b/.kktrc.ts index 52ac4ded..d8c1dbc3 100644 --- a/.kktrc.ts +++ b/.kktrc.ts @@ -5,6 +5,7 @@ import lessModules from '@kkt/less-modules'; import rawModules from '@kkt/raw-modules'; import scopePluginOptions from '@kkt/scope-plugin-options'; import pkg from './package.json'; +import { mdCodeModulesLoader } from "markdown-react-code-preview-loader"; export default (conf: WebpackConfiguration, env: 'production' | 'development', options: LoaderConfOptions) => { conf = lessModules(conf, env, options); @@ -30,7 +31,8 @@ export default (conf: WebpackConfiguration, env: 'production' | 'development', o conf.plugins!.push(new webpack.DefinePlugin({ VERSION: JSON.stringify(pkg.version), })); - + conf = mdCodeModulesLoader(conf); + if (env === 'production') { conf.module!.exprContextCritical = false; conf.output = { ...conf.output, publicPath: './' }; diff --git a/README.md b/README.md index e8fab610..1df37dce 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,8 @@ import Split from '@uiw/react-split'; - 拖拽至最小宽度,可通过设置子节点样式 `minWidth: 30`,来达到效果 - 默认情况下,不设置样式 `width`,需要将某个子节点样式设为 `flex: 1`,来自适应 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -60,16 +59,15 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo ``` ### 可用于布局 设置 `visiable={false}` 禁用拖拽栏,可用于布局。 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -109,14 +107,14 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo + ``` ### 多栏分割 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -135,14 +133,14 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo + ``` ### 线条拖拽 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -174,14 +172,14 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo +; ``` ### 垂直分割 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -194,14 +192,14 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo + ``` ### 嵌套使用 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -224,16 +222,16 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo + ``` ### 拖拽工具不显示 下面实例通过设置 `visiable` 的值来设置拖拽工具是否可见 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -265,16 +263,16 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo + ``` ### 禁用拖拽 通过设置 `disable` 的值,禁用拖拽工具拖拽。 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -314,17 +312,16 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo + ``` ### 抽屉 可拖拽左边栏宽度。 - -```jsx +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true import React from 'react'; -import ReactDOM from 'react-dom'; import Split from '@uiw/react-split'; import { Menu, Button } from 'uiw'; @@ -371,14 +368,14 @@ class Demo extends React.Component { ) } } -ReactDOM.render(, _mount_); +export default Demo + ``` ### 支持自定义拖拽工具栏 - -```jsx -import ReactDOM from 'react-dom'; +```jsx mdx:preview&background=#fff&codeSandbox=true&codePen=true +import React from 'react'; import Split from '@uiw/react-split'; const Demo = () => ( @@ -402,7 +399,7 @@ const Demo = () => ( ); -ReactDOM.render(, _mount_); +export default Demo ``` ## Props diff --git a/package.json b/package.json index 801631a2..0f21a6db 100644 --- a/package.json +++ b/package.json @@ -39,15 +39,18 @@ "react-dom": ">=16.8.0" }, "devDependencies": { + "@uiw/react-codesandbox": "^1.1.5", + "@uiw/react-codepen": "^1.0.2", + "markdown-react-code-preview-loader": "^2.1.2", + "react-code-preview-layout": "^2.0.4", "@kkt/less-modules": "~7.1.1", "@kkt/ncc": "~1.0.8", "@kkt/raw-modules": "~7.1.1", "@kkt/scope-plugin-options": "~7.1.1", "@types/react": "~17.0.39", "@types/react-dom": "~17.0.13", - "@uiw/react-code-preview": "~4.0.6", "@uiw/react-github-corners": "~1.5.3", - "@uiw/react-markdown-preview": "~3.5.1", + "@uiw/react-markdown-preview": "~4.0.22", "@uiw/reset.css": "~1.0.6", "compile-less-cli": "~1.8.11", "kkt": "~7.1.5", @@ -74,4 +77,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/website/App.tsx b/website/App.tsx index 99e98bc9..7099f9a9 100644 --- a/website/App.tsx +++ b/website/App.tsx @@ -2,12 +2,12 @@ import React from 'react'; import GitHubCorners from '@uiw/react-github-corners'; import '@uiw/reset.css'; import './App.css'; -import Page from './Page'; +import Page from './components/Markdown'; const App: React.FC = () => { return (
- +

React Split

@@ -17,7 +17,7 @@ const App: React.FC = () => { A piece of view can be divided into areas where the width or height can be adjusted by dragging.

-
+
diff --git a/website/components/Markdown/Code.tsx b/website/components/Markdown/Code.tsx index a95e0f1c..81260f64 100755 --- a/website/components/Markdown/Code.tsx +++ b/website/components/Markdown/Code.tsx @@ -1,27 +1,48 @@ -import CodePreview, { CodePreviewProps } from '@uiw/react-code-preview'; +import pkg from '../../../package.json'; +import Codepen from '@uiw/react-codepen'; +import Codesandbox from '@uiw/react-codesandbox'; +const version = pkg.version -export interface CodeProps extends CodePreviewProps { - code: string; - version: string; - codePen: boolean; - codeSandbox?: boolean; - dependencies: any; + +const getCodePenJs = (js: string, includeModule: string[]) => { + let include = (includeModule || []).join('|'); + let resultJs = js.replace(/import([\s\S]*?)(?=['"])['"].*['"]( *;|;)?/gm, (str) => { + // eslint-disable-next-line no-useless-escape + if (include && new RegExp(`from\\s+['"](${include})['"](\s.+)?;?`).test(str)) { + return str; + } + return `/** ${str} **/`; + }); + return resultJs } -export default function Code({ version, dependencies, codePen, codeSandbox, ...other }: CodeProps) { - const props: CodePreviewProps = { ...other }; +export const getToolbarExtra = (code: string, codePen: boolean, codeSandbox: boolean): React.ReactNode[] => { + let toolbarExtra: React.ReactNode[] = []; if (codePen) { - props.codePenOption = { + const codePenOption = { title: `@uiw/react-split${version} - demo`, - includeModule: ['@uiw/react-split'], - js: (props.code || '').replace('_mount_', 'document.getElementById("container")'), + // js: getCodePenJs(code || '', ['@uiw/react-split']).replace('_mount_', 'document.getElementById("container")'), + js: `${getCodePenJs(code || '', ["@uiw/react-split"]).replace( + 'export default', + 'const APP_Default = ', + )}\nReactDOM.createRoot(document.getElementById("container")).render()`, html: '
', css_external: `https://unpkg.com/@uiw/react-split@${version}/dist/split.min.css`, - js_external: `https://unpkg.com/react@17.x/umd/react.development.js;https://unpkg.com/react-dom@17.x/umd/react-dom.development.js;https://unpkg.com/classnames@2.2.6/index.js;https://unpkg.com/@uiw/react-split@${version}/dist/split.min.js;https://unpkg.com/@uiw/codepen-require-polyfill@1.1.3/index.js`, - }; + js_external: `https://unpkg.com/react@18.x/umd/react.development.js;https://unpkg.com/react-dom@18.x/umd/react-dom.development.js;https://unpkg.com/classnames@2.2.6/index.js;https://unpkg.com/@uiw/react-split@${version}/dist/split.min.js;https://unpkg.com/@uiw/codepen-require-polyfill@1.1.3/index.js`, + } + toolbarExtra.push( + + + + + , + ); } if (codeSandbox) { - props.codeSandboxOption = { + const codeSandboxOption = { files: { 'sandbox.config.json': { content: `{ @@ -35,8 +56,11 @@ export default function Code({ version, dependencies, codePen, codeSandbox, ...o 'public/index.html': { content: `
`, }, + 'src/app.js': { + content: code, + }, 'src/index.js': { - content: (props.code || '').replace('_mount_', 'document.getElementById("container")'), + content: `import React from "react";\nimport ReactClient from "react-dom/client";\nimport App from "./app";\nReactClient.createRoot(document.getElementById("container")).render();`, }, '.kktrc.js': { content: `import lessModules from "@kkt/less-modules";\nexport default (conf, env, options) => {\n conf = lessModules(conf, env, options);\n return conf;\n};`, @@ -46,8 +70,8 @@ export default function Code({ version, dependencies, codePen, codeSandbox, ...o name: 'uiw-demo', description: `uiw v${version} - demo`, dependencies: { - react: '^17.0.2', - 'react-dom': '^17.0.2', + react: '^18.x', + 'react-dom': '^18.x', '@uiw/react-split': 'latest', }, devDependencies: { @@ -63,7 +87,17 @@ export default function Code({ version, dependencies, codePen, codeSandbox, ...o }, }, }, - }; + } + toolbarExtra.push( + + + + + , + ); } - return ; -} + return toolbarExtra +} \ No newline at end of file diff --git a/website/components/Markdown/index.tsx b/website/components/Markdown/index.tsx index e6bc2c54..3f1cb8be 100644 --- a/website/components/Markdown/index.tsx +++ b/website/components/Markdown/index.tsx @@ -1,108 +1,54 @@ -import { Component } from 'react'; import MarkdownPreview from '@uiw/react-markdown-preview'; -import pkg from '../../../package.json'; -import Code from './Code'; import styles from './index.module.less'; +import data from "../../../README.md" +import { useEffect, useRef } from "react" +import CodeLayout from 'react-code-preview-layout'; +import { getMetaId, isMeta, getURLParameters } from 'markdown-react-code-preview-loader'; +import { CodeComponent, ReactMarkdownNames } from 'react-markdown/lib/ast-to-react'; +import { getToolbarExtra } from "./Code" +const CodePreview: CodeComponent | ReactMarkdownNames = ({ inline, node, ...props }) => { + const $dom = useRef(null); + const { 'data-meta': meta, ...rest } = props as any; -interface MarkdownProps { } -interface MarkdownState { - mdStr: string; -} - -const getCodeStr = (data: any[] = [], code: string = '') => { - data.forEach((node) => { - if (node.type === 'text') { - code += node.value; - } else if (node.children && Array.isArray(node.children)) { - code += getCodeStr(node.children); + useEffect(() => { + if ($dom.current) { + const parentElement = $dom.current.parentElement; + if (parentElement && parentElement.parentElement) { + parentElement.parentElement.replaceChild($dom.current, parentElement); + } } - }); - return code; -}; + }, [$dom]); -/** - * 代码注释参数 - * - * ```md - * - * ``` - * 参数用英文逗号隔开 - * - * - `bgWhite` 设置代码预览背景白色,否则为格子背景。 - * - `noCode` 不显示代码编辑器。 - * - `noPreview` 不显示代码预览效果。 - * - `noScroll` 预览区域不显示滚动条。 - * - `codePen` 显示 Codepen 按钮,要特别注意 `包导入的问题`,实例中的 `import` 主要用于 Codepen 使用。 - */ -export interface OptionsMarkdown { - bgWhite?: boolean; - noCode?: boolean; - noPreview?: boolean; - noScroll?: boolean; - codePen?: boolean; -}; - -export default class Markdown extends Component { - constructor(props:MarkdownProps) { - super(props); - this.state = { - mdStr: '', - }; + if (inline || !isMeta(meta)) { + return ; } - getMdStr?: () => Promise; - dependencies?: any; - componentDidMount() { - if (this.getMdStr) { - this.getMdStr().then((str: any) => { - this.setState({ - mdStr: str.default || str, - }); - }); - } - } - render() { + + const line = node.position?.start.line; + const metaId = getMetaId(meta) || String(line); + const Child = data.components[`${metaId}`]; + if (metaId && typeof Child === 'function') { + const code = data.data[metaId].value || ''; + const param = getURLParameters(meta); return ( - { - const { noPreview, bordered, noScroll, bgWhite, noCode, codePen, codeSandbox } = props as any; - if (inline) { - return ; - } - const config = { - noPreview, - bordered, - noScroll, - bgWhite, - noCode, - codePen, - codeSandbox, - } as any; - if (Object.keys(config).filter((name) => config[name] !== undefined).length === 0) { - return ; - } - return ( - - ); - }, - }} - /> - ) + } text={code}> + + + ); } -} \ No newline at end of file + return ; +}; + +export default function Markdown() { + return ( + + ); +} diff --git a/website/react-app-env.d.ts b/website/react-app-env.d.ts index 8642661e..240dfa2c 100644 --- a/website/react-app-env.d.ts +++ b/website/react-app-env.d.ts @@ -1,11 +1,11 @@ /// -declare module '*.less' { +declare module "*.less" { const classes: { readonly [key: string]: string }; export default classes; } - -declare module '*.md' { - const file: string; - export default file; +declare module "*.md" { + import { CodeBlockData } from "markdown-react-code-preview-loader"; + const src: CodeBlockData; + export default src; }