Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

253 图片无法回显行内元素包含行内元素无法解析 #283

46 changes: 27 additions & 19 deletions packages/core/src/create/create-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,30 @@

import { createEditor, Descendant } from 'slate'
import { withHistory } from 'slate-history'
import { withDOM } from '../editor/plugins/with-dom'

import { genEditorConfig } from '../config/index'
import { IEditorConfig } from '../config/interface'
import { IDomEditor } from '../editor/interface'
import { withConfig } from '../editor/plugins/with-config'
import { withContent } from '../editor/plugins/with-content'
import { withEventData } from '../editor/plugins/with-event-data'
import { withDOM } from '../editor/plugins/with-dom'
import { withEmitter } from '../editor/plugins/with-emitter'
import { withSelection } from '../editor/plugins/with-selection'
import { withEventData } from '../editor/plugins/with-event-data'
import { withMaxLength } from '../editor/plugins/with-max-length'
import TextArea from '../text-area/TextArea'
import { withSelection } from '../editor/plugins/with-selection'
import HoverBar from '../menus/bar/HoverBar'
import { genEditorConfig } from '../config/index'
import { IDomEditor } from '../editor/interface'
import { DomEditor } from '../editor/dom-editor'
import { IEditorConfig } from '../config/interface'
import { promiseResolveThen } from '../utils/util'
import { isRepeatedCreateTextarea, genDefaultContent, htmlToContent } from './helper'
import TextArea from '../text-area/TextArea'
import type { DOMElement } from '../utils/dom'
import { promiseResolveThen } from '../utils/util'
import {
EDITOR_TO_TEXTAREA,
TEXTAREA_TO_EDITOR,
EDITOR_TO_CONFIG,
HOVER_BAR_TO_EDITOR,
EDITOR_TO_HOVER_BAR,
EDITOR_TO_TEXTAREA,
HOVER_BAR_TO_EDITOR,
TEXTAREA_TO_EDITOR,
} from '../utils/weak-maps'
import bindNodeRelation from './bind-node-relation'
import $ from '../utils/dom'
import { genDefaultContent, htmlToContent, isRepeatedCreateTextarea } from './helper'

type PluginFnType = <T extends IDomEditor>(editor: T) => T

Expand All @@ -45,14 +44,17 @@ interface ICreateOption {
* 创建编辑器
*/
export default function (option: Partial<ICreateOption>) {
const { selector = '', config = {}, content, html, plugins = [] } = option
const {
selector = '', config = {}, content, html, plugins = [],
} = option

// 创建实例 - 使用插件
let editor = withHistory(
withMaxLength(
withEmitter(withSelection(withContent(withConfig(withDOM(withEventData(createEditor()))))))
)
withEmitter(withSelection(withContent(withConfig(withDOM(withEventData(createEditor())))))),
),
cycleccc marked this conversation as resolved.
Show resolved Hide resolved
)

if (selector) {
// 检查是否对同一个 DOM 重复创建
if (isRepeatedCreateTextarea(editor, selector)) {
Expand All @@ -62,6 +64,7 @@ export default function (option: Partial<ICreateOption>) {

// 处理配置
const editorConfig = genEditorConfig(config)

EDITOR_TO_CONFIG.set(editor, editorConfig)
const { hoverbarKeys = {} } = editorConfig

Expand All @@ -81,28 +84,32 @@ export default function (option: Partial<ICreateOption>) {
if (editor.children.length === 0) {
editor.children = genDefaultContent() // 默认内容
}
DomEditor.normalizeContent(editor) // 格式化,用户输入的 content 可能不规范(如两个相连的 text 没有合并)
// DomEditor.normalizeContent(editor) // 格式化,用户输入的 content 可能不规范(如两个相连的 text 没有合并)
cycleccc marked this conversation as resolved.
Show resolved Hide resolved

if (selector) {
// 传入了 selector ,则创建 textarea DOM
const textarea = new TextArea(selector)

cycleccc marked this conversation as resolved.
Show resolved Hide resolved
EDITOR_TO_TEXTAREA.set(editor, textarea)
TEXTAREA_TO_EDITOR.set(textarea, editor)
textarea.changeViewState() // 初始化时触发一次,以便能初始化 textarea DOM 和 selection

// 判断 textarea 最小高度,并给出提示
promiseResolveThen(() => {
const $scroll = textarea.$scroll
if ($scroll == null) return

if ($scroll == null) { return }
if ($scroll.height() < 300) {
let info = '编辑区域高度 < 300px 这可能会导致 modal hoverbar 定位异常'

cycleccc marked this conversation as resolved.
Show resolved Hide resolved
info += '\nTextarea height < 300px . This may be cause modal and hoverbar position error'
console.warn(info, $scroll)
}
})

// 创建 hoverbar DOM
let hoverbar: HoverBar | null

if (Object.keys(hoverbarKeys).length > 0) {
hoverbar = new HoverBar()
HOVER_BAR_TO_EDITOR.set(hoverbar, editor)
Expand All @@ -123,6 +130,7 @@ export default function (option: Partial<ICreateOption>) {

// 触发生命周期
const { onCreated, onDestroyed } = editorConfig

cycleccc marked this conversation as resolved.
Show resolved Hide resolved
if (onCreated) {
editor.on('created', () => onCreated(editor))
}
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/parse-html/parse-elem-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Descendant } from 'slate'

import { IDomEditor } from '../editor/interface'
import { PRE_PARSE_HTML_CONF_LIST, TEXT_TAGS } from '../index'
import { getTagName } from '../utils/dom'
import { getTagName, NodeType } from '../utils/dom'
import parseCommonElemHtml from './parse-common-elem-html'
import parseTextElemHtml from './parse-text-elem-html'

Expand Down Expand Up @@ -41,6 +41,7 @@ function parseElemHtml($elem: Dom7Array, editor: IDomEditor): Descendant | Desce
return Array.from(childNodes).map(child => {
const $childElem = $(child)

if ($childElem[0].nodeType === NodeType.TEXT_NODE) { return { text: $childElem[0].textContent || '' } }
return parseTextElemHtml($childElem, editor)
})
}
Expand Down
19 changes: 0 additions & 19 deletions packages/list-module/__tests__/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,23 +227,4 @@ describe('list plugin test', () => {
editor.insertBreak()
expect(editor.children).toEqual([{ type: 'paragraph', children: [{ text: '' }] }])
})

it('兼容之前的 JSON 格式', () => {
const listItem = { type: 'list-item', children: [{ text: 'hello' }] }
let editor = createEditor({
// 之前的 JSON 格式
content: [
{
type: 'bulleted-list',
children: [listItem],
},
],
})
const bulletedList = { type: 'bulleted-list', children: [listItem] }

editor = withList(editor) // 使用插件
editor.insertNode(bulletedList)

expect(editor.children).toEqual([listItem])
})
})
22 changes: 0 additions & 22 deletions packages/video-module/__tests__/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,5 @@ describe('videoModule module', () => {

expect(fn).toBeCalled()
})

test('使用 withVideo 插件后,Editor 调用 normalizeNode 方法确保 Video 元素后面有 paragraph、block、header 等元素', () => {
const videoElem = {
type: 'video',
src: 'test.mp4',
children: [],
}
const editor = createEditor({
content: [videoElem],
})
const newEditor = withVideo(editor)

newEditor.normalizeNode([videoElem, [0]])
expect(newEditor.children).toEqual([
{
type: 'video',
src: 'test.mp4',
children: [{ text: '' }],
},
{ type: 'paragraph', children: [{ text: '' }] },
])
})
})
})