vue-editify 0.2.14 → 0.2.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. package/examples/App.vue +41 -88
  2. package/lib/components/button/button.vue.d.ts +62 -60
  3. package/lib/components/button/index.d.ts +4 -0
  4. package/lib/components/button/props.d.ts +12 -1
  5. package/lib/components/checkbox/checkbox.vue.d.ts +9 -9
  6. package/lib/components/checkbox/index.d.ts +4 -0
  7. package/lib/components/checkbox/props.d.ts +2 -2
  8. package/lib/components/colors/colors.vue.d.ts +4 -4
  9. package/lib/components/colors/index.d.ts +4 -0
  10. package/lib/components/colors/props.d.ts +2 -2
  11. package/lib/components/icon/index.d.ts +4 -0
  12. package/lib/components/insertAttachment/index.d.ts +4 -0
  13. package/lib/{plugins/attachment → components}/insertAttachment/insertAttachment.vue.d.ts +3 -3
  14. package/lib/{plugins/attachment → components}/insertAttachment/props.d.ts +1 -1
  15. package/lib/components/insertImage/index.d.ts +4 -0
  16. package/lib/components/insertImage/insertImage.vue.d.ts +3 -3
  17. package/lib/components/insertImage/props.d.ts +1 -1
  18. package/lib/components/insertLink/index.d.ts +4 -0
  19. package/lib/components/insertLink/insertLink.vue.d.ts +6 -6
  20. package/lib/components/insertLink/props.d.ts +3 -3
  21. package/lib/components/insertMathformula/index.d.ts +4 -0
  22. package/lib/{plugins/mathformula → components}/insertMathformula/insertMathformula.vue.d.ts +3 -3
  23. package/lib/{plugins/mathformula → components}/insertMathformula/props.d.ts +2 -2
  24. package/lib/components/insertTable/index.d.ts +4 -0
  25. package/lib/components/insertTable/insertTable.vue.d.ts +3 -3
  26. package/lib/components/insertTable/props.d.ts +2 -2
  27. package/lib/components/insertVideo/index.d.ts +4 -0
  28. package/lib/components/insertVideo/insertVideo.vue.d.ts +3 -3
  29. package/lib/components/insertVideo/props.d.ts +1 -1
  30. package/lib/components/layer/index.d.ts +4 -0
  31. package/lib/components/layer/layer.vue.d.ts +10 -8
  32. package/lib/components/tooltip/index.d.ts +4 -0
  33. package/lib/components/tooltip/tooltip.vue.d.ts +6 -4
  34. package/lib/components/triangle/index.d.ts +4 -0
  35. package/lib/components/triangle/triangle.vue.d.ts +1 -1
  36. package/lib/components/updateLink/index.d.ts +4 -0
  37. package/lib/components/updateLink/props.d.ts +17 -0
  38. package/lib/components/updateLink/updateLink.vue.d.ts +38 -0
  39. package/lib/core/function.d.ts +113 -36
  40. package/lib/core/rule.d.ts +20 -0
  41. package/lib/core/tool.d.ts +36 -34
  42. package/lib/editify/editify.vue.d.ts +18 -28
  43. package/lib/editify/menu/index.d.ts +4 -0
  44. package/lib/{components → editify}/menu/menu.vue.d.ts +3 -4
  45. package/lib/{components → editify}/menu/props.d.ts +1 -1
  46. package/lib/editify/props.d.ts +3 -7
  47. package/lib/editify/toolbar/index.d.ts +4 -0
  48. package/lib/{components → editify}/toolbar/props.d.ts +2 -2
  49. package/lib/{components → editify}/toolbar/toolbar.vue.d.ts +53 -53
  50. package/lib/editify.es.js +38964 -37727
  51. package/lib/editify.umd.js +2 -2
  52. package/lib/feature/align.d.ts +32 -0
  53. package/lib/feature/attachment.d.ts +18 -0
  54. package/lib/feature/backColor.d.ts +32 -0
  55. package/lib/feature/bold.d.ts +32 -0
  56. package/lib/feature/code.d.ts +32 -0
  57. package/lib/feature/codeBlock.d.ts +32 -0
  58. package/lib/feature/fontFamily.d.ts +32 -0
  59. package/lib/feature/fontSize.d.ts +32 -0
  60. package/lib/feature/foreColor.d.ts +32 -0
  61. package/lib/feature/formatClear.d.ts +32 -0
  62. package/lib/feature/fullScreen.d.ts +18 -0
  63. package/lib/feature/heading.d.ts +32 -0
  64. package/lib/feature/image.d.ts +32 -0
  65. package/lib/feature/indent.d.ts +18 -0
  66. package/lib/feature/infoBlock.d.ts +18 -0
  67. package/lib/feature/italic.d.ts +32 -0
  68. package/lib/feature/lineHeight.d.ts +32 -0
  69. package/lib/feature/link.d.ts +26 -0
  70. package/lib/feature/mathformula.d.ts +22 -0
  71. package/lib/feature/orderList.d.ts +32 -0
  72. package/lib/feature/panel.d.ts +18 -0
  73. package/lib/feature/quote.d.ts +18 -0
  74. package/lib/feature/redo.d.ts +18 -0
  75. package/lib/feature/separator.d.ts +18 -0
  76. package/lib/feature/sourceView.d.ts +18 -0
  77. package/lib/feature/strikethrough.d.ts +32 -0
  78. package/lib/feature/sub.d.ts +32 -0
  79. package/lib/feature/super.d.ts +32 -0
  80. package/lib/feature/table.d.ts +32 -0
  81. package/lib/feature/task.d.ts +32 -0
  82. package/lib/feature/underline.d.ts +32 -0
  83. package/lib/feature/undo.d.ts +18 -0
  84. package/lib/feature/unorderList.d.ts +32 -0
  85. package/lib/feature/video.d.ts +38 -0
  86. package/lib/index.d.ts +194 -202
  87. package/package.json +5 -5
  88. package/src/components/button/button.vue +21 -24
  89. package/src/components/button/index.ts +5 -0
  90. package/src/components/button/props.ts +14 -1
  91. package/src/components/checkbox/checkbox.vue +1 -1
  92. package/src/components/checkbox/index.ts +5 -0
  93. package/src/components/checkbox/props.ts +1 -1
  94. package/src/components/colors/colors.vue +3 -3
  95. package/src/components/colors/index.ts +5 -0
  96. package/src/components/colors/props.ts +2 -2
  97. package/src/components/icon/index.ts +5 -0
  98. package/src/components/insertAttachment/index.ts +5 -0
  99. package/src/{plugins/attachment → components}/insertAttachment/insertAttachment.vue +4 -2
  100. package/src/{plugins/attachment → components}/insertAttachment/props.ts +1 -1
  101. package/src/components/insertImage/index.ts +5 -0
  102. package/src/components/insertImage/insertImage.vue +5 -5
  103. package/src/components/insertImage/props.ts +1 -1
  104. package/src/components/insertLink/index.ts +5 -0
  105. package/src/components/insertLink/insertLink.vue +10 -10
  106. package/src/components/insertLink/props.ts +3 -3
  107. package/src/components/insertMathformula/index.ts +5 -0
  108. package/src/{plugins/mathformula → components}/insertMathformula/props.ts +2 -2
  109. package/src/components/insertTable/index.ts +5 -0
  110. package/src/components/insertTable/props.ts +2 -2
  111. package/src/components/insertVideo/index.ts +5 -0
  112. package/src/components/insertVideo/insertVideo.vue +2 -2
  113. package/src/components/insertVideo/props.ts +1 -1
  114. package/src/components/layer/index.ts +5 -0
  115. package/src/components/layer/layer.vue +42 -4
  116. package/src/components/tooltip/index.ts +5 -0
  117. package/src/components/tooltip/tooltip.vue +1 -1
  118. package/src/components/triangle/index.ts +5 -0
  119. package/src/components/triangle/triangle.vue +1 -1
  120. package/src/components/updateLink/index.ts +5 -0
  121. package/src/components/updateLink/props.ts +21 -0
  122. package/src/components/{toolbar/toolbar.less → updateLink/updateLink.less} +4 -20
  123. package/src/components/updateLink/updateLink.vue +74 -0
  124. package/src/core/function.ts +289 -97
  125. package/src/core/rule.ts +108 -29
  126. package/src/core/tool.ts +237 -81
  127. package/src/editify/editify.less +4 -0
  128. package/src/editify/editify.vue +183 -194
  129. package/src/editify/menu/index.ts +5 -0
  130. package/src/editify/menu/menu.vue +215 -0
  131. package/src/{components → editify}/menu/props.ts +1 -1
  132. package/src/editify/props.ts +7 -11
  133. package/src/editify/toolbar/index.ts +5 -0
  134. package/src/{components → editify}/toolbar/props.ts +1 -1
  135. package/src/editify/toolbar/toolbar.less +10 -0
  136. package/src/editify/toolbar/toolbar.vue +103 -0
  137. package/src/feature/align.ts +126 -0
  138. package/src/feature/attachment.ts +108 -0
  139. package/src/feature/backColor.ts +169 -0
  140. package/src/feature/bold.ts +134 -0
  141. package/src/feature/code.ts +134 -0
  142. package/src/feature/codeBlock.ts +201 -0
  143. package/src/feature/fontFamily.ts +138 -0
  144. package/src/feature/fontSize.ts +140 -0
  145. package/src/feature/foreColor.ts +171 -0
  146. package/src/feature/formatClear.ts +116 -0
  147. package/src/feature/fullScreen.ts +57 -0
  148. package/src/feature/heading.ts +152 -0
  149. package/src/feature/image.ts +222 -0
  150. package/src/feature/indent.ts +72 -0
  151. package/src/feature/infoBlock.ts +93 -0
  152. package/src/feature/italic.ts +134 -0
  153. package/src/feature/lineHeight.ts +163 -0
  154. package/src/feature/link.ts +146 -0
  155. package/src/feature/mathformula.ts +146 -0
  156. package/src/feature/orderList.ts +114 -0
  157. package/src/feature/panel.ts +107 -0
  158. package/src/feature/quote.ts +60 -0
  159. package/src/feature/redo.ts +56 -0
  160. package/src/feature/separator.ts +61 -0
  161. package/src/feature/sourceView.ts +59 -0
  162. package/src/feature/strikethrough.ts +134 -0
  163. package/src/feature/sub.ts +134 -0
  164. package/src/feature/super.ts +134 -0
  165. package/src/feature/table.ts +981 -0
  166. package/src/feature/task.ts +114 -0
  167. package/src/feature/underline.ts +134 -0
  168. package/src/feature/undo.ts +56 -0
  169. package/src/feature/unorderList.ts +114 -0
  170. package/src/feature/video.ts +335 -0
  171. package/src/hljs/index.ts +1 -1
  172. package/src/index.ts +82 -25
  173. package/src/locale/en_US.ts +3 -3
  174. package/src/locale/zh_CN.ts +3 -3
  175. package/lib/plugins/attachment/index.d.ts +0 -37
  176. package/lib/plugins/infoBlock/index.d.ts +0 -55
  177. package/lib/plugins/mathformula/index.d.ts +0 -49
  178. package/lib/plugins/panel/index.d.ts +0 -48
  179. package/src/components/menu/menu.vue +0 -1655
  180. package/src/components/toolbar/toolbar.vue +0 -1677
  181. package/src/plugins/attachment/index.ts +0 -237
  182. package/src/plugins/infoBlock/index.ts +0 -238
  183. package/src/plugins/mathformula/index.ts +0 -295
  184. package/src/plugins/panel/index.ts +0 -228
  185. package/tsconfig.json +0 -31
  186. package/tsconfig.node.json +0 -11
  187. /package/src/{plugins/attachment → components}/insertAttachment/insertAttachment.less +0 -0
  188. /package/src/{plugins/mathformula → components}/insertMathformula/insertMathformula.less +0 -0
  189. /package/src/{plugins/mathformula → components}/insertMathformula/insertMathformula.vue +0 -0
  190. /package/src/{components → editify}/menu/menu.less +0 -0
