vue-editify 0.1.40 → 0.1.41
Sign up to get free protection for your applications and to get access to all the features.
- package/examples/App.vue +11 -6
- package/lib/core/function.d.ts +18 -6
- package/lib/core/tool.d.ts +0 -6
- package/lib/editify.es.js +239 -195
- package/lib/editify.umd.js +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/src/components/button/button.less +1 -1
- package/src/components/icon/icon.less +1 -1
- package/src/components/menu/menu.vue +2 -2
- package/src/components/toolbar/toolbar.vue +91 -85
- package/src/core/function.ts +89 -58
- package/src/core/rule.ts +60 -4
- package/src/core/tool.ts +2 -23
- package/src/editify/editify.less +8 -1
- package/src/editify/editify.vue +37 -32
- package/src/icon/iconfont.ttf +0 -0
- package/src/icon/iconfont.woff +0 -0
- package/src/index.ts +3 -2
- package/src/locale/en_US.ts +1 -0
- package/src/locale/zh_CN.ts +1 -0
- package/src/plugins/mathformula/index.ts +0 -1
- package/src/plugins/mathformula/insertMathformula/insertMathformula.vue +1 -1
package/src/core/rule.ts
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import { AlexEditor, AlexElement } from 'alex-editor'
|
2
2
|
import { LanguagesItemType, getHljsHtml } from '../hljs'
|
3
|
-
import { getColNumbers } from './tool'
|
4
3
|
import { isList, isTask } from './function'
|
5
4
|
import { common as DapCommon } from 'dap-util'
|
6
5
|
|
@@ -192,25 +191,55 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
|
|
192
191
|
element.styles = styles
|
193
192
|
}
|
194
193
|
const elements = AlexElement.flatElements(element.children!)
|
194
|
+
//所有的行元素
|
195
195
|
const rows = elements.filter(el => {
|
196
196
|
return el.parsedom == 'tr'
|
197
197
|
})
|
198
|
+
//colgroup元素
|
198
199
|
let colgroup = elements.find(el => {
|
199
200
|
return el.parsedom == 'colgroup'
|
200
201
|
})
|
202
|
+
//理论上的col的数量:取最多列数
|
203
|
+
const colNumber = Math.max(
|
204
|
+
...rows.map(row => {
|
205
|
+
return row.children!.length
|
206
|
+
})
|
207
|
+
)
|
208
|
+
//如果colgroup元素存在
|
201
209
|
if (colgroup) {
|
210
|
+
//遍历每个col元素设置默认的width:'auto
|
202
211
|
colgroup.children!.forEach(col => {
|
212
|
+
//如果没有任何标记
|
203
213
|
if (!col.hasMarks()) {
|
204
214
|
col.marks = {
|
205
215
|
width: 'auto'
|
206
216
|
}
|
207
|
-
}
|
217
|
+
}
|
218
|
+
//如果没有width标记
|
219
|
+
else if (!col.marks!['width']) {
|
208
220
|
col.marks!['width'] = 'auto'
|
209
221
|
}
|
210
222
|
})
|
211
|
-
|
223
|
+
//对缺少的col元素进行补全
|
224
|
+
const length = colgroup.children!.length
|
225
|
+
if (length < colNumber) {
|
226
|
+
for (let i = 0; i < colNumber - length; i++) {
|
227
|
+
const col = new AlexElement(
|
228
|
+
'closed',
|
229
|
+
'col',
|
230
|
+
{
|
231
|
+
width: 'auto'
|
232
|
+
},
|
233
|
+
null,
|
234
|
+
null
|
235
|
+
)
|
236
|
+
editor.addElementTo(col, colgroup, colgroup.children!.length)
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
//如果colgroup元素不存在则新建
|
241
|
+
else {
|
212
242
|
colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
|
213
|
-
const colNumber = getColNumbers(rows[0])
|
214
243
|
for (let i = colNumber - 1; i >= 0; i--) {
|
215
244
|
const col = new AlexElement(
|
216
245
|
'closed',
|
@@ -227,6 +256,16 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
|
|
227
256
|
element.children = []
|
228
257
|
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
229
258
|
rows.reverse().forEach(row => {
|
259
|
+
//对缺少的列进行补全
|
260
|
+
const length = row.children!.length
|
261
|
+
if (length < colNumber) {
|
262
|
+
for (let i = 0; i < colNumber - length; i++) {
|
263
|
+
const column = new AlexElement('inblock', 'td', null, null, null)
|
264
|
+
const breakElement = new AlexElement('closed', 'br', null, null, null)
|
265
|
+
editor.addElementTo(breakElement, column)
|
266
|
+
editor.addElementTo(column, row, row.children!.length)
|
267
|
+
}
|
268
|
+
}
|
230
269
|
editor.addElementTo(row, tbody)
|
231
270
|
})
|
232
271
|
editor.addElementTo(tbody, element)
|
@@ -235,6 +274,23 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
|
|
235
274
|
if (element.parsedom == 'th') {
|
236
275
|
element.parsedom = 'td'
|
237
276
|
}
|
277
|
+
if (element.parsedom == 'td') {
|
278
|
+
//移除列的rowspan和colspan属性
|
279
|
+
if (element.hasMarks()) {
|
280
|
+
if (element.marks!['rowspan']) {
|
281
|
+
delete element.marks!['rowspan']
|
282
|
+
}
|
283
|
+
if (element.marks!['colspan']) {
|
284
|
+
delete element.marks!['colspan']
|
285
|
+
}
|
286
|
+
}
|
287
|
+
//移除列的display样式
|
288
|
+
if (element.hasStyles()) {
|
289
|
+
if (element.styles!['display']) {
|
290
|
+
delete element.styles!['display']
|
291
|
+
}
|
292
|
+
}
|
293
|
+
}
|
238
294
|
}
|
239
295
|
|
240
296
|
/**
|
package/src/core/tool.ts
CHANGED
@@ -300,27 +300,6 @@ export const cloneData = function (data: any) {
|
|
300
300
|
return data
|
301
301
|
}
|
302
302
|
|
303
|
-
/**
|
304
|
-
* 根据行元素获取colgroup的col数量
|
305
|
-
* @param row
|
306
|
-
* @returns
|
307
|
-
*/
|
308
|
-
export const getColNumbers = function (row: AlexElement) {
|
309
|
-
const children = row.children || []
|
310
|
-
let num = 0
|
311
|
-
children.forEach(td => {
|
312
|
-
if (td.hasMarks() && td.marks!.hasOwnProperty('colspan')) {
|
313
|
-
const span = Number(td.marks!.colspan)
|
314
|
-
if (!isNaN(span)) {
|
315
|
-
num += span
|
316
|
-
}
|
317
|
-
} else {
|
318
|
-
num += 1
|
319
|
-
}
|
320
|
-
})
|
321
|
-
return num
|
322
|
-
}
|
323
|
-
|
324
303
|
/**
|
325
304
|
* 获取菜单按钮列表数据配置
|
326
305
|
* @param editTrans
|
@@ -766,7 +745,7 @@ export const getToolbarConfig = function (editTrans: (key: string) => any, editL
|
|
766
745
|
rightBorder: false
|
767
746
|
}
|
768
747
|
},
|
769
|
-
//(只对文本工具条中的按钮生效)添加额外的按钮禁用判定,回调参数为name
|
748
|
+
//(只对文本工具条中的按钮生效)添加额外的按钮禁用判定,回调参数为name
|
770
749
|
extraDisabled: null
|
771
750
|
}
|
772
751
|
}
|
@@ -785,7 +764,7 @@ export const getMenuConfig = function (editTrans: (key: string) => any, editLoca
|
|
785
764
|
tooltip: true,
|
786
765
|
//菜单栏显示模式,支持default/inner/fixed
|
787
766
|
mode: 'default',
|
788
|
-
//添加额外的按钮禁用判定,回调参数为name
|
767
|
+
//添加额外的按钮禁用判定,回调参数为name
|
789
768
|
extraDisabled: null,
|
790
769
|
//菜单栏的样式自定义
|
791
770
|
style: null,
|
package/src/editify/editify.less
CHANGED
@@ -357,7 +357,7 @@
|
|
357
357
|
color: @font-color-link;
|
358
358
|
transition: all 200ms;
|
359
359
|
position: relative;
|
360
|
-
|
360
|
+
margin: 0 10px;
|
361
361
|
font-size: 14px;
|
362
362
|
vertical-align: baseline;
|
363
363
|
|
@@ -388,6 +388,13 @@
|
|
388
388
|
border-radius: 4px;
|
389
389
|
margin: 0 4px;
|
390
390
|
transition: all 200ms;
|
391
|
+
max-width: 100%;
|
392
|
+
|
393
|
+
.katex,
|
394
|
+
math {
|
395
|
+
width: 100%;
|
396
|
+
overflow: hidden;
|
397
|
+
}
|
391
398
|
|
392
399
|
&:hover {
|
393
400
|
cursor: pointer;
|
package/src/editify/editify.vue
CHANGED
@@ -24,7 +24,7 @@ import { AlexEditor, AlexElement, AlexElementRangeType, AlexElementsRangeType }
|
|
24
24
|
import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
|
25
25
|
import { mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, PluginResultType } from '../core/tool'
|
26
26
|
import { parseList, orderdListHandle, commonElementHandle, tableHandle, preHandle, specialInblockHandle } from '../core/rule'
|
27
|
-
import { isTask, elementToParagraph,
|
27
|
+
import { isTask, elementToParagraph, getMatchElementsByRange, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange } from '../core/function'
|
28
28
|
import Toolbar from '../components/toolbar/toolbar.vue'
|
29
29
|
import Menu from '../components/menu/menu.vue'
|
30
30
|
import Layer from '../components/layer/layer.vue'
|
@@ -180,59 +180,70 @@ const handleToolbar = () => {
|
|
180
180
|
}
|
181
181
|
hideToolbar()
|
182
182
|
nextTick(() => {
|
183
|
-
const
|
184
|
-
const
|
185
|
-
const
|
186
|
-
const
|
187
|
-
const
|
188
|
-
|
183
|
+
const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
|
184
|
+
const pres = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'pre' })
|
185
|
+
const links = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'a' })
|
186
|
+
const images = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'img' })
|
187
|
+
const videos = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'video' })
|
188
|
+
//显示链接工具条
|
189
|
+
if (links.length == 1) {
|
189
190
|
toolbarOptions.value.type = 'link'
|
190
|
-
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${
|
191
|
+
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${links[0].key}"]`
|
191
192
|
if (toolbarOptions.value.show) {
|
192
193
|
;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
|
193
194
|
} else {
|
194
195
|
toolbarOptions.value.show = true
|
195
196
|
}
|
196
|
-
}
|
197
|
+
}
|
198
|
+
//显示图片工具条
|
199
|
+
else if (images.length == 1) {
|
197
200
|
toolbarOptions.value.type = 'image'
|
198
|
-
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${
|
201
|
+
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${images[0].key}"]`
|
199
202
|
if (toolbarOptions.value.show) {
|
200
203
|
;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
|
201
204
|
} else {
|
202
205
|
toolbarOptions.value.show = true
|
203
206
|
}
|
204
|
-
}
|
207
|
+
}
|
208
|
+
//显示视频工具条
|
209
|
+
else if (videos.length == 1) {
|
205
210
|
toolbarOptions.value.type = 'video'
|
206
|
-
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${
|
211
|
+
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${videos[0].key}"]`
|
207
212
|
if (toolbarOptions.value.show) {
|
208
213
|
;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
|
209
214
|
} else {
|
210
215
|
toolbarOptions.value.show = true
|
211
216
|
}
|
212
|
-
}
|
217
|
+
}
|
218
|
+
//显示表格工具条
|
219
|
+
else if (tables.length == 1) {
|
213
220
|
toolbarOptions.value.type = 'table'
|
214
|
-
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${
|
221
|
+
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${tables[0].key}"]`
|
215
222
|
if (toolbarOptions.value.show) {
|
216
223
|
;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
|
217
224
|
} else {
|
218
225
|
toolbarOptions.value.show = true
|
219
226
|
}
|
220
|
-
}
|
227
|
+
}
|
228
|
+
//显示代码块工具条
|
229
|
+
else if (pres.length == 1) {
|
221
230
|
toolbarOptions.value.type = 'codeBlock'
|
222
|
-
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${
|
231
|
+
toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${pres[0].key}"]`
|
223
232
|
if (toolbarOptions.value.show) {
|
224
233
|
;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
|
225
234
|
} else {
|
226
235
|
toolbarOptions.value.show = true
|
227
236
|
}
|
228
|
-
}
|
237
|
+
}
|
238
|
+
//显示文本工具条
|
239
|
+
else {
|
229
240
|
const result = dataRangeCaches.value.flatList.filter((item: AlexElementRangeType) => {
|
230
241
|
return item.element.isText()
|
231
242
|
})
|
232
243
|
if (result.length && !hasTableInRange(editor.value!, dataRangeCaches.value) && !hasPreInRange(editor.value!, dataRangeCaches.value) && !hasLinkInRange(editor.value!, dataRangeCaches.value) && !hasImageInRange(editor.value!, dataRangeCaches.value) && !hasVideoInRange(editor.value!, dataRangeCaches.value)) {
|
233
244
|
toolbarOptions.value.type = 'text'
|
234
245
|
if (toolbarOptions.value.show) {
|
235
|
-
;(
|
246
|
+
;(toolbarRef.value!.$refs.layerRef as InstanceType<typeof Layer>).setPosition()
|
236
247
|
} else {
|
237
248
|
toolbarOptions.value.show = true
|
238
249
|
}
|
@@ -366,11 +377,11 @@ const documentMouseMove = (e: Event) => {
|
|
366
377
|
if (!tableColumnResizeParams.value.element) {
|
367
378
|
return
|
368
379
|
}
|
369
|
-
const
|
370
|
-
if (
|
380
|
+
const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
|
381
|
+
if (tables.length != 1) {
|
371
382
|
return
|
372
383
|
}
|
373
|
-
const colgroup =
|
384
|
+
const colgroup = tables[0].children!.find(item => {
|
374
385
|
return item.parsedom == 'colgroup'
|
375
386
|
})!
|
376
387
|
const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
|
@@ -389,11 +400,11 @@ const documentMouseUp = () => {
|
|
389
400
|
if (!tableColumnResizeParams.value.element) {
|
390
401
|
return
|
391
402
|
}
|
392
|
-
const
|
393
|
-
if (
|
403
|
+
const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
|
404
|
+
if (tables.length != 1) {
|
394
405
|
return
|
395
406
|
}
|
396
|
-
const colgroup =
|
407
|
+
const colgroup = tables[0].children!.find(item => {
|
397
408
|
return item.parsedom == 'colgroup'
|
398
409
|
})!
|
399
410
|
const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
|
@@ -466,10 +477,6 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
|
|
466
477
|
if (el.marks!['disabled']) {
|
467
478
|
marks['disabled'] = el.marks!['disabled']
|
468
479
|
}
|
469
|
-
//td的colspan属性保留
|
470
|
-
if (el.parsedom == 'td' && el.marks!['colspan']) {
|
471
|
-
marks['colspan'] = el.marks!['colspan']
|
472
|
-
}
|
473
480
|
//图片和视频的src属性保留
|
474
481
|
if (['img', 'video'].includes(el.parsedom!) && el.marks!['src']) {
|
475
482
|
marks['src'] = el.marks!['src']
|
@@ -543,12 +550,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
|
|
543
550
|
})
|
544
551
|
//对外的自定义属性和样式保留
|
545
552
|
if (typeof props.pasteKeepMarks == 'function') {
|
546
|
-
|
547
|
-
marks = mergeObject(marks, keepMarks)!
|
553
|
+
marks = mergeObject(marks, props.pasteKeepMarks(el))!
|
548
554
|
}
|
549
555
|
if (typeof props.pasteKeepStyles == 'function') {
|
550
|
-
|
551
|
-
styles = mergeObject(styles, keepStyles)!
|
556
|
+
styles = mergeObject(styles, props.pasteKeepStyles(el))!
|
552
557
|
}
|
553
558
|
//将处理后的样式和标记给元素
|
554
559
|
el.marks = marks
|
package/src/icon/iconfont.ttf
CHANGED
Binary file
|
package/src/icon/iconfont.woff
CHANGED
Binary file
|
package/src/index.ts
CHANGED
@@ -9,16 +9,17 @@ export type { ButtonTypeType, ButtonOptionsItemType, ButtonSelectConfigType, But
|
|
9
9
|
export type { InsertImageUploadErrorType } from './components/insertImage/props'
|
10
10
|
export type { InsertVideoUploadErrorType } from './components/insertVideo/props'
|
11
11
|
export type { MenuButtonType, MenuSelectButtonType, MenuDisplayButtonType, MenuImageButtonType, MenuVideoButtonType, MenuTableButtonType, MenuCustomButtonType, CodeBlockToolbarType, TextToolbarType, ToolbarConfigType, MenuSequenceType, MenuModeType, MenuExtendType, MenuConfigType, PluginType, PluginResultType } from './core/tool'
|
12
|
+
export type { ElementMatchConfig } from './core/function'
|
12
13
|
|
13
14
|
//导出编辑器操作方法
|
14
|
-
export {
|
15
|
+
export { elementIsMatch, getMatchElementByElement, getMatchElementsByRange, elementIsInList, elementIsInTask, isList, isTask, hasPreInRange, isRangeInPre, hasQuoteInRange, isRangeInQuote, hasListInRange, isRangeInList, hasTaskInRange, isRangeInTask, hasLinkInRange, hasTableInRange, hasImageInRange, hasVideoInRange, queryTextStyle, queryTextMark, getRangeText, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock } from './core/function'
|
15
16
|
|
16
17
|
//安装函数
|
17
18
|
const install: FunctionPlugin = (app: App) => {
|
18
19
|
app.component(Editify.name!, Editify)
|
19
20
|
}
|
20
21
|
//版本号
|
21
|
-
const version = '0.1.
|
22
|
+
const version = '0.1.41'
|
22
23
|
|
23
24
|
//导出AlexElement元素
|
24
25
|
export { AlexElement } from 'alex-editor'
|
package/src/locale/en_US.ts
CHANGED
package/src/locale/zh_CN.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import { common as DapCommon } from 'dap-util'
|
2
2
|
import { ObjectType, PluginType, cloneData } from '../../core/tool'
|
3
3
|
import { ComponentInternalInstance, h } from 'vue'
|
4
|
-
|
5
4
|
import { AlexEditor, AlexElement, AlexElementsRangeType } from 'alex-editor'
|
6
5
|
import 'katex/dist/katex.css'
|
7
6
|
import KaTex from 'katex'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<template>
|
2
2
|
<div class="editify-mathformula">
|
3
|
-
<div class="editify-mathformula-label">{{ $editTrans('insertMathformula') }}</div>
|
3
|
+
<div class="editify-mathformula-label">{{ props.defaultLaTexContent ? $editTrans('editMathformula') : $editTrans('insertMathformula') }}</div>
|
4
4
|
<textarea class="editify-mathformula-textarea" v-model.trim="latexContent" :placeholder="$editTrans('mathformulaPlaceholder')" @focus="handleInputFocus" @blur="handleInputBlur"></textarea>
|
5
5
|
<div class="editify-mathformula-footer">
|
6
6
|
<span :style="{ color: color || '' }" @click="insertMathformula">{{ $editTrans('confirm') }}</span>
|