vue-editify 0.1.40 → 0.1.42
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 +20 -6
- package/lib/core/function.d.ts +18 -6
- package/lib/core/tool.d.ts +0 -6
- package/lib/editify.es.js +236 -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 +85 -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,90 @@ 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
|
19
|
+
* @returns
|
20
|
+
*/
|
21
|
+
export const elementIsMatch = (element: AlexElement, config: ElementMatchConfig) => {
|
22
|
+
//默认是符合的
|
23
|
+
let isMatch = true
|
24
|
+
//如果存在parsedom判断并且parsedom不一样
|
25
|
+
if (config.parsedom && element.parsedom && config.parsedom != element.parsedom) {
|
26
|
+
isMatch = false
|
27
|
+
}
|
28
|
+
//如果存在marks判断
|
29
|
+
if (config.marks) {
|
30
|
+
const hasMarks = Object.keys(config.marks).every(key => {
|
31
|
+
return element.hasMarks() && element.marks![key] && element.marks![key] == config.marks![key]
|
32
|
+
})
|
33
|
+
//如果不是所有的mark都有
|
34
|
+
if (!hasMarks) {
|
35
|
+
isMatch = false
|
36
|
+
}
|
37
|
+
}
|
38
|
+
//如果存在styles判断
|
39
|
+
if (config.styles) {
|
40
|
+
const hasStyles = Object.keys(config.styles).every(key => {
|
41
|
+
return element.hasStyles() && element.styles![key] && element.styles![key] == config.styles![key]
|
42
|
+
})
|
43
|
+
//如果不是所有的styles都有
|
44
|
+
if (!hasStyles) {
|
45
|
+
isMatch = false
|
46
|
+
}
|
47
|
+
}
|
48
|
+
return isMatch
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* 判断元素是否在符合条件的元素下,如果是返回符合条件的元素,否则返回null
|
53
|
+
* @param element
|
54
|
+
* @param config
|
13
55
|
* @returns
|
14
56
|
*/
|
15
|
-
export const
|
57
|
+
export const getMatchElementByElement = (element: AlexElement, config: ElementMatchConfig): AlexElement | null => {
|
16
58
|
if (element.isBlock()) {
|
17
|
-
return element
|
59
|
+
return elementIsMatch(element, config) ? element : null
|
18
60
|
}
|
19
|
-
if (
|
61
|
+
if (elementIsMatch(element, config)) {
|
20
62
|
return element
|
21
63
|
}
|
22
|
-
return
|
64
|
+
return getMatchElementByElement(element.parent!, config)
|
23
65
|
}
|
24
66
|
|
25
67
|
/**
|
26
|
-
*
|
68
|
+
* 判断光标范围内的元素是否在符合条件的元素下,如果是所有的返回符合条件的元素,否则返回[]
|
27
69
|
* @param editor
|
28
70
|
* @param dataRangeCaches
|
29
|
-
* @param
|
71
|
+
* @param config
|
30
72
|
* @returns
|
31
73
|
*/
|
32
|
-
export const
|
74
|
+
export const getMatchElementsByRange = (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType, config: ElementMatchConfig) => {
|
75
|
+
let elements: AlexElement[] = []
|
33
76
|
if (!editor.range) {
|
34
|
-
return
|
77
|
+
return elements
|
35
78
|
}
|
36
79
|
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
|
80
|
+
const element = getMatchElementByElement(editor.range.anchor.element, config)
|
81
|
+
if (element) {
|
82
|
+
elements = [element]
|
59
83
|
}
|
84
|
+
return elements
|
60
85
|
}
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
86
|
+
dataRangeCaches.flatList.forEach(item => {
|
87
|
+
const element = getMatchElementByElement(item.element, config)
|
88
|
+
if (element && !elements.some(el => el.isEqual(element))) {
|
89
|
+
elements.push(element)
|
90
|
+
}
|
91
|
+
})
|
92
|
+
return elements
|
66
93
|
}
|
67
94
|
|
68
95
|
/**
|
@@ -132,10 +159,10 @@ export const hasPreInRange = (editor: AlexEditor, dataRangeCaches: AlexElementsR
|
|
132
159
|
return false
|
133
160
|
}
|
134
161
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
135
|
-
return !!
|
162
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'pre' })
|
136
163
|
}
|
137
164
|
return dataRangeCaches.flatList.some(item => {
|
138
|
-
return !!
|
165
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'pre' })
|
139
166
|
})
|
140
167
|
}
|
141
168
|
|
@@ -150,10 +177,10 @@ export const isRangeInPre = (editor: AlexEditor, dataRangeCaches: AlexElementsRa
|
|
150
177
|
return false
|
151
178
|
}
|
152
179
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
153
|
-
return !!
|
180
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'pre' })
|
154
181
|
}
|
155
182
|
return dataRangeCaches.list.every(item => {
|
156
|
-
return !!
|
183
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'pre' })
|
157
184
|
})
|
158
185
|
}
|
159
186
|
|
@@ -168,10 +195,10 @@ export const hasQuoteInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
168
195
|
return false
|
169
196
|
}
|
170
197
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
171
|
-
return !!
|
198
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'blockquote' })
|
172
199
|
}
|
173
200
|
return dataRangeCaches.flatList.some(item => {
|
174
|
-
return !!
|
201
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'blockquote' })
|
175
202
|
})
|
176
203
|
}
|
177
204
|
|
@@ -186,10 +213,10 @@ export const isRangeInQuote = (editor: AlexEditor, dataRangeCaches: AlexElements
|
|
186
213
|
return false
|
187
214
|
}
|
188
215
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
189
|
-
return !!
|
216
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'blockquote' })
|
190
217
|
}
|
191
218
|
return dataRangeCaches.list.every(item => {
|
192
|
-
return !!
|
219
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'blockquote' })
|
193
220
|
})
|
194
221
|
}
|
195
222
|
|
@@ -278,10 +305,10 @@ export const hasLinkInRange = (editor: AlexEditor, dataRangeCaches: AlexElements
|
|
278
305
|
return false
|
279
306
|
}
|
280
307
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
281
|
-
return !!
|
308
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'a' })
|
282
309
|
}
|
283
310
|
return dataRangeCaches.flatList.some(item => {
|
284
|
-
return !!
|
311
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'a' })
|
285
312
|
})
|
286
313
|
}
|
287
314
|
|
@@ -296,10 +323,10 @@ export const hasTableInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
296
323
|
return false
|
297
324
|
}
|
298
325
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
299
|
-
return !!
|
326
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'table' })
|
300
327
|
}
|
301
328
|
return dataRangeCaches.flatList.some(item => {
|
302
|
-
return !!
|
329
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'table' })
|
303
330
|
})
|
304
331
|
}
|
305
332
|
|
@@ -314,10 +341,10 @@ export const hasImageInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
314
341
|
return false
|
315
342
|
}
|
316
343
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
317
|
-
return !!
|
344
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'img' })
|
318
345
|
}
|
319
346
|
return dataRangeCaches.flatList.some(item => {
|
320
|
-
return !!
|
347
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'img' })
|
321
348
|
})
|
322
349
|
}
|
323
350
|
|
@@ -332,10 +359,10 @@ export const hasVideoInRange = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
332
359
|
return false
|
333
360
|
}
|
334
361
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
335
|
-
return !!
|
362
|
+
return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'video' })
|
336
363
|
}
|
337
364
|
return dataRangeCaches.flatList.some(item => {
|
338
|
-
return !!
|
365
|
+
return !!getMatchElementByElement(item.element, { parsedom: 'video' })
|
339
366
|
})
|
340
367
|
}
|
341
368
|
|
@@ -1298,10 +1325,10 @@ export const insertCodeBlock = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
1298
1325
|
if (!editor.range) {
|
1299
1326
|
return
|
1300
1327
|
}
|
1301
|
-
const
|
1302
|
-
if (
|
1328
|
+
const pres = getMatchElementsByRange(editor, dataRangeCaches, { parsedom: 'pre' })
|
1329
|
+
if (pres.length == 1) {
|
1303
1330
|
let content = ''
|
1304
|
-
AlexElement.flatElements(
|
1331
|
+
AlexElement.flatElements(pres[0].children!)
|
1305
1332
|
.filter(item => {
|
1306
1333
|
return item.isText()
|
1307
1334
|
})
|
@@ -1313,9 +1340,9 @@ export const insertCodeBlock = (editor: AlexEditor, dataRangeCaches: AlexElement
|
|
1313
1340
|
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1314
1341
|
const text = new AlexElement('text', null, null, null, item)
|
1315
1342
|
editor.addElementTo(text, paragraph)
|
1316
|
-
editor.addElementBefore(paragraph,
|
1343
|
+
editor.addElementBefore(paragraph, pres[0])
|
1317
1344
|
})
|
1318
|
-
|
1345
|
+
pres[0].toEmpty()
|
1319
1346
|
} else {
|
1320
1347
|
//起点和终点在一起
|
1321
1348
|
if (editor.range.anchor.isEqual(editor.range.focus)) {
|