suneditor 3.1.3 → 3.2.0
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/dist/suneditor-contents.min.css +1 -1
- package/dist/suneditor.min.css +28 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +2 -1
- package/src/assets/design/color.css +12 -0
- package/src/assets/design/size.css +9 -2
- package/src/assets/icons/defaultIcons.js +96 -47
- package/src/assets/suneditor-contents.css +3 -2
- package/src/assets/suneditor.css +480 -31
- package/src/core/config/contextProvider.js +2 -1
- package/src/core/config/eventManager.js +41 -2
- package/src/core/config/optionProvider.js +23 -2
- package/src/core/editor.js +32 -14
- package/src/core/event/actions/index.js +76 -9
- package/src/core/event/effects/common.registry.js +2 -1
- package/src/core/event/effects/keydown.registry.js +169 -33
- package/src/core/event/effects/ruleHelpers.js +20 -6
- package/src/core/event/eventOrchestrator.js +136 -23
- package/src/core/event/handlers/handler_toolbar.js +4 -2
- package/src/core/event/handlers/handler_ww_dragDrop.js +10 -0
- package/src/core/event/handlers/handler_ww_input.js +9 -2
- package/src/core/event/handlers/handler_ww_key.js +86 -17
- package/src/core/event/handlers/handler_ww_mouse.js +45 -8
- package/src/core/event/ports.js +23 -5
- package/src/core/event/reducers/keydown.reducer.js +15 -2
- package/src/core/event/rules/keydown.rule.arrow.js +12 -2
- package/src/core/event/rules/keydown.rule.backspace.js +110 -15
- package/src/core/event/rules/keydown.rule.delete.js +62 -7
- package/src/core/event/rules/keydown.rule.enter.js +62 -31
- package/src/core/event/support/defaultLineManager.js +9 -2
- package/src/core/event/support/selectionState.js +13 -3
- package/src/core/kernel/coreKernel.js +1 -0
- package/src/core/logic/dom/char.js +13 -3
- package/src/core/logic/dom/format.js +171 -39
- package/src/core/logic/dom/html.js +357 -87
- package/src/core/logic/dom/inline.js +229 -34
- package/src/core/logic/dom/listFormat.js +111 -20
- package/src/core/logic/dom/nodeTransform.js +36 -11
- package/src/core/logic/dom/offset.js +116 -31
- package/src/core/logic/dom/selection.js +147 -29
- package/src/core/logic/panel/blockHandle.js +785 -0
- package/src/core/logic/panel/blockResolver.js +278 -0
- package/src/core/logic/panel/finder.js +16 -6
- package/src/core/logic/panel/menu.js +119 -18
- package/src/core/logic/panel/toolbar.js +75 -19
- package/src/core/logic/panel/viewer.js +76 -20
- package/src/core/logic/shell/_commandExecutor.js +44 -9
- package/src/core/logic/shell/commandDispatcher.js +46 -4
- package/src/core/logic/shell/component.js +102 -25
- package/src/core/logic/shell/focusManager.js +13 -3
- package/src/core/logic/shell/history.js +21 -6
- package/src/core/logic/shell/pluginManager.js +21 -13
- package/src/core/logic/shell/shortcuts.js +9 -1
- package/src/core/logic/shell/ui.js +139 -37
- package/src/core/schema/frameContext.js +34 -3
- package/src/core/schema/options.js +61 -19
- package/src/core/section/constructor.js +537 -103
- package/src/core/section/documentType.js +35 -6
- package/src/helper/converter.js +24 -7
- package/src/helper/dom/domCheck.js +25 -5
- package/src/helper/dom/domQuery.js +2 -1
- package/src/helper/dom/domUtils.js +17 -4
- package/src/helper/env.js +11 -2
- package/src/helper/keyCodeMap.js +6 -2
- package/src/helper/markdown.js +24 -5
- package/src/helper/msOffice.js +9 -2
- package/src/interfaces/plugins.js +1 -1
- package/src/langs/ckb.js +0 -1
- package/src/langs/cs.js +0 -1
- package/src/langs/da.js +0 -1
- package/src/langs/de.js +0 -1
- package/src/langs/en.js +0 -1
- package/src/langs/es.js +0 -1
- package/src/langs/fa.js +0 -1
- package/src/langs/fr.js +0 -1
- package/src/langs/he.js +0 -1
- package/src/langs/hu.js +0 -1
- package/src/langs/index.js +27 -1
- package/src/langs/it.js +0 -1
- package/src/langs/ja.js +0 -1
- package/src/langs/km.js +0 -1
- package/src/langs/ko.js +0 -1
- package/src/langs/lv.js +0 -1
- package/src/langs/nl.js +0 -1
- package/src/langs/pl.js +0 -1
- package/src/langs/pt_br.js +0 -1
- package/src/langs/ro.js +0 -1
- package/src/langs/ru.js +0 -1
- package/src/langs/se.js +0 -1
- package/src/langs/tr.js +0 -1
- package/src/langs/uk.js +0 -1
- package/src/langs/ur.js +0 -1
- package/src/langs/zh_cn.js +0 -1
- package/src/modules/contract/Browser.js +68 -23
- package/src/modules/contract/ColorPicker.js +12 -4
- package/src/modules/contract/Controller.js +37 -7
- package/src/modules/contract/Figure.js +159 -36
- package/src/modules/contract/HueSlider.js +27 -4
- package/src/modules/contract/Modal.js +62 -11
- package/src/modules/manager/FileManager.js +50 -8
- package/src/modules/ui/CommandMenu.js +597 -0
- package/src/modules/ui/ModalAnchorEditor.js +41 -9
- package/src/modules/ui/SelectMenu.js +481 -36
- package/src/modules/ui/index.js +1 -0
- package/src/plugins/browser/audioGallery.js +8 -1
- package/src/plugins/browser/fileBrowser.js +15 -2
- package/src/plugins/browser/fileGallery.js +8 -1
- package/src/plugins/browser/imageGallery.js +24 -3
- package/src/plugins/browser/videoGallery.js +19 -4
- package/src/plugins/command/blockquote.js +6 -1
- package/src/plugins/command/codeBlock.js +43 -5
- package/src/plugins/command/exportPDF.js +20 -4
- package/src/plugins/command/fileUpload.js +46 -11
- package/src/plugins/command/list_bulleted.js +6 -1
- package/src/plugins/command/list_numbered.js +6 -1
- package/src/plugins/dropdown/align.js +21 -33
- package/src/plugins/dropdown/backgroundColor.js +10 -2
- package/src/plugins/dropdown/blockStyle.js +17 -22
- package/src/plugins/dropdown/font.js +34 -34
- package/src/plugins/dropdown/hr.js +15 -43
- package/src/plugins/dropdown/layout.js +10 -27
- package/src/plugins/dropdown/lineHeight.js +10 -33
- package/src/plugins/dropdown/list.js +19 -25
- package/src/plugins/dropdown/paragraphStyle.js +16 -24
- package/src/plugins/dropdown/table/index.js +72 -17
- package/src/plugins/dropdown/table/render/table.html.js +3 -1
- package/src/plugins/dropdown/table/services/table.cell.js +33 -7
- package/src/plugins/dropdown/table/services/table.clipboard.js +5 -1
- package/src/plugins/dropdown/table/services/table.grid.js +40 -9
- package/src/plugins/dropdown/table/services/table.resize.js +55 -11
- package/src/plugins/dropdown/table/services/table.selection.js +27 -7
- package/src/plugins/dropdown/table/services/table.style.js +120 -20
- package/src/plugins/dropdown/template.js +13 -29
- package/src/plugins/dropdown/textStyle.js +22 -35
- package/src/plugins/field/autocomplete.js +8 -4
- package/src/plugins/field/slashCommand.js +297 -0
- package/src/plugins/index.js +3 -0
- package/src/plugins/input/fontSize.js +37 -8
- package/src/plugins/input/pageNavigator.js +7 -1
- package/src/plugins/modal/audio.js +71 -17
- package/src/plugins/modal/drawing.js +41 -11
- package/src/plugins/modal/embed.js +132 -22
- package/src/plugins/modal/image/index.js +115 -28
- package/src/plugins/modal/image/services/image.size.js +9 -2
- package/src/plugins/modal/image/services/image.upload.js +38 -4
- package/src/plugins/modal/link.js +9 -2
- package/src/plugins/modal/math.js +10 -2
- package/src/plugins/modal/video/index.js +112 -26
- package/src/plugins/modal/video/render/video.html.js +4 -1
- package/src/plugins/modal/video/services/video.size.js +15 -4
- package/src/plugins/modal/video/services/video.upload.js +10 -2
- package/src/plugins/popup/anchor.js +14 -2
- package/src/suneditor.js +8 -2
- package/src/themes/cobalt.css +12 -0
- package/src/themes/cream.css +12 -0
- package/src/themes/dark.css +12 -0
- package/src/themes/midnight.css +12 -0
- package/src/typedef.js +32 -21
- package/types/assets/icons/defaultIcons.d.ts +1 -0
- package/types/core/config/contextProvider.d.ts +7 -1
- package/types/core/config/eventManager.d.ts +37 -4
- package/types/core/config/optionProvider.d.ts +5 -1
- package/types/core/event/actions/index.d.ts +44 -6
- package/types/core/event/effects/keydown.registry.d.ts +37 -7
- package/types/core/event/effects/ruleHelpers.d.ts +6 -1
- package/types/core/event/eventOrchestrator.d.ts +6 -1
- package/types/core/event/handlers/handler_ww_clipboard.d.ts +15 -3
- package/types/core/event/handlers/handler_ww_dragDrop.d.ts +14 -2
- package/types/core/event/handlers/handler_ww_input.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_key.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_mouse.d.ts +25 -5
- package/types/core/event/ports.d.ts +7 -2
- package/types/core/event/rules/keydown.rule.backspace.d.ts +6 -1
- package/types/core/kernel/store.d.ts +4 -1
- package/types/core/logic/dom/format.d.ts +32 -14
- package/types/core/logic/dom/html.d.ts +11 -3
- package/types/core/logic/dom/nodeTransform.d.ts +6 -6
- package/types/core/logic/panel/blockHandle.d.ts +64 -0
- package/types/core/logic/panel/blockResolver.d.ts +50 -0
- package/types/core/logic/panel/menu.d.ts +72 -3
- package/types/core/logic/shell/commandDispatcher.d.ts +8 -0
- package/types/core/logic/shell/component.d.ts +5 -3
- package/types/core/logic/shell/shortcuts.d.ts +10 -1
- package/types/core/logic/shell/ui.d.ts +7 -1
- package/types/core/schema/context.d.ts +7 -1
- package/types/core/schema/frameContext.d.ts +36 -4
- package/types/core/schema/options.d.ts +110 -37
- package/types/core/section/constructor.d.ts +38 -1
- package/types/events.d.ts +208 -32
- package/types/helper/converter.d.ts +4 -2
- package/types/helper/dom/domCheck.d.ts +12 -2
- package/types/helper/dom/domQuery.d.ts +35 -7
- package/types/helper/dom/domUtils.d.ts +4 -1
- package/types/interfaces/plugins.d.ts +2 -2
- package/types/langs/_Lang.d.ts +0 -1
- package/types/modules/contract/Browser.d.ts +7 -7
- package/types/modules/contract/ColorPicker.d.ts +2 -2
- package/types/modules/contract/Controller.d.ts +7 -0
- package/types/modules/contract/Figure.d.ts +31 -4
- package/types/modules/ui/CommandMenu.d.ts +262 -0
- package/types/modules/ui/ModalAnchorEditor.d.ts +6 -1
- package/types/modules/ui/SelectMenu.d.ts +56 -3
- package/types/modules/ui/index.d.ts +1 -0
- package/types/plugins/browser/audioGallery.d.ts +17 -1
- package/types/plugins/browser/fileBrowser.d.ts +17 -1
- package/types/plugins/browser/fileGallery.d.ts +17 -1
- package/types/plugins/browser/imageGallery.d.ts +17 -1
- package/types/plugins/browser/videoGallery.d.ts +17 -1
- package/types/plugins/dropdown/align.d.ts +1 -1
- package/types/plugins/dropdown/blockStyle.d.ts +3 -1
- package/types/plugins/dropdown/table/index.d.ts +4 -1
- package/types/plugins/dropdown/table/services/table.clipboard.d.ts +5 -1
- package/types/plugins/dropdown/table/services/table.grid.d.ts +10 -2
- package/types/plugins/field/autocomplete.d.ts +0 -1
- package/types/plugins/field/slashCommand.d.ts +165 -0
- package/types/plugins/index.d.ts +3 -0
- package/types/plugins/modal/embed.d.ts +34 -0
- package/types/plugins/modal/link.d.ts +4 -1
- package/types/typedef.d.ts +48 -23
|
@@ -33,7 +33,13 @@ class Char {
|
|
|
33
33
|
check(html) {
|
|
34
34
|
const maxCharCount = this.#frameOptions.get('charCounter_max');
|
|
35
35
|
if (maxCharCount) {
|
|
36
|
-
const length = this.getLength(
|
|
36
|
+
const length = this.getLength(
|
|
37
|
+
typeof html === 'string'
|
|
38
|
+
? html
|
|
39
|
+
: this.#frameOptions.get('charCounter_type') === 'byte-html' && html.nodeType === 1
|
|
40
|
+
? /** @type {HTMLElement} */ (html).outerHTML
|
|
41
|
+
: html.textContent,
|
|
42
|
+
);
|
|
37
43
|
if (length > 0 && length + this.getLength() > maxCharCount) {
|
|
38
44
|
CounterBlink(this.#frameContext.get('charWrapper'));
|
|
39
45
|
return false;
|
|
@@ -53,7 +59,10 @@ class Char {
|
|
|
53
59
|
*/
|
|
54
60
|
getLength(content) {
|
|
55
61
|
if (typeof content !== 'string') {
|
|
56
|
-
content =
|
|
62
|
+
content =
|
|
63
|
+
this.#frameOptions.get('charCounter_type') === 'byte-html'
|
|
64
|
+
? this.#frameContext.get('wysiwyg').innerHTML
|
|
65
|
+
: this.#frameContext.get('wysiwyg').textContent;
|
|
57
66
|
}
|
|
58
67
|
return /byte/.test(this.#frameOptions.get('charCounter_type')) ? this.getByteLength(content) : content.length;
|
|
59
68
|
}
|
|
@@ -160,7 +169,8 @@ class Char {
|
|
|
160
169
|
const text = this.#$.selection.getNode().textContent;
|
|
161
170
|
const slicePosition = range.endOffset - 1; // (count - maxCharCount);
|
|
162
171
|
|
|
163
|
-
this.#$.selection.getNode().textContent =
|
|
172
|
+
this.#$.selection.getNode().textContent =
|
|
173
|
+
text.slice(0, slicePosition < 0 ? 0 : slicePosition) + text.slice(range.endOffset, text.length);
|
|
164
174
|
this.#$.selection.setRange(range.endContainer, endOff, range.endContainer, endOff);
|
|
165
175
|
}
|
|
166
176
|
} else if (count + nextCharCount > maxCharCount) {
|
|
@@ -67,7 +67,11 @@ class Format {
|
|
|
67
67
|
for (let i = 0, len = lines.length, node, newFormat; i < len; i++) {
|
|
68
68
|
node = lines[i];
|
|
69
69
|
|
|
70
|
-
if (
|
|
70
|
+
if (
|
|
71
|
+
(node.nodeName !== value ||
|
|
72
|
+
(node.className.match(/(\s|^)__se__format__[^\s]+/) || [''])[0].trim() !== className) &&
|
|
73
|
+
!this.#$.component.is(node)
|
|
74
|
+
) {
|
|
71
75
|
newFormat = /** @type {HTMLElement} */ (element.cloneNode(false));
|
|
72
76
|
dom.utils.copyFormatAttributes(newFormat, node);
|
|
73
77
|
newFormat.innerHTML = node.innerHTML;
|
|
@@ -80,7 +84,12 @@ class Format {
|
|
|
80
84
|
newFormat = null;
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
this.#$.selection.setRange(
|
|
87
|
+
this.#$.selection.setRange(
|
|
88
|
+
dom.query.getNodeFromPath(info.firstPath, first),
|
|
89
|
+
info.startOffset,
|
|
90
|
+
dom.query.getNodeFromPath(info.lastPath, last),
|
|
91
|
+
info.endOffset,
|
|
92
|
+
);
|
|
84
93
|
this.#$.history.push(false);
|
|
85
94
|
|
|
86
95
|
// document type
|
|
@@ -92,7 +101,7 @@ class Format {
|
|
|
92
101
|
/**
|
|
93
102
|
* @description If a parent node that contains an argument node finds a format node (`format.isLine`), it returns that node.
|
|
94
103
|
* @param {Node} node Reference node.
|
|
95
|
-
* @param {?(current:
|
|
104
|
+
* @param {?(current: *) => boolean} [validation] Additional validation function.
|
|
96
105
|
* @returns {HTMLElement|null}
|
|
97
106
|
* @example
|
|
98
107
|
* const line = editor.$.format.getLine(editor.$.selection.getNode());
|
|
@@ -198,7 +207,7 @@ class Format {
|
|
|
198
207
|
/**
|
|
199
208
|
* @description If a parent node that contains an argument node finds a `brLine` (`format.isBrLine`), it returns that node.
|
|
200
209
|
* @param {Node} element Reference node.
|
|
201
|
-
* @param {?(current:
|
|
210
|
+
* @param {?(current: *) => boolean} [validation] Additional validation function.
|
|
202
211
|
* @returns {HTMLBRElement|null}
|
|
203
212
|
* @example
|
|
204
213
|
* const brLine = editor.$.format.getBrLine(editor.$.selection.getNode());
|
|
@@ -219,22 +228,39 @@ class Format {
|
|
|
219
228
|
}
|
|
220
229
|
|
|
221
230
|
/**
|
|
222
|
-
* @description
|
|
223
|
-
* -
|
|
224
|
-
* -
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
231
|
+
* @description Insert a new line as the next sibling of `element`.
|
|
232
|
+
* - Selection-aware — tag/attributes default to the **currently selected line**, not
|
|
233
|
+
* - `element`'s tag. Use {@link addLineAfter} when the decision must depend only on
|
|
234
|
+
* - `element` (e.g., Enter exiting a heading).
|
|
235
|
+
*
|
|
236
|
+
* - Tag resolution: brLine context → bare `<br>`; else `lineNode` override → current
|
|
237
|
+
* - line clone → `defaultLine`. Attribute copy excludes only `id` (vs `addLineAfter`
|
|
238
|
+
* - which respects `lineAttrReset`). Inside a table cell, inserts within the cell.
|
|
239
|
+
*
|
|
240
|
+
* @param {Node} element Reference element — new line is inserted right after it
|
|
241
|
+
* @param {?(string|Node)} [lineNode] Override: string tag name, or Node whose tag
|
|
242
|
+
* and attributes (except `id`) are copied
|
|
243
|
+
* @returns {HTMLElement} The new line, or a `<br>` in brLine context
|
|
228
244
|
*/
|
|
229
245
|
addLine(element, lineNode) {
|
|
230
246
|
if (!element || !element.parentNode) return null;
|
|
231
247
|
|
|
232
248
|
const currentFormatEl = this.getLine(this.#$.selection.getNode(), null);
|
|
233
249
|
let oFormat = null;
|
|
234
|
-
if (
|
|
250
|
+
if (
|
|
251
|
+
!this.isBrLine(element) &&
|
|
252
|
+
this.isBrLine(currentFormatEl || element.parentNode) &&
|
|
253
|
+
!this.#$.component.is(element)
|
|
254
|
+
) {
|
|
235
255
|
oFormat = dom.utils.createElement('BR');
|
|
236
256
|
} else {
|
|
237
|
-
const oFormatName = lineNode
|
|
257
|
+
const oFormatName = lineNode
|
|
258
|
+
? typeof lineNode === 'string'
|
|
259
|
+
? lineNode
|
|
260
|
+
: lineNode.nodeName
|
|
261
|
+
: this.isNormalLine(currentFormatEl)
|
|
262
|
+
? currentFormatEl.nodeName
|
|
263
|
+
: this.#options.get('defaultLine');
|
|
238
264
|
oFormat = dom.utils.createElement(oFormatName, null, '<br>');
|
|
239
265
|
if ((lineNode && typeof lineNode !== 'string') || (!lineNode && this.isLine(currentFormatEl))) {
|
|
240
266
|
dom.utils.copyTagAttributes(oFormat, /** @type {Node} */ (lineNode || currentFormatEl), ['id']);
|
|
@@ -247,10 +273,42 @@ class Format {
|
|
|
247
273
|
return oFormat;
|
|
248
274
|
}
|
|
249
275
|
|
|
276
|
+
/**
|
|
277
|
+
* @description Insert a new line after the given block element.
|
|
278
|
+
* Selection-independent — determines tag/attributes from the element itself.
|
|
279
|
+
* - Heading (H1-H6), HR → new default line
|
|
280
|
+
* - LI → new LI with copied attributes
|
|
281
|
+
* - PRE / brLine → new default line (exit brLine)
|
|
282
|
+
* - Normal line → same tag with copied attributes
|
|
283
|
+
* @param {HTMLElement} element The block element to insert after
|
|
284
|
+
* @returns {HTMLElement|null} The newly created element
|
|
285
|
+
*/
|
|
286
|
+
addLineAfter(element) {
|
|
287
|
+
if (!element || !element.parentNode) return null;
|
|
288
|
+
|
|
289
|
+
const tag = element.nodeName;
|
|
290
|
+
const lineAttrReset = this.#options.get('lineAttrReset');
|
|
291
|
+
let newEl;
|
|
292
|
+
|
|
293
|
+
if (/^H[1-6]$|^HR$/i.test(tag)) {
|
|
294
|
+
newEl = dom.utils.createElement(this.#options.get('defaultLine'), null, '<br>');
|
|
295
|
+
} else if (this.isBrLine(element)) {
|
|
296
|
+
newEl = dom.utils.createElement(this.#options.get('defaultLine'), null, '<br>');
|
|
297
|
+
} else {
|
|
298
|
+
newEl = dom.utils.createElement(tag, null, '<br>');
|
|
299
|
+
dom.utils.copyTagAttributes(newEl, element, lineAttrReset);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (dom.check.isTableCell(element)) element.insertBefore(newEl, element.nextElementSibling);
|
|
303
|
+
else element.parentNode.insertBefore(newEl, /** @type {HTMLElement} */ (element).nextElementSibling);
|
|
304
|
+
|
|
305
|
+
return newEl;
|
|
306
|
+
}
|
|
307
|
+
|
|
250
308
|
/**
|
|
251
309
|
* @description If a parent node that contains an argument node finds a format node (`format.isBlock`), it returns that node.
|
|
252
310
|
* @param {Node} element Reference node.
|
|
253
|
-
* @param {?(current:
|
|
311
|
+
* @param {?(current: *) => boolean} [validation] Additional validation function.
|
|
254
312
|
* @returns {HTMLElement|null}
|
|
255
313
|
* @example
|
|
256
314
|
* const block = editor.$.format.getBlock(editor.$.selection.getNode());
|
|
@@ -262,7 +320,8 @@ class Format {
|
|
|
262
320
|
|
|
263
321
|
while (element) {
|
|
264
322
|
if (dom.check.isWysiwygFrame(element)) return null;
|
|
265
|
-
if (this.isBlock(element) && !/^(THEAD|TBODY|TR)$/i.test(element.nodeName) && validation(element))
|
|
323
|
+
if (this.isBlock(element) && !/^(THEAD|TBODY|TR)$/i.test(element.nodeName) && validation(element))
|
|
324
|
+
return element;
|
|
266
325
|
element = element.parentNode;
|
|
267
326
|
}
|
|
268
327
|
|
|
@@ -287,7 +346,11 @@ class Format {
|
|
|
287
346
|
if (!dom.check.isListCell(line)) continue;
|
|
288
347
|
|
|
289
348
|
nested = line.lastElementChild;
|
|
290
|
-
if (
|
|
349
|
+
if (
|
|
350
|
+
nested &&
|
|
351
|
+
dom.check.isListCell(line.nextElementSibling) &&
|
|
352
|
+
rangeLines.includes(line.nextElementSibling)
|
|
353
|
+
) {
|
|
291
354
|
lEl = nested.lastElementChild;
|
|
292
355
|
if (rangeLines.includes(lEl)) {
|
|
293
356
|
let list = null;
|
|
@@ -342,7 +405,11 @@ class Format {
|
|
|
342
405
|
return cc ? cc.ec : before;
|
|
343
406
|
};
|
|
344
407
|
|
|
345
|
-
for (
|
|
408
|
+
for (
|
|
409
|
+
let i = 0, len = rangeLines.length, line, originParent, depth, before, nextLine, nextList, nested;
|
|
410
|
+
i < len;
|
|
411
|
+
i++
|
|
412
|
+
) {
|
|
346
413
|
line = rangeLines[i];
|
|
347
414
|
originParent = line.parentNode;
|
|
348
415
|
if (!originParent || block.contains(originParent)) continue;
|
|
@@ -378,7 +445,12 @@ class Format {
|
|
|
378
445
|
list = list.parentNode;
|
|
379
446
|
}
|
|
380
447
|
|
|
381
|
-
const edge = this.removeBlock(originParent, {
|
|
448
|
+
const edge = this.removeBlock(originParent, {
|
|
449
|
+
selectedFormats: lineArr,
|
|
450
|
+
newBlockElement: null,
|
|
451
|
+
shouldDelete: true,
|
|
452
|
+
skipHistory: true,
|
|
453
|
+
});
|
|
382
454
|
|
|
383
455
|
if (parentDepth >= depth) {
|
|
384
456
|
parentDepth = depth;
|
|
@@ -425,9 +497,20 @@ class Format {
|
|
|
425
497
|
this.#$.nodeTransform.mergeNestedTags(block, (current) => dom.check.isList(current));
|
|
426
498
|
|
|
427
499
|
// Nested list
|
|
428
|
-
if (
|
|
429
|
-
|
|
430
|
-
|
|
500
|
+
if (
|
|
501
|
+
beforeTag &&
|
|
502
|
+
dom.query.getNodeDepth(beforeTag) > 0 &&
|
|
503
|
+
(dom.check.isList(beforeTag.parentNode) || dom.check.isList(beforeTag.parentNode.parentNode))
|
|
504
|
+
) {
|
|
505
|
+
const depthFormat = dom.query.getParentElement(
|
|
506
|
+
beforeTag,
|
|
507
|
+
(current) => this.isBlock(current) && !dom.check.isList(current),
|
|
508
|
+
);
|
|
509
|
+
const splitRange = this.#$.nodeTransform.split(
|
|
510
|
+
beforeTag,
|
|
511
|
+
null,
|
|
512
|
+
!depthFormat ? 0 : dom.query.getNodeDepth(depthFormat) + 1,
|
|
513
|
+
);
|
|
431
514
|
splitRange.parentNode.insertBefore(block, splitRange);
|
|
432
515
|
} else {
|
|
433
516
|
// basic
|
|
@@ -582,7 +665,11 @@ class Format {
|
|
|
582
665
|
}
|
|
583
666
|
|
|
584
667
|
if (!newList && dom.check.isListCell(insNode)) {
|
|
585
|
-
if (
|
|
668
|
+
if (
|
|
669
|
+
next &&
|
|
670
|
+
dom.query.getNodeDepth(insNode) !== dom.query.getNodeDepth(next) &&
|
|
671
|
+
(dom.check.isListCell(parent) || dom.utils.arrayFind(insNode.children, dom.check.isList))
|
|
672
|
+
) {
|
|
586
673
|
const insNext = insNode.nextElementSibling;
|
|
587
674
|
const detachRange = this.#$.listFormat.removeNested(insNode, false);
|
|
588
675
|
if (blockElement !== detachRange || insNext !== insNode.nextElementSibling) {
|
|
@@ -594,7 +681,8 @@ class Format {
|
|
|
594
681
|
insNode = dom.utils.createElement(
|
|
595
682
|
shouldDelete
|
|
596
683
|
? inner.nodeName
|
|
597
|
-
: dom.check.isList(blockElement.parentNode) ||
|
|
684
|
+
: dom.check.isList(blockElement.parentNode) ||
|
|
685
|
+
dom.check.isListCell(blockElement.parentNode)
|
|
598
686
|
? 'LI'
|
|
599
687
|
: dom.check.isTableCell(blockElement.parentNode)
|
|
600
688
|
? 'DIV'
|
|
@@ -659,7 +747,8 @@ class Format {
|
|
|
659
747
|
|
|
660
748
|
if (newBlockElement) firstNode = newBlockElement.previousSibling;
|
|
661
749
|
else firstNode ||= blockElement.previousSibling;
|
|
662
|
-
rangeRight =
|
|
750
|
+
rangeRight =
|
|
751
|
+
blockElement.nextSibling !== rangeEl ? blockElement.nextSibling : rangeEl ? rangeEl.nextSibling : null;
|
|
663
752
|
|
|
664
753
|
if (/** @type {HTMLElement} */ (blockElement).children.length === 0 || blockElement.textContent.length === 0) {
|
|
665
754
|
dom.utils.removeItem(blockElement);
|
|
@@ -722,7 +811,11 @@ class Format {
|
|
|
722
811
|
const eo = range.endOffset;
|
|
723
812
|
|
|
724
813
|
const lines = this.getLines(null);
|
|
725
|
-
const cells = SetLineMargin(
|
|
814
|
+
const cells = SetLineMargin(
|
|
815
|
+
lines,
|
|
816
|
+
this.#store.get('indentSize'),
|
|
817
|
+
this.#options.get('_rtl') ? 'marginRight' : 'marginLeft',
|
|
818
|
+
);
|
|
726
819
|
|
|
727
820
|
// list cells
|
|
728
821
|
if (cells.length > 0) {
|
|
@@ -746,7 +839,11 @@ class Format {
|
|
|
746
839
|
const eo = range.endOffset;
|
|
747
840
|
|
|
748
841
|
const lines = this.getLines(null);
|
|
749
|
-
const cells = SetLineMargin(
|
|
842
|
+
const cells = SetLineMargin(
|
|
843
|
+
lines,
|
|
844
|
+
this.#store.get('indentSize') * -1,
|
|
845
|
+
this.#options.get('_rtl') ? 'marginRight' : 'marginLeft',
|
|
846
|
+
);
|
|
750
847
|
|
|
751
848
|
// list cells
|
|
752
849
|
if (cells.length > 0) {
|
|
@@ -795,7 +892,9 @@ class Format {
|
|
|
795
892
|
* editor.$.format.isTextStyleNode('P'); // false
|
|
796
893
|
*/
|
|
797
894
|
isTextStyleNode(element) {
|
|
798
|
-
return typeof element === 'string'
|
|
895
|
+
return typeof element === 'string'
|
|
896
|
+
? this.#textStyleTagsCheck.test(element)
|
|
897
|
+
: element?.nodeType === 1 && this.#textStyleTagsCheck.test(element.nodeName);
|
|
799
898
|
}
|
|
800
899
|
|
|
801
900
|
/**
|
|
@@ -811,7 +910,10 @@ class Format {
|
|
|
811
910
|
isLine(element) {
|
|
812
911
|
return typeof element === 'string'
|
|
813
912
|
? this.#formatLineCheck.test(element)
|
|
814
|
-
: element?.nodeType === 1 &&
|
|
913
|
+
: element?.nodeType === 1 &&
|
|
914
|
+
(this.#formatLineCheck.test(element.nodeName) ||
|
|
915
|
+
dom.utils.hasClass(element, '__se__format__line_.+|__se__format__br_line_.+')) &&
|
|
916
|
+
!this.#nonFormat(element);
|
|
815
917
|
}
|
|
816
918
|
|
|
817
919
|
/**
|
|
@@ -839,7 +941,10 @@ class Format {
|
|
|
839
941
|
(this.#brLineBreak && this.isLine(element)) ||
|
|
840
942
|
(typeof element === 'string'
|
|
841
943
|
? this.#formatBrLineCheck.test(element)
|
|
842
|
-
: element?.nodeType === 1 &&
|
|
944
|
+
: element?.nodeType === 1 &&
|
|
945
|
+
(this.#formatBrLineCheck.test(element.nodeName) ||
|
|
946
|
+
dom.utils.hasClass(element, '__se__format__br_line_.+')) &&
|
|
947
|
+
!this.#nonFormat(element))
|
|
843
948
|
);
|
|
844
949
|
}
|
|
845
950
|
|
|
@@ -856,7 +961,10 @@ class Format {
|
|
|
856
961
|
isBlock(element) {
|
|
857
962
|
return typeof element === 'string'
|
|
858
963
|
? this.#formatBlockCheck.test(element)
|
|
859
|
-
: element?.nodeType === 1 &&
|
|
964
|
+
: element?.nodeType === 1 &&
|
|
965
|
+
(this.#formatBlockCheck.test(element.nodeName) ||
|
|
966
|
+
dom.utils.hasClass(element, '__se__format__block_.+')) &&
|
|
967
|
+
!this.#nonFormat(element);
|
|
860
968
|
}
|
|
861
969
|
|
|
862
970
|
/**
|
|
@@ -872,7 +980,10 @@ class Format {
|
|
|
872
980
|
isClosureBlock(element) {
|
|
873
981
|
return typeof element === 'string'
|
|
874
982
|
? this.#formatClosureBlockCheck.test(element)
|
|
875
|
-
: element?.nodeType === 1 &&
|
|
983
|
+
: element?.nodeType === 1 &&
|
|
984
|
+
(this.#formatClosureBlockCheck.test(element.nodeName) ||
|
|
985
|
+
dom.utils.hasClass(element, '__se__format__block_closure_.+')) &&
|
|
986
|
+
!this.#nonFormat(element);
|
|
876
987
|
}
|
|
877
988
|
|
|
878
989
|
/**
|
|
@@ -888,12 +999,15 @@ class Format {
|
|
|
888
999
|
isClosureBrLine(element) {
|
|
889
1000
|
return typeof element === 'string'
|
|
890
1001
|
? this.#formatClosureBrLineCheck.test(element)
|
|
891
|
-
: element?.nodeType === 1 &&
|
|
1002
|
+
: element?.nodeType === 1 &&
|
|
1003
|
+
(this.#formatClosureBrLineCheck.test(element.nodeName) ||
|
|
1004
|
+
dom.utils.hasClass(element, '__se__format__br_line__closure_.+')) &&
|
|
1005
|
+
!this.#nonFormat(element);
|
|
892
1006
|
}
|
|
893
1007
|
|
|
894
1008
|
/**
|
|
895
1009
|
* @description Returns a `line` array from selected range.
|
|
896
|
-
* @param {?(current:
|
|
1010
|
+
* @param {?(current: *) => boolean} [validation] The validation function. (Replaces the default validation `format.isLine(current)`)
|
|
897
1011
|
* @returns {Array<HTMLElement>}
|
|
898
1012
|
* @example
|
|
899
1013
|
* const selectedLines = editor.$.format.getLines();
|
|
@@ -907,7 +1021,12 @@ class Format {
|
|
|
907
1021
|
const childrenLen = children.length;
|
|
908
1022
|
if (childrenLen === 0) return [];
|
|
909
1023
|
|
|
910
|
-
this.#$.selection.setRange(
|
|
1024
|
+
this.#$.selection.setRange(
|
|
1025
|
+
children[0],
|
|
1026
|
+
0,
|
|
1027
|
+
children[childrenLen - 1],
|
|
1028
|
+
children[childrenLen - 1].textContent.trim().length,
|
|
1029
|
+
);
|
|
911
1030
|
range = this.#$.selection.getRange();
|
|
912
1031
|
}
|
|
913
1032
|
|
|
@@ -919,7 +1038,8 @@ class Format {
|
|
|
919
1038
|
validation ||= this.isLine.bind(this);
|
|
920
1039
|
const lineNodes = dom.query.getListChildren(commonCon, (current) => validation(current), null);
|
|
921
1040
|
|
|
922
|
-
if (commonCon.nodeType === 3 || (!dom.check.isWysiwygFrame(commonCon) && !this.isBlock(commonCon)))
|
|
1041
|
+
if (commonCon.nodeType === 3 || (!dom.check.isWysiwygFrame(commonCon) && !this.isBlock(commonCon)))
|
|
1042
|
+
lineNodes.unshift(this.getLine(commonCon, null));
|
|
923
1043
|
if (startCon === endCon || lineNodes.length === 1) return lineNodes;
|
|
924
1044
|
|
|
925
1045
|
const startLine = this.getLine(startCon, null);
|
|
@@ -933,8 +1053,10 @@ class Format {
|
|
|
933
1053
|
|
|
934
1054
|
let startRangeEl = this.getBlock(startLine, onlyTable);
|
|
935
1055
|
let endRangeEl = this.getBlock(endLine, onlyTable);
|
|
936
|
-
if (dom.check.isTableElements(startRangeEl) && dom.check.isListCell(startRangeEl.parentNode))
|
|
937
|
-
|
|
1056
|
+
if (dom.check.isTableElements(startRangeEl) && dom.check.isListCell(startRangeEl.parentNode))
|
|
1057
|
+
startRangeEl = startRangeEl.parentNode;
|
|
1058
|
+
if (dom.check.isTableElements(endRangeEl) && dom.check.isListCell(endRangeEl.parentNode))
|
|
1059
|
+
endRangeEl = endRangeEl.parentNode;
|
|
938
1060
|
|
|
939
1061
|
const sameRange = startRangeEl === endRangeEl;
|
|
940
1062
|
for (let i = 0, len = lineNodes.length, line; i < len; i++) {
|
|
@@ -970,7 +1092,10 @@ class Format {
|
|
|
970
1092
|
? this.getLines(null)
|
|
971
1093
|
: this.getLines((current) => {
|
|
972
1094
|
const component = dom.query.getParentElement(current, this.#$.component.is.bind(this.#$.component));
|
|
973
|
-
return (
|
|
1095
|
+
return (
|
|
1096
|
+
(this.isLine(current) && (!component || component === myComponent)) ||
|
|
1097
|
+
(dom.check.isComponentContainer(current) && !this.getLine(current))
|
|
1098
|
+
);
|
|
974
1099
|
});
|
|
975
1100
|
|
|
976
1101
|
if (removeDuplicate) {
|
|
@@ -1009,7 +1134,9 @@ class Format {
|
|
|
1009
1134
|
* @returns {boolean}
|
|
1010
1135
|
*/
|
|
1011
1136
|
_isExcludeSelectionElement(element) {
|
|
1012
|
-
return
|
|
1137
|
+
return (
|
|
1138
|
+
!/FIGCAPTION/i.test(element.nodeName) && (this.#$.component.is(element) || /FIGURE/i.test(element.nodeName))
|
|
1139
|
+
);
|
|
1013
1140
|
}
|
|
1014
1141
|
|
|
1015
1142
|
/**
|
|
@@ -1049,7 +1176,12 @@ class Format {
|
|
|
1049
1176
|
if (rlist.ec) last = rlist.ec;
|
|
1050
1177
|
|
|
1051
1178
|
// change format tag
|
|
1052
|
-
this.#$.selection.setRange(
|
|
1179
|
+
this.#$.selection.setRange(
|
|
1180
|
+
dom.query.getNodeFromPath(firstPath, first),
|
|
1181
|
+
startOffset,
|
|
1182
|
+
dom.query.getNodeFromPath(lastPath, last),
|
|
1183
|
+
endOffset,
|
|
1184
|
+
);
|
|
1053
1185
|
|
|
1054
1186
|
return {
|
|
1055
1187
|
lines: this.getLinesAndComponents(false),
|