vue-editify 0.0.50 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/examples/App.vue +27 -45
- package/lib/editify.es.js +6877 -7829
- package/lib/editify.umd.js +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -2
- package/src/Editify.vue +262 -1240
- package/src/components/{bussiness/Menu.vue → Menu.vue} +238 -139
- package/src/components/{bussiness/Toolbar.vue → Toolbar.vue} +227 -141
- package/src/components/base/Button.vue +6 -6
- package/src/components/base/Checkbox.vue +4 -4
- package/src/components/base/Layer.vue +12 -12
- package/src/components/{bussiness → common}/InsertImage.vue +7 -7
- package/src/components/{bussiness → common}/InsertVideo.vue +7 -7
- package/src/core/function.js +1044 -0
- package/src/core/rule.js +239 -0
- package/src/core/{index.js → tool.js} +60 -296
- package/src/index.js +1 -1
- /package/src/components/{bussiness → common}/Colors.vue +0 -0
- /package/src/components/{bussiness → common}/InsertLink.vue +0 -0
- /package/src/components/{bussiness → common}/InsertTable.vue +0 -0
package/src/core/rule.js
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
import { AlexElement } from 'alex-editor'
|
2
|
+
import { getHljsHtml } from '../hljs'
|
3
|
+
import { getColNumbers } from './tool'
|
4
|
+
import { isList, isTask } from './function'
|
5
|
+
|
6
|
+
//更新代码块内的光标位置
|
7
|
+
const updateRangeInPre = (editor, element, originalTextElements, newElements) => {
|
8
|
+
if (!editor.range) {
|
9
|
+
return
|
10
|
+
}
|
11
|
+
//如果虚拟光标的起点在代码块内对虚拟光标的起点进行重新定位
|
12
|
+
if (editor.range.anchor.element.getBlock().isEqual(element)) {
|
13
|
+
//获取起点所在文本元素的在所有文本元素中的序列
|
14
|
+
const elIndex = originalTextElements.findIndex(el => editor.range.anchor.element.isEqual(el))
|
15
|
+
//起点在整个代码内容中的位置
|
16
|
+
const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item) => total + item.textContent.length, 0) + editor.range.anchor.offset
|
17
|
+
//获取pre下新的子孙元素中全部的文本元素
|
18
|
+
const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
|
19
|
+
let i = 0
|
20
|
+
let index = 0
|
21
|
+
//遍历
|
22
|
+
while (i < newTextElements.length) {
|
23
|
+
let newIndex = index + newTextElements[i].textContent.length
|
24
|
+
if (offset >= index && offset <= newIndex) {
|
25
|
+
editor.range.anchor.element = newTextElements[i]
|
26
|
+
editor.range.anchor.offset = offset - index
|
27
|
+
break
|
28
|
+
}
|
29
|
+
i++
|
30
|
+
index = newIndex
|
31
|
+
}
|
32
|
+
}
|
33
|
+
//如果虚拟光标的终点在代码块内需要对虚拟光标的终点进行重新定位
|
34
|
+
if (editor.range.focus.element.getBlock().isEqual(element)) {
|
35
|
+
//获取终点所在文本元素的在所有文本元素中的序列
|
36
|
+
const elIndex = originalTextElements.findIndex(el => editor.range.focus.element.isEqual(el))
|
37
|
+
//终点在整个代码内容中的位置
|
38
|
+
const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item) => total + item.textContent.length, 0) + editor.range.focus.offset
|
39
|
+
//获取全部的新文本元素
|
40
|
+
const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
|
41
|
+
let i = 0
|
42
|
+
let index = 0
|
43
|
+
//遍历
|
44
|
+
while (i < newTextElements.length) {
|
45
|
+
let newIndex = index + newTextElements[i].textContent.length
|
46
|
+
if (offset >= index && offset <= newIndex) {
|
47
|
+
editor.range.focus.element = newTextElements[i]
|
48
|
+
editor.range.focus.offset = offset - index
|
49
|
+
break
|
50
|
+
}
|
51
|
+
i++
|
52
|
+
index = newIndex
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
//元素格式化时转换ol和li标签
|
58
|
+
export const parseList = (editor, element) => {
|
59
|
+
//ol标签和ul标签转为div
|
60
|
+
if (element.parsedom == 'ol' || element.parsedom == 'ul') {
|
61
|
+
if (element.hasChildren()) {
|
62
|
+
element.children.forEach((el, index) => {
|
63
|
+
const newEl = el.clone()
|
64
|
+
newEl.parsedom = 'div'
|
65
|
+
newEl.type = element.type
|
66
|
+
if (!newEl.hasMarks()) {
|
67
|
+
newEl.marks = {}
|
68
|
+
}
|
69
|
+
newEl.marks['data-editify-list'] = element.parsedom
|
70
|
+
//插入到该元素之前
|
71
|
+
editor.addElementBefore(newEl, element)
|
72
|
+
})
|
73
|
+
}
|
74
|
+
element.toEmpty()
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
//元素格式化时处理有序列表的序号值
|
79
|
+
export const orderdListHandle = function (editor, element) {
|
80
|
+
//有序列表的序号处理
|
81
|
+
if (isList(element, true)) {
|
82
|
+
//获取前一个元素
|
83
|
+
const previousElement = editor.getPreviousElement(element)
|
84
|
+
//如果前一个元素存在并且也是有序列表
|
85
|
+
if (previousElement && isList(previousElement, true)) {
|
86
|
+
const previousValue = Number(previousElement.marks['data-editify-value'])
|
87
|
+
element.marks['data-editify-value'] = previousValue + 1
|
88
|
+
}
|
89
|
+
//前一个元素不是有序列表,则从0开始
|
90
|
+
else {
|
91
|
+
element.marks['data-editify-value'] = 1
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
//元素格式化时处理媒体元素和链接
|
97
|
+
export const mediaHandle = function (editor, element) {
|
98
|
+
//图片、视频和链接设置marks
|
99
|
+
if (element.parsedom == 'img' || element.parsedom == 'video' || element.parsedom == 'a') {
|
100
|
+
const marks = {
|
101
|
+
'data-editify-element': element.key
|
102
|
+
}
|
103
|
+
if (element.hasMarks()) {
|
104
|
+
Object.assign(element.marks, marks)
|
105
|
+
} else {
|
106
|
+
element.marks = marks
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
//视频的特殊处理,两侧无元素时在两侧加上空白文本
|
111
|
+
if (element.parsedom == 'video') {
|
112
|
+
const previousElement = editor.getPreviousElement(element)
|
113
|
+
const newTextElement = editor.getNextElement(element)
|
114
|
+
//如果不存在前一个元素
|
115
|
+
if (!previousElement || previousElement.isEmpty()) {
|
116
|
+
const spaceText = AlexElement.getSpaceElement()
|
117
|
+
editor.addElementBefore(spaceText, element)
|
118
|
+
}
|
119
|
+
//如果不存在后一个元素
|
120
|
+
if (!newTextElement || newTextElement.isEmpty()) {
|
121
|
+
const spaceText = AlexElement.getSpaceElement()
|
122
|
+
editor.addElementAfter(spaceText, element)
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
//元素格式化时处理表格
|
128
|
+
export const tableHandle = function (editor, element) {
|
129
|
+
if (element.parsedom == 'table') {
|
130
|
+
const marks = {
|
131
|
+
'data-editify-element': element.key
|
132
|
+
}
|
133
|
+
if (element.hasMarks()) {
|
134
|
+
Object.assign(element.marks, marks)
|
135
|
+
} else {
|
136
|
+
element.marks = marks
|
137
|
+
}
|
138
|
+
const elements = AlexElement.flatElements(element.children)
|
139
|
+
const rows = elements.filter(el => {
|
140
|
+
return el.parsedom == 'tr'
|
141
|
+
})
|
142
|
+
let colgroup = elements.find(el => {
|
143
|
+
return el.parsedom == 'colgroup'
|
144
|
+
})
|
145
|
+
if (colgroup) {
|
146
|
+
colgroup.children.forEach(col => {
|
147
|
+
if (!col.hasMarks()) {
|
148
|
+
col.marks = {
|
149
|
+
width: 'auto'
|
150
|
+
}
|
151
|
+
} else if (!col.marks['width']) {
|
152
|
+
col.marks['width'] = 'auto'
|
153
|
+
}
|
154
|
+
})
|
155
|
+
} else {
|
156
|
+
colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
|
157
|
+
const colNumber = getColNumbers(rows[0])
|
158
|
+
for (let i = colNumber - 1; i >= 0; i--) {
|
159
|
+
const col = new AlexElement(
|
160
|
+
'closed',
|
161
|
+
'col',
|
162
|
+
{
|
163
|
+
width: 'auto'
|
164
|
+
},
|
165
|
+
null,
|
166
|
+
null
|
167
|
+
)
|
168
|
+
editor.addElementTo(col, colgroup)
|
169
|
+
}
|
170
|
+
}
|
171
|
+
element.children = []
|
172
|
+
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
173
|
+
rows.reverse().forEach(row => {
|
174
|
+
editor.addElementTo(row, tbody)
|
175
|
+
})
|
176
|
+
editor.addElementTo(tbody, element)
|
177
|
+
editor.addElementTo(colgroup, element)
|
178
|
+
}
|
179
|
+
if (element.parsedom == 'th') {
|
180
|
+
element.parsedom = 'td'
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
//元素格式化时处理pre,将pre的内容根据语言进行样式处理
|
185
|
+
export const preHandle = function (editor, element, highlight, languages) {
|
186
|
+
//如果是代码块进行处理
|
187
|
+
if (element.parsedom == 'pre') {
|
188
|
+
const marks = {
|
189
|
+
'data-editify-element': element.key
|
190
|
+
}
|
191
|
+
if (element.hasMarks()) {
|
192
|
+
Object.assign(element.marks, marks)
|
193
|
+
} else {
|
194
|
+
element.marks = marks
|
195
|
+
}
|
196
|
+
//高亮处理
|
197
|
+
if (highlight && element.hasChildren()) {
|
198
|
+
//获取语言类型
|
199
|
+
let language = element.marks['data-editify-hljs'] || ''
|
200
|
+
if (language && languages && !languages.includes(language)) {
|
201
|
+
language = ''
|
202
|
+
}
|
203
|
+
//获取pre标签下所有的文本元素
|
204
|
+
const originalTextElements = AlexElement.flatElements(element.children).filter(el => el.isText() && !el.isEmpty())
|
205
|
+
//获取pre下的代码文本值
|
206
|
+
const textContent = originalTextElements.reduce((val, item) => {
|
207
|
+
return val + item.textContent
|
208
|
+
}, '')
|
209
|
+
//将文本元素的内容转为经过hljs处理的内容
|
210
|
+
const html = getHljsHtml(textContent, language)
|
211
|
+
if (html) {
|
212
|
+
//将经过hljs处理的内容转为元素数组
|
213
|
+
const newElements = editor.parseHtml(html)
|
214
|
+
//处理光标位置
|
215
|
+
updateRangeInPre(editor, element, originalTextElements, newElements)
|
216
|
+
//将新文本元素全部加入到pre子元素数组中
|
217
|
+
element.children = newElements
|
218
|
+
newElements.forEach(newEl => {
|
219
|
+
newEl.parent = element
|
220
|
+
})
|
221
|
+
}
|
222
|
+
}
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
//元素格式化时处理一些特殊的内部块元素,转为根级块元素
|
227
|
+
export const specialInblockHandle = function (editor, element) {
|
228
|
+
if (element.hasChildren()) {
|
229
|
+
element.children.forEach(el => {
|
230
|
+
if (isList(el, true) || isList(el, false) || isTask(el) || ['blockquote', 'pre', 'table', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'].includes(el.parsedom)) {
|
231
|
+
const newEl = el.clone()
|
232
|
+
newEl.type = 'block'
|
233
|
+
const block = element.getBlock()
|
234
|
+
editor.addElementAfter(newEl, block)
|
235
|
+
el.toEmpty()
|
236
|
+
}
|
237
|
+
})
|
238
|
+
}
|
239
|
+
}
|
@@ -1,6 +1,5 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import Dap from 'dap-util'
|
1
|
+
import { common as DapCommon, string as DapString, color as DapColor } from 'dap-util'
|
2
|
+
import { languages } from '../hljs'
|
4
3
|
|
5
4
|
//粘贴html时保留的数据
|
6
5
|
export const pasteKeepData = {
|
@@ -72,16 +71,6 @@ export const editorProps = {
|
|
72
71
|
type: Boolean,
|
73
72
|
default: false
|
74
73
|
},
|
75
|
-
//编辑内容高度
|
76
|
-
height: {
|
77
|
-
type: [String, Boolean],
|
78
|
-
default: '600px'
|
79
|
-
},
|
80
|
-
//是否自适应高度
|
81
|
-
autoheight: {
|
82
|
-
type: Boolean,
|
83
|
-
default: false
|
84
|
-
},
|
85
74
|
//是否显示边框
|
86
75
|
border: {
|
87
76
|
type: Boolean,
|
@@ -92,7 +81,7 @@ export const editorProps = {
|
|
92
81
|
type: String,
|
93
82
|
default: '#03a8f3',
|
94
83
|
validator(value) {
|
95
|
-
return
|
84
|
+
return DapCommon.matchingText(value, 'hex')
|
96
85
|
}
|
97
86
|
},
|
98
87
|
//视频宽高比
|
@@ -125,11 +114,6 @@ export const editorProps = {
|
|
125
114
|
type: Object,
|
126
115
|
default: null
|
127
116
|
},
|
128
|
-
//dom转换时的额外处理
|
129
|
-
customParseNode: {
|
130
|
-
type: Function,
|
131
|
-
default: null
|
132
|
-
},
|
133
117
|
//粘贴html时额外保留的标记(全部元素生效)
|
134
118
|
pasteKeepMarks: {
|
135
119
|
type: Object,
|
@@ -140,40 +124,21 @@ export const editorProps = {
|
|
140
124
|
type: Object,
|
141
125
|
default: null
|
142
126
|
},
|
143
|
-
|
144
|
-
|
145
|
-
type:
|
146
|
-
default:
|
147
|
-
return []
|
148
|
-
}
|
127
|
+
//自定义node转元素时的处理
|
128
|
+
customParseNoe: {
|
129
|
+
type: Function,
|
130
|
+
default: null
|
149
131
|
}
|
150
132
|
}
|
151
133
|
|
152
|
-
//获取colgroup的col数量
|
153
|
-
export const getColNumbers = row => {
|
154
|
-
const children = row?.children || []
|
155
|
-
let num = 0
|
156
|
-
children.forEach(td => {
|
157
|
-
if (td.hasMarks() && td.marks.hasOwnProperty('colspan')) {
|
158
|
-
const span = Number(td.marks.colspan)
|
159
|
-
if (!isNaN(span)) {
|
160
|
-
num += span
|
161
|
-
}
|
162
|
-
} else {
|
163
|
-
num += 1
|
164
|
-
}
|
165
|
-
})
|
166
|
-
return num
|
167
|
-
}
|
168
|
-
|
169
134
|
//对象平替值方法
|
170
|
-
export const mergeObject = (o1, o2)
|
171
|
-
if (!
|
135
|
+
export const mergeObject = function (o1, o2) {
|
136
|
+
if (!DapCommon.isObject(o1) && DapCommon.isObject(o2)) {
|
172
137
|
return null
|
173
138
|
}
|
174
139
|
for (let key in o2) {
|
175
140
|
//如果o1和o2的相同属性都是对象并且不是数组,则继续merge
|
176
|
-
if (
|
141
|
+
if (DapCommon.isObject(o2[key]) && !Array.isArray(o2[key]) && DapCommon.isObject(o1[key]) && !Array.isArray(o1[key])) {
|
177
142
|
o1[key] = mergeObject(o1[key], o2[key])
|
178
143
|
}
|
179
144
|
//否则直接将o2的值给o1
|
@@ -184,275 +149,74 @@ export const mergeObject = (o1, o2) => {
|
|
184
149
|
return o1
|
185
150
|
}
|
186
151
|
|
187
|
-
|
188
|
-
export const
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
//判断是否任务列表
|
193
|
-
export const blockIsTask = element => {
|
194
|
-
return element.type == 'block' && element.parsedom == 'div' && element.hasMarks() && element.marks.hasOwnProperty('data-editify-task')
|
195
|
-
}
|
196
|
-
|
197
|
-
//将某个块元素转为段落
|
198
|
-
export const blockToParagraph = element => {
|
199
|
-
element.marks = null
|
200
|
-
element.styles = null
|
201
|
-
element.parsedom = AlexElement.BLOCK_NODE
|
202
|
-
}
|
203
|
-
|
204
|
-
//其他元素转为列表
|
205
|
-
export const blockToList = (element, ordered = false) => {
|
206
|
-
//如果是列表则返回
|
207
|
-
if (blockIsList(element, ordered)) {
|
208
|
-
return
|
152
|
+
//判断对象是否含有某个属性或者属性值是否一致
|
153
|
+
export const queryHasValue = function (obj, name, value) {
|
154
|
+
//如果value不存在则判断是否拥有属性name
|
155
|
+
if (value == null || value == undefined) {
|
156
|
+
return obj.hasOwnProperty(name)
|
209
157
|
}
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
element.marks = {}
|
158
|
+
//固有的值
|
159
|
+
let ownValue = obj[name]
|
160
|
+
//如果ownValue不存在则直接返回false
|
161
|
+
if (ownValue == null || ownValue == undefined) {
|
162
|
+
return false
|
216
163
|
}
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
//其他元素转为任务列表
|
221
|
-
export const blockToTask = element => {
|
222
|
-
//如果是任务列表则返回
|
223
|
-
if (blockIsTask(element)) {
|
224
|
-
return
|
164
|
+
//如果value是字符串,则先将值转为小写
|
165
|
+
if (typeof value == 'string') {
|
166
|
+
value = value.toLocaleLowerCase()
|
225
167
|
}
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
element.parsedom = 'div'
|
230
|
-
if (!element.hasMarks()) {
|
231
|
-
element.marks = {}
|
168
|
+
//如果ownValue是字符串,则先将值转为小写
|
169
|
+
if (typeof ownValue == 'string') {
|
170
|
+
ownValue = ownValue.toLocaleLowerCase()
|
232
171
|
}
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
//元素格式化时转换ol和li标签
|
237
|
-
export const parseList = function (element) {
|
238
|
-
//ol标签和ul标签转为div
|
239
|
-
if (element.parsedom == 'ol' || element.parsedom == 'ul') {
|
240
|
-
if (element.hasChildren()) {
|
241
|
-
element.children.forEach((el, index) => {
|
242
|
-
const newEl = el.clone()
|
243
|
-
newEl.parsedom = 'div'
|
244
|
-
newEl.type = 'block'
|
245
|
-
if (!newEl.hasMarks()) {
|
246
|
-
newEl.marks = {}
|
247
|
-
}
|
248
|
-
newEl.marks['data-editify-list'] = element.parsedom
|
249
|
-
if (element.parsedom == 'ol') {
|
250
|
-
newEl.marks['data-editify-value'] = index + 1
|
251
|
-
}
|
252
|
-
//插入到该元素之后
|
253
|
-
this.addElementAfter(newEl, element)
|
254
|
-
})
|
255
|
-
}
|
256
|
-
element.toEmpty()
|
172
|
+
//如果value是rgb或者rgba格式,则去除空格
|
173
|
+
if (typeof value == 'string' && value && (DapCommon.matchingText(value, 'rgb') || DapCommon.matchingText(value, 'rgba'))) {
|
174
|
+
value = DapString.trim(value, true)
|
257
175
|
}
|
258
|
-
|
259
|
-
if (
|
260
|
-
|
261
|
-
const previousElement = this.getPreviousElement(element)
|
262
|
-
//如果前一个元素存在并且也是有序列表
|
263
|
-
if (previousElement && previousElement.hasMarks() && previousElement.marks['data-editify-list'] == 'ol') {
|
264
|
-
const previousValue = Number(previousElement.marks['data-editify-value'])
|
265
|
-
element.marks['data-editify-value'] = previousValue + 1
|
266
|
-
}
|
267
|
-
//前一个元素不是有序列表,则从0开始
|
268
|
-
else {
|
269
|
-
element.marks['data-editify-value'] = 1
|
270
|
-
}
|
176
|
+
//如果ownValue是rgb或者rgba格式,则去除空格
|
177
|
+
if (typeof ownValue == 'string' && ownValue && (DapCommon.matchingText(ownValue, 'rgb') || DapCommon.matchingText(ownValue, 'rgba'))) {
|
178
|
+
ownValue = DapString.trim(ownValue, true)
|
271
179
|
}
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
//图片、视频和链接设置marks
|
277
|
-
if (element.parsedom == 'img' || element.parsedom == 'video' || element.parsedom == 'a') {
|
278
|
-
const marks = {
|
279
|
-
'data-editify-element': element.key
|
280
|
-
}
|
281
|
-
if (element.hasMarks()) {
|
282
|
-
Object.assign(element.marks, marks)
|
283
|
-
} else {
|
284
|
-
element.marks = marks
|
285
|
-
}
|
180
|
+
//如果是十六进制值,转为rgb值
|
181
|
+
if (typeof value == 'string' && value && DapCommon.matchingText(value, 'hex')) {
|
182
|
+
const arr = DapColor.hex2rgb(value)
|
183
|
+
value = `rgb(${arr[0]},${arr[1]},${arr[2]})`
|
286
184
|
}
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
const newTextElement = this.getNextElement(element)
|
292
|
-
//如果不存在前一个元素
|
293
|
-
if (!previousElement || previousElement.isEmpty()) {
|
294
|
-
const spaceText = AlexElement.getSpaceElement()
|
295
|
-
this.addElementBefore(spaceText, element)
|
296
|
-
}
|
297
|
-
//如果不存在后一个元素
|
298
|
-
if (!newTextElement || newTextElement.isEmpty()) {
|
299
|
-
const spaceText = AlexElement.getSpaceElement()
|
300
|
-
this.addElementAfter(spaceText, element)
|
301
|
-
}
|
185
|
+
//如果是十六进制值,转为rgb值
|
186
|
+
if (typeof ownValue == 'string' && ownValue && DapCommon.matchingText(ownValue, 'hex')) {
|
187
|
+
const arr = DapColor.hex2rgb(ownValue)
|
188
|
+
ownValue = `rgb(${arr[0]},${arr[1]},${arr[2]})`
|
302
189
|
}
|
190
|
+
return ownValue == value
|
303
191
|
}
|
304
192
|
|
305
|
-
|
306
|
-
export const
|
307
|
-
if (
|
308
|
-
|
309
|
-
'data-editify-element': element.key
|
310
|
-
}
|
311
|
-
if (element.hasMarks()) {
|
312
|
-
Object.assign(element.marks, marks)
|
313
|
-
} else {
|
314
|
-
element.marks = marks
|
315
|
-
}
|
316
|
-
const elements = AlexElement.flatElements(element.children)
|
317
|
-
const rows = elements.filter(el => {
|
318
|
-
return el.parsedom == 'tr'
|
319
|
-
})
|
320
|
-
let colgroup = elements.find(el => {
|
321
|
-
return el.parsedom == 'colgroup'
|
322
|
-
})
|
323
|
-
if (colgroup) {
|
324
|
-
colgroup.children.forEach(col => {
|
325
|
-
if (!col.hasMarks()) {
|
326
|
-
col.marks = {
|
327
|
-
width: 'auto'
|
328
|
-
}
|
329
|
-
} else if (!col.marks['width']) {
|
330
|
-
col.marks['width'] = 'auto'
|
331
|
-
}
|
332
|
-
})
|
333
|
-
} else {
|
334
|
-
colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
|
335
|
-
const colNumber = getColNumbers(rows[0])
|
336
|
-
for (let i = colNumber - 1; i >= 0; i--) {
|
337
|
-
const col = new AlexElement(
|
338
|
-
'closed',
|
339
|
-
'col',
|
340
|
-
{
|
341
|
-
width: 'auto'
|
342
|
-
},
|
343
|
-
null,
|
344
|
-
null
|
345
|
-
)
|
346
|
-
this.addElementTo(col, colgroup)
|
347
|
-
}
|
348
|
-
}
|
349
|
-
element.children = []
|
350
|
-
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
351
|
-
rows.reverse().forEach(row => {
|
352
|
-
this.addElementTo(row, tbody)
|
353
|
-
})
|
354
|
-
this.addElementTo(tbody, element)
|
355
|
-
this.addElementTo(colgroup, element)
|
356
|
-
} else if (element.parsedom == 'th') {
|
357
|
-
element.parsedom = 'td'
|
193
|
+
//深拷贝函数
|
194
|
+
export const cloneData = function (data) {
|
195
|
+
if (DapCommon.isObject(data) || Array.isArray(data)) {
|
196
|
+
return JSON.parse(JSON.stringify(data))
|
358
197
|
}
|
198
|
+
return data
|
359
199
|
}
|
360
200
|
|
361
|
-
|
362
|
-
const
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
//起点在整个代码内容中的位置
|
371
|
-
const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item, i) => total + item.textContent.length, 0) + this.range.anchor.offset
|
372
|
-
//获取pre下新的子孙元素中全部的文本元素
|
373
|
-
const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
|
374
|
-
let i = 0
|
375
|
-
let index = 0
|
376
|
-
//遍历
|
377
|
-
while (i < newTextElements.length) {
|
378
|
-
let newIndex = index + newTextElements[i].textContent.length
|
379
|
-
if (offset >= index && offset <= newIndex) {
|
380
|
-
this.range.anchor.element = newTextElements[i]
|
381
|
-
this.range.anchor.offset = offset - index
|
382
|
-
break
|
383
|
-
}
|
384
|
-
i++
|
385
|
-
index = newIndex
|
386
|
-
}
|
387
|
-
}
|
388
|
-
//如果虚拟光标的终点在代码块内需要对虚拟光标的终点进行重新定位
|
389
|
-
if (this.range.focus.element.getBlock().isEqual(element)) {
|
390
|
-
//获取终点所在文本元素的在所有文本元素中的序列
|
391
|
-
const elIndex = originalTextElements.findIndex(el => this.range.focus.element.isEqual(el))
|
392
|
-
//终点在整个代码内容中的位置
|
393
|
-
const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item, i) => total + item.textContent.length, 0) + this.range.focus.offset
|
394
|
-
//获取全部的新文本元素
|
395
|
-
const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
|
396
|
-
let i = 0
|
397
|
-
let index = 0
|
398
|
-
//遍历
|
399
|
-
while (i < newTextElements.length) {
|
400
|
-
let newIndex = index + newTextElements[i].textContent.length
|
401
|
-
if (offset >= index && offset <= newIndex) {
|
402
|
-
this.range.focus.element = newTextElements[i]
|
403
|
-
this.range.focus.offset = offset - index
|
404
|
-
break
|
201
|
+
//根据行元素获取colgroup的col数量
|
202
|
+
export const getColNumbers = function (row) {
|
203
|
+
const children = row?.children || []
|
204
|
+
let num = 0
|
205
|
+
children.forEach(td => {
|
206
|
+
if (td.hasMarks() && td.marks.hasOwnProperty('colspan')) {
|
207
|
+
const span = Number(td.marks.colspan)
|
208
|
+
if (!isNaN(span)) {
|
209
|
+
num += span
|
405
210
|
}
|
406
|
-
i++
|
407
|
-
index = newIndex
|
408
|
-
}
|
409
|
-
}
|
410
|
-
}
|
411
|
-
|
412
|
-
//元素格式化时处理pre,将pre的内容根据语言进行样式处理
|
413
|
-
export const preHandle = function (element, highlight, languages) {
|
414
|
-
//如果是代码块进行处理
|
415
|
-
if ((element.isBlock() || element.isInblock()) && element.isPreStyle()) {
|
416
|
-
const marks = {
|
417
|
-
'data-editify-element': element.key
|
418
|
-
}
|
419
|
-
if (element.hasMarks()) {
|
420
|
-
Object.assign(element.marks, marks)
|
421
211
|
} else {
|
422
|
-
|
423
|
-
}
|
424
|
-
//高亮处理
|
425
|
-
if (highlight && element.hasChildren()) {
|
426
|
-
//获取语言类型
|
427
|
-
let language = element.marks['data-editify-hljs'] || ''
|
428
|
-
if (language && languages && !languages.includes(language)) {
|
429
|
-
language = ''
|
430
|
-
}
|
431
|
-
//获取pre标签下所有的文本元素
|
432
|
-
const originalTextElements = AlexElement.flatElements(element.children).filter(el => el.isText() && !el.isEmpty())
|
433
|
-
//获取pre下的代码文本值
|
434
|
-
const textContent = originalTextElements.reduce((val, item) => {
|
435
|
-
return val + item.textContent
|
436
|
-
}, '')
|
437
|
-
//将文本元素的内容转为经过hljs处理的内容
|
438
|
-
const html = getHljsHtml(textContent, language)
|
439
|
-
if (html) {
|
440
|
-
//将经过hljs处理的内容转为元素数组
|
441
|
-
const newElements = this.parseHtml(html)
|
442
|
-
//处理光标位置
|
443
|
-
updateRangeInPre.apply(this, [element, originalTextElements, newElements])
|
444
|
-
//将新文本元素全部加入到pre子元素数组中
|
445
|
-
element.children = newElements
|
446
|
-
newElements.forEach(newEl => {
|
447
|
-
newEl.parent = element
|
448
|
-
})
|
449
|
-
}
|
212
|
+
num += 1
|
450
213
|
}
|
451
|
-
}
|
214
|
+
})
|
215
|
+
return num
|
452
216
|
}
|
453
217
|
|
454
218
|
//获取菜单按钮列表数据配置
|
455
|
-
export const getButtonOptionsConfig = function (editTrans
|
219
|
+
export const getButtonOptionsConfig = function (editTrans) {
|
456
220
|
return {
|
457
221
|
//标题配置
|
458
222
|
heading: [
|
@@ -771,7 +535,7 @@ export const getToolbarConfig = function (editTrans, editLocale) {
|
|
771
535
|
//下划线
|
772
536
|
underline: {
|
773
537
|
//是否显示此工具
|
774
|
-
show:
|
538
|
+
show: true,
|
775
539
|
//左侧边框是否显示
|
776
540
|
leftBorder: false,
|
777
541
|
//右侧边框是否显示
|
package/src/index.js
CHANGED
File without changes
|
File without changes
|
File without changes
|