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/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
@font-face {
|
2
2
|
font-family: 'editify-icon';
|
3
|
-
src: url('../../icon/iconfont.woff?t=
|
3
|
+
src: url('../../icon/iconfont.woff?t=2024051301') format('woff'), url('../../icon/iconfont.ttf?t=2024051301') format('truetype');
|
4
4
|
}
|
5
5
|
|
6
6
|
.editify-icon {
|
@@ -14,7 +14,7 @@ import InsertVideo from '../insertVideo/insertVideo.vue'
|
|
14
14
|
import InsertTable from '../insertTable/insertTable.vue'
|
15
15
|
import { h, getCurrentInstance, ref, computed, inject, ComponentInternalInstance, Ref, ComputedRef, defineComponent } from 'vue'
|
16
16
|
import { common as DapCommon } from 'dap-util'
|
17
|
-
import { getRangeText, setHeading, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock, hasPreInRange, hasTableInRange, hasQuoteInRange, hasLinkInRange, isRangeInQuote, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark,
|
17
|
+
import { getRangeText, setHeading, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock, hasPreInRange, hasTableInRange, hasQuoteInRange, hasLinkInRange, isRangeInQuote, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark, getMatchElementsByRange, hasImageInRange, hasVideoInRange, insertSeparator } from '../../core/function'
|
18
18
|
import { MenuProps } from './props'
|
19
19
|
import { MenuModeType, ObjectType, PluginResultType, MenuExtendType, MenuSequenceType, mergeObject } from '../../core/tool'
|
20
20
|
import { AlexEditor, AlexElementsRangeType } from 'alex-editor'
|
@@ -923,7 +923,7 @@ const handleRangeUpdate = () => {
|
|
923
923
|
tableConfig.value.disabled = value_hasPreInRange || value_hasTableInRange || value_hasQuoteInRange || extraDisabled('table')
|
924
924
|
|
925
925
|
//代码块按钮激活
|
926
|
-
codeBlockConfig.value.active =
|
926
|
+
codeBlockConfig.value.active = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'pre' }).length == 1
|
927
927
|
//代码块按钮禁用
|
928
928
|
codeBlockConfig.value.disabled = value_hasTableInRange || value_hasQuoteInRange || value_hasImageInRange || value_hasVideoInRange || extraDisabled('codeBlock')
|
929
929
|
|
@@ -100,7 +100,7 @@
|
|
100
100
|
<Icon value="delete-column"></Icon>
|
101
101
|
</Button>
|
102
102
|
<!-- 删除表格 -->
|
103
|
-
<Button @operate="deleteElement('table')" name="deleteTable" :title="$editTrans('deleteTable')" :tooltip="config.tooltip" :color="color">
|
103
|
+
<Button @operate="deleteElement('table')" leftBorder name="deleteTable" :title="$editTrans('deleteTable')" :tooltip="config.tooltip" :color="color">
|
104
104
|
<Icon value="delete-table"></Icon>
|
105
105
|
</Button>
|
106
106
|
</template>
|
@@ -201,7 +201,7 @@ import Checkbox from '../checkbox/checkbox.vue'
|
|
201
201
|
import Colors from '../colors/colors.vue'
|
202
202
|
import { AlexEditor, AlexElement, AlexElementsRangeType } from 'alex-editor'
|
203
203
|
import { common as DapCommon } from 'dap-util'
|
204
|
-
import {
|
204
|
+
import { getMatchElementsByRange, removeTextStyle, removeTextMark, setTextStyle, setLineHeight, setTextMark, setList, setTask, setHeading, setAlign, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark } from '../../core/function'
|
205
205
|
import { ToolbarProps } from './props'
|
206
206
|
import { Ref, computed, inject, ref } from 'vue'
|
207
207
|
import { ObjectType } from '../../core/tool'
|
@@ -229,6 +229,7 @@ const linkConfig = ref<ObjectType>({
|
|
229
229
|
//链接是否新窗口打开
|
230
230
|
newOpen: false
|
231
231
|
})
|
232
|
+
|
232
233
|
//视频参数配置
|
233
234
|
const videoConfig = ref<ObjectType>({
|
234
235
|
//是否显示控制器
|
@@ -240,6 +241,7 @@ const videoConfig = ref<ObjectType>({
|
|
240
241
|
//是否静音
|
241
242
|
muted: false
|
242
243
|
})
|
244
|
+
|
243
245
|
//代码块选择语言按钮配置
|
244
246
|
const languageConfig = ref<ObjectType>({
|
245
247
|
show: props.config.codeBlock!.languages!.show,
|
@@ -254,6 +256,8 @@ const languageConfig = ref<ObjectType>({
|
|
254
256
|
active: false,
|
255
257
|
disabled: false
|
256
258
|
})
|
259
|
+
|
260
|
+
/** 以下是文本工具条的配置参数信息 */
|
257
261
|
//标题按钮配置
|
258
262
|
const headingConfig = ref<ObjectType>({
|
259
263
|
show: props.config.text!.heading!.show,
|
@@ -674,36 +678,36 @@ const modifyLink = () => {
|
|
674
678
|
if (!linkConfig.value.url) {
|
675
679
|
return
|
676
680
|
}
|
677
|
-
const
|
678
|
-
if (
|
679
|
-
|
681
|
+
const links = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'a' })
|
682
|
+
if (links.length == 1) {
|
683
|
+
links[0].marks!.href = linkConfig.value.url
|
680
684
|
if (linkConfig.value.newOpen) {
|
681
|
-
|
685
|
+
links[0].marks!.target = '_blank'
|
682
686
|
} else {
|
683
|
-
delete
|
687
|
+
delete links[0].marks!.target
|
684
688
|
}
|
689
|
+
editor.value.formatElementStack()
|
690
|
+
editor.value.domRender()
|
685
691
|
}
|
686
|
-
editor.value.formatElementStack()
|
687
|
-
editor.value.domRender()
|
688
692
|
}
|
689
693
|
//移除链接
|
690
694
|
const removeLink = () => {
|
691
|
-
const
|
692
|
-
if (
|
693
|
-
|
694
|
-
delete
|
695
|
-
delete
|
696
|
-
delete
|
695
|
+
const links = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'a' })
|
696
|
+
if (links.length == 1) {
|
697
|
+
links[0].parsedom = AlexElement.TEXT_NODE
|
698
|
+
delete links[0].marks!['target']
|
699
|
+
delete links[0].marks!['href']
|
700
|
+
delete links[0].marks!['data-editify-element']
|
701
|
+
editor.value.formatElementStack()
|
702
|
+
editor.value.domRender()
|
703
|
+
editor.value.rangeRender()
|
697
704
|
}
|
698
|
-
editor.value.formatElementStack()
|
699
|
-
editor.value.domRender()
|
700
|
-
editor.value.rangeRender()
|
701
705
|
}
|
702
706
|
//选择代码语言
|
703
707
|
const selectLanguage = (_name: string, value: string) => {
|
704
|
-
const
|
705
|
-
if (
|
706
|
-
Object.assign(
|
708
|
+
const pres = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'pre' })
|
709
|
+
if (pres.length == 1) {
|
710
|
+
Object.assign(pres[0].marks!, {
|
707
711
|
'data-editify-hljs': value
|
708
712
|
})
|
709
713
|
editor.value.formatElementStack()
|
@@ -717,15 +721,15 @@ const insertParagraphWithPre = (type: string | undefined = 'up') => {
|
|
717
721
|
editor.value.range!.anchor.element = editor.value.range!.focus.element
|
718
722
|
editor.value.range!.anchor.offset = editor.value.range!.focus.offset
|
719
723
|
}
|
720
|
-
const
|
721
|
-
if (
|
724
|
+
const pres = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'pre' })
|
725
|
+
if (pres.length == 1) {
|
722
726
|
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
723
727
|
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
724
728
|
editor.value.addElementTo(breakEl, paragraph)
|
725
729
|
if (type == 'up') {
|
726
|
-
editor.value.addElementBefore(paragraph,
|
730
|
+
editor.value.addElementBefore(paragraph, pres[0])
|
727
731
|
} else {
|
728
|
-
editor.value.addElementAfter(paragraph,
|
732
|
+
editor.value.addElementAfter(paragraph, pres[0])
|
729
733
|
}
|
730
734
|
editor.value.range!.anchor.moveToEnd(paragraph)
|
731
735
|
editor.value.range!.focus.moveToEnd(paragraph)
|
@@ -740,17 +744,17 @@ const insertTableColumn = (type: string | undefined = 'left') => {
|
|
740
744
|
editor.value.range!.anchor.element = editor.value.range!.focus.element
|
741
745
|
editor.value.range!.anchor.offset = editor.value.range!.focus.offset
|
742
746
|
}
|
743
|
-
const
|
744
|
-
const
|
745
|
-
const
|
746
|
-
if (
|
747
|
-
const rows =
|
748
|
-
const index =
|
749
|
-
return item.isEqual(
|
747
|
+
const tables = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'table' })
|
748
|
+
const columns = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'td' })
|
749
|
+
const tbodys = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'tbody' })
|
750
|
+
if (tables.length == 1 && tbodys.length == 1 && columns.length == 1) {
|
751
|
+
const rows = tbodys[0].children
|
752
|
+
const index = columns[0].parent!.children!.findIndex(item => {
|
753
|
+
return item.isEqual(columns[0])
|
750
754
|
})
|
751
755
|
//插入列
|
752
756
|
rows!.forEach(row => {
|
753
|
-
const newColumn =
|
757
|
+
const newColumn = columns[0].clone(false)
|
754
758
|
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
755
759
|
editor.value.addElementTo(breakEl, newColumn)
|
756
760
|
if (type == 'left') {
|
@@ -760,7 +764,7 @@ const insertTableColumn = (type: string | undefined = 'left') => {
|
|
760
764
|
}
|
761
765
|
})
|
762
766
|
//插入col
|
763
|
-
const colgroup =
|
767
|
+
const colgroup = tables[0].children!.find(item => {
|
764
768
|
return item.parsedom == 'colgroup'
|
765
769
|
})!
|
766
770
|
const col = new AlexElement('closed', 'col', null, null, null)
|
@@ -772,11 +776,11 @@ const insertTableColumn = (type: string | undefined = 'left') => {
|
|
772
776
|
//渲染
|
773
777
|
editor.value.formatElementStack()
|
774
778
|
if (type == 'left') {
|
775
|
-
const previousColumn = editor.value.getPreviousElement(
|
779
|
+
const previousColumn = editor.value.getPreviousElement(columns[0])!
|
776
780
|
editor.value.range!.anchor.moveToStart(previousColumn)
|
777
781
|
editor.value.range!.focus.moveToStart(previousColumn)
|
778
782
|
} else {
|
779
|
-
const nextColumn = editor.value.getNextElement(
|
783
|
+
const nextColumn = editor.value.getNextElement(columns[0])!
|
780
784
|
editor.value.range!.anchor.moveToStart(nextColumn)
|
781
785
|
editor.value.range!.focus.moveToStart(nextColumn)
|
782
786
|
}
|
@@ -790,19 +794,19 @@ const insertTableRow = (type: string | undefined = 'up') => {
|
|
790
794
|
editor.value.range!.anchor.element = editor.value.range!.focus.element
|
791
795
|
editor.value.range!.anchor.offset = editor.value.range!.focus.offset
|
792
796
|
}
|
793
|
-
const
|
794
|
-
const
|
795
|
-
if (
|
796
|
-
const newRow =
|
797
|
+
const tables = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'table' })
|
798
|
+
const rows = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'tr' })
|
799
|
+
if (tables.length == 1 && rows.length == 1) {
|
800
|
+
const newRow = rows[0].clone()
|
797
801
|
newRow.children!.forEach(column => {
|
798
802
|
column.children = []
|
799
803
|
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
800
804
|
editor.value.addElementTo(breakEl, column)
|
801
805
|
})
|
802
806
|
if (type == 'up') {
|
803
|
-
editor.value.addElementBefore(newRow,
|
807
|
+
editor.value.addElementBefore(newRow, rows[0])
|
804
808
|
} else {
|
805
|
-
editor.value.addElementAfter(newRow,
|
809
|
+
editor.value.addElementAfter(newRow, rows[0])
|
806
810
|
}
|
807
811
|
editor.value.formatElementStack()
|
808
812
|
editor.value.range!.anchor.moveToStart(newRow)
|
@@ -817,15 +821,15 @@ const insertTableRow = (type: string | undefined = 'up') => {
|
|
817
821
|
}
|
818
822
|
//表格前后插入段落
|
819
823
|
const insertParagraphWithTable = (type: string | undefined = 'up') => {
|
820
|
-
const
|
821
|
-
if (
|
824
|
+
const tables = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'table' })
|
825
|
+
if (tables.length == 1) {
|
822
826
|
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
823
827
|
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
824
828
|
editor.value.addElementTo(breakEl, paragraph)
|
825
829
|
if (type == 'up') {
|
826
|
-
editor.value.addElementBefore(paragraph,
|
830
|
+
editor.value.addElementBefore(paragraph, tables[0])
|
827
831
|
} else {
|
828
|
-
editor.value.addElementAfter(paragraph,
|
832
|
+
editor.value.addElementAfter(paragraph, tables[0])
|
829
833
|
}
|
830
834
|
editor.value.range!.anchor.moveToEnd(paragraph)
|
831
835
|
editor.value.range!.focus.moveToEnd(paragraph)
|
@@ -836,9 +840,9 @@ const insertParagraphWithTable = (type: string | undefined = 'up') => {
|
|
836
840
|
}
|
837
841
|
//删除元素
|
838
842
|
const deleteElement = (parsedom: string) => {
|
839
|
-
const
|
840
|
-
if (
|
841
|
-
|
843
|
+
const elements = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom })
|
844
|
+
if (elements.length == 1) {
|
845
|
+
elements[0].toEmpty()
|
842
846
|
editor.value.formatElementStack()
|
843
847
|
editor.value.domRender()
|
844
848
|
editor.value.rangeRender()
|
@@ -850,17 +854,17 @@ const deleteTableRow = () => {
|
|
850
854
|
editor.value.range!.anchor.element = editor.value.range!.focus.element
|
851
855
|
editor.value.range!.anchor.offset = editor.value.range!.focus.offset
|
852
856
|
}
|
853
|
-
const
|
854
|
-
const
|
855
|
-
if (
|
856
|
-
const parent =
|
857
|
+
const tables = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'table' })
|
858
|
+
const rows = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'tr' })
|
859
|
+
if (tables.length == 1 && rows.length == 1) {
|
860
|
+
const parent = rows[0].parent!
|
857
861
|
if (parent.children!.length == 1) {
|
858
862
|
deleteElement('table')
|
859
863
|
return
|
860
864
|
}
|
861
|
-
const previousRow = editor.value.getPreviousElement(
|
862
|
-
const nextRow = editor.value.getNextElement(
|
863
|
-
|
865
|
+
const previousRow = editor.value.getPreviousElement(rows[0])!
|
866
|
+
const nextRow = editor.value.getNextElement(rows[0])!
|
867
|
+
rows[0].toEmpty()
|
864
868
|
editor.value.formatElementStack()
|
865
869
|
if (previousRow) {
|
866
870
|
editor.value.range!.anchor.moveToEnd(previousRow.children![0])
|
@@ -883,27 +887,27 @@ const deleteTableColumn = () => {
|
|
883
887
|
editor.value.range!.anchor.element = editor.value.range!.focus.element
|
884
888
|
editor.value.range!.anchor.offset = editor.value.range!.focus.offset
|
885
889
|
}
|
886
|
-
const
|
887
|
-
const
|
888
|
-
const
|
889
|
-
if (
|
890
|
-
const rows =
|
891
|
-
const parent =
|
890
|
+
const columns = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'td' })
|
891
|
+
const tbodys = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'tbody' })
|
892
|
+
const tables = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'table' })
|
893
|
+
if (tables.length == 1 && tbodys.length == 1 && columns.length == 1) {
|
894
|
+
const rows = tbodys[0].children!
|
895
|
+
const parent = columns[0].parent!
|
892
896
|
if (parent.children!.length == 1) {
|
893
897
|
deleteElement('table')
|
894
898
|
return
|
895
899
|
}
|
896
|
-
const previousColumn = editor.value.getPreviousElement(
|
897
|
-
const nextColumn = editor.value.getNextElement(
|
898
|
-
const index =
|
899
|
-
return item.isEqual(
|
900
|
+
const previousColumn = editor.value.getPreviousElement(columns[0])!
|
901
|
+
const nextColumn = editor.value.getNextElement(columns[0])!
|
902
|
+
const index = columns[0].parent!.children!.findIndex(item => {
|
903
|
+
return item.isEqual(columns[0])
|
900
904
|
})
|
901
905
|
//删除列
|
902
906
|
rows.forEach(row => {
|
903
907
|
row.children![index].toEmpty()
|
904
908
|
})
|
905
909
|
//删除col
|
906
|
-
const colgroup =
|
910
|
+
const colgroup = tables[0].children!.find(item => {
|
907
911
|
return item.parsedom == 'colgroup'
|
908
912
|
})!
|
909
913
|
colgroup.children![index].toEmpty()
|
@@ -922,29 +926,31 @@ const deleteTableColumn = () => {
|
|
922
926
|
}
|
923
927
|
//浮层显示时
|
924
928
|
const layerShow = () => {
|
925
|
-
//代码块初始化展示设置
|
926
|
-
if (props.type == 'codeBlock') {
|
927
|
-
const pre = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'pre')
|
928
|
-
if (pre) {
|
929
|
-
languageConfig.value.displayConfig.value = pre.marks!['data-editify-hljs'] || ''
|
930
|
-
}
|
931
|
-
}
|
932
929
|
//链接初始化展示
|
933
|
-
|
934
|
-
const
|
935
|
-
if (
|
936
|
-
linkConfig.value.url =
|
937
|
-
linkConfig.value.newOpen =
|
930
|
+
if (props.type == 'link') {
|
931
|
+
const links = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'a' })
|
932
|
+
if (links.length == 1) {
|
933
|
+
linkConfig.value.url = links[0].marks!['href']
|
934
|
+
linkConfig.value.newOpen = links[0].marks!['target'] == '_blank'
|
938
935
|
}
|
939
936
|
}
|
940
937
|
//视频初始化显示
|
941
938
|
else if (props.type == 'video') {
|
942
|
-
const
|
943
|
-
if (
|
944
|
-
videoConfig.value.autoplay = !!
|
945
|
-
videoConfig.value.loop = !!
|
946
|
-
videoConfig.value.controls = !!
|
947
|
-
videoConfig.value.muted = !!
|
939
|
+
const videos = getMatchElementsByRange(editor.value, dataRangeCaches.value, { parsedom: 'video' })
|
940
|
+
if (videos.length == 1) {
|
941
|
+
videoConfig.value.autoplay = !!videos[0].marks!['autoplay']
|
942
|
+
videoConfig.value.loop = !!videos[0].marks!['loop']
|
943
|
+
videoConfig.value.controls = !!videos[0].marks!['controls']
|
944
|
+
videoConfig.value.muted = !!videos[0].marks!['muted']
|
945
|
+
}
|
946
|
+
}
|
947
|
+
//代码块初始化展示设置
|
948
|
+
else if (props.type == 'codeBlock') {
|
949
|
+
const pres = getMatchElementsByRange(editor.value, dataRangeCaches.value, {
|
950
|
+
parsedom: 'pre'
|
951
|
+
})
|
952
|
+
if (pres.length == 1) {
|
953
|
+
languageConfig.value.displayConfig.value = pres[0].marks!['data-editify-hljs'] || ''
|
948
954
|
}
|
949
955
|
}
|
950
956
|
//文本工具条初始化显示
|
package/src/core/function.ts
CHANGED
@@ -6,63 +6,94 @@ import { common as DapCommon } from 'dap-util'
|
|
6
6
|
import { cloneData, queryHasValue, getButtonOptionsConfig, ObjectType } from './tool'
|
7
7
|
import { ButtonOptionsItemType } from '../components/button/props'
|
8
8
|
|
9
|
+
export type ElementMatchConfig = {
|
10
|
+
parsedom?: string
|
11
|
+
marks?: ObjectType
|
12
|
+
styles?: ObjectType
|
13
|
+
}
|
14
|
+
|
9
15
|
/**
|
10
|
-
*
|
16
|
+
* 判断元素是否符合指定的条件
|
11
17
|
* @param element
|
12
|
-
* @param
|
18
|
+
* @param config
|
13
19
|
* @returns
|
14
20
|
*/
|
15
|
-
export const
|
21
|
+
export const elementIsMatch = (element: AlexElement, config: ElementMatchConfig) => {
|
22
|
+
//如果是文本元素直接返回false
|
23
|
+
if (element.isText()) {
|
24
|
+
return false
|
25
|
+
}
|
26
|
+
//默认是符合的
|
27
|
+
let isMatch = true
|
28
|
+
//如果存在parsedom判断并且parsedom不一样
|
29
|
+
if (config.parsedom && config.parsedom != element.parsedom) {
|
30
|
+
isMatch = false
|
31
|
+
}
|
32
|
+
//如果存在marks判断
|
33
|
+
if (config.marks) {
|
34
|
+
const hasMarks = Object.keys(config.marks).every(key => {
|
35
|
+
return element.hasMarks() && element.marks![key] && element.marks![key] == config.marks![key]
|
36
|
+
})
|
37
|
+
//如果不是所有的mark都有
|
38
|
+
if (!hasMarks) {
|
39
|
+
isMatch = false
|
40
|
+
}
|
41
|
+
}
|
42
|
+
//如果存在styles判断
|
43
|
+
if (config.styles) {
|
44
|
+
const hasStyles = Object.keys(config.styles).every(key => {
|
45
|
+
return element.hasStyles() && element.styles![key] && element.styles![key] == config.styles![key]
|
46
|
+
})
|
47
|
+
//如果不是所有的styles都有
|
48
|
+
if (!hasStyles) {
|
49
|
+
isMatch = false
|
50
|
+
}
|
51
|
+
}
|
52
|
+
return isMatch
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* 判断元素是否在符合条件的元素下,如果是返回符合条件的元素,否则返回null
|
57
|
+
* @param element
|
58
|
+
* @param config
|
59
|
+
* @returns
|
60
|
+
*/
|
61
|
+
export const getMatchElementByElement = (element: AlexElement, config: ElementMatchConfig): AlexElement | null => {
|
16
62
|
if (element.isBlock()) {
|
17
|
-
return element
|
63
|
+
return elementIsMatch(element, config) ? element : null
|
18
64
|
}
|
19
|
-
if (
|
65
|
+
if (elementIsMatch(element, config)) {
|
20
66
|
return element
|
21
67
|
}
|
22
|
-
return
|
68
|
+
return getMatchElementByElement(element.parent!, config)
|
23
69
|
}
|
24
70
|
|
25
71
|
/**
|
26
|
-
*
|
72
|
+
* 判断光标范围内的元素是否在符合条件的元素下,如果是所有的返回符合条件的元素,否则返回[]
|
27
73
|
* @param editor
|
28
74
|
* @param dataRangeCaches
|
29
|
-
* @param
|
75
|
+
* @param config
|
30
76
|
* @returns
|
31
77
|
*/
|
32
|
-
export const
|
78
|
+
export const getMatchElementsByRange = (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType, config: ElementMatchConfig) => {
|
79
|
+
let elements: AlexElement[] = []
|
33
80
|
if (!editor.range) {
|
34
|
-
return
|
81
|
+
return elements
|
35
82
|
}
|
36
83
|
if (editor.range.anchor.element.isEqual(editor.range.focus.element)) {
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
return getParsedomElementByElement(item.element, parsedom)
|
41
|
-
})
|
42
|
-
let hasNull = arr.some(el => {
|
43
|
-
return el == null
|
44
|
-
})
|
45
|
-
//如果存在null,则表示有的选区元素不在指定标签下,返回null
|
46
|
-
if (hasNull) {
|
47
|
-
return null
|
48
|
-
}
|
49
|
-
//如果只有一个元素,则返回该元素
|
50
|
-
if (arr.length == 1) {
|
51
|
-
return arr[0]!
|
52
|
-
}
|
53
|
-
//默认数组中的元素都相等
|
54
|
-
let flag = true
|
55
|
-
for (let i = 1; i < arr.length; i++) {
|
56
|
-
if (!arr[i]!.isEqual(arr[0]!)) {
|
57
|
-
flag = false
|
58
|
-
break
|
84
|
+
const element = getMatchElementByElement(editor.range.anchor.element, config)
|
85
|
+
if (element) {
|
86
|
+
elements = [element]
|
59
87
|
}
|
88
|
+
return elements
|
60
89
|
}
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
90
|
+
dataRangeCaches.flatList.forEach(item => {
|
91
|
+
const element = getMatchElementByElement(item.element, config)
|
92
|
+
if (element && !elements.some(el => el.isEqual(element))) {
|
93
|
+
elements.push(element)
|
94
|
+
}
|
95
|
+
})
|
96
|
+
return elements
|
66
97
|
}
|
67
98
|
|
68
99
|
/**
|
@@ -132,10 +163,10 @@ export const hasPreInRange = (editor: AlexEditor, dataRangeCaches: AlexElementsR
|
|
132
163
|
return false
|
133
164
|
}
|
134
165
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
135
|
-
return !!
|
166
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'pre' })
|
136
167
|
}
|
137
168
|
return dataRangeCaches.flatList.some(item => {
|
138
|
-
return !!
|
169
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'pre' })
|
139
170
|
})
|
140
171
|
}
|
141
172
|
|
@@ -150,10 +181,10 @@ export const isRangeInPre = (editor: AlexEditor, dataRangeCaches: AlexElementsRa
|
|
150
181
|
return false
|
151
182
|
}
|
152
183
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
153
|
-
return !!
|
184
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'pre' })
|
154
185
|
}
|
155
186
|
return dataRangeCaches.list.every(item => {
|
156
|
-
return !!
|
187
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'pre' })
|
157
188
|
})
|
158
189
|
}
|
159
190
|
|
@@ -168,10 +199,10 @@ export const hasQuoteInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
168
199
|
return false
|
169
200
|
}
|
170
201
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
171
|
-
return !!
|
202
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'blockquote' })
|
172
203
|
}
|
173
204
|
return dataRangeCaches.flatList.some(item => {
|
174
|
-
return !!
|
205
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'blockquote' })
|
175
206
|
})
|
176
207
|
}
|
177
208
|
|
@@ -186,10 +217,10 @@ export const isRangeInQuote = (editor: AlexEditor, dataRangeCaches: AlexElements
|
|
186
217
|
return false
|
187
218
|
}
|
188
219
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
189
|
-
return !!
|
220
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'blockquote' })
|
190
221
|
}
|
191
222
|
return dataRangeCaches.list.every(item => {
|
192
|
-
return !!
|
223
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'blockquote' })
|
193
224
|
})
|
194
225
|
}
|
195
226
|
|
@@ -278,10 +309,10 @@ export const hasLinkInRange = (editor: AlexEditor, dataRangeCaches: AlexElements
|
|
278
309
|
return false
|
279
310
|
}
|
280
311
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
281
|
-
return !!
|
312
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'a' })
|
282
313
|
}
|
283
314
|
return dataRangeCaches.flatList.some(item => {
|
284
|
-
return !!
|
315
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'a' })
|
285
316
|
})
|
286
317
|
}
|
287
318
|
|
@@ -296,10 +327,10 @@ export const hasTableInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
296
327
|
return false
|
297
328
|
}
|
298
329
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
299
|
-
return !!
|
330
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'table' })
|
300
331
|
}
|
301
332
|
return dataRangeCaches.flatList.some(item => {
|
302
|
-
return !!
|
333
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'table' })
|
303
334
|
})
|
304
335
|
}
|
305
336
|
|
@@ -314,10 +345,10 @@ export const hasImageInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
314
345
|
return false
|
315
346
|
}
|
316
347
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
317
|
-
return !!
|
348
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'img' })
|
318
349
|
}
|
319
350
|
return dataRangeCaches.flatList.some(item => {
|
320
|
-
return !!
|
351
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'img' })
|
321
352
|
})
|
322
353
|
}
|
323
354
|
|
@@ -332,10 +363,10 @@ export const hasVideoInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
332
363
|
return false
|
333
364
|
}
|
334
365
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
335
|
-
return !!
|
366
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'video' })
|
336
367
|
}
|
337
368
|
return dataRangeCaches.flatList.some(item => {
|
338
|
-
return !!
|
369
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'video' })
|
339
370
|
})
|
340
371
|
}
|
341
372
|
|
@@ -1298,10 +1329,10 @@ export const insertCodeBlock = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
1298
1329
|
if (!editor.range) {
|
1299
1330
|
return
|
1300
1331
|
}
|
1301
|
-
const
|
1302
|
-
if (
|
1332
|
+
const pres = getMatchElementsByRange(editor, dataRangeCaches, { parsedom: 'pre' })
|
1333
|
+
if (pres.length == 1) {
|
1303
1334
|
let content = ''
|
1304
|
-
AlexElement.flatElements(
|
1335
|
+
AlexElement.flatElements(pres[0].children!)
|
1305
1336
|
.filter(item => {
|
1306
1337
|
return item.isText()
|
1307
1338
|
})
|
@@ -1313,9 +1344,9 @@ export const insertCodeBlock = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
1313
1344
|
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1314
1345
|
const text = new AlexElement('text', null, null, null, item)
|
1315
1346
|
editor.addElementTo(text, paragraph)
|
1316
|
-
editor.addElementBefore(paragraph,
|
1347
|
+
editor.addElementBefore(paragraph, pres[0])
|
1317
1348
|
})
|
1318
|
-
|
1349
|
+
pres[0].toEmpty()
|
1319
1350
|
} else {
|
1320
1351
|
//起点和终点在一起
|
1321
1352
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|