Skip to content

Commit

Permalink
fix: 同一节点只能绑定一个编辑器实例
Browse files Browse the repository at this point in the history
  • Loading branch information
clinfc committed Apr 17, 2021
1 parent 5496965 commit 935d03f
Show file tree
Hide file tree
Showing 17 changed files with 183 additions and 123 deletions.
6 changes: 2 additions & 4 deletions src/editor/index.ts
Expand Up @@ -10,7 +10,7 @@ import SelectionAndRangeAPI from './selection'
import CommandAPI from './command'
import Text from '../text/index'
import Menus from '../menus/index'
import initDom from './init-fns/init-dom'
import initDom, { selectorValidator } from './init-fns/init-dom'
import initSelection from './init-fns/init-selection'
import bindEvent from './init-fns/bind-event'
import i18nextInit from './init-fns/i18next-init'
Expand Down Expand Up @@ -87,9 +87,7 @@ class Editor {
this.toolbarSelector = toolbarSelector
this.textSelector = textSelector

if (toolbarSelector == null) {
throw new Error('错误:初始化编辑器时候未传入任何参数,请查阅文档')
}
selectorValidator(this)

// 属性的默认值,后面可能会再修改
// 默认配置 - 当一个页面有多个编辑器的时候,因为 JS 的特性(引用类型)会导致多个编辑器的 config 引用是同一个,所以需要 深度克隆 断掉引用
Expand Down
46 changes: 46 additions & 0 deletions src/editor/init-fns/init-dom.ts
Expand Up @@ -111,3 +111,49 @@ export default function (editor: Editor): void {
editor.toolbarElemId = toolbarElemId
editor.textElemId = textElemId
}

/**
* 工具栏/文本区域 DOM selector 有效性验证
* @param editor 编辑器实例
*/
export function selectorValidator(editor: Editor) {
const name = 'data-we-id'
const regexp = /^wangEditor-\d+$/
const { textSelector, toolbarSelector } = editor

const $el = {
bar: $('<div></div>'),
text: $('<div></div>'),
}

if (toolbarSelector == null) {
throw new Error('错误:初始化编辑器时候未传入任何参数,请查阅文档')
} else {
$el.bar = $(toolbarSelector)
if (!$el.bar.elems.length) {
throw new Error(`无效的节点选择器:${toolbarSelector}`)
}
if (regexp.test($el.bar.attr(name))) {
throw new Error('初始化节点已存在编辑器实例,无法重复创建编辑器')
}
}
if (textSelector) {
$el.text = $(textSelector)
if (!$el.text.elems.length) {
throw new Error(`无效的节点选择器:${textSelector}`)
}
if (regexp.test($el.text.attr(name))) {
throw new Error('初始化节点已存在编辑器实例,无法重复创建编辑器')
}
}

// 给节点做上标记
$el.bar.attr(name, editor.id)
$el.text.attr(name, editor.id)

// 在编辑器销毁前取消标记
editor.beforeDestroy(function () {
$el.bar.removeAttr(name)
$el.text.removeAttr(name)
})
}
13 changes: 10 additions & 3 deletions test/helpers/create-editor.ts
Expand Up @@ -6,13 +6,22 @@
import Editor from '../../src/editor/index'
import $ from 'jquery'

let count = 1

/**
* 生成唯一的节点 id
*/
export function selector() {
return `edit${count++}`
}

/**
* 创建编辑器实例,用于测试
* @param document document
* @param toolbarId toolbar id
* @param textId text id
*/
function createEditor(
export default function createEditor(
document: Document,
toolbarId: string,
textId?: string,
Expand Down Expand Up @@ -48,5 +57,3 @@ function createEditor(
editor.create()
return editor
}

export default createEditor
6 changes: 3 additions & 3 deletions test/unit/config/menus.test.ts
Expand Up @@ -3,10 +3,10 @@
* @author wangfupeng
*/

import createEditor from '../../helpers/create-editor'
import createEditor, { selector } from '../../helpers/create-editor'

test('菜单数量', () => {
const editor = createEditor(document, 'div1')
const editor = createEditor(document, selector())
const menus = editor.config.menus
const $toolbarChildren = editor.$toolbarElem.childNodes() || []
let childrenLen = $toolbarChildren.length - 1
Expand All @@ -17,7 +17,7 @@ test('菜单数量', () => {

// 各个菜单的配置,随后开发的时候再加
test('菜单 exclude', () => {
const editor = createEditor(document, 'div1', '', {
const editor = createEditor(document, selector(), '', {
excludeMenus: ['bold'],
})
const menus = editor.config.menus
Expand Down
6 changes: 3 additions & 3 deletions test/unit/editor/auto-focus.test.ts
Expand Up @@ -3,7 +3,7 @@
* @author tonghan
*/

import createEditor from '../../helpers/create-editor'
import createEditor, { selector } from '../../helpers/create-editor'
import $ from '../../../src/utils/dom-core'

const TEXT = '我是一行文字'
Expand All @@ -12,13 +12,13 @@ const $P = $('<p></p>')
$P.append($SPAN)

test('auto-focus: false', () => {
createEditor(document, 'div1', '', { focus: false })
createEditor(document, selector(), '', { focus: false })
const rangeCount = window?.getSelection()?.rangeCount
expect(rangeCount).toBe(0)
})

test('auto-focus: true', () => {
createEditor(document, 'div1')
createEditor(document, selector())
const rangeCount = window?.getSelection()?.rangeCount
expect(rangeCount).toBe(1)
})
4 changes: 2 additions & 2 deletions test/unit/editor/disable.test.ts
@@ -1,12 +1,12 @@
import createEditor from '../../helpers/create-editor'
import createEditor, { selector } from '../../helpers/create-editor'
import Editor from '../../../src/editor/index'
import disableInit from '../../../src/editor/disable'

let editor: Editor

describe('Editor disable', () => {
beforeEach(() => {
editor = createEditor(document, 'div1')
editor = createEditor(document, selector())
})

test('编辑器可以被禁用', () => {
Expand Down
35 changes: 35 additions & 0 deletions test/unit/editor/full-screen-config.test.ts
@@ -0,0 +1,35 @@
import createEditor, { selector } from '../../helpers/create-editor'
import Editor from '../../../src/editor/index'
import $ from 'jquery'

let editor: Editor
const FULLSCREEN_MENU_CLASS_SELECTOR = '.w-e-icon-fullscreen'

describe('设置全屏', () => {
beforeEach(() => {
editor = createEditor(document, selector())
})

test('编辑器默认初始化全屏菜单', () => {
const toolbarSelector = editor.$toolbarElem.elems[0].className
const fullMenuEl = $(`.${toolbarSelector}`).find(FULLSCREEN_MENU_CLASS_SELECTOR)

expect(fullMenuEl.length).toBe(1)
})

test('编辑器区和菜单分离的编辑器不初始化全屏菜单', () => {
const seprateModeEditor = createEditor(document, selector(), selector())
const toolbarSelector = seprateModeEditor.$toolbarElem.selector as string
const fullMenuEl = $(toolbarSelector).find(FULLSCREEN_MENU_CLASS_SELECTOR)

expect(fullMenuEl.length).toBe(0)
})

test('编辑器配置 showFullScreen 为false时不初始化全屏菜单', () => {
const seprateModeEditor = createEditor(document, selector(), '', { showFullScreen: false })
const toolbarSelector = seprateModeEditor.$toolbarElem.selector as string
const fullMenuEl = $(toolbarSelector).find(FULLSCREEN_MENU_CLASS_SELECTOR)

expect(fullMenuEl.length).toBe(0)
})
})
23 changes: 23 additions & 0 deletions test/unit/editor/full-screen-set.test.ts
@@ -0,0 +1,23 @@
import createEditor, { selector } from '../../helpers/create-editor'
import { setFullScreen } from '../../../src/editor/init-fns/set-full-screen'
import $ from 'jquery'

const EDIT_CONTAINER_FULLSCREEN_CLASS = 'w-e-full-screen-editor'

test('调用 setFullScreen 设置编辑器全屏模式', () => {
const editor = createEditor(document, selector())

setFullScreen(editor)

const toolbarSelector = editor.$toolbarElem.elems[0].className
const $iconElem = $(`.${toolbarSelector}`).children().last().find('i')
const $editorParent = $(`.${toolbarSelector}`).parent().get(0)
const $textContainerElem = editor.$textContainerElem

expect($iconElem.get(0).className).toContain('w-e-icon-fullscreen_exit')
console.log($editorParent.className)
expect($editorParent.className).toContain(EDIT_CONTAINER_FULLSCREEN_CLASS)
expect(+$editorParent.style.zIndex).toEqual(editor.config.zIndexFullScreen)
const bar = editor.$toolbarElem.getBoundingClientRect()
expect($textContainerElem.elems[0].style.height).toBe(`calc(100% - ${bar.height}px)`)
})
23 changes: 23 additions & 0 deletions test/unit/editor/full-screen-unset.test.ts
@@ -0,0 +1,23 @@
import createEditor, { selector } from '../../helpers/create-editor'
import { setFullScreen, setUnFullScreen } from '../../../src/editor/init-fns/set-full-screen'
import $ from 'jquery'

const EDIT_CONTAINER_FULLSCREEN_CLASS = 'w-e-full-screen-editor'

test.only('调用 setUnFullScreen 取消编辑器全屏模式', () => {
const editor = createEditor(document, selector())

setFullScreen(editor)

setUnFullScreen(editor)

const toolbarSelector = editor.$toolbarElem.elems[0].className
const $iconElem = $(`.${toolbarSelector}`).children().last().find('i')
const $editorParent = $(`.${toolbarSelector}`).parent().get(0)
const $textContainerElem = editor.$textContainerElem

expect($iconElem.get(0).className).toContain('w-e-icon-fullscreen')
expect($editorParent.className).not.toContain(EDIT_CONTAINER_FULLSCREEN_CLASS)
expect($editorParent.style.zIndex).toBe('auto')
expect($textContainerElem.elems[0].style.height).toBe(editor.config.height + 'px')
})
6 changes: 3 additions & 3 deletions test/unit/editor/history/compile.test.ts
Expand Up @@ -3,7 +3,7 @@
* @author luochao
*/

import createEditor from '../../../helpers/create-editor'
import createEditor, { selector } from '../../../helpers/create-editor'
import Editor from '../../../../src/editor'
import compile, {
compileType,
Expand Down Expand Up @@ -37,7 +37,7 @@ const originalValue = UA.isFirefox

describe('Editor history compile', () => {
beforeEach(() => {
editor = createEditor(document, 'div1')
editor = createEditor(document, selector())
})

afterEach(() => {
Expand Down Expand Up @@ -74,7 +74,7 @@ describe('Editor history compile', () => {
const observer = new MutationObserver((mutationList: MutationRecord[]) => {
const compileData = compile(mutationList)
expect(compileData instanceof Array).toBeTruthy()
expect(compileData.length).toBe(4)
expect(compileData.length).toBeGreaterThanOrEqual(4)
done()
})

Expand Down
4 changes: 2 additions & 2 deletions test/unit/editor/history/data-html.test.ts
Expand Up @@ -2,15 +2,15 @@
* @description Editor history data html cache
* @author luochao
*/
import createEditor from '../../../helpers/create-editor'
import createEditor, { selector } from '../../../helpers/create-editor'
import Editor from '../../../../src/editor'
import HtmlCache from '../../../../src/editor/history/data/html'

let editor: Editor
let htmlCache: HtmlCache
describe('Editor history html cache', () => {
beforeEach(() => {
editor = createEditor(document, 'div1', '', {
editor = createEditor(document, selector(), '', {
compatibleMode: () => true,
})

Expand Down
4 changes: 2 additions & 2 deletions test/unit/editor/history/decompile.test.ts
Expand Up @@ -3,7 +3,7 @@
* @author luochao
*/

import createEditor from '../../../helpers/create-editor'
import createEditor, { selector } from '../../../helpers/create-editor'
import Editor from '../../../../src/editor'
import compile from '../../../../src/editor/history/data/node/compile'
import { restore, revoke } from '../../../../src/editor/history/data/node/decompilation'
Expand All @@ -13,7 +13,7 @@ let editor: Editor

describe('Editor history decompile', () => {
beforeEach(() => {
editor = createEditor(document, 'div1')
editor = createEditor(document, selector())
})

test('可以通过revoke方法撤销编辑器设置的html', done => {
Expand Down
68 changes: 0 additions & 68 deletions test/unit/editor/set-full-screen.test.ts

This file was deleted.

0 comments on commit 935d03f

Please sign in to comment.