@@ -1,1677 +0,0 @@
1
- <template>
2
- <Layer v-model="show" ref="layerRef" :node="node" :scroll-node="scrollNode" border placement="bottom-start" @show="layerShow" :useRange="type == 'text'" :z-index="zIndex" :inside-elements="insideElements">
3
- <div class="editify-toolbar" ref="toolbarRef" :style="config.style">
4
- <!-- 链接工具条 -->
5
- <template v-if="type == 'link'">
6
- <div class="editify-toolbar-link">
7
- <div class="editify-toolbar-link-label">{{ $editTrans('linkAddress') }}</div>
8
- <input @change="modifyLink" @focus="handleInputFocus" @blur="handleInputBlur" :placeholder="$editTrans('linkUrlEnterPlaceholder')" v-model.trim="linkConfig.url" type="url" />
9
- <div class="editify-toolbar-link-footer">
10
- <Checkbox @change="modifyLink" v-model="linkConfig.newOpen" :label="$editTrans('newWindowOpen')" :color="color" :size="10"></Checkbox>
11
- <div class="editify-toolbar-link-operations">
12
- <span @click="removeLink">{{ $editTrans('removeLink') }}</span>
13
- <a :href="linkConfig.url" target="_blank" :style="{ color: color || '' }">{{ $editTrans('viewLink') }}</a>
14
- </div>
15
- </div>
16
- </div>
17
- </template>
18
- <!-- 图片工具条 -->
19
- <template v-else-if="type == 'image'">
20
- <!-- 设置宽度30% -->
21
- <Button @operate="setWidth('30%')" name="set30Width" :title="$editTrans('width30')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1"> 30% </Button>
22
- <!-- 设置宽度50% -->
23
- <Button @operate="setWidth('50%')" name="set50Width" :title="$editTrans('width50')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1"> 50% </Button>
24
- <!-- 设置宽度100% -->
25
- <Button rightBorder @operate="setWidth('100%')" name="set100Width" :title="$editTrans('width100')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1"> 100% </Button>
26
- <!-- 设置宽度auto -->
27
- <Button @operate="setWidth('auto')" name="setAutoWidth" :title="$editTrans('auto')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
28
- <Icon value="auto-width"></Icon>
29
- </Button>
30
- <!-- 删除图片 -->
31
- <Button @operate="deleteElement('img')" name="deleteImage" :title="$editTrans('deleteImage')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
32
- <Icon value="delete"></Icon>
33
- </Button>
34
- </template>
35
- <!-- 视频工具条 -->
36
- <template v-else-if="type == 'video'">
37
- <!-- 设置宽度30% -->
38
- <Button @operate="setWidth('30%')" name="set30Width" :title="$editTrans('width30')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1"> 30% </Button>
39
- <!-- 设置宽度50% -->
40
- <Button @operate="setWidth('50%')" name="set50Width" :title="$editTrans('width50')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1"> 50% </Button>
41
- <!-- 设置宽度100% -->
42
- <Button @operate="setWidth('100%')" name="set100Width" :title="$editTrans('width100')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1"> 100% </Button>
43
- <!-- 设置宽度auto -->
44
- <Button rightBorder @operate="setWidth('auto')" name="setAutoWidth" :title="$editTrans('auto')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
45
- <Icon value="auto-width"></Icon>
46
- </Button>
47
- <!-- 自动播放 -->
48
- <Button @operate="setVideo" name="autoplay" :title="videoConfig.autoplay ? $editTrans('disabledAutoplay') : $editTrans('autoplay')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
49
- <Icon :value="videoConfig.autoplay ? 'autoplay' : 'stop'"></Icon>
50
- </Button>
51
- <!-- 循环播放 -->
52
- <Button @operate="setVideo" name="loop" :title="videoConfig.loop ? $editTrans('disabledLoop') : $editTrans('loop')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
53
- <Icon :value="videoConfig.loop ? 'loop' : 'single'"></Icon>
54
- </Button>
55
- <!-- 是否静音 -->
56
- <Button @operate="setVideo" name="muted" :title="videoConfig.muted ? $editTrans('unmuted') : $editTrans('muted')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
57
- <Icon :value="videoConfig.muted ? 'muted' : 'unmuted'"></Icon>
58
- </Button>
59
- <!-- 是否显示控制器 -->
60
- <Button leftBorder @operate="setVideo" name="controls" :title="$editTrans('controls')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
61
- <Icon value="controls"></Icon>
62
- </Button>
63
- <!-- 删除视频 -->
64
- <Button @operate="deleteElement('video')" name="deleteVideo" :title="$editTrans('deleteVideo')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
65
- <Icon value="delete"></Icon>
66
- </Button>
67
- </template>
68
- <!-- 表格工具条 -->
69
- <template v-else-if="type == 'table'">
70
- <!-- 表格前插入段落 -->
71
- <Button @operate="insertParagraphWithTable('up')" name="textWrapUp" :title="$editTrans('textWrapUp')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
72
- <Icon value="text-wrap" class="editify-icon-rotate"></Icon>
73
- </Button>
74
- <!-- 表格后插入段落 -->
75
- <Button @operate="insertParagraphWithTable('down')" rightBorder name="textWrapDown" :title="$editTrans('textWrapDown')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
76
- <Icon value="text-wrap"></Icon>
77
- </Button>
78
- <!-- 向前插入行 -->
79
- <Button @operate="insertTableRow('up')" name="insertRowTop" :title="$editTrans('insertRowTop')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
80
- <Icon value="insert-row-top"></Icon>
81
- </Button>
82
- <!-- 向后插入行 -->
83
- <Button @operate="insertTableRow('down')" name="insertRowBottom" :title="$editTrans('insertRowBottom')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
84
- <Icon value="insert-row-bottom"></Icon>
85
- </Button>
86
- <!-- 删除行 -->
87
- <Button @operate="deleteTableRow" rightBorder name="deleteRow" :title="$editTrans('deleteRow')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
88
- <Icon value="delete-row"></Icon>
89
- </Button>
90
- <!-- 向前插入列 -->
91
- <Button @operate="insertTableColumn('left')" name="insertColumnLeft" :title="$editTrans('insertColumnLeft')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
92
- <Icon value="insert-column-left"></Icon>
93
- </Button>
94
- <!-- 向后插入列 -->
95
- <Button @operate="insertTableColumn('right')" name="insertColumnRight" :title="$editTrans('insertColumnRight')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
96
- <Icon value="insert-column-right"></Icon>
97
- </Button>
98
- <!-- 删除列 -->
99
- <Button @operate="deleteTableColumn" rightBorder name="deleteColumn" :title="$editTrans('deleteColumn')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
100
- <Icon value="delete-column"></Icon>
101
- </Button>
102
- <!-- 向左合并单元格 -->
103
- <Button :disabled="!canMergeCells('left')" @operate="mergeCells('left')" rightBorder name="mergeCellsLeft" :title="$editTrans('mergeCellsLeft')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
104
- <Icon value="merge-cells-left"></Icon>
105
- </Button>
106
- <!-- 向右合并单元格 -->
107
- <Button :disabled="!canMergeCells('right')" @operate="mergeCells('right')" rightBorder name="mergeCellsRight" :title="$editTrans('mergeCellsRight')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
108
- <Icon value="merge-cells-right"></Icon>
109
- </Button>
110
- <!-- 向上合并单元格 -->
111
- <Button :disabled="!canMergeCells('up')" @operate="mergeCells('up')" rightBorder name="mergeCellsUp" :title="$editTrans('mergeCellsUp')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
112
- <Icon value="merge-cells-up"></Icon>
113
- </Button>
114
- <!-- 向下合并单元格 -->
115
- <Button :disabled="!canMergeCells('down')" @operate="mergeCells('down')" rightBorder name="mergeCellsDown" :title="$editTrans('mergeCellsDown')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
116
- <Icon value="merge-cells-down"></Icon>
117
- </Button>
118
- <!-- 删除表格 -->
119
- <Button @operate="deleteElement('table')" leftBorder name="deleteTable" :title="$editTrans('deleteTable')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
120
- <Icon value="delete-table"></Icon>
121
- </Button>
122
- </template>
123
- <!-- 代码块工具条 -->
124
- <template v-if="type == 'codeBlock'">
125
- <!-- 代码块前插入段落 -->
126
- <Button @operate="insertParagraphWithPre('up')" name="textWrapUp" :title="$editTrans('textWrapUp')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
127
- <Icon value="text-wrap" class="editify-icon-rotate"></Icon>
128
- </Button>
129
- <!-- 代码块后插入段落 -->
130
- <Button @operate="insertParagraphWithPre('down')" name="textWrapDown" :title="$editTrans('textWrapDown')" :tooltip="config.tooltip" :color="color" :z-index="zIndex + 1">
131
- <Icon value="text-wrap"></Icon>
132
- </Button>
133
- <!-- 代码块语言选择 -->
134
- <Button v-if="languageConfig.show" ref="languagesBtnRef" name="languages" type="display" :title="$editTrans('selectLanguages')" :tooltip="config.tooltip" :leftBorder="languageConfig.leftBorder" :rightBorder="languageConfig.rightBorder" :display-config="languageConfig.displayConfig" :color="color" :active="languageConfig.active" :disabled="languageConfig.disabled" @operate="selectLanguage" :z-index="zIndex + 1"></Button>
135
- </template>
136
- <!-- 文本工具条 -->
137
- <template v-else-if="type == 'text'">
138
- <!-- 设置段落和标题 -->
139
- <Button v-if="headingConfig.show" ref="headingBtnRef" name="heading" type="display" :title="$editTrans('heading')" :tooltip="config.tooltip" :display-config="headingConfig.displayConfig" :leftBorder="headingConfig.leftBorder" :rightBorder="headingConfig.rightBorder" :color="color" :active="headingConfig.active" :disabled="headingConfig.disabled" @operate="_setHeading" :z-index="zIndex + 1"></Button>
140
- <!-- 对齐方式 -->
141
- <Button v-if="alignConfig.show" name="align" ref="alignBtnRef" type="select" :title="$editTrans('align')" :tooltip="config.tooltip" :select-config="alignConfig.selectConfig" :leftBorder="alignConfig.leftBorder" :rightBorder="alignConfig.rightBorder" :color="color" :active="alignConfig.active" :disabled="alignConfig.disabled" @operate="_setAlign" :z-index="zIndex + 1">
142
- <Icon value="align-left"></Icon>
143
- </Button>
144
- <!-- 有序列表 -->
145
- <Button v-if="orderListConfig.show" name="orderList" :title="$editTrans('orderList')" :tooltip="config.tooltip" :leftBorder="orderListConfig.leftBorder" :rightBorder="orderListConfig.rightBorder" :color="color" :active="orderListConfig.active" :disabled="orderListConfig.disabled" @operate="_setList" :z-index="zIndex + 1">
146
- <Icon value="list-ordered"></Icon>
147
- </Button>
148
- <!-- 无序列表 -->
149
- <Button v-if="unorderListConfig.show" name="unorderList" :title="$editTrans('unorderList')" :tooltip="config.tooltip" :leftBorder="unorderListConfig.leftBorder" :rightBorder="unorderListConfig.rightBorder" :color="color" :active="unorderListConfig.active" :disabled="unorderListConfig.disabled" @operate="_setList" :z-index="zIndex + 1">
150
- <Icon value="list-unordered"></Icon>
151
- </Button>
152
- <!-- 任务列表 -->
153
- <Button v-if="taskConfig.show" name="task" :title="$editTrans('task')" :tooltip="config.tooltip" :leftBorder="taskConfig.leftBorder" :rightBorder="taskConfig.rightBorder" :color="color" :active="taskConfig.active" :disabled="taskConfig.disabled" @operate="_setTask" :z-index="zIndex + 1">
154
- <Icon value="task"></Icon>
155
- </Button>
156
- <!-- 加粗 -->
157
- <Button v-if="boldConfig.show" name="bold" :title="$editTrans('bold')" :tooltip="config.tooltip" :leftBorder="boldConfig.leftBorder" :rightBorder="boldConfig.rightBorder" :color="color" :active="boldConfig.active" :disabled="boldConfig.disabled" @operate="setBold" :z-index="zIndex + 1">
158
- <Icon value="bold"></Icon>
159
- </Button>
160
- <!-- 斜体 -->
161
- <Button v-if="italicConfig.show" name="italic" :title="$editTrans('italic')" :tooltip="config.tooltip" :leftBorder="italicConfig.leftBorder" :rightBorder="italicConfig.rightBorder" :color="color" :active="italicConfig.active" :disabled="italicConfig.disabled" @operate="setItalic" :z-index="zIndex + 1">
162
- <Icon value="italic"></Icon>
163
- </Button>
164
- <!-- 删除线 -->
165
- <Button v-if="strikethroughConfig.show" name="strikethrough" :title="$editTrans('strikethrough')" :tooltip="config.tooltip" :leftBorder="strikethroughConfig.leftBorder" :rightBorder="strikethroughConfig.rightBorder" :color="color" :active="strikethroughConfig.active" :disabled="strikethroughConfig.disabled" @operate="setStrikethrough" :z-index="zIndex + 1">
166
- <Icon value="strikethrough"></Icon>
167
- </Button>
168
- <!-- 下划线 -->
169
- <Button v-if="underlineConfig.show" name="underline" :title="$editTrans('underline')" :tooltip="config.tooltip" :leftBorder="underlineConfig.leftBorder" :rightBorder="underlineConfig.rightBorder" :color="color" :active="underlineConfig.active" :disabled="underlineConfig.disabled" @operate="setUnderline" :z-index="zIndex + 1">
170
- <Icon value="underline"></Icon>
171
- </Button>
172
- <!-- 行内代码块 -->
173
- <Button v-if="codeConfig.show" name="code" :title="$editTrans('code')" :tooltip="config.tooltip" :leftBorder="codeConfig.leftBorder" :rightBorder="codeConfig.rightBorder" :color="color" :active="codeConfig.active" :disabled="codeConfig.disabled" @operate="setCodeStyle" :z-index="zIndex + 1">
174
- <Icon value="code"></Icon>
175
- </Button>
176
- <!-- 上标 -->
177
- <Button v-if="superConfig.show" name="superscript" :title="$editTrans('superscript')" :tooltip="config.tooltip" :leftBorder="superConfig.leftBorder" :rightBorder="superConfig.rightBorder" :color="color" :active="superConfig.active" :disabled="superConfig.disabled" @operate="setSuperscript" :z-index="zIndex + 1">
178
- <Icon value="superscript"></Icon>
179
- </Button>
180
- <!-- 下标 -->
181
- <Button v-if="subConfig.show" name="subscript" :title="$editTrans('subscript')" :tooltip="config.tooltip" :leftBorder="subConfig.leftBorder" :rightBorder="subConfig.rightBorder" :color="color" :active="subConfig.active" :disabled="subConfig.disabled" @operate="setSubscript" :z-index="zIndex + 1">
182
- <Icon value="subscript"></Icon>
183
- </Button>
184
- <!-- 字号大小 -->
185
- <Button v-if="fontSizeConfig.show" ref="fontSizeBtnRef" name="fontSize" type="display" :title="$editTrans('fontSize')" :tooltip="config.tooltip" :display-config="fontSizeConfig.displayConfig" :leftBorder="fontSizeConfig.leftBorder" :rightBorder="fontSizeConfig.rightBorder" :color="color" :active="fontSizeConfig.active" :disabled="fontSizeConfig.disabled" @operate="setFontSize" :z-index="zIndex + 1"></Button>
186
- <!-- 字体 -->
187
- <Button v-if="fontFamilyConfig.show" ref="fontFamilyBtnRef" name="fontFamily" type="display" :title="$editTrans('fontFamily')" :tooltip="config.tooltip" :display-config="fontFamilyConfig.displayConfig" :leftBorder="fontFamilyConfig.leftBorder" :rightBorder="fontFamilyConfig.rightBorder" :color="color" :active="fontFamilyConfig.active" :disabled="fontFamilyConfig.disabled" @operate="setFontFamily" :z-index="zIndex + 1"></Button>
188
- <!-- 行高 -->
189
- <Button v-if="lineHeightConfig.show" ref="lineHeightBtnRef" name="lineHeight" type="display" :title="$editTrans('lineHeight')" :tooltip="config.tooltip" :display-config="lineHeightConfig.displayConfig" :leftBorder="lineHeightConfig.leftBorder" :rightBorder="lineHeightConfig.rightBorder" :color="color" :active="lineHeightConfig.active" :disabled="lineHeightConfig.disabled" @operate="_setLineHeight" :z-index="zIndex + 1"></Button>
190
- <!-- 前景色 -->
191
- <Button v-if="foreColorConfig.show" name="foreColor" type="select" :title="$editTrans('foreColor')" :tooltip="config.tooltip" :select-config="foreColorConfig.selectConfig" :leftBorder="foreColorConfig.leftBorder" :rightBorder="foreColorConfig.rightBorder" :color="color" :active="foreColorConfig.active" :disabled="foreColorConfig.disabled" hideScroll ref="foreColorBtnRef" :z-index="zIndex + 1">
192
- <Icon value="font-color"></Icon>
193
- <template #layer="{ options }">
194
- <Colors :tooltip="config.tooltip" :color="color" :value="foreColorConfig.value" @change="setForeColor" :data="options"></Colors>
195
- </template>
196
- </Button>
197
- <!-- 背景色 -->
198
- <Button v-if="backColorConfig.show" name="backColor" type="select" :title="$editTrans('backColor')" :tooltip="config.tooltip" :select-config="backColorConfig.selectConfig" :leftBorder="backColorConfig.leftBorder" :rightBorder="backColorConfig.rightBorder" :color="color" :active="backColorConfig.active" :disabled="backColorConfig.disabled" hideScroll ref="backColorBtnRef" :z-index="zIndex + 1">
199
- <Icon value="brush"></Icon>
200
- <template #layer="{ options }">
201
- <Colors :tooltip="config.tooltip" :color="color" :value="backColorConfig.value" @change="setBackColor" :data="options"></Colors>
202
- </template>
203
- </Button>
204
- <!-- 清除样式 -->
205
- <Button v-if="formatClearConfig.show" name="formatClear" :title="$editTrans('formatClear')" :tooltip="config.tooltip" :leftBorder="formatClearConfig.leftBorder" :rightBorder="formatClearConfig.rightBorder" :color="color" :active="formatClearConfig.active" :disabled="formatClearConfig.disabled" @operate="clearFormat" :z-index="zIndex + 1">
206
- <Icon value="format-clear"></Icon>
207
- </Button>
208
- </template>
209
- </div>
210
- </Layer>
211
- </template>
212
- <script setup lang="ts">
213
- import { Ref, computed, inject, ref } from 'vue'
214
- import { common as DapCommon } from 'dap-util'
215
- import { AlexEditor, AlexElement, AlexElementCreateConfigType, AlexElementsRangeType } from 'alex-editor'
216
- import Layer from '@/components/layer/layer.vue'
217
- import Button from '@/components/button/button.vue'
218
- import Icon from '@/components/icon/icon.vue'
219
- import Checkbox from '@/components/checkbox/checkbox.vue'
220
- import Colors from '@/components/colors/colors.vue'
221
- import { getCellSpanNumber, getTableSize, getMatchElementByRange, removeTextStyle, removeTextMark, setTextStyle, setLineHeight, setTextMark, setList, setTask, setHeading, setAlign, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark, getMatchElementByElement, getCellMergeElement, setTableCellMerged } from '@/core/function'
222
- import { ObjectType } from '@/core/tool'
223
- import { ButtonOptionsItemType } from '@/components/button/props'
224
- import { ToolbarProps } from './props'
225
-
226
- defineOptions({
227
- name: 'Toolbar'
228
- })
229
- const props = defineProps(ToolbarProps)
230
- const emits = defineEmits(['update:modelValue'])
231
-
232
- const editor = inject<Ref<AlexEditor>>('editor')!
233
- const dataRangeCaches = inject<Ref<AlexElementsRangeType>>('dataRangeCaches')!
234
- const $editTrans = inject<(key: string) => any>('$editTrans')!
235
-
236
- const layerRef = ref<InstanceType<typeof Layer> | null>(null)
237
- const toolbarRef = ref<HTMLElement | null>(null)
238
- const foreColorBtnRef = ref<InstanceType<typeof Button> | null>(null)
239
- const backColorBtnRef = ref<InstanceType<typeof Button> | null>(null)
240
- const languagesBtnRef = ref<InstanceType<typeof Button> | null>(null)
241
- const headingBtnRef = ref<InstanceType<typeof Button> | null>(null)
242
- const alignBtnRef = ref<InstanceType<typeof Button> | null>(null)
243
- const fontSizeBtnRef = ref<InstanceType<typeof Button> | null>(null)
244
- const fontFamilyBtnRef = ref<InstanceType<typeof Button> | null>(null)
245
- const lineHeightBtnRef = ref<InstanceType<typeof Button> | null>(null)
246
-
247
- //链接参数配置
248
- const linkConfig = ref<ObjectType>({
249
- //链接地址
250
- url: '',
251
- //链接是否新窗口打开
252
- newOpen: false
253
- })
254
-
255
- //视频参数配置
256
- const videoConfig = ref<ObjectType>({
257
- //是否显示控制器
258
- controls: false,
259
- //是否循环
260
- loop: false,
261
- //是否自动播放
262
- autoplay: false,
263
- //是否静音
264
- muted: false
265
- })
266
-
267
- //代码块选择语言按钮配置
268
- const languageConfig = ref<ObjectType>({
269
- show: props.config.codeBlock!.languages!.show,
270
- displayConfig: {
271
- options: props.config.codeBlock!.languages!.options,
272
- value: '',
273
- width: props.config.codeBlock!.languages!.width,
274
- maxHeight: props.config.codeBlock!.languages!.maxHeight
275
- },
276
- leftBorder: props.config.codeBlock!.languages!.leftBorder,
277
- rightBorder: props.config.codeBlock!.languages!.rightBorder,
278
- active: false,
279
- disabled: false
280
- })
281
-
282
- /** 以下是文本工具条的配置参数信息 */
283
- //标题按钮配置
284
- const headingConfig = ref<ObjectType>({
285
- show: props.config.text!.heading!.show,
286
- displayConfig: {
287
- options: props.config.text!.heading!.options,
288
- value: '',
289
- width: props.config.text!.heading!.width,
290
- maxHeight: props.config.text!.heading!.maxHeight
291
- },
292
- defaultValue: props.config.text!.heading!.defaultValue,
293
- leftBorder: props.config.text!.heading!.leftBorder,
294
- rightBorder: props.config.text!.heading!.rightBorder,
295
- active: false,
296
- disabled: false
297
- })
298
- //对齐方式按钮配置
299
- const alignConfig = ref<ObjectType>({
300
- show: props.config.text!.align!.show,
301
- selectConfig: {
302
- options: props.config.text!.align!.options,
303
- width: props.config.text!.align!.width,
304
- maxHeight: props.config.text!.align!.maxHeight
305
- },
306
- leftBorder: props.config.text!.align!.leftBorder,
307
- rightBorder: props.config.text!.align!.rightBorder,
308
- active: false,
309
- disabled: false
310
- })
311
- //有序列表按钮配置
312
- const orderListConfig = ref<ObjectType>({
313
- show: props.config.text!.orderList!.show,
314
- leftBorder: props.config.text!.orderList!.leftBorder,
315
- rightBorder: props.config.text!.orderList!.rightBorder,
316
- active: false,
317
- disabled: false
318
- })
319
- //无序列表按钮配置
320
- const unorderListConfig = ref<ObjectType>({
321
- show: props.config.text!.unorderList!.show,
322
- leftBorder: props.config.text!.unorderList!.leftBorder,
323
- rightBorder: props.config.text!.unorderList!.rightBorder,
324
- active: false,
325
- disabled: false
326
- })
327
- //任务列表按钮配置
328
- const taskConfig = ref<ObjectType>({
329
- show: props.config.text!.task!.show,
330
- leftBorder: props.config.text!.task!.leftBorder,
331
- rightBorder: props.config.text!.task!.rightBorder,
332
- active: false,
333
- disabled: false
334
- })
335
- //粗体按钮配置
336
- const boldConfig = ref<ObjectType>({
337
- show: props.config.text!.bold!.show,
338
- leftBorder: props.config.text!.bold!.leftBorder,
339
- rightBorder: props.config.text!.bold!.rightBorder,
340
- active: false,
341
- disabled: false
342
- })
343
- //斜体按钮配置
344
- const italicConfig = ref<ObjectType>({
345
- show: props.config.text!.italic!.show,
346
- leftBorder: props.config.text!.italic!.leftBorder,
347
- rightBorder: props.config.text!.italic!.rightBorder,
348
- active: false,
349
- disabled: false
350
- })
351
- //删除线按钮配置
352
- const strikethroughConfig = ref<ObjectType>({
353
- show: props.config.text!.strikethrough!.show,
354
- leftBorder: props.config.text!.strikethrough!.leftBorder,
355
- rightBorder: props.config.text!.strikethrough!.rightBorder,
356
- active: false,
357
- disabled: false
358
- })
359
- //下划线按钮配置
360
- const underlineConfig = ref<ObjectType>({
361
- show: props.config.text!.underline!.show,
362
- leftBorder: props.config.text!.underline!.leftBorder,
363
- rightBorder: props.config.text!.underline!.rightBorder,
364
- active: false,
365
- disabled: false
366
- })
367
- //行内代码块按钮配置
368
- const codeConfig = ref<ObjectType>({
369
- show: props.config.text!.code!.show,
370
- leftBorder: props.config.text!.code!.leftBorder,
371
- rightBorder: props.config.text!.code!.rightBorder,
372
- active: false,
373
- disabled: false
374
- })
375
- //上标按钮配置
376
- const superConfig = ref<ObjectType>({
377
- show: props.config.text!.super!.show,
378
- leftBorder: props.config.text!.super!.leftBorder,
379
- rightBorder: props.config.text!.super!.rightBorder,
380
- active: false,
381
- disabled: false
382
- })
383
- //下标按钮配置
384
- const subConfig = ref<ObjectType>({
385
- show: props.config.text!.sub!.show,
386
- leftBorder: props.config.text!.sub!.leftBorder,
387
- rightBorder: props.config.text!.sub!.rightBorder,
388
- active: false,
389
- disabled: false
390
- })
391
- //字号按钮配置
392
- const fontSizeConfig = ref<ObjectType>({
393
- show: props.config.text!.fontSize!.show,
394
- displayConfig: {
395
- options: props.config.text!.fontSize!.options,
396
- value: '',
397
- width: props.config.text!.fontSize!.width,
398
- maxHeight: props.config.text!.fontSize!.maxHeight
399
- },
400
- defaultValue: props.config.text!.fontSize!.defaultValue,
401
- leftBorder: props.config.text!.fontSize!.leftBorder,
402
- rightBorder: props.config.text!.fontSize!.rightBorder,
403
- active: false,
404
- disabled: false
405
- })
406
- //字体按钮配置
407
- const fontFamilyConfig = ref<ObjectType>({
408
- show: props.config.text!.fontFamily!.show,
409
- displayConfig: {
410
- options: props.config.text!.fontFamily!.options,
411
- value: '',
412
- width: props.config.text!.fontFamily!.width,
413
- maxHeight: props.config.text!.fontFamily!.maxHeight
414
- },
415
- defaultValue: props.config.text!.fontFamily!.defaultValue,
416
- leftBorder: props.config.text!.fontFamily!.leftBorder,
417
- rightBorder: props.config.text!.fontFamily!.rightBorder,
418
- active: false,
419
- disabled: false
420
- })
421
- //行高按钮配置
422
- const lineHeightConfig = ref<ObjectType>({
423
- show: props.config.text!.lineHeight!.show,
424
- displayConfig: {
425
- options: props.config.text!.lineHeight!.options,
426
- value: '',
427
- width: props.config.text!.lineHeight!.width,
428
- maxHeight: props.config.text!.lineHeight!.maxHeight
429
- },
430
- defaultValue: props.config.text!.lineHeight!.defaultValue,
431
- leftBorder: props.config.text!.lineHeight!.leftBorder,
432
- rightBorder: props.config.text!.lineHeight!.rightBorder,
433
- active: false,
434
- disabled: false
435
- })
436
- //前景颜色按钮配置
437
- const foreColorConfig = ref<ObjectType>({
438
- show: props.config.text!.foreColor!.show,
439
- selectConfig: {
440
- options: props.config.text!.foreColor!.options
441
- },
442
- leftBorder: props.config.text!.foreColor!.leftBorder,
443
- rightBorder: props.config.text!.foreColor!.rightBorder,
444
- value: '', //选择的颜色值
445
- active: false,
446
- disabled: false
447
- })
448
- //背景颜色按钮配置
449
- const backColorConfig = ref<ObjectType>({
450
- show: props.config.text!.backColor!.show,
451
- selectConfig: {
452
- options: props.config.text!.backColor!.options
453
- },
454
- leftBorder: props.config.text!.backColor!.leftBorder,
455
- rightBorder: props.config.text!.backColor!.rightBorder,
456
- value: '', //选择的颜色值
457
- active: false,
458
- disabled: false
459
- })
460
- //清除格式按钮配置
461
- const formatClearConfig = ref<ObjectType>({
462
- show: props.config.text!.formatClear!.show,
463
- leftBorder: props.config.text!.formatClear!.leftBorder,
464
- rightBorder: props.config.text!.formatClear!.rightBorder,
465
- active: false,
466
- disabled: false
467
- })
468
-
469
- //是否显示
470
- const show = computed<boolean>({
471
- get() {
472
- return props.modelValue
473
- },
474
- set(val) {
475
- emits('update:modelValue', val)
476
- }
477
- })
478
- //是否可以合并单元格
479
- const canMergeCells = computed<(type: 'left' | 'right' | 'up' | 'down') => boolean>(() => {
480
- return (type: 'left' | 'right' | 'up' | 'down') => {
481
- if (!editor.value.range) {
482
- return false
483
- }
484
- //光标所在单元格
485
- const cell = getMatchElementByElement(editor.value.range.focus.element, {
486
- parsedom: 'td'
487
- })
488
- //如果光标不在单元格内
489
- if (!cell) {
490
- return false
491
- }
492
- //判断是否可以向左合并
493
- if (type == 'left') {
494
- //是否可以向左合并
495
- let flag = false
496
- //当前单元格的rowspan
497
- const cellSpanNum = getCellSpanNumber(cell)
498
- //获取左侧单元格
499
- const previousColumn = editor.value.getPreviousElement(cell)
500
- //如果左侧单元格存在
501
- if (previousColumn) {
502
- //左侧单元格是隐藏的单元格
503
- if (previousColumn.hasMarks() && previousColumn.marks!['data-editify-merged']) {
504
- //获取合并该隐藏单元格的那个单元格
505
- const { crossColumnElement } = getCellMergeElement(editor.value, previousColumn)
506
- //如果是被跨列合并则判断跨列单元格占据的行数与当前单元格的行数是否一致
507
- if (crossColumnElement) {
508
- const { rowspan } = getCellSpanNumber(crossColumnElement)
509
- flag = rowspan == cellSpanNum.rowspan
510
- }
511
- }
512
- //左侧单元格不是隐藏的单元格
513
- else {
514
- //判断所占行数是否一致
515
- const { rowspan } = getCellSpanNumber(previousColumn)
516
- flag = rowspan == cellSpanNum.rowspan
517
- }
518
- }
519
- return flag
520
- }
521
- //判断是否可以向右合并
522
- if (type == 'right') {
523
- //是否可以向右合并
524
- let flag = false
525
- //当前单元格的rowspan
526
- const cellSpanNum = getCellSpanNumber(cell)
527
- //获取右侧的单元格
528
- let nextColumn = editor.value.getNextElement(cell)
529
- //如果右侧单元格存在
530
- while (nextColumn) {
531
- //右侧单元格是隐藏的单元格
532
- if (nextColumn.hasMarks() && nextColumn.marks!['data-editify-merged']) {
533
- //获取合并该隐藏单元格的那个单元格
534
- const { crossColumnElement } = getCellMergeElement(editor.value, nextColumn)
535
- //如果是被跨列合并的表示属于当前单元格内,继续向右查询
536
- if (crossColumnElement) {
537
- nextColumn = editor.value.getNextElement(nextColumn)
538
- }
539
- //被跨行合并的直接结束,不能向右合并
540
- else {
541
- break
542
- }
543
- }
544
- //右侧单元格不是隐藏的
545
- else {
546
- //判断行数是否与当前单元格一致
547
- const { rowspan } = getCellSpanNumber(nextColumn)
548
- //如果一致则可以合并
549
- flag = rowspan == cellSpanNum.rowspan
550
- //不管是否一致都直接结束
551
- break
552
- }
553
- }
554
- return flag
555
- }
556
- //判断是否可以向上合并
557
- if (type == 'up') {
558
- //是否可以向上合并
559
- let flag = false
560
- //当前单元格的colspan
561
- const cellSpanNum = getCellSpanNumber(cell)
562
- //获取单元格在行中的序列
563
- const index = cell.parent!.children!.findIndex(item => item.isEqual(cell))
564
- //获取上一行
565
- const previousRow = editor.value.getPreviousElement(cell.parent!)
566
- //如果上一行存在
567
- if (previousRow) {
568
- //获取上一行中对应序列的单元格
569
- const column = previousRow.children![index]
570
- //单元格是隐藏的单元格
571
- if (column.hasMarks() && column.marks!['data-editify-merged']) {
572
- //获取合并该隐藏单元格的那个单元格
573
- const { crossRowElement } = getCellMergeElement(editor.value, column)
574
- //如果是被跨行合并则判断跨列单元格占据的列数与当前单元格的列数是否一致
575
- if (crossRowElement) {
576
- const { colspan } = getCellSpanNumber(crossRowElement)
577
- flag = colspan == cellSpanNum.colspan
578
- }
579
- }
580
- //单元格不是隐藏的单元格
581
- else {
582
- //判断所占列数是否一致
583
- const { colspan } = getCellSpanNumber(column)
584
- flag = colspan == cellSpanNum.colspan
585
- }
586
- }
587
- return flag
588
- }
589
- //判断是否可以向下合并
590
- if (type == 'down') {
591
- //是否可以向下合并
592
- let flag = false
593
- //当前单元格的colspan
594
- const cellSpanNum = getCellSpanNumber(cell)
595
- //获取单元格在行中的序列
596
- const index = cell.parent!.children!.findIndex(item => item.isEqual(cell))
597
- //获取下一行
598
- let nextRow = editor.value.getNextElement(cell.parent!)
599
- //如果下一行存在
600
- while (nextRow) {
601
- //获取下一行中对应序列的单元格
602
- const column = nextRow.children![index]
603
- //单元格是隐藏的单元格
604
- if (column.hasMarks() && column.marks!['data-editify-merged']) {
605
- //获取合并该隐藏单元格的那个单元格
606
- const { crossRowElement } = getCellMergeElement(editor.value, column)
607
- //如果是被跨行合并的表示属于当前单元格内,继续向下查询
608
- if (crossRowElement) {
609
- nextRow = editor.value.getNextElement(nextRow)
610
- }
611
- //被跨列合并的直接结束,不能向右合并
612
- else {
613
- break
614
- }
615
- }
616
- //单元格不是隐藏的
617
- else {
618
- //判断列数是否与当前单元格一致
619
- const { colspan } = getCellSpanNumber(column)
620
- //如果一致则可以合并
621
- flag = colspan == cellSpanNum.colspan
622
- //不管是否一致都直接结束
623
- break
624
- }
625
- }
626
- return flag
627
- }
628
- return false
629
- }
630
- })
631
- //点击不关闭工具条浮层的元素(算在工具条浮层元素范围内)
632
- const insideElements = computed<HTMLElement[]>(() => {
633
- let elements: HTMLElement[] = []
634
- //语言选择浮层元素
635
- if (languagesBtnRef.value && languagesBtnRef.value.layerRef && languagesBtnRef.value.layerRef.elRef) {
636
- elements.push(languagesBtnRef.value.layerRef.elRef)
637
- }
638
- //前景色选择浮层元素
639
- if (foreColorBtnRef.value && foreColorBtnRef.value.layerRef && foreColorBtnRef.value.layerRef.elRef) {
640
- elements.push(foreColorBtnRef.value.layerRef.elRef)
641
- }
642
- //背景色选择浮层元素
643
- if (backColorBtnRef.value && backColorBtnRef.value.layerRef && backColorBtnRef.value.layerRef.elRef) {
644
- elements.push(backColorBtnRef.value.layerRef.elRef)
645
- }
646
- //标题选择浮层元素
647
- if (headingBtnRef.value && headingBtnRef.value.layerRef && headingBtnRef.value.layerRef.elRef) {
648
- elements.push(headingBtnRef.value.layerRef.elRef)
649
- }
650
- //对齐方式选择浮层元素
651
- if (alignBtnRef.value && alignBtnRef.value.layerRef && alignBtnRef.value.layerRef.elRef) {
652
- elements.push(alignBtnRef.value.layerRef.elRef)
653
- }
654
- //字号选择浮层元素
655
- if (fontSizeBtnRef.value && fontSizeBtnRef.value.layerRef && fontSizeBtnRef.value.layerRef.elRef) {
656
- elements.push(fontSizeBtnRef.value.layerRef.elRef)
657
- }
658
- //字体选择浮层元素
659
- if (fontFamilyBtnRef.value && fontFamilyBtnRef.value.layerRef && fontFamilyBtnRef.value.layerRef.elRef) {
660
- elements.push(fontFamilyBtnRef.value.layerRef.elRef)
661
- }
662
- //行高选择浮层元素
663
- if (lineHeightBtnRef.value && lineHeightBtnRef.value.layerRef && lineHeightBtnRef.value.layerRef.elRef) {
664
- elements.push(lineHeightBtnRef.value.layerRef.elRef)
665
- }
666
- return elements
667
- })
668
-
669
- //输入框获取焦点
670
- const handleInputFocus = (e: Event) => {
671
- if (props.color) {
672
- ;(<HTMLInputElement>e.currentTarget).style.borderColor = props.color
673
- }
674
- }
675
- //输入框失去焦点
676
- const handleInputBlur = (e: Event) => {
677
- ;(<HTMLInputElement>e.currentTarget).style.borderColor = ''
678
- }
679
- //清除格式
680
- const clearFormat = () => {
681
- removeTextStyle(editor.value, dataRangeCaches.value)
682
- removeTextMark(editor.value, dataRangeCaches.value)
683
- editor.value.formatElementStack()
684
- editor.value.domRender()
685
- editor.value.rangeRender()
686
- }
687
- //设置背景色
688
- const setBackColor = (value: string) => {
689
- setTextStyle(editor.value, dataRangeCaches.value, {
690
- 'background-color': value
691
- })
692
- backColorBtnRef.value!.show = false
693
- editor.value.formatElementStack()
694
- editor.value.domRender()
695
- editor.value.rangeRender()
696
- }
697
- //设置前景色
698
- const setForeColor = (value: string) => {
699
- setTextStyle(editor.value, dataRangeCaches.value, {
700
- color: value
701
- })
702
- foreColorBtnRef.value!.show = false
703
- editor.value.formatElementStack()
704
- editor.value.domRender()
705
- editor.value.rangeRender()
706
- }
707
- //设置行高
708
- const _setLineHeight = (_name: string, value: string | number) => {
709
- setLineHeight(editor.value, dataRangeCaches.value, value)
710
- editor.value.formatElementStack()
711
- editor.value.domRender()
712
- editor.value.rangeRender()
713
- }
714
- //设置字体
715
- const setFontFamily = (_name: string, value: string | number) => {
716
- setTextStyle(editor.value, dataRangeCaches.value, {
717
- 'font-family': value
718
- })
719
- editor.value.formatElementStack()
720
- editor.value.domRender()
721
- editor.value.rangeRender()
722
- }
723
- //设置字号
724
- const setFontSize = (_name: string, value: string | number) => {
725
- setTextStyle(editor.value, dataRangeCaches.value, {
726
- 'font-size': value
727
- })
728
- editor.value.formatElementStack()
729
- editor.value.domRender()
730
- editor.value.rangeRender()
731
- }
732
- //设置上标
733
- const setSuperscript = () => {
734
- if (queryTextStyle(editor.value, dataRangeCaches.value, 'vertical-align', 'super')) {
735
- removeTextStyle(editor.value, dataRangeCaches.value, ['vertical-align'])
736
- } else {
737
- setTextStyle(editor.value, dataRangeCaches.value, {
738
- 'vertical-align': 'super'
739
- })
740
- }
741
- editor.value.formatElementStack()
742
- editor.value.domRender()
743
- editor.value.rangeRender()
744
- }
745
- //设置下标
746
- const setSubscript = () => {
747
- if (queryTextStyle(editor.value, dataRangeCaches.value, 'vertical-align', 'sub')) {
748
- removeTextStyle(editor.value, dataRangeCaches.value, ['vertical-align'])
749
- } else {
750
- setTextStyle(editor.value, dataRangeCaches.value, {
751
- 'vertical-align': 'sub'
752
- })
753
- }
754
- editor.value.formatElementStack()
755
- editor.value.domRender()
756
- editor.value.rangeRender()
757
- }
758
- //设置行内代码样式
759
- const setCodeStyle = () => {
760
- if (queryTextMark(editor.value, dataRangeCaches.value, 'data-editify-code')) {
761
- removeTextMark(editor.value, dataRangeCaches.value, ['data-editify-code'])
762
- } else {
763
- setTextMark(editor.value, dataRangeCaches.value, {
764
- 'data-editify-code': true
765
- })
766
- }
767
- editor.value.formatElementStack()
768
- editor.value.domRender()
769
- editor.value.rangeRender()
770
- }
771
- //设置下划线
772
- const setUnderline = () => {
773
- if (queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration', 'underline') || queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration-line', 'underline')) {
774
- removeTextStyle(editor.value, dataRangeCaches.value, ['text-decoration', 'text-decoration-line'])
775
- } else {
776
- setTextStyle(editor.value, dataRangeCaches.value, {
777
- 'text-decoration': 'underline'
778
- })
779
- }
780
- editor.value.formatElementStack()
781
- editor.value.domRender()
782
- editor.value.rangeRender()
783
- }
784
- //设置删除线
785
- const setStrikethrough = () => {
786
- if (queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration', 'line-through') || queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration-line', 'line-through')) {
787
- removeTextStyle(editor.value, dataRangeCaches.value, ['text-decoration', 'text-decoration-line'])
788
- } else {
789
- setTextStyle(editor.value, dataRangeCaches.value, {
790
- 'text-decoration': 'line-through'
791
- })
792
- }
793
- editor.value.formatElementStack()
794
- editor.value.domRender()
795
- editor.value.rangeRender()
796
- }
797
- //设置列表
798
- const _setList = (name: string) => {
799
- setList(editor.value, dataRangeCaches.value, name == 'orderList')
800
- editor.value.formatElementStack()
801
- editor.value.domRender()
802
- editor.value.rangeRender()
803
- }
804
- //设置任务列表
805
- const _setTask = () => {
806
- setTask(editor.value, dataRangeCaches.value)
807
- editor.value.formatElementStack()
808
- editor.value.domRender()
809
- editor.value.rangeRender()
810
- }
811
- //斜体
812
- const setItalic = () => {
813
- if (queryTextStyle(editor.value, dataRangeCaches.value, 'font-style', 'italic')) {
814
- removeTextStyle(editor.value, dataRangeCaches.value, ['font-style'])
815
- } else {
816
- setTextStyle(editor.value, dataRangeCaches.value, {
817
- 'font-style': 'italic'
818
- })
819
- }
820
- editor.value.formatElementStack()
821
- editor.value.domRender()
822
- editor.value.rangeRender()
823
- }
824
- //加粗
825
- const setBold = () => {
826
- if (queryTextStyle(editor.value, dataRangeCaches.value, 'font-weight', 'bold') || queryTextStyle(editor.value, dataRangeCaches.value, 'font-weight', '700')) {
827
- removeTextStyle(editor.value, dataRangeCaches.value, ['font-weight'])
828
- } else {
829
- setTextStyle(editor.value, dataRangeCaches.value, {
830
- 'font-weight': 'bold'
831
- })
832
- }
833
- editor.value.formatElementStack()
834
- editor.value.domRender()
835
- editor.value.rangeRender()
836
- }
837
- //设置标题
838
- const _setHeading = (_name: string, value: string) => {
839
- setHeading(editor.value, dataRangeCaches.value, $editTrans, value)
840
- editor.value.formatElementStack()
841
- editor.value.domRender()
842
- editor.value.rangeRender()
843
- }
844
- //设置对齐方式
845
- const _setAlign = (_name: string, value: string) => {
846
- setAlign(editor.value, dataRangeCaches.value, value as 'left' | 'right' | 'center' | 'justify')
847
- editor.value.formatElementStack()
848
- editor.value.domRender()
849
- editor.value.rangeRender()
850
- }
851
- //设置视频属性
852
- const setVideo = (prop: string) => {
853
- const element = editor.value.range!.anchor.element
854
- //当前是拥有该属性
855
- if (videoConfig.value[prop]) {
856
- delete element.marks![prop]
857
- }
858
- //当前无该属性
859
- else {
860
- element.marks![prop] = true
861
- }
862
- videoConfig.value[prop] = !videoConfig.value[prop]
863
- editor.value.formatElementStack()
864
- editor.value.domRender()
865
- editor.value.rangeRender()
866
- }
867
- //设置图片或者视频宽度
868
- const setWidth = (value: string) => {
869
- const element = editor.value.range!.anchor.element
870
- if (element) {
871
- const styles = {
872
- width: value
873
- }
874
- if (element.hasStyles()) {
875
- element.styles = Object.assign(element.styles!, styles)
876
- } else {
877
- element.styles = styles
878
- }
879
- editor.value.formatElementStack()
880
- editor.value.domRender()
881
- editor.value.rangeRender()
882
- //更新工具条位置
883
- setTimeout(() => {
884
- layerRef.value!.setPosition()
885
- }, 0)
886
- }
887
- }
888
- //修改链接
889
- const modifyLink = () => {
890
- if (!linkConfig.value.url) {
891
- return
892
- }
893
- const link = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'a' })
894
- if (link) {
895
- link.marks!.href = linkConfig.value.url
896
- if (linkConfig.value.newOpen) {
897
- link.marks!.target = '_blank'
898
- } else {
899
- delete link.marks!.target
900
- }
901
- editor.value.formatElementStack()
902
- editor.value.domRender()
903
- }
904
- }
905
- //移除链接
906
- const removeLink = () => {
907
- const link = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'a' })
908
- if (link) {
909
- link.parsedom = AlexElement.TEXT_NODE
910
- delete link.marks!['target']
911
- delete link.marks!['href']
912
- delete link.marks!['data-editify-element']
913
- editor.value.formatElementStack()
914
- editor.value.domRender()
915
- editor.value.rangeRender()
916
- }
917
- }
918
- //选择代码语言
919
- const selectLanguage = (_name: string, value: string) => {
920
- const pre = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'pre' })
921
- if (pre) {
922
- Object.assign(pre.marks!, {
923
- 'data-editify-hljs': value
924
- })
925
- editor.value.formatElementStack()
926
- editor.value.domRender()
927
- editor.value.rangeRender()
928
- }
929
- }
930
- //代码块前后插入段落
931
- const insertParagraphWithPre = (type: string | undefined = 'up') => {
932
- if (!editor.value.range!.anchor.isEqual(editor.value.range!.focus)) {
933
- editor.value.range!.anchor.element = editor.value.range!.focus.element
934
- editor.value.range!.anchor.offset = editor.value.range!.focus.offset
935
- }
936
- const pre = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'pre' })
937
- if (pre) {
938
- const paragraph = AlexElement.create({
939
- type: 'block',
940
- parsedom: AlexElement.BLOCK_NODE,
941
- children: [
942
- {
943
- type: 'closed',
944
- parsedom: 'br'
945
- }
946
- ]
947
- })
948
- if (type == 'up') {
949
- editor.value.addElementBefore(paragraph, pre)
950
- } else {
951
- editor.value.addElementAfter(paragraph, pre)
952
- }
953
- editor.value.range!.anchor.moveToEnd(paragraph)
954
- editor.value.range!.focus.moveToEnd(paragraph)
955
- editor.value.formatElementStack()
956
- editor.value.domRender()
957
- editor.value.rangeRender()
958
- }
959
- }
960
- //表格前后插入列
961
- const insertTableColumn = (type: string | undefined = 'left') => {
962
- if (!editor.value.range!.anchor.isEqual(editor.value.range!.focus)) {
963
- editor.value.range!.anchor.element = editor.value.range!.focus.element
964
- editor.value.range!.anchor.offset = editor.value.range!.focus.offset
965
- }
966
- const column = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'td' })
967
- if (column) {
968
- const row = column.parent!
969
- const tbody = row.parent!
970
- const table = tbody.parent!
971
- const rows = tbody.children
972
- const index = row.children!.findIndex(item => {
973
- return item.isEqual(column)
974
- })
975
- //插入列
976
- rows!.forEach(item => {
977
- const newColumn = AlexElement.create({
978
- type: 'inblock',
979
- parsedom: 'td',
980
- children: [
981
- {
982
- type: 'closed',
983
- parsedom: 'br'
984
- }
985
- ]
986
- })
987
- if (type == 'left') {
988
- editor.value.addElementTo(newColumn, item, index)
989
- } else {
990
- editor.value.addElementTo(newColumn, item, index + 1)
991
- }
992
- })
993
- //插入col
994
- const colgroup = table.children!.find(item => {
995
- return item.parsedom == 'colgroup'
996
- })!
997
- const col = AlexElement.create({
998
- type: 'closed',
999
- parsedom: 'col'
1000
- })
1001
- if (type == 'left') {
1002
- editor.value.addElementTo(col, colgroup, index)
1003
- } else {
1004
- editor.value.addElementTo(col, colgroup, index + 1)
1005
- }
1006
- if (type == 'left') {
1007
- const previousColumn = editor.value.getPreviousElement(column)!
1008
- editor.value.range!.anchor.moveToStart(previousColumn)
1009
- editor.value.range!.focus.moveToStart(previousColumn)
1010
- } else {
1011
- const nextColumn = editor.value.getNextElement(column)!
1012
- editor.value.range!.anchor.moveToStart(nextColumn)
1013
- editor.value.range!.focus.moveToStart(nextColumn)
1014
- }
1015
- //渲染
1016
- editor.value.formatElementStack()
1017
- editor.value.domRender()
1018
- editor.value.rangeRender()
1019
- }
1020
- }
1021
- //表格前后插入行
1022
- const insertTableRow = (type: string | undefined = 'up') => {
1023
- if (!editor.value.range!.anchor.isEqual(editor.value.range!.focus)) {
1024
- editor.value.range!.anchor.element = editor.value.range!.focus.element
1025
- editor.value.range!.anchor.offset = editor.value.range!.focus.offset
1026
- }
1027
- const row = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'tr' })
1028
- if (row) {
1029
- const tbody = row.parent!
1030
- const { columnNumber } = getTableSize(tbody.children!)
1031
- const children: AlexElementCreateConfigType[] = []
1032
- for (let i = 0; i < columnNumber; i++) {
1033
- children.push({
1034
- type: 'inblock',
1035
- parsedom: 'td',
1036
- children: [
1037
- {
1038
- type: 'closed',
1039
- parsedom: 'br'
1040
- }
1041
- ]
1042
- })
1043
- }
1044
- const newRow = AlexElement.create({
1045
- type: 'inblock',
1046
- parsedom: 'tr',
1047
- children
1048
- })
1049
- if (type == 'up') {
1050
- editor.value.addElementBefore(newRow, row)
1051
- } else {
1052
- editor.value.addElementAfter(newRow, row)
1053
- }
1054
- //重置光标
1055
- editor.value.range!.anchor.moveToStart(newRow)
1056
- editor.value.range!.focus.moveToStart(newRow)
1057
- //渲染
1058
- editor.value.formatElementStack()
1059
- editor.value.domRender()
1060
- editor.value.rangeRender()
1061
- //更新工具条位置
1062
- setTimeout(() => {
1063
- layerRef.value!.setPosition()
1064
- }, 0)
1065
- }
1066
- }
1067
- //表格前后插入段落
1068
- const insertParagraphWithTable = (type: string | undefined = 'up') => {
1069
- const table = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'table' })
1070
- if (table) {
1071
- const paragraph = AlexElement.create({
1072
- type: 'block',
1073
- parsedom: AlexElement.BLOCK_NODE,
1074
- children: [
1075
- {
1076
- type: 'closed',
1077
- parsedom: 'br'
1078
- }
1079
- ]
1080
- })
1081
- if (type == 'up') {
1082
- editor.value.addElementBefore(paragraph, table)
1083
- } else {
1084
- editor.value.addElementAfter(paragraph, table)
1085
- }
1086
- editor.value.range!.anchor.moveToEnd(paragraph)
1087
- editor.value.range!.focus.moveToEnd(paragraph)
1088
- editor.value.formatElementStack()
1089
- editor.value.domRender()
1090
- editor.value.rangeRender()
1091
- }
1092
- }
1093
- //删除元素
1094
- const deleteElement = (parsedom: string) => {
1095
- const element = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom })
1096
- if (element) {
1097
- element.toEmpty()
1098
- editor.value.formatElementStack()
1099
- editor.value.domRender()
1100
- editor.value.rangeRender()
1101
- }
1102
- }
1103
- //删除表格行
1104
- const deleteTableRow = () => {
1105
- if (!editor.value.range!.anchor.isEqual(editor.value.range!.focus)) {
1106
- editor.value.range!.anchor.element = editor.value.range!.focus.element
1107
- editor.value.range!.anchor.offset = editor.value.range!.focus.offset
1108
- }
1109
- const column = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'td' })
1110
- if (column) {
1111
- //光标所在行
1112
- const row = column.parent!
1113
- //如果只有一行则删除表格
1114
- if (row.parent!.children!.length == 1) {
1115
- deleteElement('table')
1116
- return
1117
- }
1118
- //光标所在的单元格在行中的序列
1119
- const index = row.children!.findIndex(item => {
1120
- return item.isEqual(column)
1121
- })
1122
- //上一行
1123
- const previousRow = editor.value.getPreviousElement(row)
1124
- //下一行
1125
- const nextRow = editor.value.getNextElement(row)
1126
- //遍历行中的每一个单元格
1127
- row.children!.forEach((item, i) => {
1128
- //获取单元格占的行数
1129
- const itemSpanNum = getCellSpanNumber(item)
1130
- //是隐藏的单元格
1131
- if (item.hasMarks() && item.marks!['data-editify-merged']) {
1132
- const { crossRowElement } = getCellMergeElement(editor.value, item)
1133
- //如果是被跨行单元格合并的
1134
- if (crossRowElement) {
1135
- const { rowspan } = getCellSpanNumber(crossRowElement)
1136
- if (rowspan - 1 == 1) {
1137
- delete crossRowElement.marks!['rowspan']
1138
- } else {
1139
- crossRowElement.marks!['rowspan'] = rowspan - 1
1140
- }
1141
- }
1142
- }
1143
- //是跨行的单元格
1144
- else if (itemSpanNum.rowspan > 1) {
1145
- //获取下一行
1146
- let el = editor.value.getNextElement(row)
1147
- if (el && itemSpanNum.rowspan - 1 > 1) {
1148
- if (el.children![i].hasMarks()) {
1149
- el.children![i].marks!['rowspan'] = itemSpanNum.rowspan - 1
1150
- } else {
1151
- el.children![i].marks = {
1152
- rowspan: itemSpanNum.rowspan - 1
1153
- }
1154
- }
1155
- }
1156
- }
1157
- })
1158
- //删除行
1159
- row.toEmpty()
1160
- //重置光标
1161
- if (previousRow) {
1162
- editor.value.range!.anchor.moveToEnd(previousRow.children![index])
1163
- editor.value.range!.focus.moveToEnd(previousRow.children![index])
1164
- } else {
1165
- editor.value.range!.anchor.moveToEnd(nextRow!.children![index])
1166
- editor.value.range!.focus.moveToEnd(nextRow!.children![index])
1167
- }
1168
- //渲染
1169
- editor.value.formatElementStack()
1170
- editor.value.domRender()
1171
- editor.value.rangeRender()
1172
- //更新工具条位置
1173
- setTimeout(() => {
1174
- layerRef.value!.setPosition()
1175
- }, 0)
1176
- }
1177
- }
1178
- //删除表格列
1179
- const deleteTableColumn = () => {
1180
- if (!editor.value.range!.anchor.isEqual(editor.value.range!.focus)) {
1181
- editor.value.range!.anchor.element = editor.value.range!.focus.element
1182
- editor.value.range!.anchor.offset = editor.value.range!.focus.offset
1183
- }
1184
- const column = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'td' })
1185
- if (column) {
1186
- //光标所在行
1187
- const row = column.parent!
1188
- //所有的行元素
1189
- const rows = row.parent!.children!
1190
- //表格元素
1191
- const table = row.parent!.parent!
1192
- //如果光标所在行只有一个单元格则删除表格
1193
- if (row.children!.length == 1) {
1194
- deleteElement('table')
1195
- return
1196
- }
1197
- //光标所在的单元格在行中的序列
1198
- const index = row.children!.findIndex(item => {
1199
- return item.isEqual(column)
1200
- })
1201
- //前一个单元格
1202
- const previousColumn = editor.value.getPreviousElement(column)
1203
- //后一个单元格
1204
- const nextColumn = editor.value.getNextElement(column)
1205
- //遍历所有的行元素
1206
- rows.forEach(item => {
1207
- //对应序列的单元格
1208
- const cell = item.children![index]
1209
- const cellSpanNum = getCellSpanNumber(cell)
1210
- //是隐藏的单元格
1211
- if (cell.hasMarks() && cell.marks!['data-editify-merged']) {
1212
- const { crossColumnElement } = getCellMergeElement(editor.value, cell)
1213
- //如果是被跨列单元格合并的
1214
- if (crossColumnElement) {
1215
- const { colspan } = getCellSpanNumber(crossColumnElement)
1216
- if (colspan - 1 == 1) {
1217
- delete crossColumnElement.marks!['colspan']
1218
- } else {
1219
- crossColumnElement.marks!['colspan'] = colspan - 1
1220
- }
1221
- }
1222
- }
1223
- //跨列的单元格
1224
- else if (cellSpanNum.colspan > 1) {
1225
- //获取下一个单元格
1226
- let el = editor.value.getNextElement(cell)
1227
- if (el && cellSpanNum.colspan - 1 > 1) {
1228
- if (el.hasMarks()) {
1229
- el.marks!['colspan'] = cellSpanNum.colspan - 1
1230
- } else {
1231
- el.marks = {
1232
- colspan: cellSpanNum.colspan - 1
1233
- }
1234
- }
1235
- }
1236
- }
1237
- cell.toEmpty()
1238
- })
1239
- //删除col
1240
- const colgroup = table.children!.find(item => {
1241
- return item.parsedom == 'colgroup'
1242
- })!
1243
- colgroup.children![index].toEmpty()
1244
- if (previousColumn) {
1245
- editor.value.range!.anchor.moveToEnd(previousColumn)
1246
- editor.value.range!.focus.moveToEnd(previousColumn)
1247
- } else {
1248
- editor.value.range!.anchor.moveToEnd(nextColumn!)
1249
- editor.value.range!.focus.moveToEnd(nextColumn!)
1250
- }
1251
- //渲染
1252
- editor.value.formatElementStack()
1253
- editor.value.domRender()
1254
- editor.value.rangeRender()
1255
- }
1256
- }
1257
- //合并单元格
1258
- const mergeCells = (type: 'left' | 'right' | 'up' | 'down') => {
1259
- if (!canMergeCells.value(type)) {
1260
- return
1261
- }
1262
- if (!editor.value.range!.anchor.isEqual(editor.value.range!.focus)) {
1263
- editor.value.range!.anchor.element = editor.value.range!.focus.element
1264
- editor.value.range!.anchor.offset = editor.value.range!.focus.offset
1265
- }
1266
- const column = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'td' })
1267
- if (column) {
1268
- //向左合并单元格
1269
- if (type == 'left') {
1270
- //当前单元格所占行数和列数
1271
- const cellSpanNum = getCellSpanNumber(column)
1272
- //获取左侧单元格
1273
- const previousColumn = editor.value.getPreviousElement(column)
1274
- //如果左侧单元格存在
1275
- if (previousColumn) {
1276
- //左侧单元格是隐藏的单元格
1277
- if (previousColumn.hasMarks() && previousColumn.marks!['data-editify-merged']) {
1278
- //获取合并该隐藏单元格的那个单元格
1279
- const { crossColumnElement } = getCellMergeElement(editor.value, previousColumn)
1280
- //如果是被跨列合并则判断跨列单元格占据的行数与当前单元格的行数是否一致
1281
- if (crossColumnElement) {
1282
- const { rowspan, colspan } = getCellSpanNumber(crossColumnElement)
1283
- //进行合并
1284
- if (rowspan == cellSpanNum.rowspan) {
1285
- crossColumnElement.marks!['colspan'] = colspan + cellSpanNum.colspan
1286
- column.children!.forEach(item => {
1287
- crossColumnElement.children!.push(item)
1288
- item.parent = crossColumnElement
1289
- })
1290
- setTableCellMerged(column)
1291
- editor.value.range!.anchor.moveToEnd(crossColumnElement)
1292
- editor.value.range!.focus.moveToEnd(crossColumnElement)
1293
- editor.value.formatElementStack()
1294
- editor.value.domRender()
1295
- editor.value.rangeRender()
1296
- }
1297
- }
1298
- }
1299
- //左侧单元格不是隐藏的单元格
1300
- else {
1301
- //判断所占行数是否一致
1302
- const { rowspan, colspan } = getCellSpanNumber(previousColumn)
1303
- //进行合并
1304
- if (rowspan == cellSpanNum.rowspan) {
1305
- if (previousColumn.hasMarks()) {
1306
- previousColumn.marks!['colspan'] = colspan + cellSpanNum.colspan
1307
- } else {
1308
- previousColumn.marks = {
1309
- colspan: colspan + cellSpanNum.colspan
1310
- }
1311
- }
1312
- column.children!.forEach(item => {
1313
- previousColumn.children!.push(item)
1314
- item.parent = previousColumn
1315
- })
1316
- setTableCellMerged(column)
1317
- editor.value.range!.anchor.moveToEnd(previousColumn)
1318
- editor.value.range!.focus.moveToEnd(previousColumn)
1319
- editor.value.formatElementStack()
1320
- editor.value.domRender()
1321
- editor.value.rangeRender()
1322
- }
1323
- }
1324
- }
1325
- }
1326
- //向右合并单元格
1327
- else if (type == 'right') {
1328
- //当前单元格所占行数和列数
1329
- const cellSpanNum = getCellSpanNumber(column)
1330
- //获取右侧的单元格
1331
- let nextColumn = editor.value.getNextElement(column)
1332
- //如果右侧单元格存在
1333
- while (nextColumn) {
1334
- //右侧单元格是隐藏的单元格
1335
- if (nextColumn.hasMarks() && nextColumn.marks!['data-editify-merged']) {
1336
- //获取合并该隐藏单元格的那个单元格
1337
- const { crossColumnElement } = getCellMergeElement(editor.value, nextColumn)
1338
- //如果是被跨列合并的表示属于当前单元格内,继续向右查询
1339
- if (crossColumnElement) {
1340
- nextColumn = editor.value.getNextElement(nextColumn)
1341
- }
1342
- //被跨行合并的直接结束,不能向右合并
1343
- else {
1344
- break
1345
- }
1346
- }
1347
- //右侧单元格不是隐藏的
1348
- else {
1349
- //判断行数是否与当前单元格一致
1350
- const { rowspan, colspan } = getCellSpanNumber(nextColumn)
1351
- //如果一致则可以合并
1352
- if (rowspan == cellSpanNum.rowspan) {
1353
- if (column.hasMarks()) {
1354
- column.marks!['colspan'] = cellSpanNum.colspan + colspan
1355
- } else {
1356
- column.marks = {
1357
- colspan: cellSpanNum.colspan + colspan
1358
- }
1359
- }
1360
- nextColumn.children!.forEach(item => {
1361
- column.children!.push(item)
1362
- item.parent = column
1363
- })
1364
- setTableCellMerged(nextColumn)
1365
- editor.value.range!.anchor.moveToEnd(column)
1366
- editor.value.range!.focus.moveToEnd(column)
1367
- editor.value.formatElementStack()
1368
- editor.value.domRender()
1369
- editor.value.rangeRender()
1370
- }
1371
- //不管是否一致都直接结束
1372
- break
1373
- }
1374
- }
1375
- }
1376
- //向上合并单元格
1377
- else if (type == 'up') {
1378
- //当前单元格所占行数和列数
1379
- const cellSpanNum = getCellSpanNumber(column)
1380
- //获取单元格在行中的序列
1381
- const index = column.parent!.children!.findIndex(item => item.isEqual(column))
1382
- //获取上一行
1383
- const previousRow = editor.value.getPreviousElement(column.parent!)
1384
- //如果上一行存在
1385
- if (previousRow) {
1386
- //获取上一行中对应序列的单元格
1387
- const previousColumn = previousRow.children![index]
1388
- //单元格是隐藏的单元格
1389
- if (previousColumn.hasMarks() && previousColumn.marks!['data-editify-merged']) {
1390
- //获取合并该隐藏单元格的那个单元格
1391
- const { crossRowElement } = getCellMergeElement(editor.value, previousColumn)
1392
- //如果是被跨行合并则判断跨列单元格占据的列数与当前单元格的列数是否一致
1393
- if (crossRowElement) {
1394
- const { rowspan, colspan } = getCellSpanNumber(crossRowElement)
1395
- //进行合并
1396
- if (colspan == cellSpanNum.colspan) {
1397
- crossRowElement.marks!['rowspan'] = rowspan + cellSpanNum.rowspan
1398
- column.children!.forEach(item => {
1399
- crossRowElement.children!.push(item)
1400
- item.parent = crossRowElement
1401
- })
1402
- setTableCellMerged(column)
1403
- editor.value.range!.anchor.moveToEnd(crossRowElement)
1404
- editor.value.range!.focus.moveToEnd(crossRowElement)
1405
- editor.value.formatElementStack()
1406
- editor.value.domRender()
1407
- editor.value.rangeRender()
1408
- }
1409
- }
1410
- }
1411
- //单元格不是隐藏的单元格
1412
- else {
1413
- //判断所占列数是否一致
1414
- const { rowspan, colspan } = getCellSpanNumber(previousColumn)
1415
- //进行合并
1416
- if (colspan == cellSpanNum.colspan) {
1417
- if (previousColumn.hasMarks()) {
1418
- previousColumn.marks!['rowspan'] = rowspan + cellSpanNum.rowspan
1419
- } else {
1420
- previousColumn.marks = {
1421
- rowspan: rowspan + cellSpanNum.rowspan
1422
- }
1423
- }
1424
- column.children!.forEach(item => {
1425
- previousColumn.children!.push(item)
1426
- item.parent = previousColumn
1427
- })
1428
- setTableCellMerged(column)
1429
- editor.value.range!.anchor.moveToEnd(previousColumn)
1430
- editor.value.range!.focus.moveToEnd(previousColumn)
1431
- editor.value.formatElementStack()
1432
- editor.value.domRender()
1433
- editor.value.rangeRender()
1434
- }
1435
- }
1436
- }
1437
- }
1438
- //向下合并单元格
1439
- else if (type == 'down') {
1440
- //当前单元格所占行数和列数
1441
- const cellSpanNum = getCellSpanNumber(column)
1442
- //获取单元格在行中的序列
1443
- const index = column.parent!.children!.findIndex(item => item.isEqual(column))
1444
- //获取下一行
1445
- let nextRow = editor.value.getNextElement(column.parent!)
1446
- //如果下一行存在
1447
- while (nextRow) {
1448
- //获取下一行中对应序列的单元格
1449
- const nextColumn = nextRow.children![index]
1450
- //单元格是隐藏的单元格
1451
- if (nextColumn.hasMarks() && nextColumn.marks!['data-editify-merged']) {
1452
- //获取合并该隐藏单元格的那个单元格
1453
- const { crossRowElement } = getCellMergeElement(editor.value, nextColumn)
1454
- //如果是被跨行合并的表示属于当前单元格内,继续向下查询
1455
- if (crossRowElement) {
1456
- nextRow = editor.value.getNextElement(nextRow)
1457
- }
1458
- //被跨列合并的直接结束,不能向右合并
1459
- else {
1460
- break
1461
- }
1462
- }
1463
- //单元格不是隐藏的
1464
- else {
1465
- //判断列数是否与当前单元格一致
1466
- const { rowspan, colspan } = getCellSpanNumber(nextColumn)
1467
- //如果一致则可以合并
1468
- if (colspan == cellSpanNum.colspan) {
1469
- if (column.hasMarks()) {
1470
- column.marks!['rowspan'] = cellSpanNum.rowspan + rowspan
1471
- } else {
1472
- column.marks = {
1473
- rowspan: cellSpanNum.rowspan + rowspan
1474
- }
1475
- }
1476
- nextColumn.children!.forEach(item => {
1477
- column.children!.push(item)
1478
- item.parent = column
1479
- })
1480
- setTableCellMerged(nextColumn)
1481
- editor.value.range!.anchor.moveToEnd(column)
1482
- editor.value.range!.focus.moveToEnd(column)
1483
- editor.value.formatElementStack()
1484
- editor.value.domRender()
1485
- editor.value.rangeRender()
1486
- }
1487
- //不管是否一致都直接结束
1488
- break
1489
- }
1490
- }
1491
- }
1492
- }
1493
- }
1494
- //浮层显示时
1495
- const layerShow = () => {
1496
- //链接初始化展示
1497
- if (props.type == 'link') {
1498
- const link = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'a' })
1499
- if (link) {
1500
- linkConfig.value.url = link.marks!['href']
1501
- linkConfig.value.newOpen = link.marks!['target'] == '_blank'
1502
- }
1503
- }
1504
- //视频初始化显示
1505
- else if (props.type == 'video') {
1506
- const video = getMatchElementByRange(editor.value, dataRangeCaches.value, { parsedom: 'video' })
1507
- if (video) {
1508
- videoConfig.value.autoplay = !!video.marks!['autoplay']
1509
- videoConfig.value.loop = !!video.marks!['loop']
1510
- videoConfig.value.controls = !!video.marks!['controls']
1511
- videoConfig.value.muted = !!video.marks!['muted']
1512
- }
1513
- }
1514
- //代码块初始化展示设置
1515
- else if (props.type == 'codeBlock') {
1516
- const pre = getMatchElementByRange(editor.value, dataRangeCaches.value, {
1517
- parsedom: 'pre'
1518
- })
1519
- if (pre) {
1520
- languageConfig.value.displayConfig.value = pre.marks!['data-editify-hljs'] || ''
1521
- }
1522
- }
1523
- //文本工具条初始化显示
1524
- else if (props.type == 'text') {
1525
- //额外禁用判定
1526
- const extraDisabled = (name: string) => {
1527
- if (typeof props.config.extraDisabled == 'function') {
1528
- return props.config.extraDisabled(name) || false
1529
- }
1530
- return false
1531
- }
1532
- //显示已设置标题
1533
- const findHeadingItem = headingConfig.value.displayConfig.options.find((item: string | number | ButtonOptionsItemType) => {
1534
- let val: string | number | ButtonOptionsItemType = item
1535
- if (DapCommon.isObject(item)) {
1536
- val = (<ButtonOptionsItemType>item).value!
1537
- }
1538
- return dataRangeCaches.value.list.every(el => {
1539
- if (el.element.isBlock()) {
1540
- return el.element.parsedom == val
1541
- }
1542
- return el.element.getBlock().parsedom == val
1543
- })
1544
- })
1545
- headingConfig.value.displayConfig.value = findHeadingItem ? (DapCommon.isObject(findHeadingItem) ? findHeadingItem.value : findHeadingItem) : headingConfig.value.defaultValue
1546
- //标题禁用
1547
- headingConfig.value.disabled = extraDisabled('heading')
1548
-
1549
- //对齐方式禁用
1550
- alignConfig.value.disabled = extraDisabled('align')
1551
-
1552
- //有序列表按钮激活
1553
- orderListConfig.value.active = isRangeInList(editor.value, dataRangeCaches.value, true)
1554
- //有序列表按钮禁用
1555
- orderListConfig.value.disabled = extraDisabled('orderList')
1556
-
1557
- //无序列表按钮激活
1558
- unorderListConfig.value.active = isRangeInList(editor.value, dataRangeCaches.value, false)
1559
- //无序列表按钮禁用
1560
- unorderListConfig.value.disabled = extraDisabled('unorderList')
1561
-
1562
- //任务列表按钮激活
1563
- taskConfig.value.active = isRangeInTask(editor.value, dataRangeCaches.value)
1564
- //任务列表按钮禁用
1565
- taskConfig.value.disabled = extraDisabled('task')
1566
-
1567
- //粗体按钮激活
1568
- boldConfig.value.active = queryTextStyle(editor.value, dataRangeCaches.value, 'font-weight', 'bold') || queryTextStyle(editor.value, dataRangeCaches.value, 'font-weight', '700')
1569
- //粗体按钮禁用
1570
- boldConfig.value.disabled = extraDisabled('bold')
1571
-
1572
- //斜体按钮激活
1573
- italicConfig.value.active = queryTextStyle(editor.value, dataRangeCaches.value, 'font-style', 'italic')
1574
- //斜体按钮禁用
1575
- italicConfig.value.disabled = extraDisabled('italic')
1576
-
1577
- //删除线按钮激活
1578
- strikethroughConfig.value.active = queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration', 'line-through') || queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration-line', 'line-through')
1579
- //删除线按钮禁用
1580
- strikethroughConfig.value.disabled = extraDisabled('strikethrough')
1581
-
1582
- //下划线按钮激活
1583
- underlineConfig.value.active = queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration', 'underline') || queryTextStyle(editor.value, dataRangeCaches.value, 'text-decoration-line', 'underline')
1584
- //下划线按钮禁用
1585
- underlineConfig.value.disabled = extraDisabled('underline')
1586
-
1587
- //行内代码按钮激活
1588
- codeConfig.value.active = queryTextMark(editor.value, dataRangeCaches.value, 'data-editify-code')
1589
- //行内代码按钮禁用
1590
- codeConfig.value.disabled = extraDisabled('code')
1591
-
1592
- //上标按钮激活
1593
- superConfig.value.active = queryTextStyle(editor.value, dataRangeCaches.value, 'vertical-align', 'super')
1594
- //上标按钮禁用
1595
- superConfig.value.disabled = extraDisabled('super')
1596
-
1597
- //下标按钮激活
1598
- subConfig.value.active = queryTextStyle(editor.value, dataRangeCaches.value, 'vertical-align', 'sub')
1599
- //下标按钮禁用
1600
- subConfig.value.disabled = extraDisabled('sub')
1601
-
1602
- //显示已选择字号
1603
- const findFontItem = fontSizeConfig.value.displayConfig.options.find((item: string | number | ButtonOptionsItemType) => {
1604
- if (DapCommon.isObject(item)) {
1605
- return queryTextStyle(editor.value, dataRangeCaches.value, 'font-size', (<ButtonOptionsItemType>item).value)
1606
- }
1607
- return queryTextStyle(editor.value, dataRangeCaches.value, 'font-size', <string | number>item)
1608
- })
1609
- fontSizeConfig.value.displayConfig.value = findFontItem ? (DapCommon.isObject(findFontItem) ? findFontItem.value : findFontItem) : fontSizeConfig.value.defaultValue
1610
- //字号按钮禁用
1611
- fontSizeConfig.value.disabled = extraDisabled('fontSize')
1612
-
1613
- //显示已选择字体
1614
- const findFamilyItem = fontFamilyConfig.value.displayConfig.options.find((item: string | number | ButtonOptionsItemType) => {
1615
- if (DapCommon.isObject(item)) {
1616
- return queryTextStyle(editor.value, dataRangeCaches.value, 'font-family', (<ButtonOptionsItemType>item).value)
1617
- }
1618
- return queryTextStyle(editor.value, dataRangeCaches.value, 'font-family', <string | number>item)
1619
- })
1620
- fontFamilyConfig.value.displayConfig.value = findFamilyItem ? (DapCommon.isObject(findFamilyItem) ? findFamilyItem.value : findFamilyItem) : fontFamilyConfig.value.defaultValue
1621
- //字体按钮禁用
1622
- fontFamilyConfig.value.disabled = extraDisabled('fontFamily')
1623
-
1624
- //显示已设置行高
1625
- const findHeightItem = lineHeightConfig.value.displayConfig.options.find((item: string | number | ButtonOptionsItemType) => {
1626
- let val: string | number | ButtonOptionsItemType = item
1627
- if (DapCommon.isObject(item)) {
1628
- val = (<ButtonOptionsItemType>item).value!
1629
- }
1630
- return dataRangeCaches.value.list.every(el => {
1631
- if (el.element.isBlock() || el.element.isInblock()) {
1632
- return el.element.hasStyles() && el.element.styles!['line-height'] == val
1633
- }
1634
- const block = el.element.getBlock()
1635
- const inblock = el.element.getInblock()
1636
- if (inblock) {
1637
- return inblock.hasStyles() && inblock.styles!['line-height'] == val
1638
- }
1639
- return block.hasStyles() && block.styles!['line-height'] == val
1640
- })
1641
- })
1642
- lineHeightConfig.value.displayConfig.value = findHeightItem ? (DapCommon.isObject(findHeightItem) ? findHeightItem.value : findHeightItem) : lineHeightConfig.value.defaultValue
1643
- //行高按钮禁用
1644
- lineHeightConfig.value.disabled = extraDisabled('lineHeight')
1645
-
1646
- //显示已选择的前景色
1647
- const findForeColorItem = foreColorConfig.value.selectConfig.options.find((item: string | number | ButtonOptionsItemType) => {
1648
- if (DapCommon.isObject(item)) {
1649
- return queryTextStyle(editor.value, dataRangeCaches.value, 'color', (<ButtonOptionsItemType>item).value)
1650
- }
1651
- return queryTextStyle(editor.value, dataRangeCaches.value, 'color', <string | number>item)
1652
- })
1653
- foreColorConfig.value.value = findForeColorItem ? (DapCommon.isObject(findForeColorItem) ? findForeColorItem.value : findForeColorItem) : ''
1654
- //前景色按钮禁用
1655
- foreColorConfig.value.disabled = extraDisabled('foreColor')
1656
-
1657
- //显示已选择的背景色
1658
- const findBackColorItem = backColorConfig.value.selectConfig.options.find((item: string | number | ButtonOptionsItemType) => {
1659
- if (DapCommon.isObject(item)) {
1660
- return queryTextStyle(editor.value, dataRangeCaches.value, 'background-color', (<ButtonOptionsItemType>item).value)
1661
- }
1662
- return queryTextStyle(editor.value, dataRangeCaches.value, 'background-color', <string | number>item)
1663
- })
1664
- backColorConfig.value.value = findBackColorItem ? (DapCommon.isObject(findBackColorItem) ? findBackColorItem.value : findBackColorItem) : ''
1665
- //背景色按钮禁用
1666
- backColorConfig.value.disabled = extraDisabled('backColor')
1667
-
1668
- //清除格式按钮禁用
1669
- formatClearConfig.value.disabled = extraDisabled('formatClear')
1670
- }
1671
- }
1672
-
1673
- defineExpose({
1674
- layerRef
1675
- })
1676
- </script>
1677
- <style scoped src="./toolbar.less"></style>