From 075a3b7f0316818e8304173811389cafdaf33003 Mon Sep 17 00:00:00 2001 From: zbf Date: Mon, 11 Nov 2024 11:09:50 +0800 Subject: [PATCH 1/3] feat: export `clearSideEffects` --- packages/MdEditor/hooks.ts | 9 +++--- .../layouts/Content/hooks/useHighlight.ts | 7 +++-- .../layouts/Content/hooks/useKatex.ts | 8 +++-- .../layouts/Content/hooks/useMermaid.ts | 5 +-- .../layouts/Content/markdownIt/xss/index.ts | 4 +-- packages/MdEditor/layouts/Toolbar/hooks.ts | 5 +-- packages/MdEditor/layouts/Toolbar/index.tsx | 31 +++++++++++++++++-- packages/MdEditor/static/index.ts | 15 +++++++++ packages/index.ts | 2 ++ packages/util.ts | 15 +++++++++ 10 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 packages/MdEditor/static/index.ts create mode 100644 packages/util.ts diff --git a/packages/MdEditor/hooks.ts b/packages/MdEditor/hooks.ts index 5db678a9..d2e8fc1d 100644 --- a/packages/MdEditor/hooks.ts +++ b/packages/MdEditor/hooks.ts @@ -50,6 +50,7 @@ import { PREVIEW_ONLY_CHANGED } from './static/event-name'; import { ContentExposeParam } from './layouts/Content/type'; +import { CDN_IDS } from './static'; /** * 键盘监听 @@ -165,12 +166,12 @@ export const useExpansion = (staticProps: StaticProps) => { ...css, rel: 'stylesheet', href: editorExtensions.cropper!.css, - id: `${prefix}-cropperCss` + id: CDN_IDS.croppercss }); appendHandler('script', { ...js, src: editorExtensions.cropper!.js, - id: `${prefix}-cropper` + id: CDN_IDS.cropperjs }); } @@ -181,7 +182,7 @@ export const useExpansion = (staticProps: StaticProps) => { appendHandler('script', { ...standaloneJs, src: editorExtensions.prettier!.standaloneJs, - id: `${prefix}-prettier` + id: CDN_IDS.prettier }); } @@ -191,7 +192,7 @@ export const useExpansion = (staticProps: StaticProps) => { appendHandler('script', { ...parserMarkdownJs, src: editorExtensions.prettier!.parserMarkdownJs, - id: `${prefix}-prettierMD` + id: CDN_IDS.prettierMD }); } }, [noPrettier, noUploadImg]); diff --git a/packages/MdEditor/layouts/Content/hooks/useHighlight.ts b/packages/MdEditor/layouts/Content/hooks/useHighlight.ts index 8eb42069..e21d682e 100644 --- a/packages/MdEditor/layouts/Content/hooks/useHighlight.ts +++ b/packages/MdEditor/layouts/Content/hooks/useHighlight.ts @@ -1,7 +1,8 @@ import { useContext, useEffect, useRef, useState } from 'react'; -import { prefix, configOption } from '~/config'; +import { configOption } from '~/config'; import { EditorContext } from '~/context'; import { appendHandler, updateHandler } from '~/utils/dom'; +import { CDN_IDS } from '~/static'; import { ContentPreviewProps } from '../props'; /** @@ -25,7 +26,7 @@ const useHighlight = (props: ContentPreviewProps) => { updateHandler('link', { ...highlight.css, rel: 'stylesheet', - id: `${prefix}-hlCss` + id: CDN_IDS.hlcss }); }, [highlight.css, props.noHighlight]); @@ -39,7 +40,7 @@ const useHighlight = (props: ContentPreviewProps) => { 'script', { ...highlight.js, - id: `${prefix}-hljs`, + id: CDN_IDS.hljs, onload() { hljsRef.current = window.hljs; setHljsInited(true); diff --git a/packages/MdEditor/layouts/Content/hooks/useKatex.ts b/packages/MdEditor/layouts/Content/hooks/useKatex.ts index 170d1ddd..7e52d435 100644 --- a/packages/MdEditor/layouts/Content/hooks/useKatex.ts +++ b/packages/MdEditor/layouts/Content/hooks/useKatex.ts @@ -1,6 +1,8 @@ import { useEffect, useRef, useState } from 'react'; -import { prefix, configOption } from '~/config'; +import { configOption } from '~/config'; import { appendHandler } from '~/utils/dom'; +import { CDN_IDS } from '~~/MdEditor/static'; + import { ContentPreviewProps } from '../props'; /** @@ -27,7 +29,7 @@ const useKatex = (props: ContentPreviewProps) => { 'script', { src: editorExtensions.katex!.js, - id: `${prefix}-katex`, + id: CDN_IDS.katexjs, onload() { katexRef.current = window.katex; setKatexInited(true); @@ -38,7 +40,7 @@ const useKatex = (props: ContentPreviewProps) => { appendHandler('link', { rel: 'stylesheet', href: editorExtensions.katex!.css, - id: `${prefix}-katexCss` + id: CDN_IDS.katexcss }); }, [props.noKatex]); diff --git a/packages/MdEditor/layouts/Content/hooks/useMermaid.ts b/packages/MdEditor/layouts/Content/hooks/useMermaid.ts index fbebfac3..af2a2934 100644 --- a/packages/MdEditor/layouts/Content/hooks/useMermaid.ts +++ b/packages/MdEditor/layouts/Content/hooks/useMermaid.ts @@ -4,6 +4,7 @@ import { prefix, configOption } from '~/config'; import { EditorContext } from '~/context'; import { appendHandler } from '~/utils/dom'; import { mermaidCache } from '~/utils/cache'; +import { CDN_IDS } from '~~/MdEditor/static'; import { ContentPreviewProps } from '../props'; @@ -52,7 +53,7 @@ const useMermaid = (props: ContentPreviewProps) => { ...editorExtensionsAttrs.mermaid?.js, rel: 'modulepreload', href: jsSrc, - id: `${prefix}-mermaid-m` + id: CDN_IDS.mermaidM }); import( @@ -69,7 +70,7 @@ const useMermaid = (props: ContentPreviewProps) => { { ...editorExtensionsAttrs.mermaid?.js, src: jsSrc, - id: `${prefix}-mermaid`, + id: CDN_IDS.mermaid, onload() { mermaidRef.current = window.mermaid; configMermaid(); diff --git a/packages/MdEditor/layouts/Content/markdownIt/xss/index.ts b/packages/MdEditor/layouts/Content/markdownIt/xss/index.ts index 81aa32d1..7cc26189 100644 --- a/packages/MdEditor/layouts/Content/markdownIt/xss/index.ts +++ b/packages/MdEditor/layouts/Content/markdownIt/xss/index.ts @@ -34,7 +34,7 @@ const MdWhiteList: xss.IFilterXSSOptions['whiteList'] = { ] }; -const XSSPlugin = (md: markdownit, options: XSSPluginType) => { +export const XSSPlugin = (md: markdownit, options: XSSPluginType) => { const { extendedWhiteList = {}, xss: xssOption = {} } = options; let xssIns: xss.FilterXSS; @@ -87,5 +87,3 @@ const XSSPlugin = (md: markdownit, options: XSSPluginType) => { } }); }; - -export default XSSPlugin; diff --git a/packages/MdEditor/layouts/Toolbar/hooks.ts b/packages/MdEditor/layouts/Toolbar/hooks.ts index 87e9a8ef..7004fe5e 100644 --- a/packages/MdEditor/layouts/Toolbar/hooks.ts +++ b/packages/MdEditor/layouts/Toolbar/hooks.ts @@ -1,5 +1,5 @@ import { RefObject, useCallback, useContext, useEffect, useRef, useState } from 'react'; -import { prefix, configOption } from '~/config'; +import { configOption } from '~/config'; import { EditorContext } from '~/context'; import { appendHandler } from '~/utils/dom'; import { ToolDirective } from '~/utils/content-help'; @@ -10,6 +10,7 @@ import { UPLOAD_IMAGE } from '~/static/event-name'; import bus from '~/utils/event-bus'; +import { CDN_IDS } from '~/static'; import { ToolbarProps } from './'; import { HoverData } from './TableShape'; @@ -69,7 +70,7 @@ export const useSreenfull = (props: ToolbarProps) => { { ...editorExtensionsAttrs.screenfull?.js, src: editorExtensions.screenfull!.js, - id: `${prefix}-screenfull`, + id: CDN_IDS.screenfull, onload() { // 复制实例 screenfull.current = window.screenfull; diff --git a/packages/MdEditor/layouts/Toolbar/index.tsx b/packages/MdEditor/layouts/Toolbar/index.tsx index ea61abae..3dd69b4c 100644 --- a/packages/MdEditor/layouts/Toolbar/index.tsx +++ b/packages/MdEditor/layouts/Toolbar/index.tsx @@ -1081,7 +1081,31 @@ const Toolbar = (props: ToolbarProps) => { }, [ props, - ult.toolbarTips, + ult.toolbarTips?.bold, + ult.toolbarTips?.underline, + ult.toolbarTips?.italic, + ult.toolbarTips?.strikeThrough, + ult.toolbarTips?.sub, + ult.toolbarTips?.sup, + ult.toolbarTips?.quote, + ult.toolbarTips?.unorderedList, + ult.toolbarTips?.orderedList, + ult.toolbarTips?.task, + ult.toolbarTips?.codeRow, + ult.toolbarTips?.code, + ult.toolbarTips?.link, + ult.toolbarTips?.image, + ult.toolbarTips?.revoke, + ult.toolbarTips?.next, + ult.toolbarTips?.save, + ult.toolbarTips?.prettier, + ult.toolbarTips?.pageFullscreen, + ult.toolbarTips?.fullscreen, + ult.toolbarTips?.catalog, + ult.toolbarTips?.preview, + ult.toolbarTips?.previewOnly, + ult.toolbarTips?.htmlPreview, + ult.toolbarTips?.github, emitHandler, TitleDropdown, setModalData, @@ -1094,8 +1118,9 @@ const Toolbar = (props: ToolbarProps) => { MermaidDropdown, KatexDropdown, theme, - language, - previewTheme + codeTheme, + previewTheme, + language ] ); diff --git a/packages/MdEditor/static/index.ts b/packages/MdEditor/static/index.ts new file mode 100644 index 00000000..a9f47b4d --- /dev/null +++ b/packages/MdEditor/static/index.ts @@ -0,0 +1,15 @@ +import { prefix } from '../config'; + +export const CDN_IDS: Record = { + hljs: `${prefix}-hljs`, + hlcss: `${prefix}-hlCss`, + prettier: `${prefix}-prettier`, + prettierMD: `${prefix}-prettierMD`, + cropperjs: `${prefix}-cropper`, + croppercss: `${prefix}-cropperCss`, + screenfull: `${prefix}-screenfull`, + mermaidM: `${prefix}-mermaid-m`, + mermaid: `${prefix}-mermaid`, + katexjs: `${prefix}-katex`, + katexcss: `${prefix}-katexCss` +}; diff --git a/packages/index.ts b/packages/index.ts index 851e2404..54889692 100644 --- a/packages/index.ts +++ b/packages/index.ts @@ -9,6 +9,8 @@ export { default as MdModal } from './MdEditor/components/Modal'; export { default as StrIcon } from './MdEditor/components/Icon/Str'; export { default as NormalFooterToolbar } from './NormalFooterToolbar'; +export * from '~/layouts/Content/markdownIt/xss'; export * from './config'; +export * from './util'; export * from '~/type'; diff --git a/packages/util.ts b/packages/util.ts new file mode 100644 index 00000000..a28d1c58 --- /dev/null +++ b/packages/util.ts @@ -0,0 +1,15 @@ +import { CDN_IDS } from './MdEditor/static'; + +/** + * 清空组件带来的副作用,例如 + * 1. 使用CDN嵌入的链接,为了保证多个组件能够正常使用,组件在卸载时不会主动移除 + */ +export const clearSideEffects = () => { + (Object.keys(CDN_IDS) as Array).forEach((key) => { + const ele = document.getElementById(CDN_IDS[key]); + + if (ele) { + ele.remove(); + } + }); +}; From cc56d2ae3a7014bd62a72763fc65402df8c26fc8 Mon Sep 17 00:00:00 2001 From: zbf Date: Mon, 11 Nov 2024 13:14:20 +0800 Subject: [PATCH 2/3] feat: no longer include XSS protection by default --- packages/MdEditor/layouts/Content/hooks/useMarkdownIt.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/MdEditor/layouts/Content/hooks/useMarkdownIt.ts b/packages/MdEditor/layouts/Content/hooks/useMarkdownIt.ts index 3e573b2d..687baef1 100644 --- a/packages/MdEditor/layouts/Content/hooks/useMarkdownIt.ts +++ b/packages/MdEditor/layouts/Content/hooks/useMarkdownIt.ts @@ -28,7 +28,6 @@ import KatexPlugin from '../markdownIt/katex'; import AdmonitionPlugin from '../markdownIt/admonition'; import HeadingPlugin from '../markdownIt/heading'; import CodePlugin from '../markdownIt/code'; -import XSSPlugin from '../markdownIt/xss'; import TaskListPlugin from '../markdownIt/task'; import { ContentPreviewProps } from '../props'; @@ -137,11 +136,6 @@ const useMarkdownIt = (props: ContentPreviewProps, previewOnly: boolean) => { customIconRef } }, - { - type: 'xss', - plugin: XSSPlugin, - options: {} - }, { type: 'sub', plugin: SubPlugin, From 4975782042ef5820dec4ef89dd48bf6f24282309 Mon Sep 17 00:00:00 2001 From: zbf Date: Mon, 11 Nov 2024 13:37:09 +0800 Subject: [PATCH 3/3] refactor: `inputBoxWitdh` => `inputBoxWidth` --- packages/MdEditor/Editor.tsx | 6 +++--- packages/MdEditor/config.ts | 2 +- .../layouts/Content/hooks/useResize.ts | 18 +++++++++--------- packages/MdEditor/layouts/Content/props.ts | 4 ++-- packages/MdEditor/type.ts | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/MdEditor/Editor.tsx b/packages/MdEditor/Editor.tsx index 916d1701..6cfd71a5 100644 --- a/packages/MdEditor/Editor.tsx +++ b/packages/MdEditor/Editor.tsx @@ -56,7 +56,7 @@ const Editor = forwardRef((props: EditorProps, ref: ForwardedRef) => { noHighlight = defaultProps.noHighlight, noImgZoomIn = defaultProps.noImgZoomIn, language = defaultProps.language, - inputBoxWitdh = defaultProps.inputBoxWitdh, + inputBoxWidth = defaultProps.inputBoxWidth, sanitizeMermaid = defaultProps.sanitizeMermaid, transformImgUrl = defaultProps.transformImgUrl, codeFoldable = defaultProps.codeFoldable, @@ -190,8 +190,8 @@ const Editor = forwardRef((props: EditorProps, ref: ForwardedRef) => { theme={props.theme} noImgZoomIn={noImgZoomIn} onDrop={props.onDrop} - inputBoxWitdh={inputBoxWitdh} - onInputBoxWitdhChange={props.onInputBoxWitdhChange} + inputBoxWidth={inputBoxWidth} + onInputBoxWidthChange={props.onInputBoxWidthChange} sanitizeMermaid={sanitizeMermaid} transformImgUrl={transformImgUrl} codeFoldable={codeFoldable} diff --git a/packages/MdEditor/config.ts b/packages/MdEditor/config.ts index 1e2ae1c1..c43f912e 100644 --- a/packages/MdEditor/config.ts +++ b/packages/MdEditor/config.ts @@ -477,7 +477,7 @@ export const defaultProps = { autoDetectCode: false, noHighlight: false, noImgZoomIn: false, - inputBoxWitdh: '50%', + inputBoxWidth: '50%', sanitizeMermaid: (h: string) => Promise.resolve(h), transformImgUrl: (t: string) => t, codeFoldable: true, diff --git a/packages/MdEditor/layouts/Content/hooks/useResize.ts b/packages/MdEditor/layouts/Content/hooks/useResize.ts index b94e1463..f0ee1f32 100644 --- a/packages/MdEditor/layouts/Content/hooks/useResize.ts +++ b/packages/MdEditor/layouts/Content/hooks/useResize.ts @@ -9,11 +9,11 @@ const useResize = ( resizeRef: RefObject ) => { const [inputWrapperStyle, setInputWrapperStyle] = useState({ - width: props.inputBoxWitdh + width: props.inputBoxWidth }); const [resizeOperateStyle, setResizeOperateStyle] = useState({ - left: props.inputBoxWitdh + left: props.inputBoxWidth }); /** @@ -25,7 +25,7 @@ const useResize = ( props.setting.preview || props.setting.htmlPreview ); - const resizedWidth = useRef(props.inputBoxWitdh); + const resizedWidth = useRef(props.inputBoxWidth); useEffect(() => { // 挂载后计算宽度的数值 @@ -60,7 +60,7 @@ const useResize = ( }); resizedWidth.current = ibw; - props.onInputBoxWitdhChange?.(ibw); + props.onInputBoxWidthChange?.(ibw); }; const resizeMousedown = () => { @@ -92,23 +92,23 @@ const useResize = ( }, [contentRef, props, resizeRef]); useEffect(() => { - if (props.inputBoxWitdh) { - resizedWidth.current = props.inputBoxWitdh; + if (props.inputBoxWidth) { + resizedWidth.current = props.inputBoxWidth; setInputWrapperStyle((prevState) => { return { ...prevState, - width: props.inputBoxWitdh + width: props.inputBoxWidth }; }); setResizeOperateStyle((prevState) => { return { ...prevState, - left: props.inputBoxWitdh + left: props.inputBoxWidth }; }); } - }, [props.inputBoxWitdh]); + }, [props.inputBoxWidth]); useEffect(() => { const po = props.setting.previewOnly; diff --git a/packages/MdEditor/layouts/Content/props.ts b/packages/MdEditor/layouts/Content/props.ts index 8da4ee21..f4e0cd7e 100644 --- a/packages/MdEditor/layouts/Content/props.ts +++ b/packages/MdEditor/layouts/Content/props.ts @@ -49,8 +49,8 @@ export type ContentProps = Readonly< * @returns */ onDrop?: (event: DragEvent) => void; - inputBoxWitdh: string; - onInputBoxWitdhChange?: (width: string) => void; + inputBoxWidth: string; + onInputBoxWidthChange?: (width: string) => void; transformImgUrl: (text: string) => string | Promise; } & ContentPreviewProps >; diff --git a/packages/MdEditor/type.ts b/packages/MdEditor/type.ts index 5d33fc34..8f99f4bd 100644 --- a/packages/MdEditor/type.ts +++ b/packages/MdEditor/type.ts @@ -471,11 +471,11 @@ export interface EditorProps extends MdPreviewProps { * * @example '100px'/'50%' */ - inputBoxWitdh?: string; + inputBoxWidth?: string; /** * 输入框宽度变化事件 */ - onInputBoxWitdhChange?: (width: string) => void; + onInputBoxWidthChange?: (width: string) => void; /** * 替换粘贴的图片链接 *