suneditor 3.0.4 → 3.0.5
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.min.js +1 -1
- package/package.json +1 -1
- package/src/core/logic/panel/viewer.js +9 -5
- package/src/helper/markdown.js +18 -3
- package/src/modules/contract/Controller.js +1 -2
- package/src/modules/contract/Figure.js +1 -1
- package/src/plugins/command/codeBlock.js +1 -1
- package/src/plugins/command/list_bulleted.js +1 -1
- package/src/plugins/command/list_numbered.js +1 -1
- package/src/plugins/input/fontSize.js +4 -4
package/package.json
CHANGED
|
@@ -300,7 +300,7 @@ class Viewer {
|
|
|
300
300
|
this.#originCssText = topArea.style.cssText;
|
|
301
301
|
this.#editorAreaOriginCssText = editorArea.style.cssText;
|
|
302
302
|
this.#wysiwygOriginCssText = wysiwygFrame.style.cssText;
|
|
303
|
-
this.#codeWrapperOriginCssText = codeWrapper
|
|
303
|
+
this.#codeWrapperOriginCssText = codeWrapper?.style.cssText;
|
|
304
304
|
this.#codeOriginCssText = code.style.cssText;
|
|
305
305
|
this.#codeNumberOriginCssText = codeNumbers?.style.cssText;
|
|
306
306
|
this.#markdownWrapperOriginCssText = markdownWrapper?.style.cssText;
|
|
@@ -344,9 +344,11 @@ class Viewer {
|
|
|
344
344
|
wysiwygFrame.style.cssText = (wysiwygFrame.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/) || [''])[0] + this.#frameOptions.get('_defaultStyles').editor + (isCodeView || isMarkdownView ? 'display: none;' : '');
|
|
345
345
|
|
|
346
346
|
// code wrapper
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
347
|
+
if (codeWrapper) {
|
|
348
|
+
codeWrapper.style.cssText = (codeWrapper.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/) || [''])[0] + `display: ${!isCodeView ? 'none' : 'flex'} !important;`;
|
|
349
|
+
codeWrapper.style.overflow = 'auto';
|
|
350
|
+
codeWrapper.style.height = '100%';
|
|
351
|
+
}
|
|
350
352
|
|
|
351
353
|
// markdown wrapper
|
|
352
354
|
if (markdownWrapper) {
|
|
@@ -384,7 +386,9 @@ class Viewer {
|
|
|
384
386
|
wysiwygFrame.style.cssText = this.#wysiwygOriginCssText.replace(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/, '') + (isCodeView || isMarkdownView ? 'display: none;' : '');
|
|
385
387
|
|
|
386
388
|
// code wrapper
|
|
387
|
-
|
|
389
|
+
if (codeWrapper) {
|
|
390
|
+
codeWrapper.style.cssText = this.#codeWrapperOriginCssText.replace(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/, '') + `display: ${!isCodeView ? 'none' : 'flex'} !important;`;
|
|
391
|
+
}
|
|
388
392
|
|
|
389
393
|
// code
|
|
390
394
|
code.style.cssText = this.#codeOriginCssText;
|
package/src/helper/markdown.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Markdown converter module
|
|
3
3
|
* - Supports GitHub Flavored Markdown (GFM) syntax
|
|
4
|
+
*
|
|
5
|
+
* @description Limitations — Style loss during roundtrip
|
|
6
|
+
*
|
|
7
|
+
* Markdown syntax cannot represent HTML inline styles, classes, or data attributes.
|
|
8
|
+
* When switching between WYSIWYG and Markdown view, the following behavior applies:
|
|
9
|
+
*
|
|
10
|
+
* | Content type | Behavior | Example |
|
|
11
|
+
* |-------------------------------------|---------------------------------------------|------------------------------------------------------|
|
|
12
|
+
* | Media components (`div.se-component`) | Converted to markdown — styles are lost | Image alignment, data-se-* attrs |
|
|
13
|
+
* | Styled `<span>` elements | Preserved as raw HTML in markdown | Font color, background, custom classes |
|
|
14
|
+
* | Tables, figures | Converted to markdown — styles are lost | Table cell styles, figure width, colgroup widths |
|
|
15
|
+
* | General elements (p, h1, blockquote) | Converted to markdown — styles are lost | text-align, color, font-size on paragraphs/headings |
|
|
16
|
+
*
|
|
17
|
+
* This is a fundamental limitation of the Markdown format.
|
|
18
|
+
* To preserve all HTML attributes without loss, use Code View instead.
|
|
4
19
|
*/
|
|
5
20
|
|
|
6
21
|
const VOID_ELEMENTS = /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i;
|
|
@@ -439,16 +454,16 @@ function nodeToMarkdown(node, indent, isBlock) {
|
|
|
439
454
|
|
|
440
455
|
// Span - pass through as inline (may contain styles)
|
|
441
456
|
if (tag === 'span') {
|
|
442
|
-
// Check if it has meaningful attributes that need HTML fallback
|
|
443
457
|
if (attributes.style || attributes.class) {
|
|
444
458
|
return nodeToHtmlFallback(node);
|
|
445
459
|
}
|
|
446
460
|
return childrenToInline(children);
|
|
447
461
|
}
|
|
448
462
|
|
|
449
|
-
// Figure - process children (
|
|
463
|
+
// Figure - process children (table, media)
|
|
450
464
|
if (tag === 'figure') {
|
|
451
|
-
|
|
465
|
+
const inner = children.map((c) => nodeToMarkdown(c, indent, true)).join('');
|
|
466
|
+
return /\n$/.test(inner) ? inner : inner + '\n\n';
|
|
452
467
|
}
|
|
453
468
|
if (tag === 'figcaption') {
|
|
454
469
|
const content = childrenToInline(children).trim();
|
|
@@ -377,14 +377,13 @@ class Controller {
|
|
|
377
377
|
if (!passive) {
|
|
378
378
|
this.#$.ui.onControllerContext();
|
|
379
379
|
this.#$.store.set('controlActive', true);
|
|
380
|
+
this.#$.store.set('_preventBlur', true);
|
|
380
381
|
}
|
|
381
382
|
|
|
382
383
|
if (!this.isOpen) {
|
|
383
384
|
this.#$.ui.opendControllers.push(info);
|
|
384
385
|
}
|
|
385
386
|
|
|
386
|
-
this.#$.store.set('_preventBlur', true);
|
|
387
|
-
|
|
388
387
|
this.isOpen = true;
|
|
389
388
|
|
|
390
389
|
this.host.controllerOn?.(form, target);
|
|
@@ -904,7 +904,7 @@ class Figure {
|
|
|
904
904
|
retainFigureFormat(container, originEl, anchorCover, fileManagerInst) {
|
|
905
905
|
const isInline = this.#$.component.isInline(container);
|
|
906
906
|
const originParent = originEl.parentNode;
|
|
907
|
-
let existElement = this.#$.format.isBlock(originParent) || dom.check.isWysiwygFrame(originParent) ? originEl : Figure.GetContainer(originEl)?.container || originParent || originEl;
|
|
907
|
+
let existElement = this.#$.format.isBlock(originParent) || dom.check.isWysiwygFrame(originParent) || originParent.nodeType >= 9 ? originEl : Figure.GetContainer(originEl)?.container || originParent || originEl;
|
|
908
908
|
|
|
909
909
|
if (dom.query.getParentElement(originEl, dom.check.isExcludeFormat)) {
|
|
910
910
|
existElement = anchorCover && anchorCover !== originEl ? anchorCover : originEl;
|
|
@@ -66,7 +66,7 @@ class CodeBlock extends PluginCommand {
|
|
|
66
66
|
// ───────────────── [[toolbar dropdown type]] ─────────────────
|
|
67
67
|
this.afterItem = dom.utils.createElement(
|
|
68
68
|
'button',
|
|
69
|
-
{ class: 'se-btn se-tooltip se-sub-arrow-btn', 'data-command': CodeBlock.key, 'data-type': 'dropdown' },
|
|
69
|
+
{ class: 'se-btn se-tooltip se-sub-arrow-btn', type: 'button', 'data-command': CodeBlock.key, 'data-type': 'dropdown' },
|
|
70
70
|
`${this.$.icons.arrow_down}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.codeLanguage || 'Language'}</span></span>`,
|
|
71
71
|
);
|
|
72
72
|
|
|
@@ -27,7 +27,7 @@ class List_bulleted extends PluginCommand {
|
|
|
27
27
|
this.icon = 'list_bulleted';
|
|
28
28
|
this.afterItem = dom.utils.createElement(
|
|
29
29
|
'button',
|
|
30
|
-
{ class: 'se-btn se-tooltip se-sub-arrow-btn', 'data-command': List_bulleted.key, 'data-type': 'dropdown' },
|
|
30
|
+
{ class: 'se-btn se-tooltip se-sub-arrow-btn', type: 'button', 'data-command': List_bulleted.key, 'data-type': 'dropdown' },
|
|
31
31
|
`${this.$.icons.arrow_down}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.bulletedList}</span></span>`,
|
|
32
32
|
);
|
|
33
33
|
|
|
@@ -27,7 +27,7 @@ class List_numbered extends PluginCommand {
|
|
|
27
27
|
this.icon = 'list_numbered';
|
|
28
28
|
this.afterItem = dom.utils.createElement(
|
|
29
29
|
'button',
|
|
30
|
-
{ class: 'se-btn se-tooltip se-sub-arrow-btn', 'data-command': List_numbered.key, 'data-type': 'dropdown' },
|
|
30
|
+
{ class: 'se-btn se-tooltip se-sub-arrow-btn', type: 'button', 'data-command': List_numbered.key, 'data-type': 'dropdown' },
|
|
31
31
|
`${this.$.icons.arrow_down}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.numberedList}</span></span>`,
|
|
32
32
|
);
|
|
33
33
|
|
|
@@ -152,25 +152,25 @@ class FontSize extends PluginInput {
|
|
|
152
152
|
if (showIncDec) {
|
|
153
153
|
this.beforeItem = dom.utils.createElement(
|
|
154
154
|
'button',
|
|
155
|
-
{ class: 'se-btn se-tooltip se-sub-btn', 'data-command': FontSize.key, 'data-type': 'command', 'data-value': 'dec' },
|
|
155
|
+
{ class: 'se-btn se-tooltip se-sub-btn', type: 'button', 'data-command': FontSize.key, 'data-type': 'command', 'data-value': 'dec' },
|
|
156
156
|
`${this.$.icons.minus}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.decrease}</span></span>`,
|
|
157
157
|
);
|
|
158
158
|
this.afterItem = dom.utils.createElement(
|
|
159
159
|
'button',
|
|
160
|
-
{ class: 'se-btn se-tooltip se-sub-btn', 'data-command': FontSize.key, 'data-type': 'command', 'data-value': 'inc' },
|
|
160
|
+
{ class: 'se-btn se-tooltip se-sub-btn', type: 'button', 'data-command': FontSize.key, 'data-type': 'command', 'data-value': 'inc' },
|
|
161
161
|
`${this.$.icons.plus}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.increase}</span></span>`,
|
|
162
162
|
);
|
|
163
163
|
} else if (!disableInput) {
|
|
164
164
|
this.afterItem = dom.utils.createElement(
|
|
165
165
|
'button',
|
|
166
|
-
{ class: 'se-btn se-tooltip se-sub-arrow-btn', 'data-command': FontSize.key, 'data-type': 'dropdown' },
|
|
166
|
+
{ class: 'se-btn se-tooltip se-sub-arrow-btn', type: 'button', 'data-command': FontSize.key, 'data-type': 'dropdown' },
|
|
167
167
|
`${this.$.icons.arrow_down}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.fontSize}</span></span>`,
|
|
168
168
|
);
|
|
169
169
|
this.$.menu.initDropdownTarget({ key: FontSize.key, type: 'dropdown' }, menu);
|
|
170
170
|
} else if (disableInput && !showIncDec) {
|
|
171
171
|
this.replaceButton = dom.utils.createElement(
|
|
172
172
|
'button',
|
|
173
|
-
{ class: 'se-btn se-tooltip se-btn-select se-btn-tool-font-size', 'data-command': FontSize.key, 'data-type': 'dropdown' },
|
|
173
|
+
{ class: 'se-btn se-tooltip se-btn-select se-btn-tool-font-size', type: 'button', 'data-command': FontSize.key, 'data-type': 'dropdown' },
|
|
174
174
|
`<span class="se-txt __se__font_size">${this.$.lang.fontSize}</span>${this.$.icons.arrow_down}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.$.lang.fontSize}</span></span>`,
|
|
175
175
|
);
|
|
176
176
|
this.$.menu.initDropdownTarget({ key: FontSize.key, type: 'dropdown' }, menu);
|