suneditor 3.0.0-beta.9 → 3.0.0-rc.2
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/README.md +65 -57
- package/dist/suneditor-contents.min.css +1 -0
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +110 -61
- package/src/assets/design/color.css +36 -17
- package/src/assets/design/size.css +2 -0
- package/src/assets/icons/defaultIcons.js +17 -2
- package/src/assets/suneditor-contents.css +51 -16
- package/src/assets/suneditor.css +116 -43
- package/src/core/config/contextProvider.js +288 -0
- package/src/core/config/eventManager.js +188 -0
- package/src/core/config/instanceCheck.js +59 -0
- package/src/core/config/optionProvider.js +452 -0
- package/src/core/editor.js +166 -1637
- package/src/core/event/actions/index.js +229 -0
- package/src/core/event/effects/common.registry.js +74 -0
- package/src/core/event/effects/keydown.registry.js +573 -0
- package/src/core/event/effects/ruleHelpers.js +148 -0
- package/src/core/event/eventOrchestrator.js +944 -0
- package/src/core/event/executor.js +27 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +27 -28
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +10 -8
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +22 -23
- package/src/core/event/handlers/handler_ww_input.js +75 -0
- package/src/core/event/handlers/handler_ww_key.js +228 -0
- package/src/core/event/handlers/handler_ww_mouse.js +166 -0
- package/src/core/event/ports.js +211 -0
- package/src/core/event/reducers/keydown.reducer.js +97 -0
- package/src/core/event/rules/keydown.rule.arrow.js +63 -0
- package/src/core/event/rules/keydown.rule.backspace.js +208 -0
- package/src/core/event/rules/keydown.rule.delete.js +132 -0
- package/src/core/event/rules/keydown.rule.enter.js +150 -0
- package/src/core/event/rules/keydown.rule.tab.js +35 -0
- package/src/core/event/support/defaultLineManager.js +136 -0
- package/src/core/event/support/selectionState.js +204 -0
- package/src/core/kernel/coreKernel.js +320 -0
- package/src/core/kernel/kernelInjector.js +19 -0
- package/src/core/kernel/store.js +173 -0
- package/src/core/{class → logic/dom}/char.js +42 -45
- package/src/core/logic/dom/format.js +1075 -0
- package/src/core/{class → logic/dom}/html.js +743 -624
- package/src/core/logic/dom/inline.js +1847 -0
- package/src/core/logic/dom/listFormat.js +601 -0
- package/src/core/{class → logic/dom}/nodeTransform.js +92 -72
- package/src/core/{class → logic/dom}/offset.js +254 -317
- package/src/core/logic/dom/selection.js +754 -0
- package/src/core/logic/panel/menu.js +389 -0
- package/src/core/logic/panel/toolbar.js +449 -0
- package/src/core/logic/panel/viewer.js +761 -0
- package/src/core/logic/shell/_commandExecutor.js +380 -0
- package/src/core/logic/shell/commandDispatcher.js +241 -0
- package/src/core/logic/shell/component.js +970 -0
- package/src/core/logic/shell/focusManager.js +110 -0
- package/src/core/{base → logic/shell}/history.js +110 -60
- package/src/core/logic/shell/pluginManager.js +363 -0
- package/src/core/logic/shell/shortcuts.js +130 -0
- package/src/core/logic/shell/ui.js +904 -0
- package/src/core/schema/context.js +66 -0
- package/src/core/schema/frameContext.js +160 -0
- package/src/core/schema/options.js +628 -0
- package/src/core/section/constructor.js +194 -500
- package/src/core/section/documentType.js +297 -222
- package/src/events.js +808 -543
- package/src/helper/clipboard.js +27 -16
- package/src/helper/converter.js +100 -78
- package/src/helper/dom/domCheck.js +56 -30
- package/src/helper/dom/domQuery.js +159 -89
- package/src/helper/dom/domUtils.js +114 -49
- package/src/helper/dom/index.js +5 -1
- package/src/helper/env.js +26 -26
- package/src/helper/index.js +1 -1
- package/src/helper/keyCodeMap.js +25 -28
- package/src/helper/numbers.js +4 -8
- package/src/helper/unicode.js +4 -8
- package/src/hooks/base.js +307 -0
- package/src/hooks/params.js +130 -0
- package/src/interfaces/contracts.js +227 -0
- package/src/interfaces/index.js +7 -0
- package/src/interfaces/plugins.js +239 -0
- package/src/langs/ckb.js +4 -4
- package/src/langs/cs.js +4 -4
- package/src/langs/da.js +4 -4
- package/src/langs/de.js +4 -4
- package/src/langs/en.js +4 -4
- package/src/langs/es.js +4 -4
- package/src/langs/fa.js +4 -4
- package/src/langs/fr.js +4 -4
- package/src/langs/he.js +4 -4
- package/src/langs/hu.js +4 -4
- package/src/langs/it.js +4 -4
- package/src/langs/ja.js +4 -4
- package/src/langs/km.js +4 -4
- package/src/langs/ko.js +4 -4
- package/src/langs/lv.js +4 -4
- package/src/langs/nl.js +4 -4
- package/src/langs/pl.js +4 -4
- package/src/langs/pt_br.js +13 -13
- package/src/langs/ro.js +4 -4
- package/src/langs/ru.js +4 -4
- package/src/langs/se.js +4 -4
- package/src/langs/tr.js +4 -4
- package/src/langs/uk.js +4 -4
- package/src/langs/ur.js +4 -4
- package/src/langs/zh_cn.js +4 -4
- package/src/modules/{Browser.js → contract/Browser.js} +119 -128
- package/src/modules/{ColorPicker.js → contract/ColorPicker.js} +132 -142
- package/src/modules/contract/Controller.js +589 -0
- package/src/modules/{Figure.js → contract/Figure.js} +591 -411
- package/src/modules/{HueSlider.js → contract/HueSlider.js} +125 -86
- package/src/modules/contract/Modal.js +357 -0
- package/src/modules/contract/index.js +9 -0
- package/src/modules/manager/ApiManager.js +197 -0
- package/src/modules/{FileManager.js → manager/FileManager.js} +128 -160
- package/src/modules/manager/index.js +5 -0
- package/src/modules/{ModalAnchorEditor.js → ui/ModalAnchorEditor.js} +108 -138
- package/src/modules/{SelectMenu.js → ui/SelectMenu.js} +119 -120
- package/src/modules/{_DragHandle.js → ui/_DragHandle.js} +1 -1
- package/src/modules/ui/index.js +6 -0
- package/src/plugins/browser/audioGallery.js +23 -26
- package/src/plugins/browser/fileBrowser.js +25 -28
- package/src/plugins/browser/fileGallery.js +20 -23
- package/src/plugins/browser/imageGallery.js +24 -23
- package/src/plugins/browser/videoGallery.js +27 -29
- package/src/plugins/command/blockquote.js +11 -17
- package/src/plugins/command/exportPDF.js +26 -26
- package/src/plugins/command/fileUpload.js +138 -133
- package/src/plugins/command/list_bulleted.js +48 -44
- package/src/plugins/command/list_numbered.js +48 -44
- package/src/plugins/dropdown/align.js +64 -50
- package/src/plugins/dropdown/backgroundColor.js +34 -35
- package/src/plugins/dropdown/{formatBlock.js → blockStyle.js} +43 -37
- package/src/plugins/dropdown/font.js +50 -36
- package/src/plugins/dropdown/fontColor.js +34 -35
- package/src/plugins/dropdown/hr.js +55 -50
- package/src/plugins/dropdown/layout.js +20 -15
- package/src/plugins/dropdown/lineHeight.js +46 -30
- package/src/plugins/dropdown/list.js +32 -33
- package/src/plugins/dropdown/paragraphStyle.js +40 -34
- package/src/plugins/dropdown/table/index.js +915 -0
- package/src/plugins/dropdown/table/render/table.html.js +308 -0
- package/src/plugins/dropdown/table/render/table.menu.js +121 -0
- package/src/plugins/dropdown/table/services/table.cell.js +465 -0
- package/src/plugins/dropdown/table/services/table.clipboard.js +414 -0
- package/src/plugins/dropdown/table/services/table.grid.js +504 -0
- package/src/plugins/dropdown/table/services/table.resize.js +463 -0
- package/src/plugins/dropdown/table/services/table.selection.js +466 -0
- package/src/plugins/dropdown/table/services/table.style.js +844 -0
- package/src/plugins/dropdown/table/shared/table.constants.js +109 -0
- package/src/plugins/dropdown/table/shared/table.utils.js +219 -0
- package/src/plugins/dropdown/template.js +20 -15
- package/src/plugins/dropdown/textStyle.js +28 -22
- package/src/plugins/field/mention.js +54 -49
- package/src/plugins/index.js +5 -5
- package/src/plugins/input/fontSize.js +100 -97
- package/src/plugins/input/pageNavigator.js +13 -10
- package/src/plugins/modal/audio.js +208 -219
- package/src/plugins/modal/drawing.js +99 -104
- package/src/plugins/modal/embed.js +323 -312
- package/src/plugins/modal/image/index.js +942 -0
- package/src/plugins/modal/image/render/image.html.js +150 -0
- package/src/plugins/modal/image/services/image.size.js +198 -0
- package/src/plugins/modal/image/services/image.upload.js +216 -0
- package/src/plugins/modal/image/shared/image.constants.js +20 -0
- package/src/plugins/modal/link.js +74 -54
- package/src/plugins/modal/math.js +126 -119
- package/src/plugins/modal/video/index.js +858 -0
- package/src/plugins/modal/video/render/video.html.js +131 -0
- package/src/plugins/modal/video/services/video.size.js +281 -0
- package/src/plugins/modal/video/services/video.upload.js +92 -0
- package/src/plugins/popup/anchor.js +57 -49
- package/src/suneditor.js +73 -61
- package/src/themes/cobalt.css +155 -0
- package/src/themes/dark.css +143 -120
- package/src/typedef.js +214 -63
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/assets/suneditor-contents.css.d.ts +1 -0
- package/types/assets/suneditor.css.d.ts +1 -0
- package/types/core/config/contextProvider.d.ts +148 -0
- package/types/core/config/eventManager.d.ts +68 -0
- package/types/core/config/instanceCheck.d.ts +33 -0
- package/types/core/config/optionProvider.d.ts +147 -0
- package/types/core/editor.d.ts +27 -586
- package/types/core/event/actions/index.d.ts +50 -0
- package/types/core/event/effects/common.registry.d.ts +56 -0
- package/types/core/event/effects/keydown.registry.d.ts +80 -0
- package/types/core/event/effects/ruleHelpers.d.ts +36 -0
- package/types/core/event/eventOrchestrator.d.ts +191 -0
- package/types/core/event/executor.d.ts +13 -0
- package/types/core/event/handlers/handler_toolbar.d.ts +38 -0
- package/types/core/event/handlers/handler_ww_clipboard.d.ts +36 -0
- package/types/core/event/handlers/handler_ww_dragDrop.d.ts +26 -0
- package/types/core/event/handlers/handler_ww_input.d.ts +38 -0
- package/types/core/event/handlers/handler_ww_key.d.ts +40 -0
- package/types/core/event/handlers/handler_ww_mouse.d.ts +47 -0
- package/types/core/event/ports.d.ts +256 -0
- package/types/core/event/reducers/keydown.reducer.d.ts +84 -0
- package/types/core/event/rules/keydown.rule.arrow.d.ts +19 -0
- package/types/core/event/rules/keydown.rule.backspace.d.ts +18 -0
- package/types/core/event/rules/keydown.rule.delete.d.ts +18 -0
- package/types/core/event/rules/keydown.rule.enter.d.ts +18 -0
- package/types/core/event/rules/keydown.rule.tab.d.ts +18 -0
- package/types/core/event/support/defaultLineManager.d.ts +22 -0
- package/types/core/event/support/selectionState.d.ts +29 -0
- package/types/core/kernel/coreKernel.d.ts +219 -0
- package/types/core/kernel/kernelInjector.d.ts +16 -0
- package/types/core/kernel/store.d.ts +170 -0
- package/types/core/logic/dom/char.d.ts +46 -0
- package/types/core/logic/dom/format.d.ts +234 -0
- package/types/core/logic/dom/html.d.ts +290 -0
- package/types/core/logic/dom/inline.d.ts +93 -0
- package/types/core/logic/dom/listFormat.d.ts +101 -0
- package/types/core/logic/dom/nodeTransform.d.ts +110 -0
- package/types/core/logic/dom/offset.d.ts +335 -0
- package/types/core/logic/dom/selection.d.ts +165 -0
- package/types/core/logic/panel/menu.d.ts +93 -0
- package/types/core/logic/panel/toolbar.d.ts +128 -0
- package/types/core/logic/panel/viewer.d.ts +89 -0
- package/types/core/logic/shell/_commandExecutor.d.ts +18 -0
- package/types/core/logic/shell/commandDispatcher.d.ts +65 -0
- package/types/core/logic/shell/component.d.ts +182 -0
- package/types/core/logic/shell/focusManager.d.ts +31 -0
- package/types/core/{base → logic/shell}/history.d.ts +13 -12
- package/types/core/logic/shell/pluginManager.d.ts +115 -0
- package/types/core/logic/shell/shortcuts.d.ts +131 -0
- package/types/core/logic/shell/ui.d.ts +261 -0
- package/types/core/schema/context.d.ts +104 -0
- package/types/core/schema/frameContext.d.ts +320 -0
- package/types/core/schema/options.d.ts +1241 -0
- package/types/core/section/constructor.d.ts +117 -652
- package/types/core/section/documentType.d.ts +43 -61
- package/types/events.d.ts +796 -65
- package/types/helper/clipboard.d.ts +5 -4
- package/types/helper/converter.d.ts +55 -43
- package/types/helper/dom/domCheck.d.ts +27 -19
- package/types/helper/dom/domQuery.d.ts +76 -57
- package/types/helper/dom/domUtils.d.ts +62 -39
- package/types/helper/dom/index.d.ts +87 -1
- package/types/helper/env.d.ts +16 -13
- package/types/helper/index.d.ts +8 -2
- package/types/helper/keyCodeMap.d.ts +24 -23
- package/types/helper/numbers.d.ts +4 -6
- package/types/helper/unicode.d.ts +4 -3
- package/types/hooks/base.d.ts +239 -0
- package/types/hooks/params.d.ts +65 -0
- package/types/index.d.ts +20 -117
- package/types/interfaces/contracts.d.ts +183 -0
- package/types/interfaces/index.d.ts +3 -0
- package/types/interfaces/plugins.d.ts +168 -0
- package/types/langs/_Lang.d.ts +2 -2
- package/types/langs/index.d.ts +2 -2
- package/types/modules/contract/Browser.d.ts +262 -0
- package/types/modules/contract/ColorPicker.d.ts +99 -0
- package/types/modules/contract/Controller.d.ts +204 -0
- package/types/modules/contract/Figure.d.ts +529 -0
- package/types/modules/{HueSlider.d.ts → contract/HueSlider.d.ts} +39 -28
- package/types/modules/contract/Modal.d.ts +62 -0
- package/types/modules/contract/index.d.ts +7 -0
- package/types/modules/manager/ApiManager.d.ts +106 -0
- package/types/modules/manager/FileManager.d.ts +124 -0
- package/types/modules/manager/index.d.ts +3 -0
- package/types/modules/ui/ModalAnchorEditor.d.ts +152 -0
- package/types/modules/ui/SelectMenu.d.ts +107 -0
- package/types/modules/{_DragHandle.d.ts → ui/_DragHandle.d.ts} +1 -0
- package/types/modules/ui/index.d.ts +4 -0
- package/types/plugins/browser/audioGallery.d.ts +33 -41
- package/types/plugins/browser/fileBrowser.d.ts +42 -50
- package/types/plugins/browser/fileGallery.d.ts +33 -41
- package/types/plugins/browser/imageGallery.d.ts +30 -37
- package/types/plugins/browser/videoGallery.d.ts +33 -41
- package/types/plugins/command/blockquote.d.ts +4 -21
- package/types/plugins/command/exportPDF.d.ts +23 -33
- package/types/plugins/command/fileUpload.d.ts +80 -100
- package/types/plugins/command/list_bulleted.d.ts +9 -35
- package/types/plugins/command/list_numbered.d.ts +9 -35
- package/types/plugins/dropdown/align.d.ts +23 -46
- package/types/plugins/dropdown/backgroundColor.d.ts +35 -53
- package/types/plugins/dropdown/blockStyle.d.ts +45 -0
- package/types/plugins/dropdown/font.d.ts +18 -41
- package/types/plugins/dropdown/fontColor.d.ts +35 -53
- package/types/plugins/dropdown/hr.d.ts +26 -52
- package/types/plugins/dropdown/layout.d.ts +19 -25
- package/types/plugins/dropdown/lineHeight.d.ts +21 -39
- package/types/plugins/dropdown/list.d.ts +6 -34
- package/types/plugins/dropdown/paragraphStyle.d.ts +34 -45
- package/types/plugins/dropdown/table/index.d.ts +158 -0
- package/types/plugins/dropdown/table/render/table.html.d.ts +71 -0
- package/types/plugins/dropdown/table/render/table.menu.d.ts +59 -0
- package/types/plugins/dropdown/table/services/table.cell.d.ts +76 -0
- package/types/plugins/dropdown/table/services/table.clipboard.d.ts +26 -0
- package/types/plugins/dropdown/table/services/table.grid.d.ts +77 -0
- package/types/plugins/dropdown/table/services/table.resize.d.ts +72 -0
- package/types/plugins/dropdown/table/services/table.selection.d.ts +59 -0
- package/types/plugins/dropdown/table/services/table.style.d.ts +162 -0
- package/types/plugins/dropdown/table/shared/table.constants.d.ts +134 -0
- package/types/plugins/dropdown/table/shared/table.utils.d.ts +91 -0
- package/types/plugins/dropdown/template.d.ts +19 -25
- package/types/plugins/dropdown/textStyle.d.ts +23 -30
- package/types/plugins/field/mention.d.ts +66 -72
- package/types/plugins/index.d.ts +41 -40
- package/types/plugins/input/fontSize.d.ts +57 -96
- package/types/plugins/input/pageNavigator.d.ts +5 -8
- package/types/plugins/modal/audio.d.ts +60 -153
- package/types/plugins/modal/drawing.d.ts +16 -118
- package/types/plugins/modal/embed.d.ts +46 -166
- package/types/plugins/modal/image/index.d.ts +281 -0
- package/types/plugins/modal/image/render/image.html.d.ts +45 -0
- package/types/plugins/modal/image/services/image.size.d.ts +55 -0
- package/types/plugins/modal/image/services/image.upload.d.ts +24 -0
- package/types/plugins/modal/image/shared/image.constants.d.ts +17 -0
- package/types/plugins/modal/link.d.ts +46 -66
- package/types/plugins/modal/math.d.ts +17 -86
- package/types/plugins/modal/{video.d.ts → video/index.d.ts} +89 -221
- package/types/plugins/modal/video/render/video.html.d.ts +37 -0
- package/types/plugins/modal/video/services/video.size.d.ts +74 -0
- package/types/plugins/modal/video/services/video.upload.d.ts +19 -0
- package/types/plugins/popup/anchor.d.ts +8 -38
- package/types/suneditor.d.ts +55 -24
- package/types/typedef.d.ts +344 -228
- package/CONTRIBUTING.md +0 -186
- package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +0 -194
- package/src/core/base/eventManager.js +0 -1523
- package/src/core/class/component.js +0 -856
- package/src/core/class/format.js +0 -3433
- package/src/core/class/menu.js +0 -346
- package/src/core/class/selection.js +0 -610
- package/src/core/class/shortcuts.js +0 -98
- package/src/core/class/toolbar.js +0 -431
- package/src/core/class/ui.js +0 -424
- package/src/core/class/viewer.js +0 -750
- package/src/core/section/actives.js +0 -266
- package/src/core/section/context.js +0 -102
- package/src/editorInjector/_classes.js +0 -36
- package/src/editorInjector/_core.js +0 -87
- package/src/editorInjector/index.js +0 -73
- package/src/modules/ApiManager.js +0 -191
- package/src/modules/Controller.js +0 -474
- package/src/modules/Modal.js +0 -346
- package/src/modules/index.js +0 -14
- package/src/plugins/dropdown/table.js +0 -4034
- package/src/plugins/modal/image.js +0 -1376
- package/src/plugins/modal/video.js +0 -1226
- package/types/core/base/eventHandlers/handler_toolbar.d.ts +0 -41
- package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +0 -40
- package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +0 -35
- package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +0 -45
- package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +0 -39
- package/types/core/base/eventManager.d.ts +0 -401
- package/types/core/class/char.d.ts +0 -61
- package/types/core/class/component.d.ts +0 -213
- package/types/core/class/format.d.ts +0 -623
- package/types/core/class/html.d.ts +0 -430
- package/types/core/class/menu.d.ts +0 -126
- package/types/core/class/nodeTransform.d.ts +0 -93
- package/types/core/class/offset.d.ts +0 -522
- package/types/core/class/selection.d.ts +0 -188
- package/types/core/class/shortcuts.d.ts +0 -142
- package/types/core/class/toolbar.d.ts +0 -189
- package/types/core/class/ui.d.ts +0 -164
- package/types/core/class/viewer.d.ts +0 -140
- package/types/core/section/actives.d.ts +0 -46
- package/types/core/section/context.d.ts +0 -45
- package/types/editorInjector/_classes.d.ts +0 -41
- package/types/editorInjector/_core.d.ts +0 -87
- package/types/editorInjector/index.d.ts +0 -69
- package/types/modules/ApiManager.d.ts +0 -125
- package/types/modules/Browser.d.ts +0 -326
- package/types/modules/ColorPicker.d.ts +0 -135
- package/types/modules/Controller.d.ts +0 -251
- package/types/modules/Figure.d.ts +0 -517
- package/types/modules/FileManager.d.ts +0 -202
- package/types/modules/Modal.d.ts +0 -111
- package/types/modules/ModalAnchorEditor.d.ts +0 -236
- package/types/modules/SelectMenu.d.ts +0 -194
- package/types/modules/index.d.ts +0 -26
- package/types/plugins/dropdown/formatBlock.d.ts +0 -55
- package/types/plugins/dropdown/table.d.ts +0 -627
- package/types/plugins/modal/image.d.ts +0 -451
- /package/{LICENSE → LICENSE.txt} +0 -0
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Modal, Figure } from '../../modules';
|
|
1
|
+
import { PluginModal } from '../../interfaces';
|
|
2
|
+
import { Modal, Figure } from '../../modules/contract';
|
|
3
3
|
import { dom, numbers, env, keyCodeMap } from '../../helper';
|
|
4
|
-
const { NO_EVENT } = env;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {import('../../events').ProcessInfo} ProcessInfo_embed
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {import('../../modules/Figure').FigureControls} FigureControls_embed
|
|
12
|
-
*/
|
|
4
|
+
const { _w, NO_EVENT } = env;
|
|
13
5
|
|
|
14
6
|
/**
|
|
15
7
|
* @typedef {Object} EmbedPluginOptions
|
|
@@ -22,7 +14,7 @@ const { NO_EVENT } = env;
|
|
|
22
14
|
* @property {Object<string, string>} [uploadHeaders] - Headers to include in file upload requests.
|
|
23
15
|
* @property {number} [uploadSizeLimit] - The total file upload size limit in bytes.
|
|
24
16
|
* @property {number} [uploadSingleSizeLimit] - The single file upload size limit in bytes.
|
|
25
|
-
* @property {Object<string, string>} [iframeTagAttributes] - Additional attributes to set on the
|
|
17
|
+
* @property {Object<string, string>} [iframeTagAttributes] - Additional attributes to set on the `IFRAME` tag.
|
|
26
18
|
* @property {string} [query_youtube] - YouTube query parameter.
|
|
27
19
|
* @property {string} [query_vimeo] - Vimeo query parameter.
|
|
28
20
|
* @property {Array<RegExp>} [urlPatterns] - Additional URL patterns for embed.
|
|
@@ -45,43 +37,104 @@ const { NO_EVENT } = env;
|
|
|
45
37
|
* },
|
|
46
38
|
* // Additional services...
|
|
47
39
|
* }
|
|
48
|
-
* @property {
|
|
40
|
+
* @property {SunEditor.Module.Figure.Controls} [controls] - Figure controls.
|
|
41
|
+
* @property {SunEditor.ComponentInsertType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: `options.get('componentInsertBehavior')`]
|
|
42
|
+
* - `auto`: Move cursor to the next line if possible, otherwise select the component.
|
|
43
|
+
* - `select`: Always select the inserted component.
|
|
44
|
+
* - `line`: Move cursor to the next line if possible, or create a new line and move there.
|
|
45
|
+
* - `none`: Do nothing.
|
|
49
46
|
*/
|
|
50
47
|
|
|
51
48
|
/**
|
|
52
49
|
* @class
|
|
53
50
|
* @description Embed modal plugin.
|
|
54
|
-
* - This plugin provides a modal interface for embedding external content (e.g., videos,
|
|
51
|
+
* - This plugin provides a modal interface for embedding external content (e.g., videos, `IFRAME` elements) into the editor.
|
|
55
52
|
*/
|
|
56
|
-
class Embed extends
|
|
53
|
+
class Embed extends PluginModal {
|
|
57
54
|
static key = 'embed';
|
|
58
|
-
static type = 'modal';
|
|
59
55
|
static className = '';
|
|
56
|
+
|
|
60
57
|
/**
|
|
61
|
-
* @this {Embed}
|
|
62
58
|
* @param {HTMLElement} node - The node to check.
|
|
63
59
|
* @returns {HTMLElement|null} Returns a node if the node is a valid component.
|
|
64
60
|
*/
|
|
65
61
|
static component(node) {
|
|
62
|
+
const children = node.children;
|
|
66
63
|
let src = '';
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
let target = null;
|
|
65
|
+
|
|
66
|
+
if (dom.check.isIFrame(node)) {
|
|
67
|
+
target = node;
|
|
68
|
+
src = node.src;
|
|
69
|
+
}
|
|
70
|
+
if (!src && /^DIV$/i.test(node?.nodeName) && dom.check.isIFrame(children[0])) {
|
|
71
|
+
target = children[0];
|
|
72
|
+
src = target.src;
|
|
73
|
+
}
|
|
74
|
+
if (!src && dom.utils.hasClass(node, 'se-embed-container')) {
|
|
75
|
+
/** @type {*} */
|
|
76
|
+
const srcNode = dom.query.getChildNode(node, (current) => current.src || current.href);
|
|
77
|
+
target = srcNode;
|
|
78
|
+
src = target?.src || target?.href;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (/^BLOCKQUOTE$/i.test(node?.nodeName)) {
|
|
82
|
+
const link = node.querySelector('a');
|
|
83
|
+
if (link && link.href) {
|
|
84
|
+
target = node;
|
|
85
|
+
src = link.href;
|
|
86
|
+
return this.#checkContentType(src) ? target : null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
69
89
|
|
|
70
90
|
if (src) {
|
|
71
|
-
return this
|
|
91
|
+
return this.#checkContentType(src) ? target : null;
|
|
72
92
|
}
|
|
73
|
-
|
|
93
|
+
|
|
94
|
+
return target;
|
|
74
95
|
}
|
|
75
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @description Checks if the given URL matches any of the defined URL patterns.
|
|
99
|
+
* @param {string} url - The URL to check.
|
|
100
|
+
* @returns {boolean} `true` if the URL matches a known pattern; otherwise, `false`.
|
|
101
|
+
*/
|
|
102
|
+
static #checkContentType(url) {
|
|
103
|
+
url = url?.toLowerCase() || '';
|
|
104
|
+
if (this.#urlPatterns.some((pattern) => pattern.test(url))) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** @type {Array<RegExp>} */
|
|
112
|
+
static #urlPatterns = null;
|
|
113
|
+
|
|
114
|
+
#defaultSizeX;
|
|
115
|
+
#defaultSizeY;
|
|
116
|
+
#origin_w;
|
|
117
|
+
#origin_h;
|
|
118
|
+
#resizing;
|
|
119
|
+
#onlyPercentage;
|
|
120
|
+
#nonResizing;
|
|
121
|
+
|
|
122
|
+
#linkValue = '';
|
|
123
|
+
#align = 'none';
|
|
124
|
+
#element = null;
|
|
125
|
+
#cover = null;
|
|
126
|
+
#container = null;
|
|
127
|
+
#ratio = { w: 0, h: 0 };
|
|
128
|
+
|
|
76
129
|
/**
|
|
77
130
|
* @constructor
|
|
78
|
-
* @param {
|
|
131
|
+
* @param {SunEditor.Kernel} editor - The core kernel
|
|
79
132
|
* @param {EmbedPluginOptions} pluginOptions
|
|
80
133
|
*/
|
|
81
134
|
constructor(editor, pluginOptions) {
|
|
82
|
-
// plugin
|
|
135
|
+
// plugin basic properties
|
|
83
136
|
super(editor);
|
|
84
|
-
this.title = this
|
|
137
|
+
this.title = this.$.lang.embed;
|
|
85
138
|
this.icon = 'embed';
|
|
86
139
|
|
|
87
140
|
// define plugin options
|
|
@@ -97,57 +150,54 @@ class Embed extends EditorInjector {
|
|
|
97
150
|
uploadSingleSizeLimit: numbers.get(pluginOptions.uploadSingleSizeLimit, 0),
|
|
98
151
|
iframeTagAttributes: pluginOptions.iframeTagAttributes || null,
|
|
99
152
|
query_youtube: pluginOptions.query_youtube || '',
|
|
100
|
-
query_vimeo: pluginOptions.query_vimeo || ''
|
|
153
|
+
query_vimeo: pluginOptions.query_vimeo || '',
|
|
154
|
+
insertBehavior: pluginOptions.insertBehavior,
|
|
101
155
|
};
|
|
102
156
|
|
|
103
157
|
// create HTML
|
|
104
158
|
const sizeUnit = this.pluginOptions.percentageOnlySize ? '%' : 'px';
|
|
105
|
-
const modalEl = CreateHTML_modal(
|
|
106
|
-
const figureControls = pluginOptions.controls || !this.pluginOptions.canResize ? [['align', 'edit', 'copy', 'remove']] : [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']];
|
|
159
|
+
const modalEl = CreateHTML_modal(this.$, this.pluginOptions);
|
|
160
|
+
const figureControls = pluginOptions.controls || (!this.pluginOptions.canResize ? [['align', 'edit', 'copy', 'remove']] : [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']]);
|
|
107
161
|
|
|
108
162
|
// show align
|
|
109
163
|
if (!figureControls.some((subArray) => subArray.includes('align'))) modalEl.figureAlignBtn.style.display = 'none';
|
|
110
164
|
|
|
111
165
|
// modules
|
|
112
|
-
this.modal = new Modal(this, modalEl.html);
|
|
113
|
-
this.figure = new Figure(this, figureControls, { sizeUnit: sizeUnit });
|
|
166
|
+
this.modal = new Modal(this, this.$, modalEl.html);
|
|
167
|
+
this.figure = new Figure(this, this.$, figureControls, { sizeUnit: sizeUnit });
|
|
114
168
|
|
|
115
169
|
// members
|
|
116
170
|
this.fileModalWrapper = modalEl.fileModalWrapper;
|
|
117
171
|
this.embedInput = modalEl.embedInput;
|
|
118
172
|
this.focusElement = this.embedInput;
|
|
119
173
|
this.previewSrc = modalEl.previewSrc;
|
|
120
|
-
this._linkValue = '';
|
|
121
|
-
this._align = 'none';
|
|
122
|
-
this._defaultSizeX = this.pluginOptions.defaultWidth;
|
|
123
|
-
this._defaultSizeY = this.pluginOptions.defaultHeight;
|
|
124
174
|
this.sizeUnit = sizeUnit;
|
|
125
175
|
this.proportion = null;
|
|
126
176
|
this.inputX = null;
|
|
127
177
|
this.inputY = null;
|
|
128
|
-
|
|
129
|
-
this
|
|
130
|
-
this
|
|
131
|
-
this
|
|
132
|
-
this
|
|
133
|
-
this
|
|
134
|
-
this
|
|
135
|
-
this
|
|
136
|
-
|
|
178
|
+
|
|
179
|
+
this.#defaultSizeX = this.pluginOptions.defaultWidth;
|
|
180
|
+
this.#defaultSizeY = this.pluginOptions.defaultHeight;
|
|
181
|
+
this.#origin_w = this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
|
|
182
|
+
this.#origin_h = this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
|
|
183
|
+
this.#resizing = this.pluginOptions.canResize;
|
|
184
|
+
this.#onlyPercentage = this.pluginOptions.percentageOnlySize;
|
|
185
|
+
this.#nonResizing = !this.#resizing || !this.pluginOptions.showHeightInput || this.#onlyPercentage;
|
|
186
|
+
|
|
137
187
|
this.query = {
|
|
138
188
|
facebook: {
|
|
139
189
|
pattern: /(?:https?:\/\/)?(?:www\.)?(?:facebook\.com)\/(.+)/i,
|
|
140
190
|
action: (url) => {
|
|
141
191
|
return `https://www.facebook.com/plugins/post.php?href=${encodeURIComponent(url)}&show_text=true&width=500`;
|
|
142
192
|
},
|
|
143
|
-
tag: 'iframe'
|
|
193
|
+
tag: 'iframe',
|
|
144
194
|
},
|
|
145
195
|
twitter: {
|
|
146
|
-
pattern:
|
|
196
|
+
pattern: /^(?:https?:\/\/)?(?:(?:www\.)?(?:twitter\.com|x\.com)\/(?:[^/?#]+\/)?status\/\d+(?:[/?#]|$)|platform\.twitter\.com\/embed\/Tweet\.html(?:[?#].*)?$)/i,
|
|
147
197
|
action: (url) => {
|
|
148
198
|
return `https://platform.twitter.com/embed/Tweet.html?url=${encodeURIComponent(url)}`;
|
|
149
199
|
},
|
|
150
|
-
tag: 'iframe'
|
|
200
|
+
tag: 'iframe',
|
|
151
201
|
},
|
|
152
202
|
instagram: {
|
|
153
203
|
pattern: /(?:https?:\/\/)?(?:www\.)?(?:instagram\.com)\/p\/(.+)/i,
|
|
@@ -155,14 +205,14 @@ class Embed extends EditorInjector {
|
|
|
155
205
|
const postId = url.match(this.query.instagram.pattern)[1];
|
|
156
206
|
return `https://www.instagram.com/p/${postId}/embed`;
|
|
157
207
|
},
|
|
158
|
-
tag: 'iframe'
|
|
208
|
+
tag: 'iframe',
|
|
159
209
|
},
|
|
160
210
|
linkedin: {
|
|
161
211
|
pattern: /(?:https?:\/\/)?(?:www\.)?(?:linkedin\.com)\/(.+)\/(.+)/i,
|
|
162
212
|
action: (url) => {
|
|
163
213
|
return `https://www.linkedin.com/embed/feed/update/${encodeURIComponent(url.split('/').pop())}`;
|
|
164
214
|
},
|
|
165
|
-
tag: 'iframe'
|
|
215
|
+
tag: 'iframe',
|
|
166
216
|
},
|
|
167
217
|
pinterest: {
|
|
168
218
|
pattern: /(?:https?:\/\/)?(?:www\.)?(?:pinterest\.com)\/pin\/(.+)/i,
|
|
@@ -170,7 +220,7 @@ class Embed extends EditorInjector {
|
|
|
170
220
|
const pinId = url.match(this.query.pinterest.pattern)[1];
|
|
171
221
|
return `https://assets.pinterest.com/ext/embed.html?id=${pinId}`;
|
|
172
222
|
},
|
|
173
|
-
tag: 'iframe'
|
|
223
|
+
tag: 'iframe',
|
|
174
224
|
},
|
|
175
225
|
spotify: {
|
|
176
226
|
pattern: /(?:https?:\/\/)?(?:open\.)?(?:spotify\.com)\/(track|album|playlist|show|episode)\/(.+)/i,
|
|
@@ -180,7 +230,7 @@ class Embed extends EditorInjector {
|
|
|
180
230
|
const id = match[2];
|
|
181
231
|
return `https://open.spotify.com/embed/${type}/${id}`;
|
|
182
232
|
},
|
|
183
|
-
tag: 'iframe'
|
|
233
|
+
tag: 'iframe',
|
|
184
234
|
},
|
|
185
235
|
codepen: {
|
|
186
236
|
pattern: /(?:https?:\/\/)?(?:www\.)?(?:codepen\.io)\/(.+)\/pen\/(.+)/i,
|
|
@@ -188,244 +238,167 @@ class Embed extends EditorInjector {
|
|
|
188
238
|
const [, user, penId] = url.match(this.query.codepen.pattern);
|
|
189
239
|
return `https://codepen.io/${user}/embed/${penId}`;
|
|
190
240
|
},
|
|
191
|
-
tag: 'iframe'
|
|
241
|
+
tag: 'iframe',
|
|
192
242
|
},
|
|
193
|
-
...pluginOptions.embedQuery
|
|
243
|
+
...pluginOptions.embedQuery,
|
|
194
244
|
};
|
|
195
245
|
|
|
196
246
|
const urlPatterns = [];
|
|
197
247
|
for (const key in this.query) {
|
|
198
248
|
urlPatterns.push(this.query[key].pattern);
|
|
199
249
|
}
|
|
200
|
-
|
|
250
|
+
Embed.#urlPatterns = urlPatterns.concat(pluginOptions.urlPatterns || []);
|
|
201
251
|
|
|
202
252
|
// init
|
|
203
|
-
this
|
|
253
|
+
this.$.eventManager.addEvent(this.embedInput, 'input', this.#OnLinkPreview.bind(this));
|
|
204
254
|
|
|
205
|
-
if (this
|
|
255
|
+
if (this.#resizing) {
|
|
206
256
|
this.proportion = modalEl.proportion;
|
|
207
257
|
this.inputX = modalEl.inputX;
|
|
208
258
|
this.inputY = modalEl.inputY;
|
|
209
259
|
this.inputX.value = this.pluginOptions.defaultWidth;
|
|
210
260
|
this.inputY.value = this.pluginOptions.defaultHeight;
|
|
211
261
|
|
|
212
|
-
this
|
|
213
|
-
this
|
|
214
|
-
this
|
|
262
|
+
this.$.eventManager.addEvent(this.inputX, 'keyup', this.#OnInputSize.bind(this, 'x'));
|
|
263
|
+
this.$.eventManager.addEvent(this.inputY, 'keyup', this.#OnInputSize.bind(this, 'y'));
|
|
264
|
+
this.$.eventManager.addEvent(modalEl.revertBtn, 'click', this.#OnClickRevert.bind(this));
|
|
215
265
|
}
|
|
216
266
|
}
|
|
217
267
|
|
|
218
268
|
/**
|
|
219
|
-
* @
|
|
220
|
-
* @
|
|
269
|
+
* @override
|
|
270
|
+
* @type {PluginModal['open']}
|
|
221
271
|
*/
|
|
222
272
|
open() {
|
|
223
273
|
this.modal.open();
|
|
224
274
|
}
|
|
225
275
|
|
|
226
276
|
/**
|
|
227
|
-
* @
|
|
228
|
-
* @
|
|
277
|
+
* @hook Editor.Core
|
|
278
|
+
* @type {SunEditor.Hook.Core.RetainFormat}
|
|
229
279
|
*/
|
|
230
|
-
|
|
231
|
-
|
|
280
|
+
retainFormat() {
|
|
281
|
+
return {
|
|
282
|
+
query: 'iframe',
|
|
283
|
+
/** @param {HTMLIFrameElement} element */
|
|
284
|
+
method: async (element) => {
|
|
285
|
+
if (!Embed.#checkContentType(element.src)) return;
|
|
286
|
+
|
|
287
|
+
const figureInfo = Figure.GetContainer(element);
|
|
288
|
+
if (figureInfo && figureInfo.container && figureInfo.cover) return;
|
|
289
|
+
|
|
290
|
+
this.#ready(element, true);
|
|
291
|
+
const line = this.$.format.getLine(element);
|
|
292
|
+
if (line) this.#align = line.style.textAlign || line.style.float;
|
|
293
|
+
|
|
294
|
+
this.#fixTagStructure(element);
|
|
295
|
+
},
|
|
296
|
+
};
|
|
232
297
|
}
|
|
233
298
|
|
|
234
299
|
/**
|
|
235
|
-
* @
|
|
236
|
-
* @
|
|
237
|
-
* @param {boolean} isUpdate "Indicates whether the modal is for editing an existing component (true) or registering a new one (false)."
|
|
300
|
+
* @hook Modules.Modal
|
|
301
|
+
* @type {SunEditor.Hook.Modal.On}
|
|
238
302
|
*/
|
|
239
|
-
|
|
240
|
-
if (!isUpdate && this
|
|
241
|
-
this.inputX.value = this
|
|
242
|
-
this.inputY.value = this
|
|
303
|
+
modalOn(isUpdate) {
|
|
304
|
+
if (!isUpdate && this.#resizing) {
|
|
305
|
+
this.inputX.value = this.#origin_w = this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
|
|
306
|
+
this.inputY.value = this.#origin_h = this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
|
|
243
307
|
this.proportion.disabled = true;
|
|
308
|
+
} else if (isUpdate) {
|
|
309
|
+
this.#linkValue = this.previewSrc.textContent = this.embedInput.value = this.#cover.getAttribute('data-se-origin') || '';
|
|
244
310
|
}
|
|
245
311
|
}
|
|
246
312
|
|
|
247
313
|
/**
|
|
248
|
-
* @
|
|
249
|
-
* @
|
|
250
|
-
* @returns {Promise<boolean>} Success / failure
|
|
314
|
+
* @hook Modules.Modal
|
|
315
|
+
* @type {SunEditor.Hook.Modal.Action}
|
|
251
316
|
*/
|
|
252
317
|
async modalAction() {
|
|
253
|
-
this
|
|
318
|
+
this.#align = /** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_embed_radio"]:checked')).value;
|
|
254
319
|
|
|
255
320
|
let result = false;
|
|
256
|
-
if (this.
|
|
257
|
-
result = await this.submitSRC(this
|
|
321
|
+
if (this.#linkValue.length > 0) {
|
|
322
|
+
result = await this.submitSRC(this.#linkValue);
|
|
258
323
|
}
|
|
259
324
|
|
|
260
|
-
if (result)
|
|
325
|
+
if (result) _w.setTimeout(this.$.component.select.bind(this.$.component, this.#element, Embed.key), 0);
|
|
261
326
|
|
|
262
327
|
return result;
|
|
263
328
|
}
|
|
264
329
|
|
|
265
330
|
/**
|
|
266
|
-
* @
|
|
267
|
-
* @
|
|
268
|
-
* - It ensures that the structure and attributes of the element are maintained and secure.
|
|
269
|
-
* - The method checks if the element is already wrapped in a valid container and updates its attributes if necessary.
|
|
270
|
-
* - If the element isn't properly contained, a new container is created to retain the format.
|
|
271
|
-
* @returns {{query: string, method: (element: HTMLIFrameElement) => void}} The format retention object containing the query and method to process the element.
|
|
272
|
-
* - query: The selector query to identify the relevant elements (in this case, 'audio').
|
|
273
|
-
* - method:The function to execute on the element to validate and preserve its format.
|
|
274
|
-
* - The function takes the element as an argument, checks if it is contained correctly, and applies necessary adjustments.
|
|
275
|
-
*/
|
|
276
|
-
retainFormat() {
|
|
277
|
-
return {
|
|
278
|
-
query: 'iframe',
|
|
279
|
-
method: async (element) => {
|
|
280
|
-
if (!this.checkContentType(element.src)) return;
|
|
281
|
-
|
|
282
|
-
const figureInfo = Figure.GetContainer(element);
|
|
283
|
-
if (figureInfo && figureInfo.container && figureInfo.cover) return;
|
|
284
|
-
|
|
285
|
-
this._ready(element);
|
|
286
|
-
const line = this.format.getLine(element);
|
|
287
|
-
if (line) this._align = line.style.textAlign || line.style.float;
|
|
288
|
-
|
|
289
|
-
this._update(element);
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @editorMethod Modules.Modal
|
|
296
|
-
* @description This function is called before the modal window is opened, but before it is closed.
|
|
331
|
+
* @hook Modules.Modal
|
|
332
|
+
* @type {SunEditor.Hook.Modal.Init}
|
|
297
333
|
*/
|
|
298
|
-
|
|
334
|
+
modalInit() {
|
|
299
335
|
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
300
|
-
this
|
|
336
|
+
this.#linkValue = this.previewSrc.textContent = this.embedInput.value = '';
|
|
301
337
|
|
|
302
338
|
/** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]')).checked = true;
|
|
303
|
-
this
|
|
304
|
-
this
|
|
339
|
+
this.#ratio = { w: 0, h: 0 };
|
|
340
|
+
this.#nonResizing = false;
|
|
305
341
|
|
|
306
|
-
if (this
|
|
307
|
-
this.inputX.value = this.pluginOptions.defaultWidth === this
|
|
308
|
-
this.inputY.value = this.pluginOptions.defaultHeight === this
|
|
342
|
+
if (this.#resizing) {
|
|
343
|
+
this.inputX.value = this.pluginOptions.defaultWidth === this.#defaultSizeX ? '' : this.pluginOptions.defaultWidth;
|
|
344
|
+
this.inputY.value = this.pluginOptions.defaultHeight === this.#defaultSizeY ? '' : this.pluginOptions.defaultHeight;
|
|
309
345
|
this.proportion.checked = false;
|
|
310
346
|
this.proportion.disabled = true;
|
|
311
347
|
}
|
|
312
348
|
}
|
|
313
349
|
|
|
314
350
|
/**
|
|
315
|
-
* @
|
|
316
|
-
* @
|
|
317
|
-
* @param {HTMLElement} target Target component element
|
|
351
|
+
* @hook Editor.Component
|
|
352
|
+
* @type {SunEditor.Hook.Component.Select}
|
|
318
353
|
*/
|
|
319
|
-
|
|
320
|
-
this
|
|
354
|
+
componentSelect(target) {
|
|
355
|
+
this.#ready(target);
|
|
321
356
|
}
|
|
322
357
|
|
|
323
358
|
/**
|
|
324
|
-
* @
|
|
325
|
-
* @
|
|
326
|
-
* - Ensures that the controller is properly positioned and initialized.
|
|
327
|
-
* - Prevents duplicate event handling if the component is already selected.
|
|
328
|
-
* @param {HTMLElement} target - The selected element.
|
|
359
|
+
* @hook Editor.Component
|
|
360
|
+
* @type {SunEditor.Hook.Component.Edit}
|
|
329
361
|
*/
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const figureInfo = this.figure.open(target, { nonResizing: this._nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, __fileManagerInfo: false });
|
|
333
|
-
|
|
334
|
-
this._element = target;
|
|
335
|
-
this._cover = figureInfo.cover;
|
|
336
|
-
this._container = figureInfo.container;
|
|
337
|
-
this._caption = figureInfo.caption;
|
|
338
|
-
this._align = figureInfo.align;
|
|
339
|
-
target.style.float = '';
|
|
340
|
-
|
|
341
|
-
this._origin_w = String(figureInfo.originWidth || figureInfo.w || '');
|
|
342
|
-
this._origin_h = String(figureInfo.originHeight || figureInfo.h || '');
|
|
343
|
-
|
|
344
|
-
/** @type {HTMLInputElement} */
|
|
345
|
-
const activeAlign = this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="' + this._align + '"]') || this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]');
|
|
346
|
-
activeAlign.checked = true;
|
|
347
|
-
|
|
348
|
-
if (!this._resizing) return;
|
|
349
|
-
|
|
350
|
-
const percentageRotation = this._onlyPercentage && this.figure.isVertical;
|
|
351
|
-
let w = percentageRotation ? '' : figureInfo.width;
|
|
352
|
-
if (this._onlyPercentage) {
|
|
353
|
-
w = numbers.get(w, 2);
|
|
354
|
-
if (w > 100) w = 100;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
this.inputX.value = String(w === 'auto' ? '' : w);
|
|
358
|
-
|
|
359
|
-
if (!this._onlyPercentage) {
|
|
360
|
-
const h = percentageRotation ? '' : figureInfo.height;
|
|
361
|
-
this.inputY.value = String(h === 'auto' ? '' : h);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
this.proportion.checked = true;
|
|
365
|
-
this.inputX.disabled = percentageRotation ? true : false;
|
|
366
|
-
this.inputY.disabled = percentageRotation ? true : false;
|
|
367
|
-
this.proportion.disabled = percentageRotation ? true : false;
|
|
368
|
-
|
|
369
|
-
this._ratio = this.proportion.checked
|
|
370
|
-
? figureInfo.ratio
|
|
371
|
-
: {
|
|
372
|
-
w: 1,
|
|
373
|
-
h: 1
|
|
374
|
-
};
|
|
362
|
+
componentEdit() {
|
|
363
|
+
this.modal.open();
|
|
375
364
|
}
|
|
376
365
|
|
|
377
366
|
/**
|
|
378
|
-
* @
|
|
379
|
-
* @
|
|
380
|
-
* @param {HTMLElement} target Target element
|
|
381
|
-
* @returns {Promise<void>}
|
|
367
|
+
* @hook Editor.Component
|
|
368
|
+
* @type {SunEditor.Hook.Component.Destroy}
|
|
382
369
|
*/
|
|
383
|
-
async
|
|
384
|
-
const targetEl = target || this
|
|
370
|
+
async componentDestroy(target) {
|
|
371
|
+
const targetEl = target || this.#element;
|
|
385
372
|
const container = dom.query.getParentElement(targetEl, Figure.is) || targetEl;
|
|
386
373
|
const focusEl = container.previousElementSibling || container.nextElementSibling;
|
|
387
374
|
const emptyDiv = container.parentNode;
|
|
388
375
|
|
|
389
|
-
const message = await this.triggerEvent('onEmbedDeleteBefore', { element: targetEl, container, align: this
|
|
376
|
+
const message = await this.$.eventManager.triggerEvent('onEmbedDeleteBefore', { element: targetEl, container, align: this.#align, url: this.#linkValue });
|
|
390
377
|
if (message === false) return;
|
|
391
378
|
|
|
392
379
|
dom.utils.removeItem(container);
|
|
393
|
-
this.
|
|
380
|
+
this.modalInit();
|
|
394
381
|
|
|
395
|
-
if (emptyDiv !== this
|
|
396
|
-
this
|
|
382
|
+
if (emptyDiv !== this.$.frameContext.get('wysiwyg')) {
|
|
383
|
+
this.$.nodeTransform.removeAllParents(
|
|
397
384
|
emptyDiv,
|
|
398
385
|
function (current) {
|
|
399
386
|
return current.childNodes.length === 0;
|
|
400
387
|
},
|
|
401
|
-
null
|
|
388
|
+
null,
|
|
402
389
|
);
|
|
403
390
|
}
|
|
404
391
|
|
|
405
392
|
// focus
|
|
406
|
-
this.
|
|
407
|
-
this
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* @description Checks if the given URL matches any of the defined URL patterns.
|
|
412
|
-
* @param {string} url - The URL to check.
|
|
413
|
-
* @returns {boolean} True if the URL matches a known pattern; otherwise, false.
|
|
414
|
-
*/
|
|
415
|
-
checkContentType(url) {
|
|
416
|
-
url = url?.toLowerCase() || '';
|
|
417
|
-
if (this.urlPatterns.some((pattern) => pattern.test(url))) {
|
|
418
|
-
return true;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
return false;
|
|
393
|
+
this.$.focusManager.focusEdge(focusEl);
|
|
394
|
+
this.$.history.push(false);
|
|
422
395
|
}
|
|
423
396
|
|
|
424
397
|
/**
|
|
425
398
|
* @description Finds and processes the URL for embedding by matching it against known service patterns.
|
|
426
399
|
* @param {string} url - The original URL.
|
|
427
|
-
* @returns {{origin: string, url: string, tag: string}|null} An object containing the original URL, the processed URL, and the tag type (e.g.,
|
|
428
|
-
* or null if no matching pattern is found.
|
|
400
|
+
* @returns {{origin: string, url: string, tag: string}|null} An object containing the original URL, the processed URL, and the tag type (e.g., `iframe`),
|
|
401
|
+
* or `null` if no matching pattern is found.
|
|
429
402
|
*/
|
|
430
403
|
findProcessUrl(url) {
|
|
431
404
|
const query = this.query;
|
|
@@ -435,7 +408,7 @@ class Embed extends EditorInjector {
|
|
|
435
408
|
return {
|
|
436
409
|
origin: url,
|
|
437
410
|
url: service.action(url),
|
|
438
|
-
tag: service.tag
|
|
411
|
+
tag: service.tag,
|
|
439
412
|
};
|
|
440
413
|
}
|
|
441
414
|
}
|
|
@@ -447,34 +420,36 @@ class Embed extends EditorInjector {
|
|
|
447
420
|
* @description Processes the provided source (URL or embed code) and submits it for embedding.
|
|
448
421
|
* - It parses the input, triggers any necessary events, and creates or updates the embed component.
|
|
449
422
|
* @param {string} [src] - The embed source. If not provided, uses the internally stored link value.
|
|
450
|
-
* @returns {Promise<boolean>} A promise that resolves to true on success or false on failure.
|
|
423
|
+
* @returns {Promise<boolean>} A promise that resolves to `true` on success or `false` on failure.
|
|
451
424
|
*/
|
|
452
425
|
async submitSRC(src) {
|
|
453
|
-
if (!src)
|
|
454
|
-
if (!src) return false;
|
|
426
|
+
if (!(src ||= this.#linkValue)) return false;
|
|
455
427
|
|
|
456
428
|
let embedInfo = null;
|
|
457
429
|
if (/^<iframe\s|^<blockquote\s/i.test(src)) {
|
|
458
430
|
const embedDOM = new DOMParser().parseFromString(src, 'text/html').body.children;
|
|
459
431
|
if (embedDOM.length === 0) return false;
|
|
460
|
-
embedInfo = { children: embedDOM, ...this
|
|
432
|
+
embedInfo = { children: embedDOM, ...this.#getInfo(), process: null };
|
|
461
433
|
} else {
|
|
462
434
|
const processUrl = this.findProcessUrl(src);
|
|
463
435
|
if (!processUrl) return false;
|
|
464
436
|
src = processUrl.url;
|
|
465
|
-
|
|
437
|
+
|
|
438
|
+
embedInfo = {
|
|
439
|
+
...this.#getInfo(),
|
|
440
|
+
url: src,
|
|
441
|
+
process: processUrl,
|
|
442
|
+
};
|
|
466
443
|
}
|
|
467
444
|
|
|
468
|
-
const handler = function (infos, newInfos) {
|
|
445
|
+
const handler = function (uploadCallback, infos, newInfos) {
|
|
469
446
|
infos = newInfos || infos;
|
|
470
|
-
|
|
471
|
-
}.bind(this, embedInfo);
|
|
472
|
-
// se-ts-ignore
|
|
473
|
-
void this._create;
|
|
447
|
+
uploadCallback(src, infos.process, infos.url, infos.children, infos.inputWidth, infos.inputHeight, infos.align, infos.isUpdate);
|
|
448
|
+
}.bind(this, this.#create.bind(this), embedInfo);
|
|
474
449
|
|
|
475
|
-
const result = await this.triggerEvent('onEmbedInputBefore', {
|
|
450
|
+
const result = await this.$.eventManager.triggerEvent('onEmbedInputBefore', {
|
|
476
451
|
...embedInfo,
|
|
477
|
-
handler
|
|
452
|
+
handler,
|
|
478
453
|
});
|
|
479
454
|
|
|
480
455
|
if (result === undefined) return true;
|
|
@@ -487,39 +462,90 @@ class Embed extends EditorInjector {
|
|
|
487
462
|
}
|
|
488
463
|
|
|
489
464
|
/**
|
|
490
|
-
* @
|
|
491
|
-
*
|
|
492
|
-
*
|
|
465
|
+
* @description Prepares the component for selection.
|
|
466
|
+
* - Ensures that the controller is properly positioned and initialized.
|
|
467
|
+
* - Prevents duplicate event handling if the component is already selected.
|
|
468
|
+
* @param {HTMLElement} target - The selected element.
|
|
469
|
+
* @param {boolean} [infoOnly=false] - If `true`, only retrieves information without opening the controller.
|
|
470
|
+
*/
|
|
471
|
+
#ready(target, infoOnly = false) {
|
|
472
|
+
if (!target) return;
|
|
473
|
+
const figureInfo = this.figure.open(target, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly });
|
|
474
|
+
|
|
475
|
+
this.#element = target;
|
|
476
|
+
this.#cover = figureInfo.cover;
|
|
477
|
+
this.#container = figureInfo.container;
|
|
478
|
+
this._caption = figureInfo.caption;
|
|
479
|
+
this.#align = figureInfo.align;
|
|
480
|
+
|
|
481
|
+
if (!this.#cover?.getAttribute?.('data-se-origin')) {
|
|
482
|
+
const src = target?.getAttribute?.('src') || target?.querySelector?.('a')?.href;
|
|
483
|
+
if (src && Embed.#checkContentType(src)) {
|
|
484
|
+
this.#cover.setAttribute('data-se-origin', src);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
target.style.float = '';
|
|
489
|
+
|
|
490
|
+
this.#origin_w = String(figureInfo.originWidth || figureInfo.w || '');
|
|
491
|
+
this.#origin_h = String(figureInfo.originHeight || figureInfo.h || '');
|
|
492
|
+
|
|
493
|
+
/** @type {HTMLInputElement} */
|
|
494
|
+
const activeAlign = this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="' + this.#align + '"]') || this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]');
|
|
495
|
+
activeAlign.checked = true;
|
|
496
|
+
|
|
497
|
+
if (!this.#resizing) return;
|
|
498
|
+
|
|
499
|
+
const percentageRotation = this.#onlyPercentage && this.figure.isVertical;
|
|
500
|
+
const { dw, dh } = this.figure.getSize(target);
|
|
501
|
+
this.inputX.value = dw === 'auto' ? '' : dw;
|
|
502
|
+
this.inputY.value = dh === 'auto' ? '' : dh;
|
|
503
|
+
|
|
504
|
+
this.proportion.checked = true;
|
|
505
|
+
this.inputX.disabled = percentageRotation ? true : false;
|
|
506
|
+
this.inputY.disabled = percentageRotation ? true : false;
|
|
507
|
+
this.proportion.disabled = percentageRotation ? true : false;
|
|
508
|
+
|
|
509
|
+
this.#ratio = this.proportion.checked
|
|
510
|
+
? figureInfo.ratio
|
|
511
|
+
: {
|
|
512
|
+
w: 0,
|
|
513
|
+
h: 0,
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* @description Creates an `IFRAME` element for embedding external content.
|
|
519
|
+
* @returns {HTMLIFrameElement} The created `IFRAME` element.
|
|
493
520
|
*/
|
|
494
|
-
|
|
521
|
+
#createIframeTag() {
|
|
495
522
|
/** @type {HTMLIFrameElement} */
|
|
496
523
|
const iframeTag = dom.utils.createElement('IFRAME');
|
|
497
|
-
this
|
|
524
|
+
this.#setIframeAttrs(iframeTag);
|
|
498
525
|
return iframeTag;
|
|
499
526
|
}
|
|
500
527
|
|
|
501
528
|
/**
|
|
502
|
-
* @
|
|
503
|
-
* @
|
|
504
|
-
* @returns {HTMLElement} The created iframe element.
|
|
529
|
+
* @description Creates a `BLOCKQUOTE` element for embedding external content.
|
|
530
|
+
* @returns {HTMLElement} The created `BLOCKQUOTE` element.
|
|
505
531
|
*/
|
|
506
|
-
|
|
532
|
+
#createEmbedTag() {
|
|
507
533
|
const quoteTag = dom.utils.createElement('BLOCKQUOTE');
|
|
508
534
|
return quoteTag;
|
|
509
535
|
}
|
|
510
536
|
|
|
511
537
|
/**
|
|
512
|
-
* @
|
|
513
|
-
* @
|
|
514
|
-
* @param {
|
|
515
|
-
* @param {
|
|
516
|
-
* @param {
|
|
538
|
+
* @description Creates an embed component (`IFRAME` or `BLOCKQUOTE`) and inserts it into the editor.
|
|
539
|
+
* @param {string} originSrc - The origin input source.
|
|
540
|
+
* @param {SunEditor.EventParams.ProcessInfo} process - Processed embed information.
|
|
541
|
+
* @param {string} src - The source URL.
|
|
542
|
+
* @param {Node[]} children - The embed elements.
|
|
517
543
|
* @param {string} width - The width of the embed component.
|
|
518
544
|
* @param {string} height - The height of the embed component.
|
|
519
545
|
* @param {string} align - The alignment of the embed component.
|
|
520
546
|
* @param {boolean} isUpdate - Whether this is an update to an existing embed component.
|
|
521
547
|
*/
|
|
522
|
-
|
|
548
|
+
#create(originSrc, process, src, children, width, height, align, isUpdate) {
|
|
523
549
|
let oFrame = null;
|
|
524
550
|
let cover = null;
|
|
525
551
|
let container = null;
|
|
@@ -527,16 +553,16 @@ class Embed extends EditorInjector {
|
|
|
527
553
|
|
|
528
554
|
/** update */
|
|
529
555
|
if (isUpdate) {
|
|
530
|
-
oFrame = this
|
|
556
|
+
oFrame = this.#element;
|
|
531
557
|
if (oFrame.src !== src) {
|
|
532
558
|
const processUrl = this.findProcessUrl(src);
|
|
533
559
|
if (/^iframe$/i.test(processUrl?.tag) && !/^iframe$/i.test(oFrame.nodeName)) {
|
|
534
|
-
const newTag = this
|
|
560
|
+
const newTag = this.#createIframeTag();
|
|
535
561
|
newTag.src = src;
|
|
536
562
|
oFrame.replaceWith(newTag);
|
|
537
563
|
oFrame = newTag;
|
|
538
564
|
} else if (/^blockquote$/i.test(processUrl?.tag) && !/^blockquote$/i.test(oFrame.nodeName)) {
|
|
539
|
-
const newTag = this
|
|
565
|
+
const newTag = this.#createEmbedTag();
|
|
540
566
|
newTag.setAttribute('src', src);
|
|
541
567
|
oFrame.replaceWith(newTag);
|
|
542
568
|
oFrame = newTag;
|
|
@@ -544,12 +570,12 @@ class Embed extends EditorInjector {
|
|
|
544
570
|
oFrame.src = src;
|
|
545
571
|
}
|
|
546
572
|
}
|
|
547
|
-
container = this
|
|
573
|
+
container = this.#container;
|
|
548
574
|
cover = dom.query.getParentElement(oFrame, 'FIGURE');
|
|
549
575
|
} else {
|
|
550
576
|
/** create */
|
|
551
577
|
if (process) {
|
|
552
|
-
oFrame = this
|
|
578
|
+
oFrame = this.#createIframeTag();
|
|
553
579
|
oFrame.src = src;
|
|
554
580
|
const figure = Figure.CreateContainer(oFrame, 'se-embed-container');
|
|
555
581
|
cover = figure.cover;
|
|
@@ -560,12 +586,10 @@ class Embed extends EditorInjector {
|
|
|
560
586
|
cover = figure.cover;
|
|
561
587
|
container = figure.container;
|
|
562
588
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
while ((chd = /** @type {Element} */ (children[index]))) {
|
|
589
|
+
const childNodes = Array.from(children);
|
|
590
|
+
for (const chd of childNodes) {
|
|
566
591
|
if (/^script$/i.test(chd.nodeName)) {
|
|
567
|
-
scriptTag = dom.utils.createElement('script', { src: chd.getAttribute('src'), async: 'true' }, null);
|
|
568
|
-
index++;
|
|
592
|
+
scriptTag = dom.utils.createElement('script', { src: /** @type {Element} */ (chd).getAttribute('src'), async: 'true' }, null);
|
|
569
593
|
continue;
|
|
570
594
|
}
|
|
571
595
|
cover.appendChild(chd);
|
|
@@ -574,31 +598,35 @@ class Embed extends EditorInjector {
|
|
|
574
598
|
}
|
|
575
599
|
|
|
576
600
|
/** rendering */
|
|
577
|
-
this
|
|
578
|
-
this
|
|
579
|
-
this
|
|
580
|
-
this.figure.open(oFrame, { nonResizing: this
|
|
601
|
+
this.#element = oFrame;
|
|
602
|
+
this.#cover = cover;
|
|
603
|
+
this.#container = container;
|
|
604
|
+
this.figure.open(oFrame, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
605
|
+
|
|
606
|
+
width ||= this.#defaultSizeX;
|
|
607
|
+
height ||= this.#defaultSizeY;
|
|
581
608
|
|
|
582
|
-
width = width || this._defaultSizeX;
|
|
583
|
-
height = height || this._defaultSizeY;
|
|
584
609
|
const size = this.figure.getSize(oFrame);
|
|
585
610
|
const inputUpdate = size.w !== width || size.h !== height;
|
|
586
611
|
const changeSize = !isUpdate || inputUpdate;
|
|
587
612
|
|
|
588
613
|
// set size
|
|
589
614
|
if (changeSize) {
|
|
590
|
-
this
|
|
615
|
+
this.#applySize(width, height);
|
|
591
616
|
}
|
|
592
617
|
|
|
593
618
|
// align
|
|
594
619
|
this.figure.setAlign(oFrame, align);
|
|
595
620
|
|
|
621
|
+
// origin src
|
|
622
|
+
cover.setAttribute('data-se-origin', originSrc);
|
|
623
|
+
|
|
596
624
|
if (!isUpdate) {
|
|
597
|
-
this
|
|
625
|
+
this.$.component.insert(container, { skipHistory: true, scrollTo: false, insertBehavior: this.pluginOptions.insertBehavior });
|
|
598
626
|
|
|
599
627
|
if (scriptTag) {
|
|
600
628
|
try {
|
|
601
|
-
this
|
|
629
|
+
this.$.history.pause();
|
|
602
630
|
|
|
603
631
|
scriptTag.onload = () => {
|
|
604
632
|
dom.utils.removeItem(scriptTag);
|
|
@@ -610,8 +638,8 @@ class Embed extends EditorInjector {
|
|
|
610
638
|
for (const mutation of mutations) {
|
|
611
639
|
if (mutation.type === 'childList') {
|
|
612
640
|
if (!oFrame.parentElement) {
|
|
613
|
-
this
|
|
614
|
-
this
|
|
641
|
+
this.$.history.resume();
|
|
642
|
+
this.$.history.push(false);
|
|
615
643
|
observer.disconnect();
|
|
616
644
|
break;
|
|
617
645
|
}
|
|
@@ -619,38 +647,35 @@ class Embed extends EditorInjector {
|
|
|
619
647
|
}
|
|
620
648
|
});
|
|
621
649
|
|
|
622
|
-
observer.observe(this
|
|
650
|
+
observer.observe(this.$.frameContext.get('wysiwyg'), {
|
|
623
651
|
subtree: true,
|
|
624
|
-
childList: true
|
|
652
|
+
childList: true,
|
|
625
653
|
});
|
|
626
654
|
} catch (e) {
|
|
627
|
-
this
|
|
655
|
+
this.$.history.resume();
|
|
628
656
|
console.warn('[SUNEDITOR] Embed tag script load error.', e);
|
|
629
657
|
}
|
|
630
658
|
}
|
|
631
659
|
|
|
632
|
-
if (!this
|
|
633
|
-
const line = this
|
|
634
|
-
if (line) this
|
|
660
|
+
if (!this.$.options.get('componentInsertBehavior')) {
|
|
661
|
+
const line = this.$.format.addLine(container, null);
|
|
662
|
+
if (line) this.$.selection.setRange(line, 0, line, 0);
|
|
635
663
|
}
|
|
636
664
|
return;
|
|
637
665
|
}
|
|
638
666
|
|
|
639
|
-
if (this
|
|
640
|
-
if (!scriptTag) this
|
|
667
|
+
if (!this.#resizing || !changeSize || !this.figure.isVertical) this.figure.setTransform(oFrame, width, height, 0);
|
|
668
|
+
if (!scriptTag) this.$.history.push(false);
|
|
641
669
|
}
|
|
642
670
|
|
|
643
671
|
/**
|
|
644
|
-
* @private
|
|
645
672
|
* @description Updates an existing embed component within the editor.
|
|
646
673
|
* @param {HTMLIFrameElement} oFrame - The existing embed element to be updated.
|
|
647
674
|
*/
|
|
648
|
-
|
|
675
|
+
#fixTagStructure(oFrame) {
|
|
649
676
|
if (!oFrame) return;
|
|
650
677
|
|
|
651
|
-
this
|
|
652
|
-
|
|
653
|
-
let existElement = this.format.isBlock(oFrame.parentNode) || dom.check.isWysiwygFrame(oFrame.parentNode) ? oFrame : this.format.getLine(oFrame) || oFrame;
|
|
678
|
+
this.#setIframeAttrs(oFrame);
|
|
654
679
|
|
|
655
680
|
const prevFrame = oFrame;
|
|
656
681
|
oFrame = /** @type {HTMLIFrameElement} */ (oFrame.cloneNode(true));
|
|
@@ -658,53 +683,40 @@ class Embed extends EditorInjector {
|
|
|
658
683
|
const container = figure.container;
|
|
659
684
|
|
|
660
685
|
// size
|
|
661
|
-
this.figure.open(oFrame, { nonResizing: this
|
|
686
|
+
this.figure.open(oFrame, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
662
687
|
const size = (oFrame.getAttribute('data-se-size') || ',').split(',');
|
|
663
|
-
|
|
688
|
+
|
|
689
|
+
const width = size[0] || prevFrame.width || '';
|
|
690
|
+
const height = size[1] || prevFrame.height || '';
|
|
691
|
+
this.#applySize(width, height);
|
|
664
692
|
|
|
665
693
|
// align
|
|
666
|
-
const format = this
|
|
667
|
-
if (format) this
|
|
668
|
-
this.figure.setAlign(oFrame, this
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
prevFrame.replaceWith(container);
|
|
672
|
-
} else if (dom.check.isListCell(existElement)) {
|
|
673
|
-
const refer = dom.query.getParentElement(prevFrame, (current) => current.parentNode === existElement);
|
|
674
|
-
existElement.insertBefore(container, refer);
|
|
675
|
-
dom.utils.removeItem(prevFrame);
|
|
676
|
-
this.nodeTransform.removeEmptyNode(refer, null, true);
|
|
677
|
-
} else if (this.format.isLine(existElement)) {
|
|
678
|
-
const refer = dom.query.getParentElement(prevFrame, (current) => current.parentNode === existElement);
|
|
679
|
-
existElement = this.nodeTransform.split(existElement, refer);
|
|
680
|
-
existElement.parentNode.insertBefore(container, existElement);
|
|
681
|
-
dom.utils.removeItem(prevFrame);
|
|
682
|
-
this.nodeTransform.removeEmptyNode(existElement, null, true);
|
|
683
|
-
} else {
|
|
684
|
-
/** @type {Element} */ (existElement).replaceWith(container);
|
|
685
|
-
}
|
|
694
|
+
const format = this.$.format.getLine(prevFrame);
|
|
695
|
+
if (format) this.#align = format.style.textAlign || format.style.float;
|
|
696
|
+
this.figure.setAlign(oFrame, this.#align);
|
|
697
|
+
|
|
698
|
+
this.figure.retainFigureFormat(container, this.#element, null, null);
|
|
686
699
|
|
|
687
700
|
return oFrame;
|
|
688
701
|
}
|
|
689
702
|
|
|
690
703
|
/**
|
|
691
|
-
* @private
|
|
692
704
|
* @description Applies width and height to the embed component.
|
|
693
705
|
* @param {string|number} w - The width to apply.
|
|
694
706
|
* @param {string|number} h - The height to apply.
|
|
695
707
|
*/
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
708
|
+
#applySize(w, h) {
|
|
709
|
+
w ||= this.inputX?.value || this.pluginOptions.defaultWidth;
|
|
710
|
+
h ||= this.inputY?.value || this.pluginOptions.defaultHeight;
|
|
711
|
+
|
|
712
|
+
if (this.#onlyPercentage) {
|
|
700
713
|
if (!w) w = '100%';
|
|
701
|
-
else if (
|
|
714
|
+
else if (!/%$/.test(w + '')) w += '%';
|
|
702
715
|
}
|
|
703
716
|
this.figure.setSize(w, h);
|
|
704
717
|
}
|
|
705
718
|
|
|
706
719
|
/**
|
|
707
|
-
* @private
|
|
708
720
|
* @description Retrieves embed component size and alignment information.
|
|
709
721
|
* @returns {{inputWidth: string, inputHeight: string, align: string, isUpdate: boolean, element: Element}} An object containing
|
|
710
722
|
* - inputWidth : The width of the embed component.
|
|
@@ -713,22 +725,21 @@ class Embed extends EditorInjector {
|
|
|
713
725
|
* - isUpdate : Whether the component is being updated.
|
|
714
726
|
* - element : The target element.
|
|
715
727
|
*/
|
|
716
|
-
|
|
728
|
+
#getInfo() {
|
|
717
729
|
return {
|
|
718
730
|
inputWidth: this.inputX?.value || '',
|
|
719
731
|
inputHeight: this.inputY?.value || '',
|
|
720
|
-
align: this
|
|
732
|
+
align: this.#align,
|
|
721
733
|
isUpdate: this.modal.isUpdate,
|
|
722
|
-
element: this
|
|
734
|
+
element: this.#element,
|
|
723
735
|
};
|
|
724
736
|
}
|
|
725
737
|
|
|
726
738
|
/**
|
|
727
|
-
* @
|
|
728
|
-
* @
|
|
729
|
-
* @param {HTMLIFrameElement} element - The iframe element to modify.
|
|
739
|
+
* @description Sets default attributes for an `IFRAME` element.
|
|
740
|
+
* @param {HTMLIFrameElement} element - The `IFRAME` element to modify.
|
|
730
741
|
*/
|
|
731
|
-
|
|
742
|
+
#setIframeAttrs(element) {
|
|
732
743
|
element.frameBorder = '0';
|
|
733
744
|
element.allowFullscreen = true;
|
|
734
745
|
|
|
@@ -749,25 +760,25 @@ class Embed extends EditorInjector {
|
|
|
749
760
|
const eventTarget = dom.query.getEventTarget(e);
|
|
750
761
|
const value = eventTarget.value.trim();
|
|
751
762
|
if (/^<iframe.*\/iframe>$/.test(value)) {
|
|
752
|
-
this
|
|
763
|
+
this.#linkValue = value;
|
|
753
764
|
this.previewSrc.textContent = '<IFrame :src=".."></IFrame>';
|
|
754
765
|
} else {
|
|
755
|
-
this
|
|
766
|
+
this.#linkValue = this.previewSrc.textContent = !value
|
|
756
767
|
? ''
|
|
757
|
-
: this
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
768
|
+
: this.$.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
|
|
769
|
+
? this.$.options.get('defaultUrlProtocol') + value
|
|
770
|
+
: !value.includes('://')
|
|
771
|
+
? '/' + value
|
|
772
|
+
: value;
|
|
762
773
|
}
|
|
763
774
|
}
|
|
764
775
|
|
|
765
776
|
#OnClickRevert() {
|
|
766
|
-
if (this
|
|
767
|
-
this.inputX.value = Number(this
|
|
777
|
+
if (this.#onlyPercentage) {
|
|
778
|
+
this.inputX.value = Number(this.#origin_w) > 100 ? '100' : this.#origin_w;
|
|
768
779
|
} else {
|
|
769
|
-
this.inputX.value = this
|
|
770
|
-
this.inputY.value = this
|
|
780
|
+
this.inputX.value = this.#origin_w;
|
|
781
|
+
this.inputY.value = this.#origin_h;
|
|
771
782
|
}
|
|
772
783
|
}
|
|
773
784
|
|
|
@@ -784,10 +795,10 @@ class Embed extends EditorInjector {
|
|
|
784
795
|
/** @type {HTMLInputElement} */
|
|
785
796
|
const eventTarget = dom.query.getEventTarget(e);
|
|
786
797
|
|
|
787
|
-
if (xy === 'x' && this
|
|
798
|
+
if (xy === 'x' && this.#onlyPercentage && Number(eventTarget.value) > 100) {
|
|
788
799
|
eventTarget.value = '100';
|
|
789
800
|
} else if (this.proportion.checked) {
|
|
790
|
-
const ratioSize = Figure.CalcRatio(this.inputX.value, this.inputY.value, this.sizeUnit, this
|
|
801
|
+
const ratioSize = Figure.CalcRatio(this.inputX.value, this.inputY.value, this.sizeUnit, this.#ratio);
|
|
791
802
|
if (xy === 'x') {
|
|
792
803
|
this.inputY.value = String(ratioSize.h);
|
|
793
804
|
} else {
|
|
@@ -798,7 +809,7 @@ class Embed extends EditorInjector {
|
|
|
798
809
|
}
|
|
799
810
|
|
|
800
811
|
/**
|
|
801
|
-
* @param {
|
|
812
|
+
* @param {SunEditor.Deps} $ Kernel deps
|
|
802
813
|
* @param {*} pluginOptions
|
|
803
814
|
* @returns {{
|
|
804
815
|
* html: HTMLElement,
|
|
@@ -879,7 +890,7 @@ function CreateHTML_modal({ lang, icons }, pluginOptions) {
|
|
|
879
890
|
proportion: content.querySelector('._se_check_proportion'),
|
|
880
891
|
inputX: content.querySelector('._se_size_x'),
|
|
881
892
|
inputY: content.querySelector('._se_size_y'),
|
|
882
|
-
revertBtn: content.querySelector('.se-modal-btn-revert')
|
|
893
|
+
revertBtn: content.querySelector('.se-modal-btn-revert'),
|
|
883
894
|
};
|
|
884
895
|
}
|
|
885
896
|
|