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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-editify",
3
- "version": "0.1.40",
3
+ "version": "0.1.42",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -7,7 +7,7 @@
7
7
  font-size: @font-size;
8
8
 
9
9
  .editify-button-wrap {
10
- padding: 0 4px;
10
+ padding: 2px 4px;
11
11
  position: relative;
12
12
 
13
13
  &.editify-right-border::after {
@@ -1,6 +1,6 @@
1
1
  @font-face {
2
2
  font-family: 'editify-icon';
3
- src: url('../../icon/iconfont.woff?t=1699274556400') format('woff'), url('../../icon/iconfont.ttf?t=1699274556400') format('truetype');
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, getCurrentParsedomElement, hasImageInRange, hasVideoInRange, insertSeparator } from '../../core/function'
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 = !!getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'pre')
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 { getCurrentParsedomElement, removeTextStyle, removeTextMark, setTextStyle, setLineHeight, setTextMark, setList, setTask, setHeading, setAlign, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark } from '../../core/function'
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 link = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'a')
678
- if (link) {
679
- link.marks!.href = linkConfig.value.url
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
- link.marks!.target = '_blank'
685
+ links[0].marks!.target = '_blank'
682
686
  } else {
683
- delete link.marks!.target
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 link = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'a')
692
- if (link) {
693
- link.parsedom = AlexElement.TEXT_NODE
694
- delete link.marks!['target']
695
- delete link.marks!['href']
696
- delete link.marks!['data-editify-element']
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 pre = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'pre')
705
- if (pre) {
706
- Object.assign(pre.marks!, {
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 pre = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'pre')
721
- if (pre) {
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, pre)
730
+ editor.value.addElementBefore(paragraph, pres[0])
727
731
  } else {
728
- editor.value.addElementAfter(paragraph, pre)
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 table = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'table')
744
- const column = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'td')
745
- const tbody = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'tbody')
746
- if (column && table && tbody) {
747
- const rows = tbody.children
748
- const index = column.parent!.children!.findIndex(item => {
749
- return item.isEqual(column)
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 = column.clone(false)
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 = table.children!.find(item => {
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(column)!
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(column)!
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 table = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'table')
794
- const row = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'tr')
795
- if (table && row) {
796
- const newRow = row.clone()
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, row)
807
+ editor.value.addElementBefore(newRow, rows[0])
804
808
  } else {
805
- editor.value.addElementAfter(newRow, row)
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 table = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'table')
821
- if (table) {
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, table)
830
+ editor.value.addElementBefore(paragraph, tables[0])
827
831
  } else {
828
- editor.value.addElementAfter(paragraph, table)
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 element = getCurrentParsedomElement(editor.value, dataRangeCaches.value, parsedom)
840
- if (element) {
841
- element.toEmpty()
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 table = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'table')
854
- const row = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'tr')
855
- if (table && row) {
856
- const parent = row.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(row)!
862
- const nextRow = editor.value.getNextElement(row)!
863
- row.toEmpty()
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 column = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'td')
887
- const tbody = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'tbody')
888
- const table = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'table')
889
- if (column && table && tbody) {
890
- const rows = tbody.children!
891
- const parent = column.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(column)!
897
- const nextColumn = editor.value.getNextElement(column)!
898
- const index = column.parent!.children!.findIndex(item => {
899
- return item.isEqual(column)
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 = table.children!.find(item => {
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
- else if (props.type == 'link') {
934
- const link = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'a')
935
- if (link) {
936
- linkConfig.value.url = link.marks!['href']
937
- linkConfig.value.newOpen = link.marks!['target'] == '_blank'
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 video = getCurrentParsedomElement(editor.value, dataRangeCaches.value, 'video')
943
- if (video) {
944
- videoConfig.value.autoplay = !!video.marks!['autoplay']
945
- videoConfig.value.loop = !!video.marks!['loop']
946
- videoConfig.value.controls = !!video.marks!['controls']
947
- videoConfig.value.muted = !!video.marks!['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
  //文本工具条初始化显示
@@ -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
- * 判断元素是否在某个标签下,如果是返回该标签对应的元素,否则返回null
16
+ * 判断元素是否符合指定的条件
11
17
  * @param element
12
- * @param parsedom
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 getParsedomElementByElement = (element: AlexElement, parsedom: string): AlexElement | null => {
57
+ export const getMatchElementByElement = (element: AlexElement, config: ElementMatchConfig): AlexElement | null => {
16
58
  if (element.isBlock()) {
17
- return element.parsedom == parsedom ? element : null
59
+ return elementIsMatch(element, config) ? element : null
18
60
  }
19
- if (!element.isText() && element.parsedom == parsedom) {
61
+ if (elementIsMatch(element, config)) {
20
62
  return element
21
63
  }
22
- return getParsedomElementByElement(element.parent!, parsedom)
64
+ return getMatchElementByElement(element.parent!, config)
23
65
  }
24
66
 
25
67
  /**
26
- * 获取光标是否在指定标签下,如果是返回该标签对应的元素,否则返回null
68
+ * 判断光标范围内的元素是否在符合条件的元素下,如果是所有的返回符合条件的元素,否则返回[]
27
69
  * @param editor
28
70
  * @param dataRangeCaches
29
- * @param parsedom
71
+ * @param config
30
72
  * @returns
31
73
  */
32
- export const getCurrentParsedomElement = (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType, parsedom: string) => {
74
+ export const getMatchElementsByRange = (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType, config: ElementMatchConfig) => {
75
+ let elements: AlexElement[] = []
33
76
  if (!editor.range) {
34
- return null
77
+ return elements
35
78
  }
36
79
  if (editor.range.anchor.element.isEqual(editor.range.focus.element)) {
37
- return getParsedomElementByElement(editor.range.anchor.element, parsedom)
38
- }
39
- const arr = dataRangeCaches.list.map(item => {
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
- if (flag) {
63
- return arr[0]
64
- }
65
- return null
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 !!getParsedomElementByElement(editor.range.anchor.element, 'pre')
162
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'pre' })
136
163
  }
137
164
  return dataRangeCaches.flatList.some(item => {
138
- return !!getParsedomElementByElement(item.element, 'pre')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'pre')
180
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'pre' })
154
181
  }
155
182
  return dataRangeCaches.list.every(item => {
156
- return !!getParsedomElementByElement(item.element, 'pre')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'blockquote')
198
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'blockquote' })
172
199
  }
173
200
  return dataRangeCaches.flatList.some(item => {
174
- return !!getParsedomElementByElement(item.element, 'blockquote')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'blockquote')
216
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'blockquote' })
190
217
  }
191
218
  return dataRangeCaches.list.every(item => {
192
- return !!getParsedomElementByElement(item.element, 'blockquote')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'a')
308
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'a' })
282
309
  }
283
310
  return dataRangeCaches.flatList.some(item => {
284
- return !!getParsedomElementByElement(item.element, 'a')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'table')
326
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'table' })
300
327
  }
301
328
  return dataRangeCaches.flatList.some(item => {
302
- return !!getParsedomElementByElement(item.element, 'table')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'img')
344
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'img' })
318
345
  }
319
346
  return dataRangeCaches.flatList.some(item => {
320
- return !!getParsedomElementByElement(item.element, 'img')
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 !!getParsedomElementByElement(editor.range.anchor.element, 'video')
362
+ return !!getMatchElementByElement(editor.range.anchor.element, { parsedom: 'video' })
336
363
  }
337
364
  return dataRangeCaches.flatList.some(item => {
338
- return !!getParsedomElementByElement(item.element, 'video')
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 pre = getCurrentParsedomElement(editor, dataRangeCaches, 'pre')
1302
- if (pre) {
1328
+ const pres = getMatchElementsByRange(editor, dataRangeCaches, { parsedom: 'pre' })
1329
+ if (pres.length == 1) {
1303
1330
  let content = ''
1304
- AlexElement.flatElements(pre.children!)
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, pre)
1343
+ editor.addElementBefore(paragraph, pres[0])
1317
1344
  })
1318
- pre.toEmpty()
1345
+ pres[0].toEmpty()
1319
1346
  } else {
1320
1347
  //起点和终点在一起
1321
1348
  if (editor.range.anchor.isEqual(editor.range.focus)) {