vue-editify 0.1.3 → 0.1.4

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/src/core/rule.js CHANGED
@@ -1,239 +1,239 @@
1
- import { AlexElement } from 'alex-editor'
2
- import { getHljsHtml } from '../hljs'
3
- import { getColNumbers } from './tool'
4
- import { isList, isTask } from './function'
5
-
6
- //更新代码块内的光标位置
7
- const updateRangeInPre = (editor, element, originalTextElements, newElements) => {
8
- if (!editor.range) {
9
- return
10
- }
11
- //如果虚拟光标的起点在代码块内对虚拟光标的起点进行重新定位
12
- if (editor.range.anchor.element.getBlock().isEqual(element)) {
13
- //获取起点所在文本元素的在所有文本元素中的序列
14
- const elIndex = originalTextElements.findIndex(el => editor.range.anchor.element.isEqual(el))
15
- //起点在整个代码内容中的位置
16
- const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item) => total + item.textContent.length, 0) + editor.range.anchor.offset
17
- //获取pre下新的子孙元素中全部的文本元素
18
- const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
19
- let i = 0
20
- let index = 0
21
- //遍历
22
- while (i < newTextElements.length) {
23
- let newIndex = index + newTextElements[i].textContent.length
24
- if (offset >= index && offset <= newIndex) {
25
- editor.range.anchor.element = newTextElements[i]
26
- editor.range.anchor.offset = offset - index
27
- break
28
- }
29
- i++
30
- index = newIndex
31
- }
32
- }
33
- //如果虚拟光标的终点在代码块内需要对虚拟光标的终点进行重新定位
34
- if (editor.range.focus.element.getBlock().isEqual(element)) {
35
- //获取终点所在文本元素的在所有文本元素中的序列
36
- const elIndex = originalTextElements.findIndex(el => editor.range.focus.element.isEqual(el))
37
- //终点在整个代码内容中的位置
38
- const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item) => total + item.textContent.length, 0) + editor.range.focus.offset
39
- //获取全部的新文本元素
40
- const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
41
- let i = 0
42
- let index = 0
43
- //遍历
44
- while (i < newTextElements.length) {
45
- let newIndex = index + newTextElements[i].textContent.length
46
- if (offset >= index && offset <= newIndex) {
47
- editor.range.focus.element = newTextElements[i]
48
- editor.range.focus.offset = offset - index
49
- break
50
- }
51
- i++
52
- index = newIndex
53
- }
54
- }
55
- }
56
-
57
- //元素格式化时转换ol和li标签
58
- export const parseList = (editor, element) => {
59
- //ol标签和ul标签转为div
60
- if (element.parsedom == 'ol' || element.parsedom == 'ul') {
61
- if (element.hasChildren()) {
62
- element.children.forEach((el, index) => {
63
- const newEl = el.clone()
64
- newEl.parsedom = 'div'
65
- newEl.type = element.type
66
- if (!newEl.hasMarks()) {
67
- newEl.marks = {}
68
- }
69
- newEl.marks['data-editify-list'] = element.parsedom
70
- //插入到该元素之前
71
- editor.addElementBefore(newEl, element)
72
- })
73
- }
74
- element.toEmpty()
75
- }
76
- }
77
-
78
- //元素格式化时处理有序列表的序号值
79
- export const orderdListHandle = function (editor, element) {
80
- //有序列表的序号处理
81
- if (isList(element, true)) {
82
- //获取前一个元素
83
- const previousElement = editor.getPreviousElement(element)
84
- //如果前一个元素存在并且也是有序列表
85
- if (previousElement && isList(previousElement, true)) {
86
- const previousValue = Number(previousElement.marks['data-editify-value'])
87
- element.marks['data-editify-value'] = previousValue + 1
88
- }
89
- //前一个元素不是有序列表,则从0开始
90
- else {
91
- element.marks['data-editify-value'] = 1
92
- }
93
- }
94
- }
95
-
96
- //元素格式化时处理媒体元素和链接
97
- export const mediaHandle = function (editor, element) {
98
- //图片、视频和链接设置marks
99
- if (element.parsedom == 'img' || element.parsedom == 'video' || element.parsedom == 'a') {
100
- const marks = {
101
- 'data-editify-element': element.key
102
- }
103
- if (element.hasMarks()) {
104
- Object.assign(element.marks, marks)
105
- } else {
106
- element.marks = marks
107
- }
108
- }
109
-
110
- //视频的特殊处理,两侧无元素时在两侧加上空白文本
111
- if (element.parsedom == 'video') {
112
- const previousElement = editor.getPreviousElement(element)
113
- const newTextElement = editor.getNextElement(element)
114
- //如果不存在前一个元素
115
- if (!previousElement || previousElement.isEmpty()) {
116
- const spaceText = AlexElement.getSpaceElement()
117
- editor.addElementBefore(spaceText, element)
118
- }
119
- //如果不存在后一个元素
120
- if (!newTextElement || newTextElement.isEmpty()) {
121
- const spaceText = AlexElement.getSpaceElement()
122
- editor.addElementAfter(spaceText, element)
123
- }
124
- }
125
- }
126
-
127
- //元素格式化时处理表格
128
- export const tableHandle = function (editor, element) {
129
- if (element.parsedom == 'table') {
130
- const marks = {
131
- 'data-editify-element': element.key
132
- }
133
- if (element.hasMarks()) {
134
- Object.assign(element.marks, marks)
135
- } else {
136
- element.marks = marks
137
- }
138
- const elements = AlexElement.flatElements(element.children)
139
- const rows = elements.filter(el => {
140
- return el.parsedom == 'tr'
141
- })
142
- let colgroup = elements.find(el => {
143
- return el.parsedom == 'colgroup'
144
- })
145
- if (colgroup) {
146
- colgroup.children.forEach(col => {
147
- if (!col.hasMarks()) {
148
- col.marks = {
149
- width: 'auto'
150
- }
151
- } else if (!col.marks['width']) {
152
- col.marks['width'] = 'auto'
153
- }
154
- })
155
- } else {
156
- colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
157
- const colNumber = getColNumbers(rows[0])
158
- for (let i = colNumber - 1; i >= 0; i--) {
159
- const col = new AlexElement(
160
- 'closed',
161
- 'col',
162
- {
163
- width: 'auto'
164
- },
165
- null,
166
- null
167
- )
168
- editor.addElementTo(col, colgroup)
169
- }
170
- }
171
- element.children = []
172
- const tbody = new AlexElement('inblock', 'tbody', null, null, null)
173
- rows.reverse().forEach(row => {
174
- editor.addElementTo(row, tbody)
175
- })
176
- editor.addElementTo(tbody, element)
177
- editor.addElementTo(colgroup, element)
178
- }
179
- if (element.parsedom == 'th') {
180
- element.parsedom = 'td'
181
- }
182
- }
183
-
184
- //元素格式化时处理pre,将pre的内容根据语言进行样式处理
185
- export const preHandle = function (editor, element, highlight, languages) {
186
- //如果是代码块进行处理
187
- if (element.parsedom == 'pre') {
188
- const marks = {
189
- 'data-editify-element': element.key
190
- }
191
- if (element.hasMarks()) {
192
- Object.assign(element.marks, marks)
193
- } else {
194
- element.marks = marks
195
- }
196
- //高亮处理
197
- if (highlight && element.hasChildren()) {
198
- //获取语言类型
199
- let language = element.marks['data-editify-hljs'] || ''
200
- if (language && languages && !languages.includes(language)) {
201
- language = ''
202
- }
203
- //获取pre标签下所有的文本元素
204
- const originalTextElements = AlexElement.flatElements(element.children).filter(el => el.isText() && !el.isEmpty())
205
- //获取pre下的代码文本值
206
- const textContent = originalTextElements.reduce((val, item) => {
207
- return val + item.textContent
208
- }, '')
209
- //将文本元素的内容转为经过hljs处理的内容
210
- const html = getHljsHtml(textContent, language)
211
- if (html) {
212
- //将经过hljs处理的内容转为元素数组
213
- const newElements = editor.parseHtml(html)
214
- //处理光标位置
215
- updateRangeInPre(editor, element, originalTextElements, newElements)
216
- //将新文本元素全部加入到pre子元素数组中
217
- element.children = newElements
218
- newElements.forEach(newEl => {
219
- newEl.parent = element
220
- })
221
- }
222
- }
223
- }
224
- }
225
-
226
- //元素格式化时处理一些特殊的内部块元素,转为根级块元素
227
- export const specialInblockHandle = function (editor, element) {
228
- if (element.hasChildren()) {
229
- element.children.forEach(el => {
230
- if (isList(el, true) || isList(el, false) || isTask(el) || ['blockquote', 'pre', 'table', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'].includes(el.parsedom)) {
231
- const newEl = el.clone()
232
- newEl.type = 'block'
233
- const block = element.getBlock()
234
- editor.addElementAfter(newEl, block)
235
- el.toEmpty()
236
- }
237
- })
238
- }
239
- }
1
+ import { AlexElement } from 'alex-editor'
2
+ import { getHljsHtml } from '../hljs'
3
+ import { getColNumbers } from './tool'
4
+ import { isList, isTask } from './function'
5
+
6
+ //更新代码块内的光标位置
7
+ const updateRangeInPre = (editor, element, originalTextElements, newElements) => {
8
+ if (!editor.range) {
9
+ return
10
+ }
11
+ //如果虚拟光标的起点在代码块内对虚拟光标的起点进行重新定位
12
+ if (editor.range.anchor.element.getBlock().isEqual(element)) {
13
+ //获取起点所在文本元素的在所有文本元素中的序列
14
+ const elIndex = originalTextElements.findIndex(el => editor.range.anchor.element.isEqual(el))
15
+ //起点在整个代码内容中的位置
16
+ const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item) => total + item.textContent.length, 0) + editor.range.anchor.offset
17
+ //获取pre下新的子孙元素中全部的文本元素
18
+ const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
19
+ let i = 0
20
+ let index = 0
21
+ //遍历
22
+ while (i < newTextElements.length) {
23
+ let newIndex = index + newTextElements[i].textContent.length
24
+ if (offset >= index && offset <= newIndex) {
25
+ editor.range.anchor.element = newTextElements[i]
26
+ editor.range.anchor.offset = offset - index
27
+ break
28
+ }
29
+ i++
30
+ index = newIndex
31
+ }
32
+ }
33
+ //如果虚拟光标的终点在代码块内需要对虚拟光标的终点进行重新定位
34
+ if (editor.range.focus.element.getBlock().isEqual(element)) {
35
+ //获取终点所在文本元素的在所有文本元素中的序列
36
+ const elIndex = originalTextElements.findIndex(el => editor.range.focus.element.isEqual(el))
37
+ //终点在整个代码内容中的位置
38
+ const offset = originalTextElements.filter((el, i) => i < elIndex).reduce((total, item) => total + item.textContent.length, 0) + editor.range.focus.offset
39
+ //获取全部的新文本元素
40
+ const newTextElements = AlexElement.flatElements(newElements).filter(el => el.isText() && !el.isEmpty())
41
+ let i = 0
42
+ let index = 0
43
+ //遍历
44
+ while (i < newTextElements.length) {
45
+ let newIndex = index + newTextElements[i].textContent.length
46
+ if (offset >= index && offset <= newIndex) {
47
+ editor.range.focus.element = newTextElements[i]
48
+ editor.range.focus.offset = offset - index
49
+ break
50
+ }
51
+ i++
52
+ index = newIndex
53
+ }
54
+ }
55
+ }
56
+
57
+ //元素格式化时转换ol和li标签
58
+ export const parseList = (editor, element) => {
59
+ //ol标签和ul标签转为div
60
+ if (element.parsedom == 'ol' || element.parsedom == 'ul') {
61
+ if (element.hasChildren()) {
62
+ element.children.forEach((el, index) => {
63
+ const newEl = el.clone()
64
+ newEl.parsedom = 'div'
65
+ newEl.type = element.type
66
+ if (!newEl.hasMarks()) {
67
+ newEl.marks = {}
68
+ }
69
+ newEl.marks['data-editify-list'] = element.parsedom
70
+ //插入到该元素之前
71
+ editor.addElementBefore(newEl, element)
72
+ })
73
+ }
74
+ element.toEmpty()
75
+ }
76
+ }
77
+
78
+ //元素格式化时处理有序列表的序号值
79
+ export const orderdListHandle = function (editor, element) {
80
+ //有序列表的序号处理
81
+ if (isList(element, true)) {
82
+ //获取前一个元素
83
+ const previousElement = editor.getPreviousElement(element)
84
+ //如果前一个元素存在并且也是有序列表
85
+ if (previousElement && isList(previousElement, true)) {
86
+ const previousValue = Number(previousElement.marks['data-editify-value'])
87
+ element.marks['data-editify-value'] = previousValue + 1
88
+ }
89
+ //前一个元素不是有序列表,则从0开始
90
+ else {
91
+ element.marks['data-editify-value'] = 1
92
+ }
93
+ }
94
+ }
95
+
96
+ //元素格式化时处理媒体元素和链接
97
+ export const mediaHandle = function (editor, element) {
98
+ //图片、视频和链接设置marks
99
+ if (element.parsedom == 'img' || element.parsedom == 'video' || element.parsedom == 'a') {
100
+ const marks = {
101
+ 'data-editify-element': element.key
102
+ }
103
+ if (element.hasMarks()) {
104
+ Object.assign(element.marks, marks)
105
+ } else {
106
+ element.marks = marks
107
+ }
108
+ }
109
+
110
+ //视频的特殊处理,两侧无元素时在两侧加上空白文本
111
+ if (element.parsedom == 'video') {
112
+ const previousElement = editor.getPreviousElement(element)
113
+ const newTextElement = editor.getNextElement(element)
114
+ //如果不存在前一个元素
115
+ if (!previousElement || previousElement.isEmpty()) {
116
+ const spaceText = AlexElement.getSpaceElement()
117
+ editor.addElementBefore(spaceText, element)
118
+ }
119
+ //如果不存在后一个元素
120
+ if (!newTextElement || newTextElement.isEmpty()) {
121
+ const spaceText = AlexElement.getSpaceElement()
122
+ editor.addElementAfter(spaceText, element)
123
+ }
124
+ }
125
+ }
126
+
127
+ //元素格式化时处理表格
128
+ export const tableHandle = function (editor, element) {
129
+ if (element.parsedom == 'table') {
130
+ const marks = {
131
+ 'data-editify-element': element.key
132
+ }
133
+ if (element.hasMarks()) {
134
+ Object.assign(element.marks, marks)
135
+ } else {
136
+ element.marks = marks
137
+ }
138
+ const elements = AlexElement.flatElements(element.children)
139
+ const rows = elements.filter(el => {
140
+ return el.parsedom == 'tr'
141
+ })
142
+ let colgroup = elements.find(el => {
143
+ return el.parsedom == 'colgroup'
144
+ })
145
+ if (colgroup) {
146
+ colgroup.children.forEach(col => {
147
+ if (!col.hasMarks()) {
148
+ col.marks = {
149
+ width: 'auto'
150
+ }
151
+ } else if (!col.marks['width']) {
152
+ col.marks['width'] = 'auto'
153
+ }
154
+ })
155
+ } else {
156
+ colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
157
+ const colNumber = getColNumbers(rows[0])
158
+ for (let i = colNumber - 1; i >= 0; i--) {
159
+ const col = new AlexElement(
160
+ 'closed',
161
+ 'col',
162
+ {
163
+ width: 'auto'
164
+ },
165
+ null,
166
+ null
167
+ )
168
+ editor.addElementTo(col, colgroup)
169
+ }
170
+ }
171
+ element.children = []
172
+ const tbody = new AlexElement('inblock', 'tbody', null, null, null)
173
+ rows.reverse().forEach(row => {
174
+ editor.addElementTo(row, tbody)
175
+ })
176
+ editor.addElementTo(tbody, element)
177
+ editor.addElementTo(colgroup, element)
178
+ }
179
+ if (element.parsedom == 'th') {
180
+ element.parsedom = 'td'
181
+ }
182
+ }
183
+
184
+ //元素格式化时处理pre,将pre的内容根据语言进行样式处理
185
+ export const preHandle = function (editor, element, highlight, languages) {
186
+ //如果是代码块进行处理
187
+ if (element.parsedom == 'pre') {
188
+ const marks = {
189
+ 'data-editify-element': element.key
190
+ }
191
+ if (element.hasMarks()) {
192
+ Object.assign(element.marks, marks)
193
+ } else {
194
+ element.marks = marks
195
+ }
196
+ //高亮处理
197
+ if (highlight && element.hasChildren()) {
198
+ //获取语言类型
199
+ let language = element.marks['data-editify-hljs'] || ''
200
+ if (language && languages && !languages.includes(language)) {
201
+ language = ''
202
+ }
203
+ //获取pre标签下所有的文本元素
204
+ const originalTextElements = AlexElement.flatElements(element.children).filter(el => el.isText() && !el.isEmpty())
205
+ //获取pre下的代码文本值
206
+ const textContent = originalTextElements.reduce((val, item) => {
207
+ return val + item.textContent
208
+ }, '')
209
+ //将文本元素的内容转为经过hljs处理的内容
210
+ const html = getHljsHtml(textContent, language)
211
+ if (html) {
212
+ //将经过hljs处理的内容转为元素数组
213
+ const newElements = editor.parseHtml(html)
214
+ //处理光标位置
215
+ updateRangeInPre(editor, element, originalTextElements, newElements)
216
+ //将新文本元素全部加入到pre子元素数组中
217
+ element.children = newElements
218
+ newElements.forEach(newEl => {
219
+ newEl.parent = element
220
+ })
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ //元素格式化时处理一些特殊的内部块元素,转为根级块元素
227
+ export const specialInblockHandle = function (editor, element) {
228
+ if (element.hasChildren()) {
229
+ element.children.forEach(el => {
230
+ if (isList(el, true) || isList(el, false) || isTask(el) || ['blockquote', 'pre', 'table', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'].includes(el.parsedom)) {
231
+ const newEl = el.clone()
232
+ newEl.type = 'block'
233
+ const block = element.getBlock()
234
+ editor.addElementAfter(newEl, block)
235
+ el.toEmpty()
236
+ }
237
+ })
238
+ }
239
+ }