diff --git a/packages/core/src/editor/dom-editor.ts b/packages/core/src/editor/dom-editor.ts index f7a32f80e..5c0ff093d 100644 --- a/packages/core/src/editor/dom-editor.ts +++ b/packages/core/src/editor/dom-editor.ts @@ -29,6 +29,8 @@ import $, { DOMRange, DOMSelection, DOMStaticRange, + isDocument, + isShadowRoot, isDOMElement, normalizeDOMPoint, isDOMSelection, @@ -122,7 +124,7 @@ export const DomEditor = { const el = DomEditor.toDOMNode(editor, editor) const root = el.getRootNode() - if ((root instanceof Document || root instanceof ShadowRoot) && root.getSelection != null) { + if ((isDocument(root) || isShadowRoot(root)) && Reflect.get(root, 'getSelection') != null) { return root } return el.ownerDocument diff --git a/packages/core/src/editor/plugins/with-content.ts b/packages/core/src/editor/plugins/with-content.ts index 1af7d7444..a5daf175f 100644 --- a/packages/core/src/editor/plugins/with-content.ts +++ b/packages/core/src/editor/plugins/with-content.ts @@ -370,7 +370,7 @@ export const withContent = (editor: T) => { * 重置 HTML 内容 * @param html html string */ - e.setHtml = (html: string = '') => { + e.setHtml = (html: string | null = '') => { // 记录编辑器当前状态 const isEditorDisabled = e.isDisabled() const isEditorFocused = e.isFocused() @@ -384,7 +384,7 @@ export const withContent = (editor: T) => { // https://github.com/wangeditor-team/wangEditor/issues/4754 e.clear() // 设置新内容 - const newContent = htmlToContent(e, html) + const newContent = htmlToContent(e, html == null ? '' : html) Transforms.insertFragment(e, newContent) // 恢复编辑器状态和选区 diff --git a/packages/core/src/text-area/event-handlers/beforeInput.ts b/packages/core/src/text-area/event-handlers/beforeInput.ts index 86a4c2be4..e7adaeec0 100644 --- a/packages/core/src/text-area/event-handlers/beforeInput.ts +++ b/packages/core/src/text-area/event-handlers/beforeInput.ts @@ -8,7 +8,7 @@ import { DomEditor } from '../../editor/dom-editor' import { IDomEditor } from '../../editor/interface' import TextArea from '../TextArea' import { hasEditableTarget } from '../helpers' -import { DOMStaticRange } from '../../utils/dom' +import { DOMStaticRange, isDataTransfer } from '../../utils/dom' import { HAS_BEFORE_INPUT_SUPPORT } from '../../utils/ua' import { EDITOR_TO_CAN_PASTE } from '../../utils/weak-maps' @@ -138,7 +138,7 @@ function handleBeforeInput(e: Event, textarea: TextArea, editor: IDomEditor) { if (!EDITOR_TO_CAN_PASTE.get(editor)) break // 不可默认粘贴 } - if (data instanceof DataTransfer) { + if (isDataTransfer(data)) { // 这里处理非纯文本(如 html 图片文件等)的粘贴。对于纯文本的粘贴,使用 paste 事件 editor.insertData(data) } else if (typeof data === 'string') { diff --git a/packages/core/src/utils/dom.ts b/packages/core/src/utils/dom.ts index 0402d65b3..8c6284d5d 100644 --- a/packages/core/src/utils/dom.ts +++ b/packages/core/src/utils/dom.ts @@ -68,6 +68,25 @@ if (empty) $.fn.empty = empty export default $ +import { toString } from './util' + +export const isDocument = (value: any): value is Document => { + return toString(value) === '[object HTMLDocument]' +} + +export const isShadowRoot = (value: any): value is ShadowRoot => { + return toString(value) === '[object ShadowRoot]' +} + +export const isDataTransfer = (value: any): value is DataTransfer => { + return toString(value) === '[object DataTransfer]' +} + +const HTML_ELEMENT_STR_REG_EXP = /\[object HTML([A-Z][a-z]*)*Element\]/ +export const isHTMLElememt = (value: any): value is HTMLElement => { + return HTML_ELEMENT_STR_REG_EXP.test(toString(value)) +} + // ------------------------------- 分割线,以下内容参考 slate-react dom.ts ------------------------------- // COMPAT: This is required to prevent TypeScript aliases from doing some very @@ -109,20 +128,14 @@ export const isDOMElement = (value: any): value is DOMElement => { * Check if a value is a DOM node. */ export const isDOMNode = (value: any): value is DOMNode => { - const window = getDefaultView(value) - return ( - !!window && - // @ts-ignore - value instanceof window.Node - ) + return value != null && typeof value.nodeType === 'number' } /** * Check if a value is a DOM selection. */ export const isDOMSelection = (value: any): value is DOMSelection => { - const window = value && value.anchorNode && getDefaultView(value.anchorNode) - return !!window && value instanceof window.Selection + return toString(value) === '[object Selection]' } /** @@ -343,7 +356,7 @@ export function walkTextNodes( handler: (textNode: DOMNode, parent: DOMElement) => void ) { // void elem 内部的 text 不处理 - if (elem instanceof HTMLElement && elem.dataset.slateVoid === 'true') return + if (isHTMLElememt(elem) && elem.dataset.slateVoid === 'true') return for (let nodes = elem.childNodes, i = nodes.length; i--; ) { const node = nodes[i] diff --git a/packages/core/src/utils/util.ts b/packages/core/src/utils/util.ts index 7a6827c35..4c520f680 100644 --- a/packages/core/src/utils/util.ts +++ b/packages/core/src/utils/util.ts @@ -88,3 +88,5 @@ export function deReplaceHtmlSpecialSymbols(str: string) { .replace(/™/g, '™') .replace(/"/g, '"') } + +export const toString = (val: unknown): string => Object.prototype.toString.call(val)