vue-editify 0.1.40 → 0.1.41
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 +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>
|