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
|
@@ -49,7 +49,9 @@ class Drawing extends PluginModal {
|
|
|
49
49
|
this.pluginOptions = {
|
|
50
50
|
outputFormat: pluginOptions.outputFormat || 'dataurl', // dataurl, svg
|
|
51
51
|
useFormatType: pluginOptions.useFormatType ?? false,
|
|
52
|
-
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType)
|
|
52
|
+
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType)
|
|
53
|
+
? pluginOptions.defaultFormatType
|
|
54
|
+
: 'block',
|
|
53
55
|
keepFormatType: pluginOptions.keepFormatType ?? false,
|
|
54
56
|
lineWidth: pluginOptions.lineWidth || 5,
|
|
55
57
|
lineReconnect: !!pluginOptions.lineReconnect,
|
|
@@ -70,9 +72,13 @@ class Drawing extends PluginModal {
|
|
|
70
72
|
|
|
71
73
|
// exception
|
|
72
74
|
if (!this.$.plugins.image) {
|
|
73
|
-
console.warn(
|
|
75
|
+
console.warn(
|
|
76
|
+
'[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need either "image" plugin. Please add the "image" plugin.',
|
|
77
|
+
);
|
|
74
78
|
} else if (this.pluginOptions.outputFormat === 'svg' && !this.$.plugins.image.pluginOptions.uploadUrl) {
|
|
75
|
-
console.warn(
|
|
79
|
+
console.warn(
|
|
80
|
+
'[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need the "image" plugin with the "uploadUrl" option. Please add the "image" plugin with the "uploadUrl" option.',
|
|
81
|
+
);
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
// create HTML
|
|
@@ -119,7 +125,11 @@ class Drawing extends PluginModal {
|
|
|
119
125
|
};
|
|
120
126
|
|
|
121
127
|
// init
|
|
122
|
-
this.$.eventManager.addEvent(
|
|
128
|
+
this.$.eventManager.addEvent(
|
|
129
|
+
modalEl.querySelector('[data-command="remove"]'),
|
|
130
|
+
'click',
|
|
131
|
+
this.#OnRemove.bind(this),
|
|
132
|
+
);
|
|
123
133
|
}
|
|
124
134
|
|
|
125
135
|
/**
|
|
@@ -128,7 +138,9 @@ class Drawing extends PluginModal {
|
|
|
128
138
|
*/
|
|
129
139
|
open() {
|
|
130
140
|
if (this.pluginOptions.useFormatType) {
|
|
131
|
-
this.#activeAsInline(
|
|
141
|
+
this.#activeAsInline(
|
|
142
|
+
(this.pluginOptions.keepFormatType ? this.as : this.pluginOptions.defaultFormatType) === 'inline',
|
|
143
|
+
);
|
|
132
144
|
}
|
|
133
145
|
this.modal.open();
|
|
134
146
|
this.#initDrawing();
|
|
@@ -180,10 +192,26 @@ class Drawing extends PluginModal {
|
|
|
180
192
|
|
|
181
193
|
this.#setCtx();
|
|
182
194
|
|
|
183
|
-
this.#eventsRegister.touchstart = this.$.eventManager.addEvent(canvas, 'touchstart', this.#events.touchstart, {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
195
|
+
this.#eventsRegister.touchstart = this.$.eventManager.addEvent(canvas, 'touchstart', this.#events.touchstart, {
|
|
196
|
+
passive: false,
|
|
197
|
+
capture: true,
|
|
198
|
+
});
|
|
199
|
+
this.#eventsRegister.touchmove = this.$.eventManager.addEvent(
|
|
200
|
+
canvas,
|
|
201
|
+
'touchmove',
|
|
202
|
+
this.#events.touchmove,
|
|
203
|
+
true,
|
|
204
|
+
);
|
|
205
|
+
this.#eventsRegister.mousedown = this.$.eventManager.addEvent(canvas, 'mousedown', this.#events.mousedown, {
|
|
206
|
+
passive: false,
|
|
207
|
+
capture: true,
|
|
208
|
+
});
|
|
209
|
+
this.#eventsRegister.mousemove = this.$.eventManager.addEvent(
|
|
210
|
+
canvas,
|
|
211
|
+
'mousemove',
|
|
212
|
+
this.#events.mousemove,
|
|
213
|
+
true,
|
|
214
|
+
);
|
|
187
215
|
this.#eventsRegister.mouseup = this.$.eventManager.addEvent(canvas, 'mouseup', this.#events.mouseup, true);
|
|
188
216
|
this.#eventsRegister.mouseleave = this.$.eventManager.addEvent(canvas, 'mouseleave', this.#events.mouseleave);
|
|
189
217
|
this.#eventsRegister.mouseenter = this.$.eventManager.addEvent(canvas, 'mouseenter', this.#events.mouseenter);
|
|
@@ -202,7 +230,8 @@ class Drawing extends PluginModal {
|
|
|
202
230
|
canvas.width = newWidth;
|
|
203
231
|
canvas.height = newHeight;
|
|
204
232
|
if (prevWidth !== canvas.width || prevHeight !== canvas.height) {
|
|
205
|
-
if (this.pluginOptions.maintainRatio)
|
|
233
|
+
if (this.pluginOptions.maintainRatio)
|
|
234
|
+
this.#adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight);
|
|
206
235
|
this.#drawAll();
|
|
207
236
|
}
|
|
208
237
|
});
|
|
@@ -241,7 +270,8 @@ class Drawing extends PluginModal {
|
|
|
241
270
|
#setCtx() {
|
|
242
271
|
this.ctx.lineWidth = this.pluginOptions.lineWidth;
|
|
243
272
|
this.ctx.lineCap = this.pluginOptions.lineCap;
|
|
244
|
-
this.ctx.strokeStyle =
|
|
273
|
+
this.ctx.strokeStyle =
|
|
274
|
+
this.pluginOptions.lineColor || _w.getComputedStyle(this.$.contextProvider.carrierWrapper).color;
|
|
245
275
|
}
|
|
246
276
|
|
|
247
277
|
/**
|
|
@@ -39,6 +39,17 @@ const { _w, NO_EVENT } = env;
|
|
|
39
39
|
* { query_vimeo: 'autoplay=1' }
|
|
40
40
|
* ```
|
|
41
41
|
* @property {Array<RegExp>} [urlPatterns] - Additional URL patterns to recognize as embeddable content.
|
|
42
|
+
* @property {Array<RegExp|string>} [scriptSrcWhitelist] - Allowed `<script src=...>` patterns for raw embed HTML
|
|
43
|
+
* - (e.g. Twitter blockquote + `widgets.js`). Each entry is a `RegExp` (tested against the full src) or a `string` (matched via `startsWith`).
|
|
44
|
+
* - Defaults to `[]` — all script tags are rejected.** Inline scripts (no `src`) are always rejected.
|
|
45
|
+
* ```js
|
|
46
|
+
* {
|
|
47
|
+
* scriptSrcWhitelist: [
|
|
48
|
+
* /^https:\/\/platform\.x\.com\/widgets\.js$/,
|
|
49
|
+
* /^https:\/\/www\.instagram\.com\/embed\.js$/,
|
|
50
|
+
* ]
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
42
53
|
* @property {Object<string, {pattern: RegExp, action: (url: string) => string, tag: string}>} [embedQuery] - Custom embed service definitions.
|
|
43
54
|
* Each key is a service name, with `pattern` to match the URL, `action` to transform it into an embed URL, and `tag` for the output element.
|
|
44
55
|
* ```js
|
|
@@ -125,6 +136,18 @@ class Embed extends PluginModal {
|
|
|
125
136
|
return false;
|
|
126
137
|
}
|
|
127
138
|
|
|
139
|
+
/**
|
|
140
|
+
* @description Validate a `<script src>` against the configured whitelist for raw embed HTML.
|
|
141
|
+
* Inline scripts (no `src`) are always rejected.
|
|
142
|
+
* @param {string} src
|
|
143
|
+
* @param {Array<RegExp|string>} whitelist
|
|
144
|
+
* @returns {boolean}
|
|
145
|
+
*/
|
|
146
|
+
static #isAllowedScriptSrc(src, whitelist) {
|
|
147
|
+
if (!src) return false;
|
|
148
|
+
return whitelist.some((p) => (p instanceof RegExp ? p.test(src) : src.startsWith(p)));
|
|
149
|
+
}
|
|
150
|
+
|
|
128
151
|
/** @type {Array<RegExp>} */
|
|
129
152
|
static #urlPatterns = null;
|
|
130
153
|
|
|
@@ -158,8 +181,18 @@ class Embed extends PluginModal {
|
|
|
158
181
|
this.pluginOptions = {
|
|
159
182
|
canResize: pluginOptions.canResize === undefined ? true : pluginOptions.canResize,
|
|
160
183
|
showHeightInput: pluginOptions.showHeightInput === undefined ? true : !!pluginOptions.showHeightInput,
|
|
161
|
-
defaultWidth:
|
|
162
|
-
|
|
184
|
+
defaultWidth:
|
|
185
|
+
!pluginOptions.defaultWidth || !numbers.get(pluginOptions.defaultWidth, 0)
|
|
186
|
+
? ''
|
|
187
|
+
: numbers.is(pluginOptions.defaultWidth)
|
|
188
|
+
? pluginOptions.defaultWidth + 'px'
|
|
189
|
+
: pluginOptions.defaultWidth,
|
|
190
|
+
defaultHeight:
|
|
191
|
+
!pluginOptions.defaultHeight || !numbers.get(pluginOptions.defaultHeight, 0)
|
|
192
|
+
? ''
|
|
193
|
+
: numbers.is(pluginOptions.defaultHeight)
|
|
194
|
+
? pluginOptions.defaultHeight + 'px'
|
|
195
|
+
: pluginOptions.defaultHeight,
|
|
163
196
|
percentageOnlySize: !!pluginOptions.percentageOnlySize,
|
|
164
197
|
uploadUrl: typeof pluginOptions.uploadUrl === 'string' ? pluginOptions.uploadUrl : null,
|
|
165
198
|
uploadHeaders: pluginOptions.uploadHeaders || null,
|
|
@@ -168,16 +201,22 @@ class Embed extends PluginModal {
|
|
|
168
201
|
iframeTagAttributes: pluginOptions.iframeTagAttributes || null,
|
|
169
202
|
query_youtube: pluginOptions.query_youtube || '',
|
|
170
203
|
query_vimeo: pluginOptions.query_vimeo || '',
|
|
204
|
+
scriptSrcWhitelist: Array.isArray(pluginOptions.scriptSrcWhitelist) ? pluginOptions.scriptSrcWhitelist : [],
|
|
171
205
|
insertBehavior: pluginOptions.insertBehavior,
|
|
172
206
|
};
|
|
173
207
|
|
|
174
208
|
// create HTML
|
|
175
209
|
const sizeUnit = this.pluginOptions.percentageOnlySize ? '%' : 'px';
|
|
176
210
|
const modalEl = CreateHTML_modal(this.$, this.pluginOptions);
|
|
177
|
-
const figureControls =
|
|
211
|
+
const figureControls =
|
|
212
|
+
pluginOptions.controls ||
|
|
213
|
+
(!this.pluginOptions.canResize
|
|
214
|
+
? [['align', 'edit', 'copy', 'remove']]
|
|
215
|
+
: [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']]);
|
|
178
216
|
|
|
179
217
|
// show align
|
|
180
|
-
if (!figureControls.some((subArray) => subArray.includes('align')))
|
|
218
|
+
if (!figureControls.some((subArray) => subArray.includes('align')))
|
|
219
|
+
modalEl.figureAlignBtn.style.display = 'none';
|
|
181
220
|
|
|
182
221
|
// modules
|
|
183
222
|
this.modal = new Modal(this, this.$, modalEl.html);
|
|
@@ -210,7 +249,8 @@ class Embed extends PluginModal {
|
|
|
210
249
|
tag: 'iframe',
|
|
211
250
|
},
|
|
212
251
|
twitter: {
|
|
213
|
-
pattern:
|
|
252
|
+
pattern:
|
|
253
|
+
/^(?:https?:\/\/)?(?:(?:www\.)?(?:twitter\.com|x\.com)\/(?:[^/?#]+\/)?status\/\d+(?:[/?#]|$)|platform\.twitter\.com\/embed\/Tweet\.html(?:[?#].*)?$)/i,
|
|
214
254
|
action: (url) => {
|
|
215
255
|
return `https://platform.twitter.com/embed/Tweet.html?url=${encodeURIComponent(url)}`;
|
|
216
256
|
},
|
|
@@ -319,11 +359,16 @@ class Embed extends PluginModal {
|
|
|
319
359
|
*/
|
|
320
360
|
modalOn(isUpdate) {
|
|
321
361
|
if (!isUpdate && this.#resizing) {
|
|
322
|
-
this.inputX.value = this.#origin_w =
|
|
323
|
-
|
|
362
|
+
this.inputX.value = this.#origin_w =
|
|
363
|
+
this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
|
|
364
|
+
this.inputY.value = this.#origin_h =
|
|
365
|
+
this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
|
|
324
366
|
this.proportion.disabled = true;
|
|
325
367
|
} else if (isUpdate) {
|
|
326
|
-
this.#linkValue =
|
|
368
|
+
this.#linkValue =
|
|
369
|
+
this.previewSrc.textContent =
|
|
370
|
+
this.embedInput.value =
|
|
371
|
+
this.#cover.getAttribute('data-se-origin') || '';
|
|
327
372
|
}
|
|
328
373
|
}
|
|
329
374
|
|
|
@@ -332,7 +377,9 @@ class Embed extends PluginModal {
|
|
|
332
377
|
* @type {SunEditor.Hook.Modal.Action}
|
|
333
378
|
*/
|
|
334
379
|
async modalAction() {
|
|
335
|
-
this.#align = /** @type {HTMLInputElement} */ (
|
|
380
|
+
this.#align = /** @type {HTMLInputElement} */ (
|
|
381
|
+
this.modal.form.querySelector('input[name="suneditor_embed_radio"]:checked')
|
|
382
|
+
).value;
|
|
336
383
|
|
|
337
384
|
let result = false;
|
|
338
385
|
if (this.#linkValue.length > 0) {
|
|
@@ -352,13 +399,17 @@ class Embed extends PluginModal {
|
|
|
352
399
|
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
353
400
|
this.#linkValue = this.previewSrc.textContent = this.embedInput.value = '';
|
|
354
401
|
|
|
355
|
-
/** @type {HTMLInputElement} */ (
|
|
402
|
+
/** @type {HTMLInputElement} */ (
|
|
403
|
+
this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]')
|
|
404
|
+
).checked = true;
|
|
356
405
|
this.#ratio = { w: 0, h: 0 };
|
|
357
406
|
this.#nonResizing = false;
|
|
358
407
|
|
|
359
408
|
if (this.#resizing) {
|
|
360
|
-
this.inputX.value =
|
|
361
|
-
|
|
409
|
+
this.inputX.value =
|
|
410
|
+
this.pluginOptions.defaultWidth === this.#defaultSizeX ? '' : this.pluginOptions.defaultWidth;
|
|
411
|
+
this.inputY.value =
|
|
412
|
+
this.pluginOptions.defaultHeight === this.#defaultSizeY ? '' : this.pluginOptions.defaultHeight;
|
|
362
413
|
this.proportion.checked = false;
|
|
363
414
|
this.proportion.disabled = true;
|
|
364
415
|
}
|
|
@@ -390,7 +441,12 @@ class Embed extends PluginModal {
|
|
|
390
441
|
const focusEl = container.previousElementSibling || container.nextElementSibling;
|
|
391
442
|
const emptyDiv = container.parentNode;
|
|
392
443
|
|
|
393
|
-
const message = await this.$.eventManager.triggerEvent('onEmbedDeleteBefore', {
|
|
444
|
+
const message = await this.$.eventManager.triggerEvent('onEmbedDeleteBefore', {
|
|
445
|
+
element: targetEl,
|
|
446
|
+
container,
|
|
447
|
+
align: this.#align,
|
|
448
|
+
url: this.#linkValue,
|
|
449
|
+
});
|
|
394
450
|
if (message === false) return;
|
|
395
451
|
|
|
396
452
|
dom.utils.removeItem(container);
|
|
@@ -446,6 +502,20 @@ class Embed extends PluginModal {
|
|
|
446
502
|
if (/^<iframe\s|^<blockquote\s/i.test(src)) {
|
|
447
503
|
const embedDOM = new DOMParser().parseFromString(src, 'text/html').body.children;
|
|
448
504
|
if (embedDOM.length === 0) return false;
|
|
505
|
+
|
|
506
|
+
// Validate every iframe in the raw HTML against the URL whitelist.
|
|
507
|
+
for (let i = 0; i < embedDOM.length; i++) {
|
|
508
|
+
const node = /** @type {Element} */ (embedDOM[i]);
|
|
509
|
+
if (/^iframe$/i.test(node.nodeName) && !Embed.#checkContentType(node.getAttribute('src') || ''))
|
|
510
|
+
return false;
|
|
511
|
+
const nested = node.querySelectorAll?.('iframe');
|
|
512
|
+
if (nested) {
|
|
513
|
+
for (let j = 0; j < nested.length; j++) {
|
|
514
|
+
if (!Embed.#checkContentType(nested[j].getAttribute('src') || '')) return false;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
449
519
|
embedInfo = { children: embedDOM, ...this.#getInfo(), process: null };
|
|
450
520
|
} else {
|
|
451
521
|
const processUrl = this.findProcessUrl(src);
|
|
@@ -461,7 +531,16 @@ class Embed extends PluginModal {
|
|
|
461
531
|
|
|
462
532
|
const handler = function (uploadCallback, infos, newInfos) {
|
|
463
533
|
infos = newInfos || infos;
|
|
464
|
-
uploadCallback(
|
|
534
|
+
uploadCallback(
|
|
535
|
+
src,
|
|
536
|
+
infos.process,
|
|
537
|
+
infos.url,
|
|
538
|
+
infos.children,
|
|
539
|
+
infos.inputWidth,
|
|
540
|
+
infos.inputHeight,
|
|
541
|
+
infos.align,
|
|
542
|
+
infos.isUpdate,
|
|
543
|
+
);
|
|
465
544
|
}.bind(this, this.#create.bind(this), embedInfo);
|
|
466
545
|
|
|
467
546
|
const result = await this.$.eventManager.triggerEvent('onEmbedInputBefore', {
|
|
@@ -487,7 +566,13 @@ class Embed extends PluginModal {
|
|
|
487
566
|
*/
|
|
488
567
|
#ready(target, infoOnly = false) {
|
|
489
568
|
if (!target) return;
|
|
490
|
-
const figureInfo = this.figure.open(target, {
|
|
569
|
+
const figureInfo = this.figure.open(target, {
|
|
570
|
+
nonResizing: this.#nonResizing,
|
|
571
|
+
nonSizeInfo: false,
|
|
572
|
+
nonBorder: false,
|
|
573
|
+
figureTarget: false,
|
|
574
|
+
infoOnly,
|
|
575
|
+
});
|
|
491
576
|
|
|
492
577
|
this.#element = target;
|
|
493
578
|
this.#cover = figureInfo.cover;
|
|
@@ -508,7 +593,9 @@ class Embed extends PluginModal {
|
|
|
508
593
|
this.#origin_h = String(figureInfo.originHeight || figureInfo.h || '');
|
|
509
594
|
|
|
510
595
|
/** @type {HTMLInputElement} */
|
|
511
|
-
const activeAlign =
|
|
596
|
+
const activeAlign =
|
|
597
|
+
this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="' + this.#align + '"]') ||
|
|
598
|
+
this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]');
|
|
512
599
|
activeAlign.checked = true;
|
|
513
600
|
|
|
514
601
|
if (!this.#resizing) return;
|
|
@@ -604,9 +691,12 @@ class Embed extends PluginModal {
|
|
|
604
691
|
container = figure.container;
|
|
605
692
|
|
|
606
693
|
const childNodes = Array.from(children);
|
|
694
|
+
const scriptWhitelist = this.pluginOptions.scriptSrcWhitelist;
|
|
607
695
|
for (const chd of childNodes) {
|
|
608
696
|
if (/^script$/i.test(chd.nodeName)) {
|
|
609
|
-
|
|
697
|
+
const scriptSrc = /** @type {Element} */ (chd).getAttribute('src') || '';
|
|
698
|
+
if (!Embed.#isAllowedScriptSrc(scriptSrc, scriptWhitelist)) continue;
|
|
699
|
+
scriptTag = dom.utils.createElement('script', { src: scriptSrc, async: 'true' }, null);
|
|
610
700
|
continue;
|
|
611
701
|
}
|
|
612
702
|
cover.appendChild(chd);
|
|
@@ -618,7 +708,13 @@ class Embed extends PluginModal {
|
|
|
618
708
|
this.#element = oFrame;
|
|
619
709
|
this.#cover = cover;
|
|
620
710
|
this.#container = container;
|
|
621
|
-
this.figure.open(oFrame, {
|
|
711
|
+
this.figure.open(oFrame, {
|
|
712
|
+
nonResizing: this.#nonResizing,
|
|
713
|
+
nonSizeInfo: false,
|
|
714
|
+
nonBorder: false,
|
|
715
|
+
figureTarget: false,
|
|
716
|
+
infoOnly: true,
|
|
717
|
+
});
|
|
622
718
|
|
|
623
719
|
width ||= this.#defaultSizeX;
|
|
624
720
|
height ||= this.#defaultSizeY;
|
|
@@ -639,7 +735,11 @@ class Embed extends PluginModal {
|
|
|
639
735
|
cover.setAttribute('data-se-origin', originSrc);
|
|
640
736
|
|
|
641
737
|
if (!isUpdate) {
|
|
642
|
-
this.$.component.insert(container, {
|
|
738
|
+
this.$.component.insert(container, {
|
|
739
|
+
skipHistory: true,
|
|
740
|
+
scrollTo: false,
|
|
741
|
+
insertBehavior: this.pluginOptions.insertBehavior,
|
|
742
|
+
});
|
|
643
743
|
|
|
644
744
|
if (scriptTag) {
|
|
645
745
|
try {
|
|
@@ -681,7 +781,8 @@ class Embed extends PluginModal {
|
|
|
681
781
|
return;
|
|
682
782
|
}
|
|
683
783
|
|
|
684
|
-
if (!this.#resizing || !changeSize || !this.figure.isVertical)
|
|
784
|
+
if (!this.#resizing || !changeSize || !this.figure.isVertical)
|
|
785
|
+
this.figure.setTransform(oFrame, width, height, 0);
|
|
685
786
|
if (!scriptTag) this.$.history.push(false);
|
|
686
787
|
}
|
|
687
788
|
|
|
@@ -700,7 +801,13 @@ class Embed extends PluginModal {
|
|
|
700
801
|
const container = figure.container;
|
|
701
802
|
|
|
702
803
|
// size
|
|
703
|
-
this.figure.open(oFrame, {
|
|
804
|
+
this.figure.open(oFrame, {
|
|
805
|
+
nonResizing: this.#nonResizing,
|
|
806
|
+
nonSizeInfo: false,
|
|
807
|
+
nonBorder: false,
|
|
808
|
+
figureTarget: false,
|
|
809
|
+
infoOnly: true,
|
|
810
|
+
});
|
|
704
811
|
const size = (oFrame.getAttribute('data-se-size') || ',').split(',');
|
|
705
812
|
|
|
706
813
|
const width = size[0] || prevFrame.width || '';
|
|
@@ -860,7 +967,10 @@ function CreateHTML_modal({ lang, icons }, pluginOptions) {
|
|
|
860
967
|
const onlyPercentDisplay = onlyPercentage ? ' style="display: none !important;"' : '';
|
|
861
968
|
const heightDisplay = !pluginOptions.showHeightInput ? ' style="display: none !important;"' : '';
|
|
862
969
|
const ratioDisplay = !pluginOptions.showRatioOption ? ' style="display: none !important;"' : '';
|
|
863
|
-
const onlyWidthDisplay =
|
|
970
|
+
const onlyWidthDisplay =
|
|
971
|
+
!onlyPercentage && !pluginOptions.showHeightInput && !pluginOptions.showRatioOption
|
|
972
|
+
? ' style="display: none !important;"'
|
|
973
|
+
: '';
|
|
864
974
|
html += /*html*/ `
|
|
865
975
|
<div class="se-modal-form">
|
|
866
976
|
<div class="se-modal-size-text">
|