ckeditor5 1.35.1 → 1.36.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.
- checksums.yaml +4 -4
- data/README.md +15 -13
- data/lib/ckeditor5/rails/engine.rb +2 -1
- data/lib/ckeditor5/rails/presets/manager.rb +31 -15
- data/lib/ckeditor5/rails/version.rb +2 -2
- data/npm_package/dist/index.cjs +1 -1
- data/npm_package/dist/index.cjs.map +1 -1
- data/npm_package/dist/index.mjs +27 -36
- data/npm_package/dist/index.mjs.map +1 -1
- data/npm_package/dist/src/components/editor/editor.d.ts.map +1 -1
- data/npm_package/package.json +3 -3
- data/spec/e2e/features/editor_types_spec.rb +8 -5
- data/spec/lib/ckeditor5/rails/presets/manager_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fe60a1f3e60146b007d2fb6f5d52e62b1fca488ce3337afe1618b1f33a7079e9
|
|
4
|
+
data.tar.gz: cf64c72dd3f360c38d4cd79958b97a5523b94392e8b896c8ff45c55542f6d505
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d9ff984d4dc1e68c04a562c4fa3f5d04429c1ed4e0aa2f8391e7d35f216e68234d31b31af46decbb86468ea3f8c7cf627913a4464b10aa71aa3a8b31e37f56f7
|
|
7
|
+
data.tar.gz: 24d267271521c791d9765df3a939734a7fe97f1ff0f304f0086e855f34095bbb4ff317e785b4e5ae9cbf529084c54320aab44b2588aa0a774e249e18defef4ac
|
data/README.md
CHANGED
|
@@ -96,7 +96,7 @@ CKEditor5::Rails.configure do
|
|
|
96
96
|
|
|
97
97
|
# Optionally, you can specify version of CKEditor 5 to use.
|
|
98
98
|
# If it's not specified the default version specified in the gem will be used.
|
|
99
|
-
# version '47.6.
|
|
99
|
+
# version '47.6.1'
|
|
100
100
|
|
|
101
101
|
# Upload images to the server using the simple upload adapter, instead of Base64 encoding.
|
|
102
102
|
# simple_upload_adapter
|
|
@@ -249,7 +249,7 @@ You can create your own by defining it in the `config/initializers/ckeditor5.rb`
|
|
|
249
249
|
|
|
250
250
|
CKEditor5::Rails.configure do
|
|
251
251
|
# It's possible to override the default preset right in the initializer.
|
|
252
|
-
version '47.6.
|
|
252
|
+
version '47.6.1'
|
|
253
253
|
|
|
254
254
|
# New presets inherit properties from the default preset defined in the initializer.
|
|
255
255
|
# In this example, the custom preset inherits everything from default but disables the menubar:
|
|
@@ -259,7 +259,7 @@ CKEditor5::Rails.configure do
|
|
|
259
259
|
|
|
260
260
|
# In order to define preset from scratch, you can use the `inherit: false` option.
|
|
261
261
|
presets.define :blank_preset, inherit: false do
|
|
262
|
-
version '47.6.
|
|
262
|
+
version '47.6.1'
|
|
263
263
|
|
|
264
264
|
# It tells the integration to fetch the newest security patches and bug fixes.
|
|
265
265
|
# It may be disabled, but it's highly recommended to keep it enabled to avoid
|
|
@@ -314,9 +314,9 @@ Configuration of the editor can be complex, and it's recommended to use the [CKE
|
|
|
314
314
|
|
|
315
315
|
### Automatic upgrades 🔄
|
|
316
316
|
|
|
317
|
-
The gem includes a feature that automatically upgrades the CKEditor 5 version when it's released. It's
|
|
317
|
+
The gem includes a feature that automatically upgrades the CKEditor 5 version when it's released. It's **disabled** by default for the `:default` preset. It means that the editor will automatically check the version of the editor during the initialization and upgrade it to the latest version if the new patch or minor version is released.
|
|
318
318
|
|
|
319
|
-
If you want to
|
|
319
|
+
If you want to enable automatic upgrades, you can use the `automatic_upgrades` method in the preset configuration.
|
|
320
320
|
|
|
321
321
|
```rb
|
|
322
322
|
# config/initializers/ckeditor5.rb
|
|
@@ -324,10 +324,12 @@ If you want to disable automatic upgrades, you can pass the `enabled: false` key
|
|
|
324
324
|
CKEditor5::Rails.configure do
|
|
325
325
|
# ... other configuration
|
|
326
326
|
|
|
327
|
-
automatic_upgrades
|
|
327
|
+
automatic_upgrades
|
|
328
328
|
end
|
|
329
329
|
```
|
|
330
330
|
|
|
331
|
+
Keep in mind that the version is checked every 4 days, so the editor will not be upgraded immediately after the new version is released. However, it'll slow down the application for certain requests when the version check is performed.
|
|
332
|
+
|
|
331
333
|
### Available Configuration Methods ⚙️
|
|
332
334
|
|
|
333
335
|
#### `cdn(cdn = nil, &block)` method
|
|
@@ -381,7 +383,7 @@ Defines the version of CKEditor 5 to be used. The example below shows how to set
|
|
|
381
383
|
CKEditor5::Rails.configure do
|
|
382
384
|
# ... other configuration
|
|
383
385
|
|
|
384
|
-
version '47.6.
|
|
386
|
+
version '47.6.1'
|
|
385
387
|
end
|
|
386
388
|
```
|
|
387
389
|
|
|
@@ -393,7 +395,7 @@ In order to disable default patches, you can pass the `apply_patches: false` key
|
|
|
393
395
|
CKEditor5::Rails.configure do
|
|
394
396
|
# ... other configuration
|
|
395
397
|
|
|
396
|
-
version '47.6.
|
|
398
|
+
version '47.6.1', apply_patches: false
|
|
397
399
|
end
|
|
398
400
|
```
|
|
399
401
|
|
|
@@ -408,7 +410,7 @@ The patches are defined in the `lib/ckeditor5/rails/plugins/patches` directory.
|
|
|
408
410
|
|
|
409
411
|
<br />
|
|
410
412
|
|
|
411
|
-
Defines if automatic upgrades should be enabled. It's
|
|
413
|
+
Defines if automatic upgrades should be enabled. It's disabled for the `:default` preset by default. The example below shows how to enable automatic upgrades:
|
|
412
414
|
|
|
413
415
|
```rb
|
|
414
416
|
# config/initializers/ckeditor5.rb
|
|
@@ -416,7 +418,7 @@ Defines if automatic upgrades should be enabled. It's enabled for the `:default`
|
|
|
416
418
|
CKEditor5::Rails.configure do
|
|
417
419
|
# ... other configuration
|
|
418
420
|
|
|
419
|
-
automatic_upgrades
|
|
421
|
+
automatic_upgrades
|
|
420
422
|
end
|
|
421
423
|
```
|
|
422
424
|
|
|
@@ -1373,7 +1375,7 @@ It may be useful when you want to define a preset based on the current user or r
|
|
|
1373
1375
|
class ApplicationController < ActionController::Base
|
|
1374
1376
|
def show
|
|
1375
1377
|
@preset = ckeditor5_preset do
|
|
1376
|
-
version '47.6.
|
|
1378
|
+
version '47.6.1'
|
|
1377
1379
|
|
|
1378
1380
|
toolbar :sourceEditing, :|, :bold, :italic, :underline, :strikethrough,
|
|
1379
1381
|
:subscript, :superscript, :removeFormat, :|, :bulletedList, :numberedList,
|
|
@@ -1408,7 +1410,7 @@ If you want to override the preset defined in the initializer, you can search fo
|
|
|
1408
1410
|
class ApplicationController < ActionController::Base
|
|
1409
1411
|
def show
|
|
1410
1412
|
@preset = ckeditor5_preset(:default).override do
|
|
1411
|
-
version '47.6.
|
|
1413
|
+
version '47.6.1'
|
|
1412
1414
|
|
|
1413
1415
|
toolbar :sourceEditing, :|, :bold, :italic, :underline, :strikethrough,
|
|
1414
1416
|
:subscript, :superscript, :removeFormat, :|, :bulletedList, :numberedList,
|
|
@@ -1581,7 +1583,7 @@ In that scenario it's recommended to add `gpl` method to the initializer along w
|
|
|
1581
1583
|
|
|
1582
1584
|
CKEditor5::Rails.configure do
|
|
1583
1585
|
gpl
|
|
1584
|
-
version '47.6.
|
|
1586
|
+
version '47.6.1'
|
|
1585
1587
|
end
|
|
1586
1588
|
```
|
|
1587
1589
|
|
|
@@ -79,9 +79,10 @@ module CKEditor5::Rails
|
|
|
79
79
|
|
|
80
80
|
delegate :version, :gpl, :premium, :cdn, :translations, :license_key,
|
|
81
81
|
:type, :menubar, :plugins, :plugin, :inline_plugin,
|
|
82
|
-
:toolbar, :block_toolbar, :balloon_toolbar,
|
|
82
|
+
:toolbar, :block_toolbar, :balloon_toolbar, :special_characters,
|
|
83
83
|
:language, :ckbox, :configure, :automatic_upgrades, :simple_upload_adapter,
|
|
84
84
|
:editable_height, :wproofreader, :custom_translations, :apply_integration_patches,
|
|
85
|
+
:patch_plugin, :external_plugin,
|
|
85
86
|
:compression, :compression?, to: :default_preset
|
|
86
87
|
|
|
87
88
|
def initialize(configuration)
|
|
@@ -89,39 +89,55 @@ module CKEditor5::Rails::Presets
|
|
|
89
89
|
# menubar
|
|
90
90
|
# end
|
|
91
91
|
# end
|
|
92
|
-
def define_default_preset
|
|
92
|
+
def define_default_preset # rubocop:disable Metrics/MethodLength
|
|
93
93
|
define :default do
|
|
94
94
|
# Set default version from gem constant
|
|
95
95
|
version CKEditor5::Rails::DEFAULT_CKEDITOR_VERSION
|
|
96
96
|
|
|
97
|
-
# Enable automatic version upgrades for security patches
|
|
98
|
-
automatic_upgrades
|
|
99
|
-
|
|
100
97
|
# Use GPL license and classic editor type
|
|
101
98
|
gpl
|
|
102
99
|
type :classic
|
|
103
100
|
menubar
|
|
104
101
|
|
|
105
102
|
# Configure default toolbar items
|
|
106
|
-
toolbar :undo, :redo, :|, :heading, :|, :
|
|
107
|
-
:
|
|
103
|
+
toolbar :undo, :redo, :|, :heading, :|, :fontFamily, :fontSize, :fontColor,
|
|
104
|
+
:fontBackgroundColor, :alignment, :|, :bold, :italic, :underline,
|
|
105
|
+
:strikethrough, :superscript, :subscript, :|, :link, :insertImage,
|
|
106
|
+
:insertTable, :insertTableLayout, :blockQuote, :emoji, :mediaEmbed, :|,
|
|
108
107
|
:bulletedList, :numberedList, :todoList, :outdent, :indent
|
|
109
108
|
|
|
110
109
|
# Configure default plugins
|
|
111
|
-
plugins :AccessibilityHelp, :Autoformat, :AutoImage, :Autosave,
|
|
110
|
+
plugins :Alignment, :AccessibilityHelp, :Autoformat, :AutoImage, :Autosave,
|
|
112
111
|
:BlockQuote, :Bold, :CloudServices,
|
|
113
|
-
:Essentials, :Heading, :
|
|
114
|
-
:
|
|
115
|
-
:ImageTextAlternative, :ImageToolbar, :ImageUpload,
|
|
116
|
-
:IndentBlock, :Italic, :Link, :LinkImage, :List, :ListProperties,
|
|
117
|
-
:MediaEmbed, :Paragraph, :PasteFromOffice, :PictureEditing,
|
|
118
|
-
:SelectAll, :Table, :TableCaption, :TableCellProperties,
|
|
112
|
+
:Essentials, :Emoji, :Heading, :FontFamily, :FontSize, :FontColor, :FontBackgroundColor,
|
|
113
|
+
:ImageBlock, :ImageCaption, :ImageInline, :ImageInsert, :ImageInsertViaUrl,
|
|
114
|
+
:ImageResize, :ImageStyle, :ImageTextAlternative, :ImageToolbar, :ImageUpload,
|
|
115
|
+
:Indent, :IndentBlock, :Italic, :Link, :LinkImage, :List, :ListProperties,
|
|
116
|
+
:MediaEmbed, :Mention, :Paragraph, :PasteFromOffice, :PictureEditing,
|
|
117
|
+
:SelectAll, :Table, :TableLayout, :TableCaption, :TableCellProperties,
|
|
119
118
|
:TableColumnResize, :TableProperties, :TableToolbar,
|
|
120
|
-
:TextTransformation, :TodoList, :Underline, :
|
|
119
|
+
:TextTransformation, :TodoList, :Underline, :Strikethrough, :Superscript,
|
|
120
|
+
:Subscript, :Undo, :Base64UploadAdapter
|
|
121
|
+
|
|
122
|
+
# Configure default table toolbar
|
|
123
|
+
configure :table, {
|
|
124
|
+
contentToolbar: %i[
|
|
125
|
+
tableColumn tableRow mergeTableCells tableProperties
|
|
126
|
+
tableCellProperties toggleTableCaption
|
|
127
|
+
]
|
|
128
|
+
}
|
|
121
129
|
|
|
122
130
|
# Configure default image toolbar
|
|
123
131
|
configure :image, {
|
|
124
|
-
toolbar: [
|
|
132
|
+
toolbar: [
|
|
133
|
+
'imageStyle:inline',
|
|
134
|
+
'imageStyle:block',
|
|
135
|
+
'imageStyle:wrapText',
|
|
136
|
+
:|,
|
|
137
|
+
:toggleImageCaption,
|
|
138
|
+
:imageTextAlternative,
|
|
139
|
+
:imageResize
|
|
140
|
+
]
|
|
125
141
|
}
|
|
126
142
|
end
|
|
127
143
|
end
|
data/npm_package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var C=Object.create;var w=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty;var k=(s,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of x(t))!S.call(s,n)&&n!==e&&w(s,n,{get:()=>t[n],enumerable:!(i=A(t,n))||i.enumerable});return s};var g=(s,t,e)=>(e=s!=null?C(P(s)):{},k(t||!s||!s.__esModule?w(e,"default",{value:s,enumerable:!0}):e,s));function p(s){switch(document.readyState){case"loading":document.addEventListener("DOMContentLoaded",s,{once:!0});break;case"interactive":case"complete":setTimeout(s,0);break;default:console.warn("Unexpected document.readyState:",document.readyState),setTimeout(s,0)}}const b=new Map;function R(s){if(b.has(s))return b.get(s);const t=new Promise((e,i)=>{const n=document.createElement("script");n.src=s,n.onload=e,n.onerror=i,document.head.appendChild(n)});return b.set(s,t),t}function M(s){return typeof s=="string"&&s!=="__proto__"&&s!=="constructor"&&s!=="prototype"}function $(s){return Array.from(document.styleSheets).some(t=>t.href===s||t.href===new URL(s,window.location.href).href)}function y(s=[]){const t=s.map(e=>new Promise((i,n)=>{if($(e)){i();return}const r=document.createElement("link");r.rel="stylesheet",r.href=e,r.onerror=n,r.onload=()=>i(),document.head.appendChild(r)}));return Promise.all(t)}function h(s=[]){const t=async({url:i,import_name:n,import_as:r,window_name:o,stylesheets:a})=>{if(a?.length&&await y(a),o){let l=function(){return Object.prototype.hasOwnProperty.call(window,o)};if(i&&!l()&&await R(i),l()||window.dispatchEvent(new CustomEvent(`ckeditor:request-cjs-plugin:${o}`)),!l())throw new Error(`Plugin window['${o}'] not found in global scope. Please ensure the plugin is loaded before CKEditor initialization.`);return window[o]}const c=await import(n),d=c[r||"default"];if(!d)throw new Error(`Plugin "${r||"default"}" not found in the ESM module "${n}"! Available imports: ${Object.keys(c).join(", ")}! Consider changing "import_as" value.`);return d};function e(i){return t(typeof i=="string"?{import_name:"ckeditor5",import_as:i}:i)}return Promise.all(s.map(e))}function u(s){if(!s||typeof s!="object")return s;if(Array.isArray(s))return s.map(i=>u(i));const t=s;if(t.$element&&typeof t.$element=="string"){const i=document.querySelector(t.$element);return i||console.warn(`Element not found for selector: ${t.$element}`),i||null}const e=Object.create(null);for(const[i,n]of Object.entries(s))e[i]=u(n);return e}function I(){return Math.random().toString(36).substring(2)}class T extends HTMLElement{instance=null;instancePromise=Promise.withResolvers();#e=new Set;static get observedAttributes(){return["plugins","config"]}async connectedCallback(){try{p(()=>this.#t())}catch(t){console.error("Failed to initialize context:",t),this.dispatchEvent(new CustomEvent("context-error",{detail:t}))}}async attributeChangedCallback(t,e,i){e!==null&&e!==i&&await this.#t()}async disconnectedCallback(){this.instance&&(await this.instance.destroy(),this.instance=null)}registerEditor(t){this.#e.add(t)}unregisterEditor(t){this.#e.delete(t)}async#t(){this.instance&&(this.instancePromise=Promise.withResolvers(),await this.instance.destroy(),this.instance=null),window.dispatchEvent(new CustomEvent("ckeditor:context:attach:before",{detail:{element:this}}));const{Context:t,ContextWatchdog:e}=await import("ckeditor5"),i=await this.#i(),n=this.#s();window.dispatchEvent(new CustomEvent("ckeditor:context:attach",{detail:{config:n,element:this}})),this.instance=new e(t,{crashNumberLimit:10}),await this.instance.create({...n,plugins:i}),this.instance.on("itemError",(...r)=>{console.error("Context item error:",...r)}),this.instancePromise.resolve(this.instance),this.dispatchEvent(new CustomEvent("context-ready",{detail:this.instance})),await Promise.all([...this.#e].map(r=>r.reinitializeEditor()))}async#i(){const t=this.getAttribute("plugins");return h(t?JSON.parse(t):[])}#s(){const t=JSON.parse(this.getAttribute("config")||"{}");return u(t)}}customElements.define("ckeditor-context-component",T);class L extends HTMLElement{static get observedAttributes(){return["name"]}get name(){return this.getAttribute("name")||"editable"}get editableElement(){return this.querySelector("div")}connectedCallback(){p(()=>{const t=this.#e();if(!t)throw new Error("ckeditor-editable-component must be a child of ckeditor-component");if(this.innerHTML=`<div>${this.innerHTML}</div>`,this.style.display="block",t.isDecoupled())t.runAfterEditorReady(e=>{this.appendChild(e.ui.view[this.name].element)});else{if(!this.name)throw new Error('Editable component missing required "name" attribute');t.editables[this.name]=this}})}attributeChangedCallback(t,e,i){if(e!==i)if(t==="name"){if(!e)return;const n=this.#e();n&&(n.editables[i]=n.editables[e],delete n.editables[e])}else this.editableElement.setAttribute(t,i)}disconnectedCallback(){const t=this.#e();t&&delete t.editables[this.name]}#e(){return this.closest("ckeditor-component")||document.body.querySelector("ckeditor-component")}}customElements.define("ckeditor-editable-component",L);class E{#e;#t;constructor(t,e={}){return this.#e=t,this.#t=e,new Proxy(this,{get(i,n){return typeof i[n]=="function"?i[n].bind(i):i.#t[n]},set(i,n,r){return i.#t[n]!==r&&(i.attachRoot(n,r),i.#t[n]=r),!0},deleteProperty(i,n){return i.detachRoot(n),delete i.#t[n],!0}})}async attachRoot(t,e){return await this.detachRoot(t),this.#e.runAfterEditorReady(i=>{const{ui:n,editing:r,model:o}=i;i.addRoot(t,{isUndoable:!1,data:e.innerHTML});const a=o.document.getRoot(t);n.getEditableElement(t)&&i.detachEditable(a);const c=n.view.createEditable(t,e);n.addEditable(c),r.view.forceRender()})}async detachRoot(t){return this.#e.runAfterEditorReady(e=>{const i=e.model.document.getRoot(t);i&&(e.detachEditable(i),e.detachRoot(t,!0))})}getAll(){return this.#t}}class m extends HTMLElement{instancePromise=Promise.withResolvers();watchdog=null;instance=null;editables=Object.create({});#e="";#t=null;#i=null;#s=null;static get observedAttributes(){return["config","plugins","translations","type"]}static get inputAttributes(){return["name","required","value"]}get oneditorchange(){return this.#r("editorchange")}set oneditorchange(t){this.#o("editorchange",t)}get oneditorready(){return this.#r("editorready")}set oneditorready(t){this.#o("editorready",t)}get oneditorerror(){return this.#r("editorerror")}set oneditorerror(t){this.#o("editorerror",t)}#r(t){if(this.hasAttribute(`on${t}`)){const e=this.getAttribute(`on${t}`);if(!M(e))throw new Error(`Unsafe event handler attribute value: ${e}`);return window[e]||new Function("event",e)}return this[`#${t}Handler`]}#o(t,e){typeof e=="string"?this.setAttribute(`on${t}`,e):(this.removeAttribute(`on${t}`),this[`#${t}Handler`]=e)}connectedCallback(){this.#t=this.closest("ckeditor-context-component"),this.#e=this.innerHTML;try{p(async()=>{this.#t&&(await this.#t.instancePromise.promise,this.#t.registerEditor(this)),await this.reinitializeEditor()})}catch(t){console.error("Failed to initialize editor:",t);const e=new CustomEvent("editor-error",{detail:t});this.dispatchEvent(e),this.oneditorerror?.(e)}}async attributeChangedCallback(t,e,i){e!==null&&e!==i&&m.observedAttributes.includes(t)&&this.isConnected&&await this.reinitializeEditor()}async disconnectedCallback(){this.#t&&this.#t.unregisterEditor(this);try{await this.#d()}catch(t){console.error("Failed to destroy editor:",t)}}runAfterEditorReady(t){return this.instance?Promise.resolve(t(this.instance)):this.instancePromise.promise.then(t)}get#n(){switch(this.getAttribute("type")){case"ClassicEditor":return"textarea";default:return"div"}}get#a(){return this.#t?.instance}async#d(){this.#i&&await this.#a.remove(this.#i),await this.instance?.destroy(),this.watchdog?.destroy()}#l(){const t=JSON.parse(this.getAttribute("config")||"{}");return u(t)}async#u(t){await Promise.all([this.#b(),this.#w()]);let e=t;t instanceof E?e=t.getAll():typeof t!="string"&&(e=t.main);const i={...e instanceof HTMLElement&&{element:e},...typeof e=="string"&&{data:e},...e instanceof Object&&{editables:e}};window.dispatchEvent(new CustomEvent("ckeditor:attach:before",{detail:i}));const n=await this.#v(),[r,o]=await Promise.all([this.#y(),this.#E()]),a={...this.#l(),...o.length&&{translations:o},plugins:r};window.dispatchEvent(new CustomEvent("ckeditor:attach",{detail:{config:a,...i}})),console.warn("Initializing CKEditor with:",{config:a,watchdog:this.hasWatchdog(),context:this.#t});let c=null,d=null,l=null;if(this.#t)l=I(),await this.#a.add({creator:(f,v)=>n.create(f,v),id:l,sourceElementOrData:e,type:"editor",config:a}),d=this.#a.getItem(l);else if(this.hasWatchdog()){const{EditorWatchdog:f}=await import("ckeditor5");c=new f(n),await c.create(e,a),d=c.editor}else d=await n.create(e,a);return console.warn("CKEditor initialized:",{instance:d,watchdog:c,config:d.config._config}),{contextId:l,instance:d,watchdog:c}}async reinitializeEditor(){this.instance&&(this.instancePromise=Promise.withResolvers(),await this.#d(),this.instance=null),this.style.display="block",!this.isMultiroot()&&!this.isDecoupled()&&(this.innerHTML=`<${this.#n}>${this.#e}</${this.#n}>`,this.#p()),this.isMultiroot()?this.editables=new E(this,this.#h()):this.isDecoupled()?this.editables=null:this.editables=this.#h();try{const{watchdog:t,instance:e,contextId:i}=await this.#u(this.editables||this.#l().initialData||"");this.watchdog=t,this.instance=e,this.#i=i,this.#f(),this.#g(),this.#m(),this.instancePromise.resolve(this.instance);const n=new CustomEvent("editor-ready",{detail:this.instance});this.dispatchEvent(n),this.oneditorready?.(n)}catch(t){throw this.instancePromise.reject(t),t}}#m(){const t=i=>this.instance.getData({rootName:i}),e=()=>this.instance?.model.document.getRootNames().reduce((i,n)=>({...i,[n]:t(n)}),{});this.instance?.model.document.on("change:data",()=>{const i=new CustomEvent("editor-change",{detail:{editor:this.instance,data:e()},bubbles:!0});this.dispatchEvent(i),this.oneditorchange?.(i)})}isClassic(){return this.getAttribute("type")==="ClassicEditor"}isBallon(){return this.getAttribute("type")==="BalloonEditor"}isMultiroot(){return this.getAttribute("type")==="MultiRootEditor"}isDecoupled(){return this.getAttribute("type")==="DecoupledEditor"}hasWatchdog(){return this.getAttribute("watchdog")==="true"}#h(){if(this.isDecoupled())return{};if(this.isMultiroot())return[...this.querySelectorAll("ckeditor-editable-component")].reduce((i,n)=>{if(!n.name)throw new Error('Editable component missing required "name" attribute');return i[n.name]=n,i},Object.create(null));const t=this.querySelector(this.#n);if(!t)throw new Error(`No ${this.#n} element found`);return{main:t}}#p(){const t=this.querySelector("textarea");if(t)for(const e of m.inputAttributes)this.hasAttribute(e)&&t.setAttribute(e,this.getAttribute(e))}#f(){if(!this.instance)return;const t=this.querySelector("textarea");if(!t)return;const e=()=>{this.style.position="relative",t.innerHTML="",t.value=this.instance.getData(),t.tabIndex=-1,Object.assign(t.style,{display:"flex",position:"absolute",bottom:"0",left:"50%",width:"1px",height:"1px",opacity:"0",pointerEvents:"none",margin:"0",padding:"0",border:"none"})};e(),this.instance.model.document.on("change:data",()=>{t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0})),e()})}#g(){if(!this.isClassic()&&!this.isBallon())return;const{instance:t}=this,e=Number.parseInt(this.getAttribute("editable-height"),10);Number.isNaN(e)||t.editing.view.change(i=>{i.setStyle("height",`${e}px`,t.editing.view.document.getRoot())})}#c(){return this.#s||=JSON.parse(this.getAttribute("bundle"))}async#b(){await y(this.#c()?.stylesheets||[])}async#w(){const t=(this.#c()?.scripts||[]).filter(e=>!!e.window_name);await h(t)}async#E(){const t=this.#c()?.scripts.filter(e=>e.translation);return h(t)}async#y(){const t=this.getAttribute("plugins"),i=(t?JSON.parse(t):[]).map(n=>typeof n=="string"?{import_name:"ckeditor5",import_as:n}:n);return h(i)}async#v(){const t=await import("ckeditor5"),e=this.getAttribute("type");if(!e||!Object.prototype.hasOwnProperty.call(t,e))throw new Error(`Invalid editor type: ${e}`);return t[e]}}customElements.define("ckeditor-component",m);class O extends HTMLElement{connectedCallback(){p(async()=>{const t=this.getAttribute("name"),e=await this.#e().instancePromise.promise;this.appendChild(e.ui.view[t].element)})}#e(){return this.closest("ckeditor-component")||document.body.querySelector("ckeditor-component")}}customElements.define("ckeditor-ui-part-component",O);
|
|
1
|
+
"use strict";var C=Object.create;var w=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty;var k=(s,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of P(t))!S.call(s,n)&&n!==e&&w(s,n,{get:()=>t[n],enumerable:!(i=A(t,n))||i.enumerable});return s};var g=(s,t,e)=>(e=s!=null?C(x(s)):{},k(t||!s||!s.__esModule?w(e,"default",{value:s,enumerable:!0}):e,s));function p(s){switch(document.readyState){case"loading":document.addEventListener("DOMContentLoaded",s,{once:!0});break;case"interactive":case"complete":setTimeout(s,0);break;default:console.warn("Unexpected document.readyState:",document.readyState),setTimeout(s,0)}}const b=new Map;function R(s){if(b.has(s))return b.get(s);const t=new Promise((e,i)=>{const n=document.createElement("script");n.src=s,n.onload=e,n.onerror=i,document.head.appendChild(n)});return b.set(s,t),t}function M(s){return typeof s=="string"&&s!=="__proto__"&&s!=="constructor"&&s!=="prototype"}function $(s){return Array.from(document.styleSheets).some(t=>t.href===s||t.href===new URL(s,window.location.href).href)}function E(s=[]){const t=s.map(e=>new Promise((i,n)=>{if($(e)){i();return}const r=document.createElement("link");r.rel="stylesheet",r.href=e,r.onerror=n,r.onload=()=>i(),document.head.appendChild(r)}));return Promise.all(t)}function h(s=[]){const t=async({url:i,import_name:n,import_as:r,window_name:o,stylesheets:a})=>{if(a?.length&&await E(a),o){let d=function(){return Object.prototype.hasOwnProperty.call(window,o)};if(i&&!d()&&await R(i),d()||window.dispatchEvent(new CustomEvent(`ckeditor:request-cjs-plugin:${o}`)),!d())throw new Error(`Plugin window['${o}'] not found in global scope. Please ensure the plugin is loaded before CKEditor initialization.`);return window[o]}const c=await import(n),l=c[r||"default"];if(!l)throw new Error(`Plugin "${r||"default"}" not found in the ESM module "${n}"! Available imports: ${Object.keys(c).join(", ")}! Consider changing "import_as" value.`);return l};function e(i){return t(typeof i=="string"?{import_name:"ckeditor5",import_as:i}:i)}return Promise.all(s.map(e))}function u(s){if(!s||typeof s!="object")return s;if(Array.isArray(s))return s.map(i=>u(i));const t=s;if(t.$element&&typeof t.$element=="string"){const i=document.querySelector(t.$element);return i||console.warn(`Element not found for selector: ${t.$element}`),i||null}const e=Object.create(null);for(const[i,n]of Object.entries(s))e[i]=u(n);return e}function I(){return Math.random().toString(36).substring(2)}class T extends HTMLElement{instance=null;instancePromise=Promise.withResolvers();#e=new Set;static get observedAttributes(){return["plugins","config"]}async connectedCallback(){try{p(()=>this.#t())}catch(t){console.error("Failed to initialize context:",t),this.dispatchEvent(new CustomEvent("context-error",{detail:t}))}}async attributeChangedCallback(t,e,i){e!==null&&e!==i&&await this.#t()}async disconnectedCallback(){this.instance&&(await this.instance.destroy(),this.instance=null)}registerEditor(t){this.#e.add(t)}unregisterEditor(t){this.#e.delete(t)}async#t(){this.instance&&(this.instancePromise=Promise.withResolvers(),await this.instance.destroy(),this.instance=null),window.dispatchEvent(new CustomEvent("ckeditor:context:attach:before",{detail:{element:this}}));const{Context:t,ContextWatchdog:e}=await import("ckeditor5"),i=await this.#i(),n=this.#s();window.dispatchEvent(new CustomEvent("ckeditor:context:attach",{detail:{config:n,element:this}})),this.instance=new e(t,{crashNumberLimit:10}),await this.instance.create({...n,plugins:i}),this.instance.on("itemError",(...r)=>{console.error("Context item error:",...r)}),this.instancePromise.resolve(this.instance),this.dispatchEvent(new CustomEvent("context-ready",{detail:this.instance})),await Promise.all([...this.#e].map(r=>r.reinitializeEditor()))}async#i(){const t=this.getAttribute("plugins");return h(t?JSON.parse(t):[])}#s(){const t=JSON.parse(this.getAttribute("config")||"{}");return u(t)}}customElements.define("ckeditor-context-component",T);class L extends HTMLElement{static get observedAttributes(){return["name"]}get name(){return this.getAttribute("name")||"editable"}get editableElement(){return this.querySelector("div")}connectedCallback(){p(()=>{const t=this.#e();if(!t)throw new Error("ckeditor-editable-component must be a child of ckeditor-component");if(this.innerHTML=`<div>${this.innerHTML}</div>`,this.style.display="block",t.isDecoupled())t.runAfterEditorReady(e=>{this.appendChild(e.ui.view[this.name].element)});else{if(!this.name)throw new Error('Editable component missing required "name" attribute');t.editables[this.name]=this}})}attributeChangedCallback(t,e,i){if(e!==i)if(t==="name"){if(!e)return;const n=this.#e();n&&(n.editables[i]=n.editables[e],delete n.editables[e])}else this.editableElement.setAttribute(t,i)}disconnectedCallback(){const t=this.#e();t&&delete t.editables[this.name]}#e(){return this.closest("ckeditor-component")||document.body.querySelector("ckeditor-component")}}customElements.define("ckeditor-editable-component",L);class y{#e;#t;constructor(t,e={}){return this.#e=t,this.#t=e,new Proxy(this,{get(i,n){return typeof i[n]=="function"?i[n].bind(i):i.#t[n]},set(i,n,r){return i.#t[n]!==r&&(i.attachRoot(n,r),i.#t[n]=r),!0},deleteProperty(i,n){return i.detachRoot(n),delete i.#t[n],!0}})}async attachRoot(t,e){return await this.detachRoot(t),this.#e.runAfterEditorReady(i=>{const{ui:n,editing:r,model:o}=i;i.addRoot(t,{isUndoable:!1,data:e.innerHTML});const a=o.document.getRoot(t);n.getEditableElement(t)&&i.detachEditable(a);const c=n.view.createEditable(t,e);n.addEditable(c),r.view.forceRender()})}async detachRoot(t){return this.#e.runAfterEditorReady(e=>{const i=e.model.document.getRoot(t);i&&(e.detachEditable(i),e.detachRoot(t,!0))})}getAll(){return this.#t}}class m extends HTMLElement{instancePromise=Promise.withResolvers();watchdog=null;instance=null;editables=Object.create({});#e="";#t=null;#i=null;#s=null;static get observedAttributes(){return["config","plugins","translations","type"]}static get inputAttributes(){return["name","required","value"]}get oneditorchange(){return this.#r("editorchange")}set oneditorchange(t){this.#o("editorchange",t)}get oneditorready(){return this.#r("editorready")}set oneditorready(t){this.#o("editorready",t)}get oneditorerror(){return this.#r("editorerror")}set oneditorerror(t){this.#o("editorerror",t)}#r(t){if(this.hasAttribute(`on${t}`)){const e=this.getAttribute(`on${t}`);if(!M(e))throw new Error(`Unsafe event handler attribute value: ${e}`);return window[e]||new Function("event",e)}return this[`#${t}Handler`]}#o(t,e){typeof e=="string"?this.setAttribute(`on${t}`,e):(this.removeAttribute(`on${t}`),this[`#${t}Handler`]=e)}connectedCallback(){this.#t=this.closest("ckeditor-context-component"),this.#e=this.innerHTML;try{p(async()=>{this.#t&&(await this.#t.instancePromise.promise,this.#t.registerEditor(this)),await this.reinitializeEditor()})}catch(t){console.error("Failed to initialize editor:",t);const e=new CustomEvent("editor-error",{detail:t});this.dispatchEvent(e),this.oneditorerror?.(e)}}async attributeChangedCallback(t,e,i){e!==null&&e!==i&&m.observedAttributes.includes(t)&&this.isConnected&&await this.reinitializeEditor()}async disconnectedCallback(){this.#t&&this.#t.unregisterEditor(this);try{await this.#d()}catch(t){console.error("Failed to destroy editor:",t)}}runAfterEditorReady(t){return this.instance?Promise.resolve(t(this.instance)):this.instancePromise.promise.then(t)}get#n(){return this.getAttribute("type")==="ClassicEditor"?"textarea":"div"}get#a(){return this.#t?.instance}async#d(){this.#i&&await this.#a.remove(this.#i),await this.instance?.destroy(),this.watchdog?.destroy()}#l(){const t=JSON.parse(this.getAttribute("config")||"{}");return u(t)}async#u(t){await Promise.all([this.#b(),this.#w()]);let e=t;t instanceof y?e=t.getAll():typeof t!="string"&&(e=t.main);const i={...e instanceof HTMLElement&&{element:e},...typeof e=="string"&&{data:e},...e instanceof Object&&{editables:e}};window.dispatchEvent(new CustomEvent("ckeditor:attach:before",{detail:i}));const n=await this.#v(),[r,o]=await Promise.all([this.#E(),this.#y()]),a={...this.#l(),...o.length&&{translations:o},plugins:r};window.dispatchEvent(new CustomEvent("ckeditor:attach",{detail:{config:a,...i}}));let c=null,l=null,d=null;if(this.#t)d=I(),await this.#a.add({creator:(f,v)=>n.create(f,v),id:d,sourceElementOrData:e,type:"editor",config:a}),l=this.#a.getItem(d);else if(this.hasWatchdog()){const{EditorWatchdog:f}=await import("ckeditor5");c=new f(n),await c.create(e,a),l=c.editor}else l=await n.create(e,a);return{contextId:d,instance:l,watchdog:c}}async reinitializeEditor(){this.instance&&(this.instancePromise=Promise.withResolvers(),await this.#d(),this.instance=null),this.style.display="block",!this.isMultiroot()&&!this.isDecoupled()&&(this.innerHTML=`<${this.#n}>${this.#e}</${this.#n}>`,this.#p()),this.isMultiroot()?this.editables=new y(this,this.#h()):this.isDecoupled()?this.editables=null:this.editables=this.#h();try{const{watchdog:t,instance:e,contextId:i}=await this.#u(this.editables||this.#l().initialData||"");this.watchdog=t,this.instance=e,this.#i=i,this.#f(),this.#g(),this.#m(),this.instancePromise.resolve(this.instance);const n=new CustomEvent("editor-ready",{detail:this.instance});this.dispatchEvent(n),this.oneditorready?.(n)}catch(t){throw this.instancePromise.reject(t),t}}#m(){const t=i=>this.instance.getData({rootName:i}),e=()=>this.instance?.model.document.getRootNames().reduce((i,n)=>({...i,[n]:t(n)}),{});this.instance?.model.document.on("change:data",()=>{const i=new CustomEvent("editor-change",{detail:{editor:this.instance,data:e()},bubbles:!0});this.dispatchEvent(i),this.oneditorchange?.(i)})}isClassic(){return this.getAttribute("type")==="ClassicEditor"}isBallon(){return this.getAttribute("type")==="BalloonEditor"}isMultiroot(){return this.getAttribute("type")==="MultiRootEditor"}isDecoupled(){return this.getAttribute("type")==="DecoupledEditor"}hasWatchdog(){return this.getAttribute("watchdog")==="true"}#h(){if(this.isDecoupled())return{};if(this.isMultiroot())return[...this.querySelectorAll("ckeditor-editable-component")].reduce((i,n)=>{if(!n.name)throw new Error('Editable component missing required "name" attribute');return i[n.name]=n,i},Object.create(null));const t=this.querySelector(this.#n);if(!t)throw new Error(`No ${this.#n} element found`);return{main:t}}#p(){const t=this.querySelector("textarea");if(t)for(const e of m.inputAttributes)this.hasAttribute(e)&&t.setAttribute(e,this.getAttribute(e))}#f(){if(!this.instance)return;const t=this.querySelector("textarea");if(!t)return;const e=()=>{this.style.position="relative",t.innerHTML="",t.value=this.instance.getData(),t.tabIndex=-1,Object.assign(t.style,{display:"flex",position:"absolute",bottom:"0",left:"50%",width:"1px",height:"1px",opacity:"0",pointerEvents:"none",margin:"0",padding:"0",border:"none"})};e(),this.instance.model.document.on("change:data",()=>{t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0})),e()})}#g(){if(!this.isClassic()&&!this.isBallon())return;const{instance:t}=this,e=Number.parseInt(this.getAttribute("editable-height"),10);Number.isNaN(e)||t.editing.view.change(i=>{i.setStyle("height",`${e}px`,t.editing.view.document.getRoot())})}#c(){return this.#s||=JSON.parse(this.getAttribute("bundle"))}async#b(){await E(this.#c()?.stylesheets||[])}async#w(){const t=(this.#c()?.scripts||[]).filter(e=>!!e.window_name);await h(t)}async#y(){const t=this.#c()?.scripts.filter(e=>e.translation);return h(t)}async#E(){const t=this.getAttribute("plugins"),i=(t?JSON.parse(t):[]).map(n=>typeof n=="string"?{import_name:"ckeditor5",import_as:n}:n);return h(i)}async#v(){const t=await import("ckeditor5"),e=this.getAttribute("type");if(!e||!Object.prototype.hasOwnProperty.call(t,e))throw new Error(`Invalid editor type: ${e}`);return t[e]}}customElements.define("ckeditor-component",m);class O extends HTMLElement{connectedCallback(){p(async()=>{const t=this.getAttribute("name"),e=await this.#e().instancePromise.promise;this.appendChild(e.ui.view[t].element)})}#e(){return this.closest("ckeditor-component")||document.body.querySelector("ckeditor-component")}}customElements.define("ckeditor-ui-part-component",O);
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/helpers/exec-if-dom-ready.ts","../src/helpers/inject-script.ts","../src/helpers/is-safe-key.ts","../src/helpers/load-async-css.ts","../src/helpers/load-async-imports.ts","../src/helpers/resolve-config-element-references.ts","../src/helpers/uid.ts","../src/components/context.ts","../src/components/editable.ts","../src/components/editor/multiroot-editables-tracker.ts","../src/components/editor/editor.ts","../src/components/ui-part.ts"],"sourcesContent":["/**\n * Executes callback when DOM is ready.\n *\n * @param callback - Function to execute when DOM is ready.\n */\nexport function execIfDOMReady(callback: VoidFunction) {\n switch (document.readyState) {\n case 'loading':\n document.addEventListener('DOMContentLoaded', callback, { once: true });\n break;\n\n case 'interactive':\n case 'complete':\n setTimeout(callback, 0);\n break;\n\n default:\n console.warn('Unexpected document.readyState:', document.readyState);\n setTimeout(callback, 0);\n }\n}\n","const SCRIPT_LOAD_PROMISES = new Map();\n\n/**\n * Dynamically loads script files based on configuration.\n * Uses caching to avoid loading the same script multiple times.\n *\n * @param url - URL of the script to load\n */\nexport function injectScript(url: string) {\n if (SCRIPT_LOAD_PROMISES.has(url)) {\n return SCRIPT_LOAD_PROMISES.get(url);\n }\n\n const promise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = resolve;\n script.onerror = reject;\n\n document.head.appendChild(script);\n });\n\n SCRIPT_LOAD_PROMISES.set(url, promise);\n return promise;\n}\n","/**\n * Checks if a key is safe to use in configuration objects to prevent prototype pollution\n *\n * @param key - Key name to check\n * @returns True if key is safe to use\n */\nexport function isSafeKey(key: string) {\n return (\n typeof key === 'string'\n && key !== '__proto__'\n && key !== 'constructor'\n && key !== 'prototype'\n );\n}\n","/**\n * Checks if stylesheet with given href already exists in document\n *\n * @param href - Stylesheet URL to check\n * @returns True if stylesheet already exists\n */\nfunction stylesheetExists(href: string) {\n return Array\n .from(document.styleSheets)\n .some(sheet =>\n sheet.href === href || sheet.href === new URL(href, window.location.href).href,\n );\n}\n\n/**\n * Dynamically loads CSS files based on configuration\n *\n * @param stylesheets - Array of CSS file URLs to load\n * @returns Array of promises for each CSS file load\n * @throws When CSS file loading fails\n */\nexport function loadAsyncCSS(stylesheets: string[] = []) {\n const promises = stylesheets.map(href =>\n new Promise<void>((resolve, reject) => {\n if (stylesheetExists(href)) {\n resolve();\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = href;\n\n link.onerror = reject;\n link.onload = () => resolve();\n\n document.head.appendChild(link);\n }),\n );\n\n return Promise.all(promises);\n}\n","import { injectScript } from './inject-script';\nimport { loadAsyncCSS } from './load-async-css';\n\n/**\n * Dynamically imports modules based on configuration\n *\n * @param imports - Array of import configurations\n * @param imports[].name - Name of inline plugin (for inline type)\n * @param imports[].code - Source code of inline plugin (for inline type)\n * @param imports[].import_name - Module path to import (for external type)\n * @param imports[].import_as - Name to import as (for external type)\n * @param imports[].window_name - Global window object name (for external type)\n * @param imports[].type - Type of import\n * @returns Array of loaded modules\n * @throws When plugin loading fails\n */\nexport function loadAsyncImports(imports: Array<AsyncImportRawDescription | string> = []) {\n const loadExternalPlugin = async ({ url, import_name, import_as, window_name, stylesheets }: AsyncImportRawDescription) => {\n if (stylesheets?.length) {\n await loadAsyncCSS(stylesheets);\n }\n\n if (window_name) {\n function isScriptPresent() {\n return Object.prototype.hasOwnProperty.call(window, window_name!);\n }\n\n if (url && !isScriptPresent()) {\n await injectScript(url);\n }\n\n if (!isScriptPresent()) {\n window.dispatchEvent(\n new CustomEvent(`ckeditor:request-cjs-plugin:${window_name}`),\n );\n }\n\n if (!isScriptPresent()) {\n throw new Error(\n `Plugin window['${window_name}'] not found in global scope. `\n + 'Please ensure the plugin is loaded before CKEditor initialization.',\n );\n }\n\n return (window as any)[window_name!];\n }\n\n const module = await import(import_name!);\n const imported = module[import_as || 'default'];\n\n if (!imported) {\n throw new Error(\n `Plugin \"${import_as || 'default'}\" not found in the ESM module `\n + `\"${import_name}\"! Available imports: ${Object.keys(module).join(', ')}! `\n + 'Consider changing \"import_as\" value.',\n );\n }\n\n return imported;\n };\n\n function uncompressImport(pkg: any) {\n if (typeof pkg === 'string') {\n return loadExternalPlugin({ import_name: 'ckeditor5', import_as: pkg });\n }\n\n return loadExternalPlugin(pkg);\n }\n\n return Promise.all(imports.map(uncompressImport));\n}\n\n/**\n * Type definition for plugin raw descriptor\n */\nexport type AsyncImportRawDescription = {\n url?: string;\n import_name?: string;\n import_as?: string;\n window_name?: string;\n stylesheets?: string[];\n};\n","/**\n * Resolves element references in configuration object.\n * Looks for objects with { $element: \"selector\" } format and replaces them with actual DOM elements.\n *\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved element references\n */\nexport function resolveConfigElementReferences<T>(obj: T): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => resolveConfigElementReferences(item)) as T;\n }\n\n const anyObj = obj as any;\n\n if (anyObj.$element && typeof anyObj.$element === 'string') {\n const element = document.querySelector(anyObj.$element);\n\n if (!element) {\n console.warn(`Element not found for selector: ${anyObj.$element}`);\n }\n\n return (element || null) as T;\n }\n\n const result = Object.create(null);\n\n for (const [key, value] of Object.entries(obj)) {\n result[key] = resolveConfigElementReferences(value);\n }\n\n return result as T;\n}\n","/**\n * Generates a unique identifier string\n *\n * @returns Random string that can be used as unique identifier\n */\nexport function uid() {\n return Math.random().toString(36).substring(2);\n}\n","import type { ContextWatchdog } from 'ckeditor5';\n\nimport { execIfDOMReady, loadAsyncImports, resolveConfigElementReferences } from 'src/helpers';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorContextComponent extends HTMLElement {\n instance: ContextWatchdog | null = null;\n\n instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n #connectedEditors = new Set<CKEditorComponent>();\n\n static get observedAttributes() {\n return ['plugins', 'config'];\n }\n\n async connectedCallback() {\n try {\n execIfDOMReady(() => this.#initializeContext());\n }\n catch (error) {\n console.error('Failed to initialize context:', error);\n this.dispatchEvent(new CustomEvent('context-error', { detail: error }));\n }\n }\n\n async attributeChangedCallback(_: unknown, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null && oldValue !== newValue) {\n await this.#initializeContext();\n }\n }\n\n async disconnectedCallback() {\n if (this.instance) {\n await this.instance.destroy();\n this.instance = null;\n }\n }\n\n /**\n * Register editor component with this context\n *\n * @param editor - Editor component to register.\n */\n registerEditor(editor: CKEditorComponent) {\n this.#connectedEditors.add(editor);\n }\n\n /**\n * Unregister editor component from this context\n *\n * @param editor - Editor component to unregister\n */\n unregisterEditor(editor: CKEditorComponent) {\n this.#connectedEditors.delete(editor);\n }\n\n /**\n * Initialize CKEditor context with shared configuration\n *\n * @private\n */\n async #initializeContext() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n await this.instance.destroy();\n\n this.instance = null;\n }\n\n // Broadcast context initialization event\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach:before', { detail: { element: this } }),\n );\n\n const { Context, ContextWatchdog } = await import('ckeditor5');\n const plugins = await this.#getPlugins();\n const config = this.#getConfig();\n\n // Broadcast context mounting event with configuration\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach', { detail: { config, element: this } }),\n );\n\n this.instance = new ContextWatchdog(Context, {\n crashNumberLimit: 10,\n });\n\n await this.instance.create({\n ...config,\n plugins,\n });\n\n this.instance.on('itemError', (...args) => {\n console.error('Context item error:', ...args);\n });\n\n this.instancePromise.resolve(this.instance);\n this.dispatchEvent(new CustomEvent('context-ready', { detail: this.instance }));\n\n // Reinitialize connected editors.\n await Promise.all(\n [...this.#connectedEditors].map(editor => editor.reinitializeEditor()),\n );\n }\n\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n\n return loadAsyncImports(raw ? JSON.parse(raw) : []);\n }\n\n /**\n * Gets context configuration with resolved element references.\n *\n * @private\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n}\n\ncustomElements.define('ckeditor-context-component', CKEditorContextComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers/exec-if-dom-ready';\n\nexport class CKEditorEditableComponent extends HTMLElement {\n /**\n * List of attributes that trigger updates when changed\n *\n * @static\n * @returns {string[]} Array of attribute names to observe\n */\n static get observedAttributes() {\n return ['name'];\n }\n\n /**\n * Gets the name of this editable region\n */\n get name() {\n return this.getAttribute('name') || 'editable';\n }\n\n /**\n * Gets the actual editable DOM element.\n */\n get editableElement() {\n return this.querySelector('div')!;\n }\n\n /**\n * Lifecycle callback when element is added to DOM\n * Sets up the editable element and registers it with the parent editor\n */\n connectedCallback() {\n execIfDOMReady(() => {\n const editorComponent = this.#queryEditorElement();\n\n if (!editorComponent) {\n throw new Error('ckeditor-editable-component must be a child of ckeditor-component');\n }\n\n this.innerHTML = `<div>${this.innerHTML}</div>`;\n this.style.display = 'block';\n\n if (editorComponent.isDecoupled()) {\n editorComponent.runAfterEditorReady((editor) => {\n this.appendChild((editor.ui.view as any)[this.name].element);\n });\n }\n else {\n if (!this.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n\n editorComponent.editables![this.name] = this;\n }\n });\n }\n\n /**\n * Lifecycle callback for attribute changes\n * Handles name changes and propagates other attributes to editable element\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n if (oldValue === newValue) {\n return;\n }\n\n if (name === 'name') {\n if (!oldValue) {\n return;\n }\n\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n editorComponent.editables![newValue] = editorComponent.editables![oldValue]!;\n delete editorComponent.editables![oldValue];\n }\n }\n else {\n this.editableElement.setAttribute(name, newValue!);\n }\n }\n\n /**\n * Lifecycle callback when element is removed\n * Un-registers this editable from the parent editor\n */\n disconnectedCallback() {\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n delete editorComponent.editables![this.name];\n }\n }\n\n /**\n * Finds the parent editor component\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-editable-component', CKEditorEditableComponent);\n","import type { MultiRootEditor } from 'ckeditor5';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorMultiRootEditablesTracker {\n #editorElement: CKEditorComponent;\n #editables: Record<string, HTMLElement>;\n\n /**\n * Creates new tracker instance wrapped in a Proxy for dynamic property access\n *\n * @param editorElement - Parent editor component reference\n * @param initialEditables - Initial editable elements\n * @returns Proxy wrapping the tracker\n */\n constructor(\n editorElement: CKEditorComponent,\n initialEditables: Record<string, HTMLElement> = {},\n ) {\n this.#editorElement = editorElement;\n this.#editables = initialEditables;\n\n return new Proxy(this, {\n /**\n * Handles property access, returns class methods or editable elements\n *\n * @param target - The tracker instance\n * @param name - Property name being accessed\n */\n get(target: CKEditorMultiRootEditablesTracker, name: string) {\n if (typeof (target as any)[name] === 'function') {\n return (target as any)[name].bind(target);\n }\n\n return target.#editables[name];\n },\n\n /**\n * Handles setting new editable elements, triggers root attachment\n *\n * @param target - The tracker instance\n * @param name - Name of the editable root\n * @param element - Element to attach as editable\n */\n set(target: CKEditorMultiRootEditablesTracker, name: string, element: HTMLElement) {\n if (target.#editables[name] !== element) {\n void target.attachRoot(name, element);\n target.#editables[name] = element;\n }\n return true;\n },\n\n /**\n * Handles removing editable elements, triggers root detachment\n *\n * @param target - The tracker instance\n * @param name - Name of the root to remove\n */\n deleteProperty(target: CKEditorMultiRootEditablesTracker, name: string) {\n void target.detachRoot(name);\n delete target.#editables[name];\n\n return true;\n },\n });\n }\n\n /**\n * Attaches a new editable root to the editor.\n * Creates new editor root and binds UI elements.\n *\n * @param name - Name of the editable root\n * @param element - DOM element to use as editable\n * @returns Resolves when root is attached\n */\n async attachRoot(name: string, element: HTMLElement) {\n await this.detachRoot(name);\n\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const { ui, editing, model } = editor;\n\n editor.addRoot(name, {\n isUndoable: false,\n data: element.innerHTML,\n });\n\n const root = model.document.getRoot(name);\n\n if (ui.getEditableElement(name)) {\n editor.detachEditable(root!);\n }\n\n const editable = ui.view.createEditable(name, element);\n ui.addEditable(editable);\n editing.view.forceRender();\n });\n }\n\n /**\n * Detaches an editable root from the editor.\n * Removes editor root and cleans up UI bindings.\n *\n * @param name - Name of root to detach\n * @returns Resolves when root is detached\n */\n async detachRoot(name: string) {\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const root = editor.model.document.getRoot(name);\n\n if (root) {\n editor.detachEditable(root);\n editor.detachRoot(name, true);\n }\n });\n }\n\n /**\n * Gets all currently tracked editable elements\n *\n * @returns Map of all editable elements\n */\n getAll() {\n return this.#editables;\n }\n}\n","import type { Editor, EditorWatchdog, Watchdog } from 'ckeditor5';\n\nimport type { AsyncImportRawDescription } from '../../helpers';\nimport type { CKEditorContextComponent } from '../context';\nimport type { CKEditorEditableComponent } from '../editable';\n\nimport {\n execIfDOMReady,\n isSafeKey,\n loadAsyncCSS,\n loadAsyncImports,\n resolveConfigElementReferences,\n uid,\n} from '../../helpers';\nimport { CKEditorMultiRootEditablesTracker } from './multiroot-editables-tracker';\n\nexport class CKEditorComponent extends HTMLElement {\n instancePromise = Promise.withResolvers<Editor>();\n\n watchdog: Watchdog | null = null;\n\n instance: Editor | null = null;\n\n editables: Record<string, HTMLElement> | null = Object.create({});\n\n #initialHTML: string = '';\n\n #context: CKEditorContextComponent | null = null;\n\n #contextEditorId: string | null = null;\n\n #bundle: object | null = null;\n\n /**\n * List of attributes that trigger updates when changed.\n */\n static get observedAttributes() {\n return ['config', 'plugins', 'translations', 'type'];\n }\n\n /**\n * List of input attributes that trigger updates when changed.\n */\n static get inputAttributes() {\n return ['name', 'required', 'value'];\n }\n\n get oneditorchange() {\n return this.#getEventHandler('editorchange');\n }\n\n set oneditorchange(handler) {\n this.#setEventHandler('editorchange', handler);\n }\n\n get oneditorready() {\n return this.#getEventHandler('editorready');\n }\n\n set oneditorready(handler) {\n this.#setEventHandler('editorready', handler);\n }\n\n get oneditorerror() {\n return this.#getEventHandler('editorerror');\n }\n\n set oneditorerror(handler) {\n this.#setEventHandler('editorerror', handler);\n }\n\n /**\n * Gets event handler function from attribute or property\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @returns Event handler or null\n */\n #getEventHandler(name: string): Function | null {\n if (this.hasAttribute(`on${name}`)) {\n const handler = this.getAttribute(`on${name}`)!;\n\n if (!isSafeKey(handler)) {\n throw new Error(`Unsafe event handler attribute value: ${handler}`);\n }\n\n // eslint-disable-next-line no-new-func\n return (window as any)[handler] || new Function('event', handler);\n }\n return (this as any)[`#${name}Handler`];\n }\n\n /**\n * Sets event handler function\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @param handler - Event handler\n */\n #setEventHandler(name: string, handler: Function | null) {\n if (typeof handler === 'string') {\n this.setAttribute(`on${name}`, handler);\n }\n else {\n this.removeAttribute(`on${name}`);\n (this as any)[`#${name}Handler`] = handler;\n }\n }\n\n /**\n * Lifecycle callback when element is connected to DOM\n * Initializes the editor when DOM is ready\n *\n * @protected\n */\n connectedCallback() {\n this.#context = this.closest('ckeditor-context-component');\n this.#initialHTML = this.innerHTML;\n\n try {\n execIfDOMReady(async () => {\n if (this.#context) {\n await this.#context.instancePromise.promise;\n this.#context.registerEditor(this);\n }\n\n await this.reinitializeEditor();\n });\n }\n catch (error) {\n console.error('Failed to initialize editor:', error);\n\n const event = new CustomEvent('editor-error', { detail: error });\n\n this.dispatchEvent(event);\n this.oneditorerror?.(event);\n }\n }\n\n /**\n * Handles attribute changes and reinitializes editor if needed\n *\n * @protected\n * @param name - Name of changed attribute\n * @param oldValue - Previous attribute value\n * @param newValue - New attribute value\n */\n async attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null\n && oldValue !== newValue\n && CKEditorComponent.observedAttributes.includes(name) && this.isConnected) {\n await this.reinitializeEditor();\n }\n }\n\n /**\n * Lifecycle callback when element is removed from DOM\n * Destroys the editor instance\n * @protected\n */\n async disconnectedCallback() {\n if (this.#context) {\n this.#context.unregisterEditor(this);\n }\n\n try {\n await this.#destroy();\n }\n catch (error) {\n console.error('Failed to destroy editor:', error);\n }\n }\n\n /**\n * Runs a callback after the editor is ready. It waits for editor\n * initialization if needed.\n *\n * @param callback - Callback to run\n */\n runAfterEditorReady<E extends Editor>(callback: (editor: E) => void): Promise<void> {\n if (this.instance) {\n return Promise.resolve(callback(this.instance as unknown as E));\n }\n\n return this.instancePromise.promise.then(callback as unknown as any);\n }\n\n /**\n * Determines appropriate editor element tag based on editor type\n */\n get #editorElementTag() {\n switch (this.getAttribute('type')) {\n case 'ClassicEditor':\n return 'textarea';\n\n default:\n return 'div';\n }\n }\n\n /**\n * Gets the CKEditor context instance if available.\n */\n get #contextWatchdog() {\n return this.#context?.instance;\n }\n\n /**\n * Destroys the editor instance and watchdog if available\n */\n async #destroy() {\n if (this.#contextEditorId) {\n await this.#contextWatchdog!.remove(this.#contextEditorId);\n }\n\n await this.instance?.destroy();\n this.watchdog?.destroy();\n }\n\n /**\n * Gets editor configuration with resolved element references\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n\n /**\n * Creates a new CKEditor instance\n */\n async #initializeEditor(editablesOrContent: Record<string, HTMLElement | string> | CKEditorMultiRootEditablesTracker | string | HTMLElement) {\n await Promise.all([\n this.#ensureStylesheetsInjected(),\n this.#ensureWindowScriptsInjected(),\n ]);\n\n // Depending on the type of the editor the content supplied on the first\n // argument is different. For ClassicEditor it's a element or string, for MultiRootEditor\n // it's an object with editables, for DecoupledEditor it's string.\n let content: any = editablesOrContent;\n\n if (editablesOrContent instanceof CKEditorMultiRootEditablesTracker) {\n content = editablesOrContent.getAll();\n }\n else if (typeof editablesOrContent !== 'string') {\n content = (editablesOrContent as any)['main'];\n }\n\n // Broadcast editor initialization event. It's good time to load add inline window plugins.\n const beforeInitEventDetails = {\n ...content instanceof HTMLElement && { element: content },\n ...typeof content === 'string' && { data: content },\n ...content instanceof Object && { editables: content },\n };\n\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach:before', { detail: beforeInitEventDetails }),\n );\n\n // Start fetching constructor.\n const Editor = await this.#getEditorConstructor();\n const [plugins, translations] = await Promise.all([\n this.#getPlugins(),\n this.#getTranslations(),\n ]);\n\n const config = {\n ...this.#getConfig(),\n ...translations.length && {\n translations,\n },\n plugins,\n };\n\n // Broadcast editor mounting event. It's good time to map configuration.\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach', { detail: { config, ...beforeInitEventDetails } }),\n );\n\n console.warn('Initializing CKEditor with:', { config, watchdog: this.hasWatchdog(), context: this.#context });\n\n // Initialize watchdog if needed\n let watchdog: EditorWatchdog | null = null;\n let instance: Editor | null = null;\n let contextId: string | null = null;\n\n if (this.#context) {\n contextId = uid();\n\n await this.#contextWatchdog!.add({\n creator: (_element, _config) => Editor.create(_element, _config),\n id: contextId,\n sourceElementOrData: content,\n type: 'editor',\n config,\n });\n\n instance = this.#contextWatchdog!.getItem(contextId) as Editor;\n }\n else if (this.hasWatchdog()) {\n // Let's create use with plain watchdog.\n const { EditorWatchdog } = await import('ckeditor5');\n watchdog = new EditorWatchdog(Editor);\n\n await watchdog.create(content, config);\n\n instance = watchdog.editor;\n }\n else {\n // Let's create the editor without watchdog.\n instance = await Editor.create(content, config);\n }\n\n console.warn('CKEditor initialized:', {\n instance,\n watchdog,\n config: (instance!.config as any)._config,\n });\n\n return {\n contextId,\n instance,\n watchdog,\n };\n }\n\n /**\n * Re-initializes the editor by destroying existing instance and creating new one\n *\n * @private\n * @returns {Promise<void>}\n */\n async reinitializeEditor() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers();\n\n await this.#destroy();\n\n this.instance = null;\n }\n\n this.style.display = 'block';\n\n if (!this.isMultiroot() && !this.isDecoupled()) {\n this.innerHTML = `<${this.#editorElementTag}>${this.#initialHTML}</${this.#editorElementTag}>`;\n this.#assignInputAttributes();\n }\n\n // Let's track changes in editables if it's a multiroot editor.\n if (this.isMultiroot()) {\n this.editables = new CKEditorMultiRootEditablesTracker(this, this.#queryEditables()) as unknown as Record<string, HTMLElement>;\n }\n else if (this.isDecoupled()) {\n this.editables = null;\n }\n else {\n this.editables = this.#queryEditables();\n }\n\n try {\n const { watchdog, instance, contextId } = await this.#initializeEditor(this.editables || this.#getConfig().initialData || '');\n\n this.watchdog = watchdog;\n this.instance = instance!;\n this.#contextEditorId = contextId;\n\n this.#setupContentSync();\n this.#setupEditableHeight();\n this.#setupDataChangeListener();\n\n this.instancePromise.resolve(this.instance!);\n\n // Broadcast editor ready event\n const event = new CustomEvent('editor-ready', { detail: this.instance });\n\n this.dispatchEvent(event);\n this.oneditorready?.(event);\n }\n catch (err) {\n this.instancePromise.reject(err);\n throw err;\n }\n }\n\n /**\n * Sets up data change listener that broadcasts content changes\n */\n #setupDataChangeListener() {\n const getRootContent = (rootName: string) => this.instance!.getData({ rootName });\n const getAllRoots = () =>\n this.instance?.model.document\n .getRootNames()\n .reduce((acc, rootName) => ({\n ...acc,\n [rootName]: getRootContent(rootName),\n }), {});\n\n this.instance?.model.document.on('change:data', () => {\n const event = new CustomEvent('editor-change', {\n detail: {\n editor: this.instance,\n data: getAllRoots(),\n },\n bubbles: true,\n });\n\n this.dispatchEvent(event);\n this.oneditorchange?.(event);\n });\n }\n\n /**\n * Checks if current editor is classic type\n */\n isClassic() {\n return this.getAttribute('type') === 'ClassicEditor';\n }\n\n /**\n * Checks if current editor is balloon type\n */\n isBallon() {\n return this.getAttribute('type') === 'BalloonEditor';\n }\n\n /**\n * Checks if current editor is multiroot type\n */\n isMultiroot() {\n return this.getAttribute('type') === 'MultiRootEditor';\n }\n\n /**\n * Checks if current editor is decoupled type\n */\n isDecoupled() {\n return this.getAttribute('type') === 'DecoupledEditor';\n }\n\n /**\n * Checks if current editor has watchdog enabled\n */\n hasWatchdog() {\n return this.getAttribute('watchdog') === 'true';\n }\n\n /**\n * Queries and validates editable elements\n */\n #queryEditables() {\n if (this.isDecoupled()) {\n return {};\n }\n\n if (this.isMultiroot()) {\n const editables = [...this.querySelectorAll('ckeditor-editable-component')] as CKEditorEditableComponent[];\n\n return editables.reduce((acc, element) => {\n if (!element.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n acc[element.name] = element;\n return acc;\n }, Object.create(null));\n }\n\n const mainEditable = this.querySelector(this.#editorElementTag);\n\n if (!mainEditable) {\n throw new Error(`No ${this.#editorElementTag} element found`);\n }\n\n return { main: mainEditable };\n }\n\n /**\n * Copies input-related attributes from component to the main editable element\n *\n * @private\n */\n #assignInputAttributes() {\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n for (const attr of CKEditorComponent.inputAttributes) {\n if (this.hasAttribute(attr)) {\n textarea.setAttribute(attr, this.getAttribute(attr)!);\n }\n }\n }\n\n /**\n * Sets up content sync between editor and textarea element.\n *\n * @private\n */\n #setupContentSync() {\n if (!this.instance) {\n return;\n }\n\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n // Initial sync\n const syncInput = () => {\n this.style.position = 'relative';\n\n textarea.innerHTML = '';\n textarea.value = this.instance!.getData();\n textarea.tabIndex = -1;\n\n Object.assign(textarea.style, {\n display: 'flex',\n position: 'absolute',\n bottom: '0',\n left: '50%',\n width: '1px',\n height: '1px',\n opacity: '0',\n pointerEvents: 'none',\n margin: '0',\n padding: '0',\n border: 'none',\n });\n };\n\n syncInput();\n\n // Listen for changes\n this.instance.model.document.on('change:data', () => {\n textarea.dispatchEvent(new Event('input', { bubbles: true }));\n textarea.dispatchEvent(new Event('change', { bubbles: true }));\n\n syncInput();\n });\n }\n\n /**\n * Sets up editable height for ClassicEditor\n *\n * @private\n */\n #setupEditableHeight() {\n if (!this.isClassic() && !this.isBallon()) {\n return;\n }\n\n const { instance } = this;\n const height = Number.parseInt(this.getAttribute('editable-height')!, 10);\n\n if (Number.isNaN(height)) {\n return;\n }\n\n instance!.editing.view.change((writer) => {\n writer.setStyle('height', `${height}px`, instance!.editing.view.document.getRoot()!);\n });\n }\n\n /**\n * Gets bundle JSON description from translations attribute\n */\n #getBundle(): BundleDescription {\n return this.#bundle ||= JSON.parse(this.getAttribute('bundle')!);\n }\n\n /**\n * Checks if all required stylesheets are injected. If not, inject.\n */\n async #ensureStylesheetsInjected() {\n await loadAsyncCSS(this.#getBundle()?.stylesheets || []);\n }\n\n /**\n * Checks if all required scripts are injected. If not, inject.\n */\n async #ensureWindowScriptsInjected() {\n const windowScripts = (this.#getBundle()?.scripts || []).filter(script => !!script.window_name);\n\n await loadAsyncImports(windowScripts);\n }\n\n /**\n * Loads translation modules\n */\n async #getTranslations() {\n const translations = this.#getBundle()?.scripts.filter(script => script.translation);\n\n return loadAsyncImports(translations);\n }\n\n /**\n * Loads plugin modules\n */\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n const items = raw ? JSON.parse(raw) : [];\n const mappedItems = items.map((item: any) =>\n typeof item === 'string'\n ? { import_name: 'ckeditor5', import_as: item }\n : item,\n );\n\n return loadAsyncImports(mappedItems);\n }\n\n /**\n * Gets editor constructor based on type attribute\n */\n async #getEditorConstructor() {\n const CKEditor = await import('ckeditor5');\n const editorType = this.getAttribute('type');\n\n if (!editorType || !Object.prototype.hasOwnProperty.call(CKEditor, editorType)) {\n throw new Error(`Invalid editor type: ${editorType}`);\n }\n\n return (CKEditor as any)[editorType] as EditorConstructor;\n }\n}\n\ntype EditorConstructor = {\n create: (...args: any[]) => Promise<Editor>;\n};\n\ntype BundleDescription = {\n stylesheets: string[];\n scripts: Array<AsyncImportRawDescription & {\n translation?: boolean;\n }>;\n};\n\ncustomElements.define('ckeditor-component', CKEditorComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers';\n\nclass CKEditorUIPartComponent extends HTMLElement {\n /**\n * Lifecycle callback when element is added to DOM.\n * Adds the toolbar to the editor UI.\n */\n connectedCallback() {\n execIfDOMReady(async () => {\n const uiPart = this.getAttribute('name')!;\n const editor = await this.#queryEditorElement()!.instancePromise.promise;\n\n this.appendChild((editor.ui.view as any)[uiPart].element);\n });\n }\n\n /**\n * Finds the parent editor component.\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-ui-part-component', CKEditorUIPartComponent);\n"],"names":["execIfDOMReady","callback","SCRIPT_LOAD_PROMISES","injectScript","url","promise","resolve","reject","script","isSafeKey","key","stylesheetExists","href","sheet","loadAsyncCSS","stylesheets","promises","link","loadAsyncImports","imports","loadExternalPlugin","import_name","import_as","window_name","isScriptPresent","module","imported","uncompressImport","pkg","resolveConfigElementReferences","obj","item","anyObj","element","result","value","uid","CKEditorContextComponent","#connectedEditors","#initializeContext","error","_","oldValue","newValue","editor","Context","ContextWatchdog","plugins","#getPlugins","config","#getConfig","args","raw","CKEditorEditableComponent","editorComponent","#queryEditorElement","name","CKEditorMultiRootEditablesTracker","#editorElement","#editables","editorElement","initialEditables","target","ui","editing","model","root","editable","CKEditorComponent","#initialHTML","#context","#contextEditorId","#bundle","#getEventHandler","handler","#setEventHandler","event","#destroy","#editorElementTag","#contextWatchdog","#initializeEditor","editablesOrContent","#ensureStylesheetsInjected","#ensureWindowScriptsInjected","content","beforeInitEventDetails","Editor","#getEditorConstructor","translations","#getTranslations","watchdog","instance","contextId","_element","_config","EditorWatchdog","#assignInputAttributes","#queryEditables","#setupContentSync","#setupEditableHeight","#setupDataChangeListener","err","getRootContent","rootName","getAllRoots","acc","mainEditable","textarea","attr","syncInput","height","writer","#getBundle","windowScripts","mappedItems","CKEditor","editorType","CKEditorUIPartComponent","uiPart"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/helpers/exec-if-dom-ready.ts","../src/helpers/inject-script.ts","../src/helpers/is-safe-key.ts","../src/helpers/load-async-css.ts","../src/helpers/load-async-imports.ts","../src/helpers/resolve-config-element-references.ts","../src/helpers/uid.ts","../src/components/context.ts","../src/components/editable.ts","../src/components/editor/multiroot-editables-tracker.ts","../src/components/editor/editor.ts","../src/components/ui-part.ts"],"sourcesContent":["/**\n * Executes callback when DOM is ready.\n *\n * @param callback - Function to execute when DOM is ready.\n */\nexport function execIfDOMReady(callback: VoidFunction) {\n switch (document.readyState) {\n case 'loading':\n document.addEventListener('DOMContentLoaded', callback, { once: true });\n break;\n\n case 'interactive':\n case 'complete':\n setTimeout(callback, 0);\n break;\n\n default:\n console.warn('Unexpected document.readyState:', document.readyState);\n setTimeout(callback, 0);\n }\n}\n","const SCRIPT_LOAD_PROMISES = new Map();\n\n/**\n * Dynamically loads script files based on configuration.\n * Uses caching to avoid loading the same script multiple times.\n *\n * @param url - URL of the script to load\n */\nexport function injectScript(url: string) {\n if (SCRIPT_LOAD_PROMISES.has(url)) {\n return SCRIPT_LOAD_PROMISES.get(url);\n }\n\n const promise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = resolve;\n script.onerror = reject;\n\n document.head.appendChild(script);\n });\n\n SCRIPT_LOAD_PROMISES.set(url, promise);\n return promise;\n}\n","/**\n * Checks if a key is safe to use in configuration objects to prevent prototype pollution\n *\n * @param key - Key name to check\n * @returns True if key is safe to use\n */\nexport function isSafeKey(key: string) {\n return (\n typeof key === 'string'\n && key !== '__proto__'\n && key !== 'constructor'\n && key !== 'prototype'\n );\n}\n","/**\n * Checks if stylesheet with given href already exists in document\n *\n * @param href - Stylesheet URL to check\n * @returns True if stylesheet already exists\n */\nfunction stylesheetExists(href: string) {\n return Array\n .from(document.styleSheets)\n .some(sheet =>\n sheet.href === href || sheet.href === new URL(href, window.location.href).href,\n );\n}\n\n/**\n * Dynamically loads CSS files based on configuration\n *\n * @param stylesheets - Array of CSS file URLs to load\n * @returns Array of promises for each CSS file load\n * @throws When CSS file loading fails\n */\nexport function loadAsyncCSS(stylesheets: string[] = []) {\n const promises = stylesheets.map(href =>\n new Promise<void>((resolve, reject) => {\n if (stylesheetExists(href)) {\n resolve();\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = href;\n\n link.onerror = reject;\n link.onload = () => resolve();\n\n document.head.appendChild(link);\n }),\n );\n\n return Promise.all(promises);\n}\n","import { injectScript } from './inject-script';\nimport { loadAsyncCSS } from './load-async-css';\n\n/**\n * Dynamically imports modules based on configuration\n *\n * @param imports - Array of import configurations\n * @param imports[].name - Name of inline plugin (for inline type)\n * @param imports[].code - Source code of inline plugin (for inline type)\n * @param imports[].import_name - Module path to import (for external type)\n * @param imports[].import_as - Name to import as (for external type)\n * @param imports[].window_name - Global window object name (for external type)\n * @param imports[].type - Type of import\n * @returns Array of loaded modules\n * @throws When plugin loading fails\n */\nexport function loadAsyncImports(imports: Array<AsyncImportRawDescription | string> = []) {\n const loadExternalPlugin = async ({ url, import_name, import_as, window_name, stylesheets }: AsyncImportRawDescription) => {\n if (stylesheets?.length) {\n await loadAsyncCSS(stylesheets);\n }\n\n if (window_name) {\n function isScriptPresent() {\n return Object.prototype.hasOwnProperty.call(window, window_name!);\n }\n\n if (url && !isScriptPresent()) {\n await injectScript(url);\n }\n\n if (!isScriptPresent()) {\n window.dispatchEvent(\n new CustomEvent(`ckeditor:request-cjs-plugin:${window_name}`),\n );\n }\n\n if (!isScriptPresent()) {\n throw new Error(\n `Plugin window['${window_name}'] not found in global scope. `\n + 'Please ensure the plugin is loaded before CKEditor initialization.',\n );\n }\n\n return (window as any)[window_name!];\n }\n\n const module = await import(import_name!);\n const imported = module[import_as || 'default'];\n\n if (!imported) {\n throw new Error(\n `Plugin \"${import_as || 'default'}\" not found in the ESM module `\n + `\"${import_name}\"! Available imports: ${Object.keys(module).join(', ')}! `\n + 'Consider changing \"import_as\" value.',\n );\n }\n\n return imported;\n };\n\n function uncompressImport(pkg: any) {\n if (typeof pkg === 'string') {\n return loadExternalPlugin({ import_name: 'ckeditor5', import_as: pkg });\n }\n\n return loadExternalPlugin(pkg);\n }\n\n return Promise.all(imports.map(uncompressImport));\n}\n\n/**\n * Type definition for plugin raw descriptor\n */\nexport type AsyncImportRawDescription = {\n url?: string;\n import_name?: string;\n import_as?: string;\n window_name?: string;\n stylesheets?: string[];\n};\n","/**\n * Resolves element references in configuration object.\n * Looks for objects with { $element: \"selector\" } format and replaces them with actual DOM elements.\n *\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved element references\n */\nexport function resolveConfigElementReferences<T>(obj: T): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => resolveConfigElementReferences(item)) as T;\n }\n\n const anyObj = obj as any;\n\n if (anyObj.$element && typeof anyObj.$element === 'string') {\n const element = document.querySelector(anyObj.$element);\n\n if (!element) {\n console.warn(`Element not found for selector: ${anyObj.$element}`);\n }\n\n return (element || null) as T;\n }\n\n const result = Object.create(null);\n\n for (const [key, value] of Object.entries(obj)) {\n result[key] = resolveConfigElementReferences(value);\n }\n\n return result as T;\n}\n","/**\n * Generates a unique identifier string\n *\n * @returns Random string that can be used as unique identifier\n */\nexport function uid() {\n return Math.random().toString(36).substring(2);\n}\n","import type { ContextWatchdog } from 'ckeditor5';\n\nimport { execIfDOMReady, loadAsyncImports, resolveConfigElementReferences } from 'src/helpers';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorContextComponent extends HTMLElement {\n instance: ContextWatchdog | null = null;\n\n instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n #connectedEditors = new Set<CKEditorComponent>();\n\n static get observedAttributes() {\n return ['plugins', 'config'];\n }\n\n async connectedCallback() {\n try {\n execIfDOMReady(() => this.#initializeContext());\n }\n catch (error) {\n console.error('Failed to initialize context:', error);\n this.dispatchEvent(new CustomEvent('context-error', { detail: error }));\n }\n }\n\n async attributeChangedCallback(_: unknown, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null && oldValue !== newValue) {\n await this.#initializeContext();\n }\n }\n\n async disconnectedCallback() {\n if (this.instance) {\n await this.instance.destroy();\n this.instance = null;\n }\n }\n\n /**\n * Register editor component with this context\n *\n * @param editor - Editor component to register.\n */\n registerEditor(editor: CKEditorComponent) {\n this.#connectedEditors.add(editor);\n }\n\n /**\n * Unregister editor component from this context\n *\n * @param editor - Editor component to unregister\n */\n unregisterEditor(editor: CKEditorComponent) {\n this.#connectedEditors.delete(editor);\n }\n\n /**\n * Initialize CKEditor context with shared configuration\n *\n * @private\n */\n async #initializeContext() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n await this.instance.destroy();\n\n this.instance = null;\n }\n\n // Broadcast context initialization event\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach:before', { detail: { element: this } }),\n );\n\n const { Context, ContextWatchdog } = await import('ckeditor5');\n const plugins = await this.#getPlugins();\n const config = this.#getConfig();\n\n // Broadcast context mounting event with configuration\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach', { detail: { config, element: this } }),\n );\n\n this.instance = new ContextWatchdog(Context, {\n crashNumberLimit: 10,\n });\n\n await this.instance.create({\n ...config,\n plugins,\n });\n\n this.instance.on('itemError', (...args) => {\n console.error('Context item error:', ...args);\n });\n\n this.instancePromise.resolve(this.instance);\n this.dispatchEvent(new CustomEvent('context-ready', { detail: this.instance }));\n\n // Reinitialize connected editors.\n await Promise.all(\n [...this.#connectedEditors].map(editor => editor.reinitializeEditor()),\n );\n }\n\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n\n return loadAsyncImports(raw ? JSON.parse(raw) : []);\n }\n\n /**\n * Gets context configuration with resolved element references.\n *\n * @private\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n}\n\ncustomElements.define('ckeditor-context-component', CKEditorContextComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers/exec-if-dom-ready';\n\nexport class CKEditorEditableComponent extends HTMLElement {\n /**\n * List of attributes that trigger updates when changed\n *\n * @static\n * @returns {string[]} Array of attribute names to observe\n */\n static get observedAttributes() {\n return ['name'];\n }\n\n /**\n * Gets the name of this editable region\n */\n get name() {\n return this.getAttribute('name') || 'editable';\n }\n\n /**\n * Gets the actual editable DOM element.\n */\n get editableElement() {\n return this.querySelector('div')!;\n }\n\n /**\n * Lifecycle callback when element is added to DOM\n * Sets up the editable element and registers it with the parent editor\n */\n connectedCallback() {\n execIfDOMReady(() => {\n const editorComponent = this.#queryEditorElement();\n\n if (!editorComponent) {\n throw new Error('ckeditor-editable-component must be a child of ckeditor-component');\n }\n\n this.innerHTML = `<div>${this.innerHTML}</div>`;\n this.style.display = 'block';\n\n if (editorComponent.isDecoupled()) {\n editorComponent.runAfterEditorReady((editor) => {\n this.appendChild((editor.ui.view as any)[this.name].element);\n });\n }\n else {\n if (!this.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n\n editorComponent.editables![this.name] = this;\n }\n });\n }\n\n /**\n * Lifecycle callback for attribute changes\n * Handles name changes and propagates other attributes to editable element\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n if (oldValue === newValue) {\n return;\n }\n\n if (name === 'name') {\n if (!oldValue) {\n return;\n }\n\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n editorComponent.editables![newValue] = editorComponent.editables![oldValue]!;\n delete editorComponent.editables![oldValue];\n }\n }\n else {\n this.editableElement.setAttribute(name, newValue!);\n }\n }\n\n /**\n * Lifecycle callback when element is removed\n * Un-registers this editable from the parent editor\n */\n disconnectedCallback() {\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n delete editorComponent.editables![this.name];\n }\n }\n\n /**\n * Finds the parent editor component\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-editable-component', CKEditorEditableComponent);\n","import type { MultiRootEditor } from 'ckeditor5';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorMultiRootEditablesTracker {\n #editorElement: CKEditorComponent;\n #editables: Record<string, HTMLElement>;\n\n /**\n * Creates new tracker instance wrapped in a Proxy for dynamic property access\n *\n * @param editorElement - Parent editor component reference\n * @param initialEditables - Initial editable elements\n * @returns Proxy wrapping the tracker\n */\n constructor(\n editorElement: CKEditorComponent,\n initialEditables: Record<string, HTMLElement> = {},\n ) {\n this.#editorElement = editorElement;\n this.#editables = initialEditables;\n\n return new Proxy(this, {\n /**\n * Handles property access, returns class methods or editable elements\n *\n * @param target - The tracker instance\n * @param name - Property name being accessed\n */\n get(target: CKEditorMultiRootEditablesTracker, name: string) {\n if (typeof (target as any)[name] === 'function') {\n return (target as any)[name].bind(target);\n }\n\n return target.#editables[name];\n },\n\n /**\n * Handles setting new editable elements, triggers root attachment\n *\n * @param target - The tracker instance\n * @param name - Name of the editable root\n * @param element - Element to attach as editable\n */\n set(target: CKEditorMultiRootEditablesTracker, name: string, element: HTMLElement) {\n if (target.#editables[name] !== element) {\n void target.attachRoot(name, element);\n target.#editables[name] = element;\n }\n return true;\n },\n\n /**\n * Handles removing editable elements, triggers root detachment\n *\n * @param target - The tracker instance\n * @param name - Name of the root to remove\n */\n deleteProperty(target: CKEditorMultiRootEditablesTracker, name: string) {\n void target.detachRoot(name);\n delete target.#editables[name];\n\n return true;\n },\n });\n }\n\n /**\n * Attaches a new editable root to the editor.\n * Creates new editor root and binds UI elements.\n *\n * @param name - Name of the editable root\n * @param element - DOM element to use as editable\n * @returns Resolves when root is attached\n */\n async attachRoot(name: string, element: HTMLElement) {\n await this.detachRoot(name);\n\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const { ui, editing, model } = editor;\n\n editor.addRoot(name, {\n isUndoable: false,\n data: element.innerHTML,\n });\n\n const root = model.document.getRoot(name);\n\n if (ui.getEditableElement(name)) {\n editor.detachEditable(root!);\n }\n\n const editable = ui.view.createEditable(name, element);\n ui.addEditable(editable);\n editing.view.forceRender();\n });\n }\n\n /**\n * Detaches an editable root from the editor.\n * Removes editor root and cleans up UI bindings.\n *\n * @param name - Name of root to detach\n * @returns Resolves when root is detached\n */\n async detachRoot(name: string) {\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const root = editor.model.document.getRoot(name);\n\n if (root) {\n editor.detachEditable(root);\n editor.detachRoot(name, true);\n }\n });\n }\n\n /**\n * Gets all currently tracked editable elements\n *\n * @returns Map of all editable elements\n */\n getAll() {\n return this.#editables;\n }\n}\n","import type { Editor, EditorWatchdog, Watchdog } from 'ckeditor5';\n\nimport type { AsyncImportRawDescription } from '../../helpers';\nimport type { CKEditorContextComponent } from '../context';\nimport type { CKEditorEditableComponent } from '../editable';\n\nimport {\n execIfDOMReady,\n isSafeKey,\n loadAsyncCSS,\n loadAsyncImports,\n resolveConfigElementReferences,\n uid,\n} from '../../helpers';\nimport { CKEditorMultiRootEditablesTracker } from './multiroot-editables-tracker';\n\nexport class CKEditorComponent extends HTMLElement {\n instancePromise = Promise.withResolvers<Editor>();\n\n watchdog: Watchdog | null = null;\n\n instance: Editor | null = null;\n\n editables: Record<string, HTMLElement> | null = Object.create({});\n\n #initialHTML: string = '';\n\n #context: CKEditorContextComponent | null = null;\n\n #contextEditorId: string | null = null;\n\n #bundle: object | null = null;\n\n /**\n * List of attributes that trigger updates when changed.\n */\n static get observedAttributes() {\n return ['config', 'plugins', 'translations', 'type'];\n }\n\n /**\n * List of input attributes that trigger updates when changed.\n */\n static get inputAttributes() {\n return ['name', 'required', 'value'];\n }\n\n get oneditorchange() {\n return this.#getEventHandler('editorchange');\n }\n\n set oneditorchange(handler) {\n this.#setEventHandler('editorchange', handler);\n }\n\n get oneditorready() {\n return this.#getEventHandler('editorready');\n }\n\n set oneditorready(handler) {\n this.#setEventHandler('editorready', handler);\n }\n\n get oneditorerror() {\n return this.#getEventHandler('editorerror');\n }\n\n set oneditorerror(handler) {\n this.#setEventHandler('editorerror', handler);\n }\n\n /**\n * Gets event handler function from attribute or property\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @returns Event handler or null\n */\n #getEventHandler(name: string): Function | null {\n if (this.hasAttribute(`on${name}`)) {\n const handler = this.getAttribute(`on${name}`)!;\n\n if (!isSafeKey(handler)) {\n throw new Error(`Unsafe event handler attribute value: ${handler}`);\n }\n\n // eslint-disable-next-line no-new-func\n return (window as any)[handler] || new Function('event', handler);\n }\n return (this as any)[`#${name}Handler`];\n }\n\n /**\n * Sets event handler function\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @param handler - Event handler\n */\n #setEventHandler(name: string, handler: Function | null) {\n if (typeof handler === 'string') {\n this.setAttribute(`on${name}`, handler);\n }\n else {\n this.removeAttribute(`on${name}`);\n (this as any)[`#${name}Handler`] = handler;\n }\n }\n\n /**\n * Lifecycle callback when element is connected to DOM\n * Initializes the editor when DOM is ready\n *\n * @protected\n */\n connectedCallback() {\n this.#context = this.closest('ckeditor-context-component');\n this.#initialHTML = this.innerHTML;\n\n try {\n execIfDOMReady(async () => {\n if (this.#context) {\n await this.#context.instancePromise.promise;\n this.#context.registerEditor(this);\n }\n\n await this.reinitializeEditor();\n });\n }\n catch (error) {\n console.error('Failed to initialize editor:', error);\n\n const event = new CustomEvent('editor-error', { detail: error });\n\n this.dispatchEvent(event);\n this.oneditorerror?.(event);\n }\n }\n\n /**\n * Handles attribute changes and reinitializes editor if needed\n *\n * @protected\n * @param name - Name of changed attribute\n * @param oldValue - Previous attribute value\n * @param newValue - New attribute value\n */\n async attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null\n && oldValue !== newValue\n && CKEditorComponent.observedAttributes.includes(name) && this.isConnected) {\n await this.reinitializeEditor();\n }\n }\n\n /**\n * Lifecycle callback when element is removed from DOM\n * Destroys the editor instance\n * @protected\n */\n async disconnectedCallback() {\n if (this.#context) {\n this.#context.unregisterEditor(this);\n }\n\n try {\n await this.#destroy();\n }\n catch (error) {\n console.error('Failed to destroy editor:', error);\n }\n }\n\n /**\n * Runs a callback after the editor is ready. It waits for editor\n * initialization if needed.\n *\n * @param callback - Callback to run\n */\n runAfterEditorReady<E extends Editor>(callback: (editor: E) => void): Promise<void> {\n if (this.instance) {\n return Promise.resolve(callback(this.instance as unknown as E));\n }\n\n return this.instancePromise.promise.then(callback as unknown as any);\n }\n\n /**\n * Determines appropriate editor element tag based on editor type\n */\n get #editorElementTag() {\n switch (this.getAttribute('type')) {\n case 'ClassicEditor':\n return 'textarea';\n\n default:\n return 'div';\n }\n }\n\n /**\n * Gets the CKEditor context instance if available.\n */\n get #contextWatchdog() {\n return this.#context?.instance;\n }\n\n /**\n * Destroys the editor instance and watchdog if available\n */\n async #destroy() {\n if (this.#contextEditorId) {\n await this.#contextWatchdog!.remove(this.#contextEditorId);\n }\n\n await this.instance?.destroy();\n this.watchdog?.destroy();\n }\n\n /**\n * Gets editor configuration with resolved element references\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n\n /**\n * Creates a new CKEditor instance\n */\n async #initializeEditor(editablesOrContent: Record<string, HTMLElement | string> | CKEditorMultiRootEditablesTracker | string | HTMLElement) {\n await Promise.all([\n this.#ensureStylesheetsInjected(),\n this.#ensureWindowScriptsInjected(),\n ]);\n\n // Depending on the type of the editor the content supplied on the first\n // argument is different. For ClassicEditor it's a element or string, for MultiRootEditor\n // it's an object with editables, for DecoupledEditor it's string.\n let content: any = editablesOrContent;\n\n if (editablesOrContent instanceof CKEditorMultiRootEditablesTracker) {\n content = editablesOrContent.getAll();\n }\n else if (typeof editablesOrContent !== 'string') {\n content = (editablesOrContent as any)['main'];\n }\n\n // Broadcast editor initialization event. It's good time to load add inline window plugins.\n const beforeInitEventDetails = {\n ...content instanceof HTMLElement && { element: content },\n ...typeof content === 'string' && { data: content },\n ...content instanceof Object && { editables: content },\n };\n\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach:before', { detail: beforeInitEventDetails }),\n );\n\n // Start fetching constructor.\n const Editor = await this.#getEditorConstructor();\n const [plugins, translations] = await Promise.all([\n this.#getPlugins(),\n this.#getTranslations(),\n ]);\n\n const config = {\n ...this.#getConfig(),\n ...translations.length && {\n translations,\n },\n plugins,\n };\n\n // Broadcast editor mounting event. It's good time to map configuration.\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach', { detail: { config, ...beforeInitEventDetails } }),\n );\n\n // Initialize watchdog if needed\n let watchdog: EditorWatchdog | null = null;\n let instance: Editor | null = null;\n let contextId: string | null = null;\n\n if (this.#context) {\n contextId = uid();\n\n await this.#contextWatchdog!.add({\n creator: (_element, _config) => Editor.create(_element, _config),\n id: contextId,\n sourceElementOrData: content,\n type: 'editor',\n config,\n });\n\n instance = this.#contextWatchdog!.getItem(contextId) as Editor;\n }\n else if (this.hasWatchdog()) {\n // Let's create use with plain watchdog.\n const { EditorWatchdog } = await import('ckeditor5');\n watchdog = new EditorWatchdog(Editor);\n\n await watchdog.create(content, config);\n\n instance = watchdog.editor;\n }\n else {\n // Let's create the editor without watchdog.\n instance = await Editor.create(content, config);\n }\n\n return {\n contextId,\n instance,\n watchdog,\n };\n }\n\n /**\n * Re-initializes the editor by destroying existing instance and creating new one\n *\n * @private\n * @returns {Promise<void>}\n */\n async reinitializeEditor() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers();\n\n await this.#destroy();\n\n this.instance = null;\n }\n\n this.style.display = 'block';\n\n if (!this.isMultiroot() && !this.isDecoupled()) {\n this.innerHTML = `<${this.#editorElementTag}>${this.#initialHTML}</${this.#editorElementTag}>`;\n this.#assignInputAttributes();\n }\n\n // Let's track changes in editables if it's a multiroot editor.\n if (this.isMultiroot()) {\n this.editables = new CKEditorMultiRootEditablesTracker(this, this.#queryEditables()) as unknown as Record<string, HTMLElement>;\n }\n else if (this.isDecoupled()) {\n this.editables = null;\n }\n else {\n this.editables = this.#queryEditables();\n }\n\n try {\n const { watchdog, instance, contextId } = await this.#initializeEditor(this.editables || this.#getConfig().initialData || '');\n\n this.watchdog = watchdog;\n this.instance = instance!;\n this.#contextEditorId = contextId;\n\n this.#setupContentSync();\n this.#setupEditableHeight();\n this.#setupDataChangeListener();\n\n this.instancePromise.resolve(this.instance!);\n\n // Broadcast editor ready event\n const event = new CustomEvent('editor-ready', { detail: this.instance });\n\n this.dispatchEvent(event);\n this.oneditorready?.(event);\n }\n catch (err) {\n this.instancePromise.reject(err);\n throw err;\n }\n }\n\n /**\n * Sets up data change listener that broadcasts content changes\n */\n #setupDataChangeListener() {\n const getRootContent = (rootName: string) => this.instance!.getData({ rootName });\n const getAllRoots = () =>\n this.instance?.model.document\n .getRootNames()\n .reduce((acc, rootName) => ({\n ...acc,\n [rootName]: getRootContent(rootName),\n }), {});\n\n this.instance?.model.document.on('change:data', () => {\n const event = new CustomEvent('editor-change', {\n detail: {\n editor: this.instance,\n data: getAllRoots(),\n },\n bubbles: true,\n });\n\n this.dispatchEvent(event);\n this.oneditorchange?.(event);\n });\n }\n\n /**\n * Checks if current editor is classic type\n */\n isClassic() {\n return this.getAttribute('type') === 'ClassicEditor';\n }\n\n /**\n * Checks if current editor is balloon type\n */\n isBallon() {\n return this.getAttribute('type') === 'BalloonEditor';\n }\n\n /**\n * Checks if current editor is multiroot type\n */\n isMultiroot() {\n return this.getAttribute('type') === 'MultiRootEditor';\n }\n\n /**\n * Checks if current editor is decoupled type\n */\n isDecoupled() {\n return this.getAttribute('type') === 'DecoupledEditor';\n }\n\n /**\n * Checks if current editor has watchdog enabled\n */\n hasWatchdog() {\n return this.getAttribute('watchdog') === 'true';\n }\n\n /**\n * Queries and validates editable elements\n */\n #queryEditables() {\n if (this.isDecoupled()) {\n return {};\n }\n\n if (this.isMultiroot()) {\n const editables = [...this.querySelectorAll('ckeditor-editable-component')] as CKEditorEditableComponent[];\n\n return editables.reduce((acc, element) => {\n if (!element.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n acc[element.name] = element;\n return acc;\n }, Object.create(null));\n }\n\n const mainEditable = this.querySelector(this.#editorElementTag);\n\n if (!mainEditable) {\n throw new Error(`No ${this.#editorElementTag} element found`);\n }\n\n return { main: mainEditable };\n }\n\n /**\n * Copies input-related attributes from component to the main editable element\n *\n * @private\n */\n #assignInputAttributes() {\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n for (const attr of CKEditorComponent.inputAttributes) {\n if (this.hasAttribute(attr)) {\n textarea.setAttribute(attr, this.getAttribute(attr)!);\n }\n }\n }\n\n /**\n * Sets up content sync between editor and textarea element.\n *\n * @private\n */\n #setupContentSync() {\n if (!this.instance) {\n return;\n }\n\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n // Initial sync\n const syncInput = () => {\n this.style.position = 'relative';\n\n textarea.innerHTML = '';\n textarea.value = this.instance!.getData();\n textarea.tabIndex = -1;\n\n Object.assign(textarea.style, {\n display: 'flex',\n position: 'absolute',\n bottom: '0',\n left: '50%',\n width: '1px',\n height: '1px',\n opacity: '0',\n pointerEvents: 'none',\n margin: '0',\n padding: '0',\n border: 'none',\n });\n };\n\n syncInput();\n\n // Listen for changes\n this.instance.model.document.on('change:data', () => {\n textarea.dispatchEvent(new Event('input', { bubbles: true }));\n textarea.dispatchEvent(new Event('change', { bubbles: true }));\n\n syncInput();\n });\n }\n\n /**\n * Sets up editable height for ClassicEditor\n *\n * @private\n */\n #setupEditableHeight() {\n if (!this.isClassic() && !this.isBallon()) {\n return;\n }\n\n const { instance } = this;\n const height = Number.parseInt(this.getAttribute('editable-height')!, 10);\n\n if (Number.isNaN(height)) {\n return;\n }\n\n instance!.editing.view.change((writer) => {\n writer.setStyle('height', `${height}px`, instance!.editing.view.document.getRoot()!);\n });\n }\n\n /**\n * Gets bundle JSON description from translations attribute\n */\n #getBundle(): BundleDescription {\n return this.#bundle ||= JSON.parse(this.getAttribute('bundle')!);\n }\n\n /**\n * Checks if all required stylesheets are injected. If not, inject.\n */\n async #ensureStylesheetsInjected() {\n await loadAsyncCSS(this.#getBundle()?.stylesheets || []);\n }\n\n /**\n * Checks if all required scripts are injected. If not, inject.\n */\n async #ensureWindowScriptsInjected() {\n const windowScripts = (this.#getBundle()?.scripts || []).filter(script => !!script.window_name);\n\n await loadAsyncImports(windowScripts);\n }\n\n /**\n * Loads translation modules\n */\n async #getTranslations() {\n const translations = this.#getBundle()?.scripts.filter(script => script.translation);\n\n return loadAsyncImports(translations);\n }\n\n /**\n * Loads plugin modules\n */\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n const items = raw ? JSON.parse(raw) : [];\n const mappedItems = items.map((item: any) =>\n typeof item === 'string'\n ? { import_name: 'ckeditor5', import_as: item }\n : item,\n );\n\n return loadAsyncImports(mappedItems);\n }\n\n /**\n * Gets editor constructor based on type attribute\n */\n async #getEditorConstructor() {\n const CKEditor = await import('ckeditor5');\n const editorType = this.getAttribute('type');\n\n if (!editorType || !Object.prototype.hasOwnProperty.call(CKEditor, editorType)) {\n throw new Error(`Invalid editor type: ${editorType}`);\n }\n\n return (CKEditor as any)[editorType] as EditorConstructor;\n }\n}\n\ntype EditorConstructor = {\n create: (...args: any[]) => Promise<Editor>;\n};\n\ntype BundleDescription = {\n stylesheets: string[];\n scripts: Array<AsyncImportRawDescription & {\n translation?: boolean;\n }>;\n};\n\ncustomElements.define('ckeditor-component', CKEditorComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers';\n\nclass CKEditorUIPartComponent extends HTMLElement {\n /**\n * Lifecycle callback when element is added to DOM.\n * Adds the toolbar to the editor UI.\n */\n connectedCallback() {\n execIfDOMReady(async () => {\n const uiPart = this.getAttribute('name')!;\n const editor = await this.#queryEditorElement()!.instancePromise.promise;\n\n this.appendChild((editor.ui.view as any)[uiPart].element);\n });\n }\n\n /**\n * Finds the parent editor component.\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-ui-part-component', CKEditorUIPartComponent);\n"],"names":["execIfDOMReady","callback","SCRIPT_LOAD_PROMISES","injectScript","url","promise","resolve","reject","script","isSafeKey","key","stylesheetExists","href","sheet","loadAsyncCSS","stylesheets","promises","link","loadAsyncImports","imports","loadExternalPlugin","import_name","import_as","window_name","isScriptPresent","module","imported","uncompressImport","pkg","resolveConfigElementReferences","obj","item","anyObj","element","result","value","uid","CKEditorContextComponent","#connectedEditors","#initializeContext","error","_","oldValue","newValue","editor","Context","ContextWatchdog","plugins","#getPlugins","config","#getConfig","args","raw","CKEditorEditableComponent","editorComponent","#queryEditorElement","name","CKEditorMultiRootEditablesTracker","#editorElement","#editables","editorElement","initialEditables","target","ui","editing","model","root","editable","CKEditorComponent","#initialHTML","#context","#contextEditorId","#bundle","#getEventHandler","handler","#setEventHandler","event","#destroy","#editorElementTag","#contextWatchdog","#initializeEditor","editablesOrContent","#ensureStylesheetsInjected","#ensureWindowScriptsInjected","content","beforeInitEventDetails","Editor","#getEditorConstructor","translations","#getTranslations","watchdog","instance","contextId","_element","_config","EditorWatchdog","#assignInputAttributes","#queryEditables","#setupContentSync","#setupEditableHeight","#setupDataChangeListener","err","getRootContent","rootName","getAllRoots","acc","mainEditable","textarea","attr","syncInput","height","writer","#getBundle","windowScripts","mappedItems","CKEditor","editorType","CKEditorUIPartComponent","uiPart"],"mappings":"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"}
|
data/npm_package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ function p(s) {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
const g = /* @__PURE__ */ new Map();
|
|
15
|
-
function
|
|
15
|
+
function E(s) {
|
|
16
16
|
if (g.has(s))
|
|
17
17
|
return g.get(s);
|
|
18
18
|
const t = new Promise((e, i) => {
|
|
@@ -45,23 +45,23 @@ function w(s = []) {
|
|
|
45
45
|
function h(s = []) {
|
|
46
46
|
const t = async ({ url: i, import_name: n, import_as: r, window_name: o, stylesheets: a }) => {
|
|
47
47
|
if (a?.length && await w(a), o) {
|
|
48
|
-
let
|
|
48
|
+
let d = function() {
|
|
49
49
|
return Object.prototype.hasOwnProperty.call(window, o);
|
|
50
50
|
};
|
|
51
|
-
if (i && !
|
|
51
|
+
if (i && !d() && await E(i), d() || window.dispatchEvent(
|
|
52
52
|
new CustomEvent(`ckeditor:request-cjs-plugin:${o}`)
|
|
53
|
-
), !
|
|
53
|
+
), !d())
|
|
54
54
|
throw new Error(
|
|
55
55
|
`Plugin window['${o}'] not found in global scope. Please ensure the plugin is loaded before CKEditor initialization.`
|
|
56
56
|
);
|
|
57
57
|
return window[o];
|
|
58
58
|
}
|
|
59
|
-
const c = await import(n),
|
|
60
|
-
if (!
|
|
59
|
+
const c = await import(n), l = c[r || "default"];
|
|
60
|
+
if (!l)
|
|
61
61
|
throw new Error(
|
|
62
62
|
`Plugin "${r || "default"}" not found in the ESM module "${n}"! Available imports: ${Object.keys(c).join(", ")}! Consider changing "import_as" value.`
|
|
63
63
|
);
|
|
64
|
-
return
|
|
64
|
+
return l;
|
|
65
65
|
};
|
|
66
66
|
function e(i) {
|
|
67
67
|
return t(typeof i == "string" ? { import_name: "ckeditor5", import_as: i } : i);
|
|
@@ -86,7 +86,7 @@ function u(s) {
|
|
|
86
86
|
function A() {
|
|
87
87
|
return Math.random().toString(36).substring(2);
|
|
88
88
|
}
|
|
89
|
-
class
|
|
89
|
+
class P extends HTMLElement {
|
|
90
90
|
instance = null;
|
|
91
91
|
instancePromise = Promise.withResolvers();
|
|
92
92
|
#e = /* @__PURE__ */ new Set();
|
|
@@ -159,8 +159,8 @@ class x extends HTMLElement {
|
|
|
159
159
|
return u(t);
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
customElements.define("ckeditor-context-component",
|
|
163
|
-
class
|
|
162
|
+
customElements.define("ckeditor-context-component", P);
|
|
163
|
+
class x extends HTMLElement {
|
|
164
164
|
/**
|
|
165
165
|
* List of attributes that trigger updates when changed
|
|
166
166
|
*
|
|
@@ -231,7 +231,7 @@ class P extends HTMLElement {
|
|
|
231
231
|
return this.closest("ckeditor-component") || document.body.querySelector("ckeditor-component");
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
|
-
customElements.define("ckeditor-editable-component",
|
|
234
|
+
customElements.define("ckeditor-editable-component", x);
|
|
235
235
|
class b {
|
|
236
236
|
#e;
|
|
237
237
|
#t;
|
|
@@ -437,12 +437,7 @@ class m extends HTMLElement {
|
|
|
437
437
|
* Determines appropriate editor element tag based on editor type
|
|
438
438
|
*/
|
|
439
439
|
get #n() {
|
|
440
|
-
|
|
441
|
-
case "ClassicEditor":
|
|
442
|
-
return "textarea";
|
|
443
|
-
default:
|
|
444
|
-
return "div";
|
|
445
|
-
}
|
|
440
|
+
return this.getAttribute("type") === "ClassicEditor" ? "textarea" : "div";
|
|
446
441
|
}
|
|
447
442
|
/**
|
|
448
443
|
* Gets the CKEditor context instance if available.
|
|
@@ -482,8 +477,8 @@ class m extends HTMLElement {
|
|
|
482
477
|
new CustomEvent("ckeditor:attach:before", { detail: i })
|
|
483
478
|
);
|
|
484
479
|
const n = await this.#v(), [r, o] = await Promise.all([
|
|
485
|
-
this.#
|
|
486
|
-
this.#
|
|
480
|
+
this.#E(),
|
|
481
|
+
this.#y()
|
|
487
482
|
]), a = {
|
|
488
483
|
...this.#l(),
|
|
489
484
|
...o.length && {
|
|
@@ -493,28 +488,24 @@ class m extends HTMLElement {
|
|
|
493
488
|
};
|
|
494
489
|
window.dispatchEvent(
|
|
495
490
|
new CustomEvent("ckeditor:attach", { detail: { config: a, ...i } })
|
|
496
|
-
)
|
|
497
|
-
let c = null,
|
|
491
|
+
);
|
|
492
|
+
let c = null, l = null, d = null;
|
|
498
493
|
if (this.#t)
|
|
499
|
-
|
|
500
|
-
creator: (f,
|
|
501
|
-
id:
|
|
494
|
+
d = A(), await this.#a.add({
|
|
495
|
+
creator: (f, y) => n.create(f, y),
|
|
496
|
+
id: d,
|
|
502
497
|
sourceElementOrData: e,
|
|
503
498
|
type: "editor",
|
|
504
499
|
config: a
|
|
505
|
-
}),
|
|
500
|
+
}), l = this.#a.getItem(d);
|
|
506
501
|
else if (this.hasWatchdog()) {
|
|
507
502
|
const { EditorWatchdog: f } = await import("ckeditor5");
|
|
508
|
-
c = new f(n), await c.create(e, a),
|
|
503
|
+
c = new f(n), await c.create(e, a), l = c.editor;
|
|
509
504
|
} else
|
|
510
|
-
|
|
511
|
-
return
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
config: d.config._config
|
|
515
|
-
}), {
|
|
516
|
-
contextId: l,
|
|
517
|
-
instance: d,
|
|
505
|
+
l = await n.create(e, a);
|
|
506
|
+
return {
|
|
507
|
+
contextId: d,
|
|
508
|
+
instance: l,
|
|
518
509
|
watchdog: c
|
|
519
510
|
};
|
|
520
511
|
}
|
|
@@ -677,14 +668,14 @@ class m extends HTMLElement {
|
|
|
677
668
|
/**
|
|
678
669
|
* Loads translation modules
|
|
679
670
|
*/
|
|
680
|
-
async #
|
|
671
|
+
async #y() {
|
|
681
672
|
const t = this.#c()?.scripts.filter((e) => e.translation);
|
|
682
673
|
return h(t);
|
|
683
674
|
}
|
|
684
675
|
/**
|
|
685
676
|
* Loads plugin modules
|
|
686
677
|
*/
|
|
687
|
-
async #
|
|
678
|
+
async #E() {
|
|
688
679
|
const t = this.getAttribute("plugins"), i = (t ? JSON.parse(t) : []).map(
|
|
689
680
|
(n) => typeof n == "string" ? { import_name: "ckeditor5", import_as: n } : n
|
|
690
681
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/helpers/exec-if-dom-ready.ts","../src/helpers/inject-script.ts","../src/helpers/is-safe-key.ts","../src/helpers/load-async-css.ts","../src/helpers/load-async-imports.ts","../src/helpers/resolve-config-element-references.ts","../src/helpers/uid.ts","../src/components/context.ts","../src/components/editable.ts","../src/components/editor/multiroot-editables-tracker.ts","../src/components/editor/editor.ts","../src/components/ui-part.ts"],"sourcesContent":["/**\n * Executes callback when DOM is ready.\n *\n * @param callback - Function to execute when DOM is ready.\n */\nexport function execIfDOMReady(callback: VoidFunction) {\n switch (document.readyState) {\n case 'loading':\n document.addEventListener('DOMContentLoaded', callback, { once: true });\n break;\n\n case 'interactive':\n case 'complete':\n setTimeout(callback, 0);\n break;\n\n default:\n console.warn('Unexpected document.readyState:', document.readyState);\n setTimeout(callback, 0);\n }\n}\n","const SCRIPT_LOAD_PROMISES = new Map();\n\n/**\n * Dynamically loads script files based on configuration.\n * Uses caching to avoid loading the same script multiple times.\n *\n * @param url - URL of the script to load\n */\nexport function injectScript(url: string) {\n if (SCRIPT_LOAD_PROMISES.has(url)) {\n return SCRIPT_LOAD_PROMISES.get(url);\n }\n\n const promise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = resolve;\n script.onerror = reject;\n\n document.head.appendChild(script);\n });\n\n SCRIPT_LOAD_PROMISES.set(url, promise);\n return promise;\n}\n","/**\n * Checks if a key is safe to use in configuration objects to prevent prototype pollution\n *\n * @param key - Key name to check\n * @returns True if key is safe to use\n */\nexport function isSafeKey(key: string) {\n return (\n typeof key === 'string'\n && key !== '__proto__'\n && key !== 'constructor'\n && key !== 'prototype'\n );\n}\n","/**\n * Checks if stylesheet with given href already exists in document\n *\n * @param href - Stylesheet URL to check\n * @returns True if stylesheet already exists\n */\nfunction stylesheetExists(href: string) {\n return Array\n .from(document.styleSheets)\n .some(sheet =>\n sheet.href === href || sheet.href === new URL(href, window.location.href).href,\n );\n}\n\n/**\n * Dynamically loads CSS files based on configuration\n *\n * @param stylesheets - Array of CSS file URLs to load\n * @returns Array of promises for each CSS file load\n * @throws When CSS file loading fails\n */\nexport function loadAsyncCSS(stylesheets: string[] = []) {\n const promises = stylesheets.map(href =>\n new Promise<void>((resolve, reject) => {\n if (stylesheetExists(href)) {\n resolve();\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = href;\n\n link.onerror = reject;\n link.onload = () => resolve();\n\n document.head.appendChild(link);\n }),\n );\n\n return Promise.all(promises);\n}\n","import { injectScript } from './inject-script';\nimport { loadAsyncCSS } from './load-async-css';\n\n/**\n * Dynamically imports modules based on configuration\n *\n * @param imports - Array of import configurations\n * @param imports[].name - Name of inline plugin (for inline type)\n * @param imports[].code - Source code of inline plugin (for inline type)\n * @param imports[].import_name - Module path to import (for external type)\n * @param imports[].import_as - Name to import as (for external type)\n * @param imports[].window_name - Global window object name (for external type)\n * @param imports[].type - Type of import\n * @returns Array of loaded modules\n * @throws When plugin loading fails\n */\nexport function loadAsyncImports(imports: Array<AsyncImportRawDescription | string> = []) {\n const loadExternalPlugin = async ({ url, import_name, import_as, window_name, stylesheets }: AsyncImportRawDescription) => {\n if (stylesheets?.length) {\n await loadAsyncCSS(stylesheets);\n }\n\n if (window_name) {\n function isScriptPresent() {\n return Object.prototype.hasOwnProperty.call(window, window_name!);\n }\n\n if (url && !isScriptPresent()) {\n await injectScript(url);\n }\n\n if (!isScriptPresent()) {\n window.dispatchEvent(\n new CustomEvent(`ckeditor:request-cjs-plugin:${window_name}`),\n );\n }\n\n if (!isScriptPresent()) {\n throw new Error(\n `Plugin window['${window_name}'] not found in global scope. `\n + 'Please ensure the plugin is loaded before CKEditor initialization.',\n );\n }\n\n return (window as any)[window_name!];\n }\n\n const module = await import(import_name!);\n const imported = module[import_as || 'default'];\n\n if (!imported) {\n throw new Error(\n `Plugin \"${import_as || 'default'}\" not found in the ESM module `\n + `\"${import_name}\"! Available imports: ${Object.keys(module).join(', ')}! `\n + 'Consider changing \"import_as\" value.',\n );\n }\n\n return imported;\n };\n\n function uncompressImport(pkg: any) {\n if (typeof pkg === 'string') {\n return loadExternalPlugin({ import_name: 'ckeditor5', import_as: pkg });\n }\n\n return loadExternalPlugin(pkg);\n }\n\n return Promise.all(imports.map(uncompressImport));\n}\n\n/**\n * Type definition for plugin raw descriptor\n */\nexport type AsyncImportRawDescription = {\n url?: string;\n import_name?: string;\n import_as?: string;\n window_name?: string;\n stylesheets?: string[];\n};\n","/**\n * Resolves element references in configuration object.\n * Looks for objects with { $element: \"selector\" } format and replaces them with actual DOM elements.\n *\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved element references\n */\nexport function resolveConfigElementReferences<T>(obj: T): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => resolveConfigElementReferences(item)) as T;\n }\n\n const anyObj = obj as any;\n\n if (anyObj.$element && typeof anyObj.$element === 'string') {\n const element = document.querySelector(anyObj.$element);\n\n if (!element) {\n console.warn(`Element not found for selector: ${anyObj.$element}`);\n }\n\n return (element || null) as T;\n }\n\n const result = Object.create(null);\n\n for (const [key, value] of Object.entries(obj)) {\n result[key] = resolveConfigElementReferences(value);\n }\n\n return result as T;\n}\n","/**\n * Generates a unique identifier string\n *\n * @returns Random string that can be used as unique identifier\n */\nexport function uid() {\n return Math.random().toString(36).substring(2);\n}\n","import type { ContextWatchdog } from 'ckeditor5';\n\nimport { execIfDOMReady, loadAsyncImports, resolveConfigElementReferences } from 'src/helpers';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorContextComponent extends HTMLElement {\n instance: ContextWatchdog | null = null;\n\n instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n #connectedEditors = new Set<CKEditorComponent>();\n\n static get observedAttributes() {\n return ['plugins', 'config'];\n }\n\n async connectedCallback() {\n try {\n execIfDOMReady(() => this.#initializeContext());\n }\n catch (error) {\n console.error('Failed to initialize context:', error);\n this.dispatchEvent(new CustomEvent('context-error', { detail: error }));\n }\n }\n\n async attributeChangedCallback(_: unknown, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null && oldValue !== newValue) {\n await this.#initializeContext();\n }\n }\n\n async disconnectedCallback() {\n if (this.instance) {\n await this.instance.destroy();\n this.instance = null;\n }\n }\n\n /**\n * Register editor component with this context\n *\n * @param editor - Editor component to register.\n */\n registerEditor(editor: CKEditorComponent) {\n this.#connectedEditors.add(editor);\n }\n\n /**\n * Unregister editor component from this context\n *\n * @param editor - Editor component to unregister\n */\n unregisterEditor(editor: CKEditorComponent) {\n this.#connectedEditors.delete(editor);\n }\n\n /**\n * Initialize CKEditor context with shared configuration\n *\n * @private\n */\n async #initializeContext() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n await this.instance.destroy();\n\n this.instance = null;\n }\n\n // Broadcast context initialization event\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach:before', { detail: { element: this } }),\n );\n\n const { Context, ContextWatchdog } = await import('ckeditor5');\n const plugins = await this.#getPlugins();\n const config = this.#getConfig();\n\n // Broadcast context mounting event with configuration\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach', { detail: { config, element: this } }),\n );\n\n this.instance = new ContextWatchdog(Context, {\n crashNumberLimit: 10,\n });\n\n await this.instance.create({\n ...config,\n plugins,\n });\n\n this.instance.on('itemError', (...args) => {\n console.error('Context item error:', ...args);\n });\n\n this.instancePromise.resolve(this.instance);\n this.dispatchEvent(new CustomEvent('context-ready', { detail: this.instance }));\n\n // Reinitialize connected editors.\n await Promise.all(\n [...this.#connectedEditors].map(editor => editor.reinitializeEditor()),\n );\n }\n\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n\n return loadAsyncImports(raw ? JSON.parse(raw) : []);\n }\n\n /**\n * Gets context configuration with resolved element references.\n *\n * @private\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n}\n\ncustomElements.define('ckeditor-context-component', CKEditorContextComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers/exec-if-dom-ready';\n\nexport class CKEditorEditableComponent extends HTMLElement {\n /**\n * List of attributes that trigger updates when changed\n *\n * @static\n * @returns {string[]} Array of attribute names to observe\n */\n static get observedAttributes() {\n return ['name'];\n }\n\n /**\n * Gets the name of this editable region\n */\n get name() {\n return this.getAttribute('name') || 'editable';\n }\n\n /**\n * Gets the actual editable DOM element.\n */\n get editableElement() {\n return this.querySelector('div')!;\n }\n\n /**\n * Lifecycle callback when element is added to DOM\n * Sets up the editable element and registers it with the parent editor\n */\n connectedCallback() {\n execIfDOMReady(() => {\n const editorComponent = this.#queryEditorElement();\n\n if (!editorComponent) {\n throw new Error('ckeditor-editable-component must be a child of ckeditor-component');\n }\n\n this.innerHTML = `<div>${this.innerHTML}</div>`;\n this.style.display = 'block';\n\n if (editorComponent.isDecoupled()) {\n editorComponent.runAfterEditorReady((editor) => {\n this.appendChild((editor.ui.view as any)[this.name].element);\n });\n }\n else {\n if (!this.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n\n editorComponent.editables![this.name] = this;\n }\n });\n }\n\n /**\n * Lifecycle callback for attribute changes\n * Handles name changes and propagates other attributes to editable element\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n if (oldValue === newValue) {\n return;\n }\n\n if (name === 'name') {\n if (!oldValue) {\n return;\n }\n\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n editorComponent.editables![newValue] = editorComponent.editables![oldValue]!;\n delete editorComponent.editables![oldValue];\n }\n }\n else {\n this.editableElement.setAttribute(name, newValue!);\n }\n }\n\n /**\n * Lifecycle callback when element is removed\n * Un-registers this editable from the parent editor\n */\n disconnectedCallback() {\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n delete editorComponent.editables![this.name];\n }\n }\n\n /**\n * Finds the parent editor component\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-editable-component', CKEditorEditableComponent);\n","import type { MultiRootEditor } from 'ckeditor5';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorMultiRootEditablesTracker {\n #editorElement: CKEditorComponent;\n #editables: Record<string, HTMLElement>;\n\n /**\n * Creates new tracker instance wrapped in a Proxy for dynamic property access\n *\n * @param editorElement - Parent editor component reference\n * @param initialEditables - Initial editable elements\n * @returns Proxy wrapping the tracker\n */\n constructor(\n editorElement: CKEditorComponent,\n initialEditables: Record<string, HTMLElement> = {},\n ) {\n this.#editorElement = editorElement;\n this.#editables = initialEditables;\n\n return new Proxy(this, {\n /**\n * Handles property access, returns class methods or editable elements\n *\n * @param target - The tracker instance\n * @param name - Property name being accessed\n */\n get(target: CKEditorMultiRootEditablesTracker, name: string) {\n if (typeof (target as any)[name] === 'function') {\n return (target as any)[name].bind(target);\n }\n\n return target.#editables[name];\n },\n\n /**\n * Handles setting new editable elements, triggers root attachment\n *\n * @param target - The tracker instance\n * @param name - Name of the editable root\n * @param element - Element to attach as editable\n */\n set(target: CKEditorMultiRootEditablesTracker, name: string, element: HTMLElement) {\n if (target.#editables[name] !== element) {\n void target.attachRoot(name, element);\n target.#editables[name] = element;\n }\n return true;\n },\n\n /**\n * Handles removing editable elements, triggers root detachment\n *\n * @param target - The tracker instance\n * @param name - Name of the root to remove\n */\n deleteProperty(target: CKEditorMultiRootEditablesTracker, name: string) {\n void target.detachRoot(name);\n delete target.#editables[name];\n\n return true;\n },\n });\n }\n\n /**\n * Attaches a new editable root to the editor.\n * Creates new editor root and binds UI elements.\n *\n * @param name - Name of the editable root\n * @param element - DOM element to use as editable\n * @returns Resolves when root is attached\n */\n async attachRoot(name: string, element: HTMLElement) {\n await this.detachRoot(name);\n\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const { ui, editing, model } = editor;\n\n editor.addRoot(name, {\n isUndoable: false,\n data: element.innerHTML,\n });\n\n const root = model.document.getRoot(name);\n\n if (ui.getEditableElement(name)) {\n editor.detachEditable(root!);\n }\n\n const editable = ui.view.createEditable(name, element);\n ui.addEditable(editable);\n editing.view.forceRender();\n });\n }\n\n /**\n * Detaches an editable root from the editor.\n * Removes editor root and cleans up UI bindings.\n *\n * @param name - Name of root to detach\n * @returns Resolves when root is detached\n */\n async detachRoot(name: string) {\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const root = editor.model.document.getRoot(name);\n\n if (root) {\n editor.detachEditable(root);\n editor.detachRoot(name, true);\n }\n });\n }\n\n /**\n * Gets all currently tracked editable elements\n *\n * @returns Map of all editable elements\n */\n getAll() {\n return this.#editables;\n }\n}\n","import type { Editor, EditorWatchdog, Watchdog } from 'ckeditor5';\n\nimport type { AsyncImportRawDescription } from '../../helpers';\nimport type { CKEditorContextComponent } from '../context';\nimport type { CKEditorEditableComponent } from '../editable';\n\nimport {\n execIfDOMReady,\n isSafeKey,\n loadAsyncCSS,\n loadAsyncImports,\n resolveConfigElementReferences,\n uid,\n} from '../../helpers';\nimport { CKEditorMultiRootEditablesTracker } from './multiroot-editables-tracker';\n\nexport class CKEditorComponent extends HTMLElement {\n instancePromise = Promise.withResolvers<Editor>();\n\n watchdog: Watchdog | null = null;\n\n instance: Editor | null = null;\n\n editables: Record<string, HTMLElement> | null = Object.create({});\n\n #initialHTML: string = '';\n\n #context: CKEditorContextComponent | null = null;\n\n #contextEditorId: string | null = null;\n\n #bundle: object | null = null;\n\n /**\n * List of attributes that trigger updates when changed.\n */\n static get observedAttributes() {\n return ['config', 'plugins', 'translations', 'type'];\n }\n\n /**\n * List of input attributes that trigger updates when changed.\n */\n static get inputAttributes() {\n return ['name', 'required', 'value'];\n }\n\n get oneditorchange() {\n return this.#getEventHandler('editorchange');\n }\n\n set oneditorchange(handler) {\n this.#setEventHandler('editorchange', handler);\n }\n\n get oneditorready() {\n return this.#getEventHandler('editorready');\n }\n\n set oneditorready(handler) {\n this.#setEventHandler('editorready', handler);\n }\n\n get oneditorerror() {\n return this.#getEventHandler('editorerror');\n }\n\n set oneditorerror(handler) {\n this.#setEventHandler('editorerror', handler);\n }\n\n /**\n * Gets event handler function from attribute or property\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @returns Event handler or null\n */\n #getEventHandler(name: string): Function | null {\n if (this.hasAttribute(`on${name}`)) {\n const handler = this.getAttribute(`on${name}`)!;\n\n if (!isSafeKey(handler)) {\n throw new Error(`Unsafe event handler attribute value: ${handler}`);\n }\n\n // eslint-disable-next-line no-new-func\n return (window as any)[handler] || new Function('event', handler);\n }\n return (this as any)[`#${name}Handler`];\n }\n\n /**\n * Sets event handler function\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @param handler - Event handler\n */\n #setEventHandler(name: string, handler: Function | null) {\n if (typeof handler === 'string') {\n this.setAttribute(`on${name}`, handler);\n }\n else {\n this.removeAttribute(`on${name}`);\n (this as any)[`#${name}Handler`] = handler;\n }\n }\n\n /**\n * Lifecycle callback when element is connected to DOM\n * Initializes the editor when DOM is ready\n *\n * @protected\n */\n connectedCallback() {\n this.#context = this.closest('ckeditor-context-component');\n this.#initialHTML = this.innerHTML;\n\n try {\n execIfDOMReady(async () => {\n if (this.#context) {\n await this.#context.instancePromise.promise;\n this.#context.registerEditor(this);\n }\n\n await this.reinitializeEditor();\n });\n }\n catch (error) {\n console.error('Failed to initialize editor:', error);\n\n const event = new CustomEvent('editor-error', { detail: error });\n\n this.dispatchEvent(event);\n this.oneditorerror?.(event);\n }\n }\n\n /**\n * Handles attribute changes and reinitializes editor if needed\n *\n * @protected\n * @param name - Name of changed attribute\n * @param oldValue - Previous attribute value\n * @param newValue - New attribute value\n */\n async attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null\n && oldValue !== newValue\n && CKEditorComponent.observedAttributes.includes(name) && this.isConnected) {\n await this.reinitializeEditor();\n }\n }\n\n /**\n * Lifecycle callback when element is removed from DOM\n * Destroys the editor instance\n * @protected\n */\n async disconnectedCallback() {\n if (this.#context) {\n this.#context.unregisterEditor(this);\n }\n\n try {\n await this.#destroy();\n }\n catch (error) {\n console.error('Failed to destroy editor:', error);\n }\n }\n\n /**\n * Runs a callback after the editor is ready. It waits for editor\n * initialization if needed.\n *\n * @param callback - Callback to run\n */\n runAfterEditorReady<E extends Editor>(callback: (editor: E) => void): Promise<void> {\n if (this.instance) {\n return Promise.resolve(callback(this.instance as unknown as E));\n }\n\n return this.instancePromise.promise.then(callback as unknown as any);\n }\n\n /**\n * Determines appropriate editor element tag based on editor type\n */\n get #editorElementTag() {\n switch (this.getAttribute('type')) {\n case 'ClassicEditor':\n return 'textarea';\n\n default:\n return 'div';\n }\n }\n\n /**\n * Gets the CKEditor context instance if available.\n */\n get #contextWatchdog() {\n return this.#context?.instance;\n }\n\n /**\n * Destroys the editor instance and watchdog if available\n */\n async #destroy() {\n if (this.#contextEditorId) {\n await this.#contextWatchdog!.remove(this.#contextEditorId);\n }\n\n await this.instance?.destroy();\n this.watchdog?.destroy();\n }\n\n /**\n * Gets editor configuration with resolved element references\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n\n /**\n * Creates a new CKEditor instance\n */\n async #initializeEditor(editablesOrContent: Record<string, HTMLElement | string> | CKEditorMultiRootEditablesTracker | string | HTMLElement) {\n await Promise.all([\n this.#ensureStylesheetsInjected(),\n this.#ensureWindowScriptsInjected(),\n ]);\n\n // Depending on the type of the editor the content supplied on the first\n // argument is different. For ClassicEditor it's a element or string, for MultiRootEditor\n // it's an object with editables, for DecoupledEditor it's string.\n let content: any = editablesOrContent;\n\n if (editablesOrContent instanceof CKEditorMultiRootEditablesTracker) {\n content = editablesOrContent.getAll();\n }\n else if (typeof editablesOrContent !== 'string') {\n content = (editablesOrContent as any)['main'];\n }\n\n // Broadcast editor initialization event. It's good time to load add inline window plugins.\n const beforeInitEventDetails = {\n ...content instanceof HTMLElement && { element: content },\n ...typeof content === 'string' && { data: content },\n ...content instanceof Object && { editables: content },\n };\n\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach:before', { detail: beforeInitEventDetails }),\n );\n\n // Start fetching constructor.\n const Editor = await this.#getEditorConstructor();\n const [plugins, translations] = await Promise.all([\n this.#getPlugins(),\n this.#getTranslations(),\n ]);\n\n const config = {\n ...this.#getConfig(),\n ...translations.length && {\n translations,\n },\n plugins,\n };\n\n // Broadcast editor mounting event. It's good time to map configuration.\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach', { detail: { config, ...beforeInitEventDetails } }),\n );\n\n console.warn('Initializing CKEditor with:', { config, watchdog: this.hasWatchdog(), context: this.#context });\n\n // Initialize watchdog if needed\n let watchdog: EditorWatchdog | null = null;\n let instance: Editor | null = null;\n let contextId: string | null = null;\n\n if (this.#context) {\n contextId = uid();\n\n await this.#contextWatchdog!.add({\n creator: (_element, _config) => Editor.create(_element, _config),\n id: contextId,\n sourceElementOrData: content,\n type: 'editor',\n config,\n });\n\n instance = this.#contextWatchdog!.getItem(contextId) as Editor;\n }\n else if (this.hasWatchdog()) {\n // Let's create use with plain watchdog.\n const { EditorWatchdog } = await import('ckeditor5');\n watchdog = new EditorWatchdog(Editor);\n\n await watchdog.create(content, config);\n\n instance = watchdog.editor;\n }\n else {\n // Let's create the editor without watchdog.\n instance = await Editor.create(content, config);\n }\n\n console.warn('CKEditor initialized:', {\n instance,\n watchdog,\n config: (instance!.config as any)._config,\n });\n\n return {\n contextId,\n instance,\n watchdog,\n };\n }\n\n /**\n * Re-initializes the editor by destroying existing instance and creating new one\n *\n * @private\n * @returns {Promise<void>}\n */\n async reinitializeEditor() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers();\n\n await this.#destroy();\n\n this.instance = null;\n }\n\n this.style.display = 'block';\n\n if (!this.isMultiroot() && !this.isDecoupled()) {\n this.innerHTML = `<${this.#editorElementTag}>${this.#initialHTML}</${this.#editorElementTag}>`;\n this.#assignInputAttributes();\n }\n\n // Let's track changes in editables if it's a multiroot editor.\n if (this.isMultiroot()) {\n this.editables = new CKEditorMultiRootEditablesTracker(this, this.#queryEditables()) as unknown as Record<string, HTMLElement>;\n }\n else if (this.isDecoupled()) {\n this.editables = null;\n }\n else {\n this.editables = this.#queryEditables();\n }\n\n try {\n const { watchdog, instance, contextId } = await this.#initializeEditor(this.editables || this.#getConfig().initialData || '');\n\n this.watchdog = watchdog;\n this.instance = instance!;\n this.#contextEditorId = contextId;\n\n this.#setupContentSync();\n this.#setupEditableHeight();\n this.#setupDataChangeListener();\n\n this.instancePromise.resolve(this.instance!);\n\n // Broadcast editor ready event\n const event = new CustomEvent('editor-ready', { detail: this.instance });\n\n this.dispatchEvent(event);\n this.oneditorready?.(event);\n }\n catch (err) {\n this.instancePromise.reject(err);\n throw err;\n }\n }\n\n /**\n * Sets up data change listener that broadcasts content changes\n */\n #setupDataChangeListener() {\n const getRootContent = (rootName: string) => this.instance!.getData({ rootName });\n const getAllRoots = () =>\n this.instance?.model.document\n .getRootNames()\n .reduce((acc, rootName) => ({\n ...acc,\n [rootName]: getRootContent(rootName),\n }), {});\n\n this.instance?.model.document.on('change:data', () => {\n const event = new CustomEvent('editor-change', {\n detail: {\n editor: this.instance,\n data: getAllRoots(),\n },\n bubbles: true,\n });\n\n this.dispatchEvent(event);\n this.oneditorchange?.(event);\n });\n }\n\n /**\n * Checks if current editor is classic type\n */\n isClassic() {\n return this.getAttribute('type') === 'ClassicEditor';\n }\n\n /**\n * Checks if current editor is balloon type\n */\n isBallon() {\n return this.getAttribute('type') === 'BalloonEditor';\n }\n\n /**\n * Checks if current editor is multiroot type\n */\n isMultiroot() {\n return this.getAttribute('type') === 'MultiRootEditor';\n }\n\n /**\n * Checks if current editor is decoupled type\n */\n isDecoupled() {\n return this.getAttribute('type') === 'DecoupledEditor';\n }\n\n /**\n * Checks if current editor has watchdog enabled\n */\n hasWatchdog() {\n return this.getAttribute('watchdog') === 'true';\n }\n\n /**\n * Queries and validates editable elements\n */\n #queryEditables() {\n if (this.isDecoupled()) {\n return {};\n }\n\n if (this.isMultiroot()) {\n const editables = [...this.querySelectorAll('ckeditor-editable-component')] as CKEditorEditableComponent[];\n\n return editables.reduce((acc, element) => {\n if (!element.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n acc[element.name] = element;\n return acc;\n }, Object.create(null));\n }\n\n const mainEditable = this.querySelector(this.#editorElementTag);\n\n if (!mainEditable) {\n throw new Error(`No ${this.#editorElementTag} element found`);\n }\n\n return { main: mainEditable };\n }\n\n /**\n * Copies input-related attributes from component to the main editable element\n *\n * @private\n */\n #assignInputAttributes() {\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n for (const attr of CKEditorComponent.inputAttributes) {\n if (this.hasAttribute(attr)) {\n textarea.setAttribute(attr, this.getAttribute(attr)!);\n }\n }\n }\n\n /**\n * Sets up content sync between editor and textarea element.\n *\n * @private\n */\n #setupContentSync() {\n if (!this.instance) {\n return;\n }\n\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n // Initial sync\n const syncInput = () => {\n this.style.position = 'relative';\n\n textarea.innerHTML = '';\n textarea.value = this.instance!.getData();\n textarea.tabIndex = -1;\n\n Object.assign(textarea.style, {\n display: 'flex',\n position: 'absolute',\n bottom: '0',\n left: '50%',\n width: '1px',\n height: '1px',\n opacity: '0',\n pointerEvents: 'none',\n margin: '0',\n padding: '0',\n border: 'none',\n });\n };\n\n syncInput();\n\n // Listen for changes\n this.instance.model.document.on('change:data', () => {\n textarea.dispatchEvent(new Event('input', { bubbles: true }));\n textarea.dispatchEvent(new Event('change', { bubbles: true }));\n\n syncInput();\n });\n }\n\n /**\n * Sets up editable height for ClassicEditor\n *\n * @private\n */\n #setupEditableHeight() {\n if (!this.isClassic() && !this.isBallon()) {\n return;\n }\n\n const { instance } = this;\n const height = Number.parseInt(this.getAttribute('editable-height')!, 10);\n\n if (Number.isNaN(height)) {\n return;\n }\n\n instance!.editing.view.change((writer) => {\n writer.setStyle('height', `${height}px`, instance!.editing.view.document.getRoot()!);\n });\n }\n\n /**\n * Gets bundle JSON description from translations attribute\n */\n #getBundle(): BundleDescription {\n return this.#bundle ||= JSON.parse(this.getAttribute('bundle')!);\n }\n\n /**\n * Checks if all required stylesheets are injected. If not, inject.\n */\n async #ensureStylesheetsInjected() {\n await loadAsyncCSS(this.#getBundle()?.stylesheets || []);\n }\n\n /**\n * Checks if all required scripts are injected. If not, inject.\n */\n async #ensureWindowScriptsInjected() {\n const windowScripts = (this.#getBundle()?.scripts || []).filter(script => !!script.window_name);\n\n await loadAsyncImports(windowScripts);\n }\n\n /**\n * Loads translation modules\n */\n async #getTranslations() {\n const translations = this.#getBundle()?.scripts.filter(script => script.translation);\n\n return loadAsyncImports(translations);\n }\n\n /**\n * Loads plugin modules\n */\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n const items = raw ? JSON.parse(raw) : [];\n const mappedItems = items.map((item: any) =>\n typeof item === 'string'\n ? { import_name: 'ckeditor5', import_as: item }\n : item,\n );\n\n return loadAsyncImports(mappedItems);\n }\n\n /**\n * Gets editor constructor based on type attribute\n */\n async #getEditorConstructor() {\n const CKEditor = await import('ckeditor5');\n const editorType = this.getAttribute('type');\n\n if (!editorType || !Object.prototype.hasOwnProperty.call(CKEditor, editorType)) {\n throw new Error(`Invalid editor type: ${editorType}`);\n }\n\n return (CKEditor as any)[editorType] as EditorConstructor;\n }\n}\n\ntype EditorConstructor = {\n create: (...args: any[]) => Promise<Editor>;\n};\n\ntype BundleDescription = {\n stylesheets: string[];\n scripts: Array<AsyncImportRawDescription & {\n translation?: boolean;\n }>;\n};\n\ncustomElements.define('ckeditor-component', CKEditorComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers';\n\nclass CKEditorUIPartComponent extends HTMLElement {\n /**\n * Lifecycle callback when element is added to DOM.\n * Adds the toolbar to the editor UI.\n */\n connectedCallback() {\n execIfDOMReady(async () => {\n const uiPart = this.getAttribute('name')!;\n const editor = await this.#queryEditorElement()!.instancePromise.promise;\n\n this.appendChild((editor.ui.view as any)[uiPart].element);\n });\n }\n\n /**\n * Finds the parent editor component.\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-ui-part-component', CKEditorUIPartComponent);\n"],"names":["execIfDOMReady","callback","SCRIPT_LOAD_PROMISES","injectScript","url","promise","resolve","reject","script","isSafeKey","key","stylesheetExists","href","sheet","loadAsyncCSS","stylesheets","promises","link","loadAsyncImports","imports","loadExternalPlugin","import_name","import_as","window_name","isScriptPresent","module","imported","uncompressImport","pkg","resolveConfigElementReferences","obj","item","anyObj","element","result","value","uid","CKEditorContextComponent","#connectedEditors","#initializeContext","error","_","oldValue","newValue","editor","Context","ContextWatchdog","plugins","#getPlugins","config","#getConfig","args","raw","CKEditorEditableComponent","editorComponent","#queryEditorElement","name","CKEditorMultiRootEditablesTracker","#editorElement","#editables","editorElement","initialEditables","target","ui","editing","model","root","editable","CKEditorComponent","#initialHTML","#context","#contextEditorId","#bundle","#getEventHandler","handler","#setEventHandler","event","#destroy","#editorElementTag","#contextWatchdog","#initializeEditor","editablesOrContent","#ensureStylesheetsInjected","#ensureWindowScriptsInjected","content","beforeInitEventDetails","Editor","#getEditorConstructor","translations","#getTranslations","watchdog","instance","contextId","_element","_config","EditorWatchdog","#assignInputAttributes","#queryEditables","#setupContentSync","#setupEditableHeight","#setupDataChangeListener","err","getRootContent","rootName","getAllRoots","acc","mainEditable","textarea","attr","syncInput","height","writer","#getBundle","windowScripts","mappedItems","CKEditor","editorType","CKEditorUIPartComponent","uiPart"],"mappings":"AAKO,SAASA,EAAeC,GAAwB;AACrD,UAAQ,SAAS,YAAA;AAAA,IACf,KAAK;AACH,eAAS,iBAAiB,oBAAoBA,GAAU,EAAE,MAAM,IAAM;AACtE;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AACH,iBAAWA,GAAU,CAAC;AACtB;AAAA,IAEF;AACE,cAAQ,KAAK,mCAAmC,SAAS,UAAU,GACnE,WAAWA,GAAU,CAAC;AAAA,EAAA;AAE5B;ACpBA,MAAMC,wBAA2B,IAAA;AAQ1B,SAASC,EAAaC,GAAa;AACxC,MAAIF,EAAqB,IAAIE,CAAG;AAC9B,WAAOF,EAAqB,IAAIE,CAAG;AAGrC,QAAMC,IAAU,IAAI,QAAQ,CAACC,GAASC,MAAW;AAC/C,UAAMC,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAAA,EAAO,MAAMJ,GACbI,EAAO,SAASF,GAChBE,EAAO,UAAUD,GAEjB,SAAS,KAAK,YAAYC,CAAM;AAAA,EAClC,CAAC;AAED,SAAAN,EAAqB,IAAIE,GAAKC,CAAO,GAC9BA;AACT;AClBO,SAASI,EAAUC,GAAa;AACrC,SACE,OAAOA,KAAQ,YACZA,MAAQ,eACRA,MAAQ,iBACRA,MAAQ;AAEf;ACPA,SAASC,EAAiBC,GAAc;AACtC,SAAO,MACJ,KAAK,SAAS,WAAW,EACzB;AAAA,IAAK,CAAAC,MACJA,EAAM,SAASD,KAAQC,EAAM,SAAS,IAAI,IAAID,GAAM,OAAO,SAAS,IAAI,EAAE;AAAA,EAAA;AAEhF;AASO,SAASE,EAAaC,IAAwB,IAAI;AACvD,QAAMC,IAAWD,EAAY;AAAA,IAAI,CAAAH,MAC/B,IAAI,QAAc,CAACN,GAASC,MAAW;AACrC,UAAII,EAAiBC,CAAI,GAAG;AAC1B,QAAAN,EAAA;AACA;AAAA,MACF;AAEA,YAAMW,IAAO,SAAS,cAAc,MAAM;AAC1C,MAAAA,EAAK,MAAM,cACXA,EAAK,OAAOL,GAEZK,EAAK,UAAUV,GACfU,EAAK,SAAS,MAAMX,EAAA,GAEpB,SAAS,KAAK,YAAYW,CAAI;AAAA,IAChC,CAAC;AAAA,EAAA;AAGH,SAAO,QAAQ,IAAID,CAAQ;AAC7B;ACzBO,SAASE,EAAiBC,IAAqD,IAAI;AACxF,QAAMC,IAAqB,OAAO,EAAE,KAAAhB,GAAK,aAAAiB,GAAa,WAAAC,GAAW,aAAAC,GAAa,aAAAR,QAA6C;AAKzH,QAJIA,GAAa,UACf,MAAMD,EAAaC,CAAW,GAG5BQ,GAAa;AACf,UAASC,IAAT,WAA2B;AACzB,eAAO,OAAO,UAAU,eAAe,KAAK,QAAQD,CAAY;AAAA,MAClE;AAYA,UAVInB,KAAO,CAACoB,OACV,MAAMrB,EAAaC,CAAG,GAGnBoB,OACH,OAAO;AAAA,QACL,IAAI,YAAY,+BAA+BD,CAAW,EAAE;AAAA,MAAA,GAI5D,CAACC;AACH,cAAM,IAAI;AAAA,UACR,kBAAkBD,CAAW;AAAA,QAAA;AAKjC,aAAQ,OAAeA,CAAY;AAAA,IACrC;AAEA,UAAME,IAAS,MAAM,OAAOJ,IACtBK,IAAWD,EAAOH,KAAa,SAAS;AAE9C,QAAI,CAACI;AACH,YAAM,IAAI;AAAA,QACR,WAAWJ,KAAa,SAAS,kCAC3BD,CAAW,yBAAyB,OAAO,KAAKI,CAAM,EAAE,KAAK,IAAI,CAAC;AAAA,MAAA;AAK5E,WAAOC;AAAA,EACT;AAEA,WAASC,EAAiBC,GAAU;AAClC,WACSR,EADL,OAAOQ,KAAQ,WACS,EAAE,aAAa,aAAa,WAAWA,MAGzCA,CAH8C;AAAA,EAI1E;AAEA,SAAO,QAAQ,IAAIT,EAAQ,IAAIQ,CAAgB,CAAC;AAClD;AC/DO,SAASE,EAAkCC,GAAW;AAC3D,MAAI,CAACA,KAAO,OAAOA,KAAQ;AACzB,WAAOA;AAGT,MAAI,MAAM,QAAQA,CAAG;AACnB,WAAOA,EAAI,IAAI,CAAAC,MAAQF,EAA+BE,CAAI,CAAC;AAG7D,QAAMC,IAASF;AAEf,MAAIE,EAAO,YAAY,OAAOA,EAAO,YAAa,UAAU;AAC1D,UAAMC,IAAU,SAAS,cAAcD,EAAO,QAAQ;AAEtD,WAAKC,KACH,QAAQ,KAAK,mCAAmCD,EAAO,QAAQ,EAAE,GAG3DC,KAAW;AAAA,EACrB;AAEA,QAAMC,IAAS,uBAAO,OAAO,IAAI;AAEjC,aAAW,CAACxB,GAAKyB,CAAK,KAAK,OAAO,QAAQL,CAAG;AAC3C,IAAAI,EAAOxB,CAAG,IAAImB,EAA+BM,CAAK;AAGpD,SAAOD;AACT;AC9BO,SAASE,IAAM;AACpB,SAAO,KAAK,SAAS,SAAS,EAAE,EAAE,UAAU,CAAC;AAC/C;ACDO,MAAMC,UAAiC,YAAY;AAAA,EACxD,WAAmC;AAAA,EAEnC,kBAAkB,QAAQ,cAAA;AAAA,EAE1BC,yBAAwB,IAAA;AAAA,EAExB,WAAW,qBAAqB;AAC9B,WAAO,CAAC,WAAW,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAM,oBAAoB;AACxB,QAAI;AACF,MAAAtC,EAAe,MAAM,KAAKuC,IAAoB;AAAA,IAChD,SACOC,GAAO;AACZ,cAAQ,MAAM,iCAAiCA,CAAK,GACpD,KAAK,cAAc,IAAI,YAAY,iBAAiB,EAAE,QAAQA,EAAA,CAAO,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,yBAAyBC,GAAYC,GAAyBC,GAAyB;AAC3F,IAAID,MAAa,QAAQA,MAAaC,KACpC,MAAM,KAAKJ,GAAA;AAAA,EAEf;AAAA,EAEA,MAAM,uBAAuB;AAC3B,IAAI,KAAK,aACP,MAAM,KAAK,SAAS,QAAA,GACpB,KAAK,WAAW;AAAA,EAEpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAeK,GAA2B;AACxC,SAAKN,GAAkB,IAAIM,CAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiBA,GAA2B;AAC1C,SAAKN,GAAkB,OAAOM,CAAM;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAML,KAAqB;AACzB,IAAI,KAAK,aACP,KAAK,kBAAkB,QAAQ,cAAA,GAE/B,MAAM,KAAK,SAAS,QAAA,GAEpB,KAAK,WAAW,OAIlB,OAAO;AAAA,MACL,IAAI,YAAY,kCAAkC,EAAE,QAAQ,EAAE,SAAS,OAAK,CAAG;AAAA,IAAA;AAGjF,UAAM,EAAE,SAAAM,GAAS,iBAAAC,MAAoB,MAAM,OAAO,WAAW,GACvDC,IAAU,MAAM,KAAKC,GAAA,GACrBC,IAAS,KAAKC,GAAA;AAGpB,WAAO;AAAA,MACL,IAAI,YAAY,2BAA2B,EAAE,QAAQ,EAAE,QAAAD,GAAQ,SAAS,OAAK,CAAG;AAAA,IAAA,GAGlF,KAAK,WAAW,IAAIH,EAAgBD,GAAS;AAAA,MAC3C,kBAAkB;AAAA,IAAA,CACnB,GAED,MAAM,KAAK,SAAS,OAAO;AAAA,MACzB,GAAGI;AAAA,MACH,SAAAF;AAAA,IAAA,CACD,GAED,KAAK,SAAS,GAAG,aAAa,IAAII,MAAS;AACzC,cAAQ,MAAM,uBAAuB,GAAGA,CAAI;AAAA,IAC9C,CAAC,GAED,KAAK,gBAAgB,QAAQ,KAAK,QAAQ,GAC1C,KAAK,cAAc,IAAI,YAAY,iBAAiB,EAAE,QAAQ,KAAK,SAAA,CAAU,CAAC,GAG9E,MAAM,QAAQ;AAAA,MACZ,CAAC,GAAG,KAAKb,EAAiB,EAAE,IAAI,CAAAM,MAAUA,EAAO,mBAAA,CAAoB;AAAA,IAAA;AAAA,EAEzE;AAAA,EAEA,MAAMI,KAAc;AAClB,UAAMI,IAAM,KAAK,aAAa,SAAS;AAEvC,WAAOlC,EAAiBkC,IAAM,KAAK,MAAMA,CAAG,IAAI,EAAE;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOAF,KAAa;AACX,UAAMD,IAAS,KAAK,MAAM,KAAK,aAAa,QAAQ,KAAK,IAAI;AAE7D,WAAOpB,EAA+BoB,CAAM;AAAA,EAC9C;AACF;AAEA,eAAe,OAAO,8BAA8BZ,CAAwB;AC1HrE,MAAMgB,UAAkC,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzD,WAAW,qBAAqB;AAC9B,WAAO,CAAC,MAAM;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAO;AACT,WAAO,KAAK,aAAa,MAAM,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,kBAAkB;AACpB,WAAO,KAAK,cAAc,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB;AAClB,IAAArD,EAAe,MAAM;AACnB,YAAMsD,IAAkB,KAAKC,GAAA;AAE7B,UAAI,CAACD;AACH,cAAM,IAAI,MAAM,mEAAmE;AAMrF,UAHA,KAAK,YAAY,QAAQ,KAAK,SAAS,UACvC,KAAK,MAAM,UAAU,SAEjBA,EAAgB;AAClB,QAAAA,EAAgB,oBAAoB,CAACV,MAAW;AAC9C,eAAK,YAAaA,EAAO,GAAG,KAAa,KAAK,IAAI,EAAE,OAAO;AAAA,QAC7D,CAAC;AAAA,WAEE;AACH,YAAI,CAAC,KAAK;AACR,gBAAM,IAAI,MAAM,sDAAsD;AAGxE,QAAAU,EAAgB,UAAW,KAAK,IAAI,IAAI;AAAA,MAC1C;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAyBE,GAAcd,GAAkBC,GAAkB;AACzE,QAAID,MAAaC;AAIjB,UAAIa,MAAS,QAAQ;AACnB,YAAI,CAACd;AACH;AAGF,cAAMY,IAAkB,KAAKC,GAAA;AAE7B,QAAID,MACFA,EAAgB,UAAWX,CAAQ,IAAIW,EAAgB,UAAWZ,CAAQ,GAC1E,OAAOY,EAAgB,UAAWZ,CAAQ;AAAA,MAE9C;AAEE,aAAK,gBAAgB,aAAac,GAAMb,CAAS;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB;AACrB,UAAMW,IAAkB,KAAKC,GAAA;AAE7B,IAAID,KACF,OAAOA,EAAgB,UAAW,KAAK,IAAI;AAAA,EAE/C;AAAA;AAAA;AAAA;AAAA,EAKAC,KAAgD;AAC9C,WAAO,KAAK,QAAQ,oBAAoB,KAAK,SAAS,KAAK,cAAc,oBAAoB;AAAA,EAC/F;AACF;AAEA,eAAe,OAAO,+BAA+BF,CAAyB;ACrGvE,MAAMI,EAAkC;AAAA,EAC7CC;AAAA,EACAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACEC,GACAC,IAAgD,IAChD;AACA,gBAAKH,KAAiBE,GACtB,KAAKD,KAAaE,GAEX,IAAI,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOrB,IAAIC,GAA2CN,GAAc;AAC3D,eAAI,OAAQM,EAAeN,CAAI,KAAM,aAC3BM,EAAeN,CAAI,EAAE,KAAKM,CAAM,IAGnCA,EAAOH,GAAWH,CAAI;AAAA,MAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,IAAIM,GAA2CN,GAAcvB,GAAsB;AACjF,eAAI6B,EAAOH,GAAWH,CAAI,MAAMvB,MACzB6B,EAAO,WAAWN,GAAMvB,CAAO,GACpC6B,EAAOH,GAAWH,CAAI,IAAIvB,IAErB;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,eAAe6B,GAA2CN,GAAc;AACtE,eAAKM,EAAO,WAAWN,CAAI,GAC3B,OAAOM,EAAOH,GAAWH,CAAI,GAEtB;AAAA,MACT;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,WAAWA,GAAcvB,GAAsB;AACnD,iBAAM,KAAK,WAAWuB,CAAI,GAEnB,KAAKE,GAAe,oBAAqC,CAACd,MAAW;AAC1E,YAAM,EAAE,IAAAmB,GAAI,SAAAC,GAAS,OAAAC,EAAA,IAAUrB;AAE/B,MAAAA,EAAO,QAAQY,GAAM;AAAA,QACnB,YAAY;AAAA,QACZ,MAAMvB,EAAQ;AAAA,MAAA,CACf;AAED,YAAMiC,IAAOD,EAAM,SAAS,QAAQT,CAAI;AAExC,MAAIO,EAAG,mBAAmBP,CAAI,KAC5BZ,EAAO,eAAesB,CAAK;AAG7B,YAAMC,IAAWJ,EAAG,KAAK,eAAeP,GAAMvB,CAAO;AACrD,MAAA8B,EAAG,YAAYI,CAAQ,GACvBH,EAAQ,KAAK,YAAA;AAAA,IACf,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAWR,GAAc;AAC7B,WAAO,KAAKE,GAAe,oBAAqC,CAACd,MAAW;AAC1E,YAAMsB,IAAOtB,EAAO,MAAM,SAAS,QAAQY,CAAI;AAE/C,MAAIU,MACFtB,EAAO,eAAesB,CAAI,GAC1BtB,EAAO,WAAWY,GAAM,EAAI;AAAA,IAEhC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS;AACP,WAAO,KAAKG;AAAA,EACd;AACF;AC5GO,MAAMS,UAA0B,YAAY;AAAA,EACjD,kBAAkB,QAAQ,cAAA;AAAA,EAE1B,WAA4B;AAAA,EAE5B,WAA0B;AAAA,EAE1B,YAAgD,uBAAO,OAAO,EAAE;AAAA,EAEhEC,KAAuB;AAAA,EAEvBC,KAA4C;AAAA,EAE5CC,KAAkC;AAAA,EAElCC,KAAyB;AAAA;AAAA;AAAA;AAAA,EAKzB,WAAW,qBAAqB;AAC9B,WAAO,CAAC,UAAU,WAAW,gBAAgB,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,kBAAkB;AAC3B,WAAO,CAAC,QAAQ,YAAY,OAAO;AAAA,EACrC;AAAA,EAEA,IAAI,iBAAiB;AACnB,WAAO,KAAKC,GAAiB,cAAc;AAAA,EAC7C;AAAA,EAEA,IAAI,eAAeC,GAAS;AAC1B,SAAKC,GAAiB,gBAAgBD,CAAO;AAAA,EAC/C;AAAA,EAEA,IAAI,gBAAgB;AAClB,WAAO,KAAKD,GAAiB,aAAa;AAAA,EAC5C;AAAA,EAEA,IAAI,cAAcC,GAAS;AACzB,SAAKC,GAAiB,eAAeD,CAAO;AAAA,EAC9C;AAAA,EAEA,IAAI,gBAAgB;AAClB,WAAO,KAAKD,GAAiB,aAAa;AAAA,EAC5C;AAAA,EAEA,IAAI,cAAcC,GAAS;AACzB,SAAKC,GAAiB,eAAeD,CAAO;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASAD,GAAiBjB,GAA+B;AAC9C,QAAI,KAAK,aAAa,KAAKA,CAAI,EAAE,GAAG;AAClC,YAAMkB,IAAU,KAAK,aAAa,KAAKlB,CAAI,EAAE;AAE7C,UAAI,CAAC/C,EAAUiE,CAAO;AACpB,cAAM,IAAI,MAAM,yCAAyCA,CAAO,EAAE;AAIpE,aAAQ,OAAeA,CAAO,KAAK,IAAI,SAAS,SAASA,CAAO;AAAA,IAClE;AACA,WAAQ,KAAa,IAAIlB,CAAI,SAAS;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASAmB,GAAiBnB,GAAckB,GAA0B;AACvD,IAAI,OAAOA,KAAY,WACrB,KAAK,aAAa,KAAKlB,CAAI,IAAIkB,CAAO,KAGtC,KAAK,gBAAgB,KAAKlB,CAAI,EAAE,GAC/B,KAAa,IAAIA,CAAI,SAAS,IAAIkB;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB;AAClB,SAAKJ,KAAW,KAAK,QAAQ,4BAA4B,GACzD,KAAKD,KAAe,KAAK;AAEzB,QAAI;AACF,MAAArE,EAAe,YAAY;AACzB,QAAI,KAAKsE,OACP,MAAM,KAAKA,GAAS,gBAAgB,SACpC,KAAKA,GAAS,eAAe,IAAI,IAGnC,MAAM,KAAK,mBAAA;AAAA,MACb,CAAC;AAAA,IACH,SACO9B,GAAO;AACZ,cAAQ,MAAM,gCAAgCA,CAAK;AAEnD,YAAMoC,IAAQ,IAAI,YAAY,gBAAgB,EAAE,QAAQpC,GAAO;AAE/D,WAAK,cAAcoC,CAAK,GACxB,KAAK,gBAAgBA,CAAK;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,yBAAyBpB,GAAcd,GAAyBC,GAAyB;AAC7F,IAAID,MAAa,QACZA,MAAaC,KACbyB,EAAkB,mBAAmB,SAASZ,CAAI,KAAK,KAAK,eAC/D,MAAM,KAAK,mBAAA;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,uBAAuB;AAC3B,IAAI,KAAKc,MACP,KAAKA,GAAS,iBAAiB,IAAI;AAGrC,QAAI;AACF,YAAM,KAAKO,GAAA;AAAA,IACb,SACOrC,GAAO;AACZ,cAAQ,MAAM,6BAA6BA,CAAK;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAsCvC,GAA8C;AAClF,WAAI,KAAK,WACA,QAAQ,QAAQA,EAAS,KAAK,QAAwB,CAAC,IAGzD,KAAK,gBAAgB,QAAQ,KAAKA,CAA0B;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI6E,KAAoB;AACtB,YAAQ,KAAK,aAAa,MAAM,GAAA;AAAA,MAC9B,KAAK;AACH,eAAO;AAAA,MAET;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA,EAKA,IAAIC,KAAmB;AACrB,WAAO,KAAKT,IAAU;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAMO,KAAW;AACf,IAAI,KAAKN,MACP,MAAM,KAAKQ,GAAkB,OAAO,KAAKR,EAAgB,GAG3D,MAAM,KAAK,UAAU,QAAA,GACrB,KAAK,UAAU,QAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKArB,KAAa;AACX,UAAMD,IAAS,KAAK,MAAM,KAAK,aAAa,QAAQ,KAAK,IAAI;AAE7D,WAAOpB,EAA+BoB,CAAM;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM+B,GAAkBC,GAAqH;AAC3I,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAKC,GAAA;AAAA,MACL,KAAKC,GAAA;AAAA,IAA6B,CACnC;AAKD,QAAIC,IAAeH;AAEnB,IAAIA,aAA8BxB,IAChC2B,IAAUH,EAAmB,OAAA,IAEtB,OAAOA,KAAuB,aACrCG,IAAWH,EAA2B;AAIxC,UAAMI,IAAyB;AAAA,MAC7B,GAAGD,aAAmB,eAAe,EAAE,SAASA,EAAA;AAAA,MAChD,GAAG,OAAOA,KAAY,YAAY,EAAE,MAAMA,EAAA;AAAA,MAC1C,GAAGA,aAAmB,UAAU,EAAE,WAAWA,EAAA;AAAA,IAAQ;AAGvD,WAAO;AAAA,MACL,IAAI,YAAY,0BAA0B,EAAE,QAAQC,GAAwB;AAAA,IAAA;AAI9E,UAAMC,IAAS,MAAM,KAAKC,GAAA,GACpB,CAACxC,GAASyC,CAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,MAChD,KAAKxC,GAAA;AAAA,MACL,KAAKyC,GAAA;AAAA,IAAiB,CACvB,GAEKxC,IAAS;AAAA,MACb,GAAG,KAAKC,GAAA;AAAA,MACR,GAAGsC,EAAa,UAAU;AAAA,QACxB,cAAAA;AAAA,MAAA;AAAA,MAEF,SAAAzC;AAAA,IAAA;AAIF,WAAO;AAAA,MACL,IAAI,YAAY,mBAAmB,EAAE,QAAQ,EAAE,QAAAE,GAAQ,GAAGoC,IAAuB,CAAG;AAAA,IAAA,GAGtF,QAAQ,KAAK,+BAA+B,EAAE,QAAApC,GAAQ,UAAU,KAAK,eAAe,SAAS,KAAKqB,GAAA,CAAU;AAG5G,QAAIoB,IAAkC,MAClCC,IAA0B,MAC1BC,IAA2B;AAE/B,QAAI,KAAKtB;AACP,MAAAsB,IAAYxD,EAAA,GAEZ,MAAM,KAAK2C,GAAkB,IAAI;AAAA,QAC/B,SAAS,CAACc,GAAUC,MAAYR,EAAO,OAAOO,GAAUC,CAAO;AAAA,QAC/D,IAAIF;AAAA,QACJ,qBAAqBR;AAAA,QACrB,MAAM;AAAA,QACN,QAAAnC;AAAA,MAAA,CACD,GAED0C,IAAW,KAAKZ,GAAkB,QAAQa,CAAS;AAAA,aAE5C,KAAK,eAAe;AAE3B,YAAM,EAAE,gBAAAG,EAAA,IAAmB,MAAM,OAAO,WAAW;AACnD,MAAAL,IAAW,IAAIK,EAAeT,CAAM,GAEpC,MAAMI,EAAS,OAAON,GAASnC,CAAM,GAErC0C,IAAWD,EAAS;AAAA,IACtB;AAGE,MAAAC,IAAW,MAAML,EAAO,OAAOF,GAASnC,CAAM;AAGhD,mBAAQ,KAAK,yBAAyB;AAAA,MACpC,UAAA0C;AAAA,MACA,UAAAD;AAAA,MACA,QAASC,EAAU,OAAe;AAAA,IAAA,CACnC,GAEM;AAAA,MACL,WAAAC;AAAA,MACA,UAAAD;AAAA,MACA,UAAAD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB;AACzB,IAAI,KAAK,aACP,KAAK,kBAAkB,QAAQ,cAAA,GAE/B,MAAM,KAAKb,GAAA,GAEX,KAAK,WAAW,OAGlB,KAAK,MAAM,UAAU,SAEjB,CAAC,KAAK,YAAA,KAAiB,CAAC,KAAK,kBAC/B,KAAK,YAAY,IAAI,KAAKC,EAAiB,IAAI,KAAKT,EAAY,KAAK,KAAKS,EAAiB,KAC3F,KAAKkB,GAAA,IAIH,KAAK,gBACP,KAAK,YAAY,IAAIvC,EAAkC,MAAM,KAAKwC,IAAiB,IAE5E,KAAK,gBACZ,KAAK,YAAY,OAGjB,KAAK,YAAY,KAAKA,GAAA;AAGxB,QAAI;AACF,YAAM,EAAE,UAAAP,GAAU,UAAAC,GAAU,WAAAC,EAAA,IAAc,MAAM,KAAKZ,GAAkB,KAAK,aAAa,KAAK9B,GAAA,EAAa,eAAe,EAAE;AAE5H,WAAK,WAAWwC,GAChB,KAAK,WAAWC,GAChB,KAAKpB,KAAmBqB,GAExB,KAAKM,GAAA,GACL,KAAKC,GAAA,GACL,KAAKC,GAAA,GAEL,KAAK,gBAAgB,QAAQ,KAAK,QAAS;AAG3C,YAAMxB,IAAQ,IAAI,YAAY,gBAAgB,EAAE,QAAQ,KAAK,UAAU;AAEvE,WAAK,cAAcA,CAAK,GACxB,KAAK,gBAAgBA,CAAK;AAAA,IAC5B,SACOyB,GAAK;AACV,iBAAK,gBAAgB,OAAOA,CAAG,GACzBA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKAD,KAA2B;AACzB,UAAME,IAAiB,CAACC,MAAqB,KAAK,SAAU,QAAQ,EAAE,UAAAA,GAAU,GAC1EC,IAAc,MAClB,KAAK,UAAU,MAAM,SAClB,eACA,OAAO,CAACC,GAAKF,OAAc;AAAA,MAC1B,GAAGE;AAAA,MACH,CAACF,CAAQ,GAAGD,EAAeC,CAAQ;AAAA,IAAA,IACjC,CAAA,CAAE;AAEV,SAAK,UAAU,MAAM,SAAS,GAAG,eAAe,MAAM;AACpD,YAAM3B,IAAQ,IAAI,YAAY,iBAAiB;AAAA,QAC7C,QAAQ;AAAA,UACN,QAAQ,KAAK;AAAA,UACb,MAAM4B,EAAA;AAAA,QAAY;AAAA,QAEpB,SAAS;AAAA,MAAA,CACV;AAED,WAAK,cAAc5B,CAAK,GACxB,KAAK,iBAAiBA,CAAK;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY;AACV,WAAO,KAAK,aAAa,MAAM,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AACT,WAAO,KAAK,aAAa,MAAM,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,WAAO,KAAK,aAAa,MAAM,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,WAAO,KAAK,aAAa,MAAM,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,WAAO,KAAK,aAAa,UAAU,MAAM;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKAqB,KAAkB;AAChB,QAAI,KAAK;AACP,aAAO,CAAA;AAGT,QAAI,KAAK;AAGP,aAFkB,CAAC,GAAG,KAAK,iBAAiB,6BAA6B,CAAC,EAEzD,OAAO,CAACQ,GAAKxE,MAAY;AACxC,YAAI,CAACA,EAAQ;AACX,gBAAM,IAAI,MAAM,sDAAsD;AAExE,eAAAwE,EAAIxE,EAAQ,IAAI,IAAIA,GACbwE;AAAA,MACT,GAAG,uBAAO,OAAO,IAAI,CAAC;AAGxB,UAAMC,IAAe,KAAK,cAAc,KAAK5B,EAAiB;AAE9D,QAAI,CAAC4B;AACH,YAAM,IAAI,MAAM,MAAM,KAAK5B,EAAiB,gBAAgB;AAG9D,WAAO,EAAE,MAAM4B,EAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOAV,KAAyB;AACvB,UAAMW,IAAW,KAAK,cAAc,UAAU;AAE9C,QAAKA;AAIL,iBAAWC,KAAQxC,EAAkB;AACnC,QAAI,KAAK,aAAawC,CAAI,KACxBD,EAAS,aAAaC,GAAM,KAAK,aAAaA,CAAI,CAAE;AAAA,EAG1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOAV,KAAoB;AAClB,QAAI,CAAC,KAAK;AACR;AAGF,UAAMS,IAAW,KAAK,cAAc,UAAU;AAE9C,QAAI,CAACA;AACH;AAIF,UAAME,IAAY,MAAM;AACtB,WAAK,MAAM,WAAW,YAEtBF,EAAS,YAAY,IACrBA,EAAS,QAAQ,KAAK,SAAU,QAAA,GAChCA,EAAS,WAAW,IAEpB,OAAO,OAAOA,EAAS,OAAO;AAAA,QAC5B,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAEA,IAAAE,EAAA,GAGA,KAAK,SAAS,MAAM,SAAS,GAAG,eAAe,MAAM;AACnD,MAAAF,EAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,GAAA,CAAM,CAAC,GAC5DA,EAAS,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,GAAA,CAAM,CAAC,GAE7DE,EAAA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOAV,KAAuB;AACrB,QAAI,CAAC,KAAK,UAAA,KAAe,CAAC,KAAK;AAC7B;AAGF,UAAM,EAAE,UAAAR,MAAa,MACfmB,IAAS,OAAO,SAAS,KAAK,aAAa,iBAAiB,GAAI,EAAE;AAExE,IAAI,OAAO,MAAMA,CAAM,KAIvBnB,EAAU,QAAQ,KAAK,OAAO,CAACoB,MAAW;AACxC,MAAAA,EAAO,SAAS,UAAU,GAAGD,CAAM,MAAMnB,EAAU,QAAQ,KAAK,SAAS,QAAA,CAAU;AAAA,IACrF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKAqB,KAAgC;AAC9B,WAAO,KAAKxC,OAAY,KAAK,MAAM,KAAK,aAAa,QAAQ,CAAE;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAMU,KAA6B;AACjC,UAAMpE,EAAa,KAAKkG,GAAA,GAAc,eAAe,CAAA,CAAE;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM7B,KAA+B;AACnC,UAAM8B,KAAiB,KAAKD,GAAA,GAAc,WAAW,IAAI,OAAO,CAAAxG,MAAU,CAAC,CAACA,EAAO,WAAW;AAE9F,UAAMU,EAAiB+F,CAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAMxB,KAAmB;AACvB,UAAMD,IAAe,KAAKwB,MAAc,QAAQ,OAAO,CAAAxG,MAAUA,EAAO,WAAW;AAEnF,WAAOU,EAAiBsE,CAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAMxC,KAAc;AAClB,UAAMI,IAAM,KAAK,aAAa,SAAS,GAEjC8D,KADQ9D,IAAM,KAAK,MAAMA,CAAG,IAAI,CAAA,GACZ;AAAA,MAAI,CAACrB,MAC7B,OAAOA,KAAS,WACZ,EAAE,aAAa,aAAa,WAAWA,MACvCA;AAAA,IAAA;AAGN,WAAOb,EAAiBgG,CAAW;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM3B,KAAwB;AAC5B,UAAM4B,IAAW,MAAM,OAAO,WAAW,GACnCC,IAAa,KAAK,aAAa,MAAM;AAE3C,QAAI,CAACA,KAAc,CAAC,OAAO,UAAU,eAAe,KAAKD,GAAUC,CAAU;AAC3E,YAAM,IAAI,MAAM,wBAAwBA,CAAU,EAAE;AAGtD,WAAQD,EAAiBC,CAAU;AAAA,EACrC;AACF;AAaA,eAAe,OAAO,sBAAsBhD,CAAiB;AC5nB7D,MAAMiD,UAAgC,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAKhD,oBAAoB;AAClB,IAAArH,EAAe,YAAY;AACzB,YAAMsH,IAAS,KAAK,aAAa,MAAM,GACjC1E,IAAS,MAAM,KAAKW,GAAA,EAAuB,gBAAgB;AAEjE,WAAK,YAAaX,EAAO,GAAG,KAAa0E,CAAM,EAAE,OAAO;AAAA,IAC1D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA/D,KAAgD;AAC9C,WAAO,KAAK,QAAQ,oBAAoB,KAAK,SAAS,KAAK,cAAc,oBAAoB;AAAA,EAC/F;AACF;AAEA,eAAe,OAAO,8BAA8B8D,CAAuB;"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/helpers/exec-if-dom-ready.ts","../src/helpers/inject-script.ts","../src/helpers/is-safe-key.ts","../src/helpers/load-async-css.ts","../src/helpers/load-async-imports.ts","../src/helpers/resolve-config-element-references.ts","../src/helpers/uid.ts","../src/components/context.ts","../src/components/editable.ts","../src/components/editor/multiroot-editables-tracker.ts","../src/components/editor/editor.ts","../src/components/ui-part.ts"],"sourcesContent":["/**\n * Executes callback when DOM is ready.\n *\n * @param callback - Function to execute when DOM is ready.\n */\nexport function execIfDOMReady(callback: VoidFunction) {\n switch (document.readyState) {\n case 'loading':\n document.addEventListener('DOMContentLoaded', callback, { once: true });\n break;\n\n case 'interactive':\n case 'complete':\n setTimeout(callback, 0);\n break;\n\n default:\n console.warn('Unexpected document.readyState:', document.readyState);\n setTimeout(callback, 0);\n }\n}\n","const SCRIPT_LOAD_PROMISES = new Map();\n\n/**\n * Dynamically loads script files based on configuration.\n * Uses caching to avoid loading the same script multiple times.\n *\n * @param url - URL of the script to load\n */\nexport function injectScript(url: string) {\n if (SCRIPT_LOAD_PROMISES.has(url)) {\n return SCRIPT_LOAD_PROMISES.get(url);\n }\n\n const promise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = resolve;\n script.onerror = reject;\n\n document.head.appendChild(script);\n });\n\n SCRIPT_LOAD_PROMISES.set(url, promise);\n return promise;\n}\n","/**\n * Checks if a key is safe to use in configuration objects to prevent prototype pollution\n *\n * @param key - Key name to check\n * @returns True if key is safe to use\n */\nexport function isSafeKey(key: string) {\n return (\n typeof key === 'string'\n && key !== '__proto__'\n && key !== 'constructor'\n && key !== 'prototype'\n );\n}\n","/**\n * Checks if stylesheet with given href already exists in document\n *\n * @param href - Stylesheet URL to check\n * @returns True if stylesheet already exists\n */\nfunction stylesheetExists(href: string) {\n return Array\n .from(document.styleSheets)\n .some(sheet =>\n sheet.href === href || sheet.href === new URL(href, window.location.href).href,\n );\n}\n\n/**\n * Dynamically loads CSS files based on configuration\n *\n * @param stylesheets - Array of CSS file URLs to load\n * @returns Array of promises for each CSS file load\n * @throws When CSS file loading fails\n */\nexport function loadAsyncCSS(stylesheets: string[] = []) {\n const promises = stylesheets.map(href =>\n new Promise<void>((resolve, reject) => {\n if (stylesheetExists(href)) {\n resolve();\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = href;\n\n link.onerror = reject;\n link.onload = () => resolve();\n\n document.head.appendChild(link);\n }),\n );\n\n return Promise.all(promises);\n}\n","import { injectScript } from './inject-script';\nimport { loadAsyncCSS } from './load-async-css';\n\n/**\n * Dynamically imports modules based on configuration\n *\n * @param imports - Array of import configurations\n * @param imports[].name - Name of inline plugin (for inline type)\n * @param imports[].code - Source code of inline plugin (for inline type)\n * @param imports[].import_name - Module path to import (for external type)\n * @param imports[].import_as - Name to import as (for external type)\n * @param imports[].window_name - Global window object name (for external type)\n * @param imports[].type - Type of import\n * @returns Array of loaded modules\n * @throws When plugin loading fails\n */\nexport function loadAsyncImports(imports: Array<AsyncImportRawDescription | string> = []) {\n const loadExternalPlugin = async ({ url, import_name, import_as, window_name, stylesheets }: AsyncImportRawDescription) => {\n if (stylesheets?.length) {\n await loadAsyncCSS(stylesheets);\n }\n\n if (window_name) {\n function isScriptPresent() {\n return Object.prototype.hasOwnProperty.call(window, window_name!);\n }\n\n if (url && !isScriptPresent()) {\n await injectScript(url);\n }\n\n if (!isScriptPresent()) {\n window.dispatchEvent(\n new CustomEvent(`ckeditor:request-cjs-plugin:${window_name}`),\n );\n }\n\n if (!isScriptPresent()) {\n throw new Error(\n `Plugin window['${window_name}'] not found in global scope. `\n + 'Please ensure the plugin is loaded before CKEditor initialization.',\n );\n }\n\n return (window as any)[window_name!];\n }\n\n const module = await import(import_name!);\n const imported = module[import_as || 'default'];\n\n if (!imported) {\n throw new Error(\n `Plugin \"${import_as || 'default'}\" not found in the ESM module `\n + `\"${import_name}\"! Available imports: ${Object.keys(module).join(', ')}! `\n + 'Consider changing \"import_as\" value.',\n );\n }\n\n return imported;\n };\n\n function uncompressImport(pkg: any) {\n if (typeof pkg === 'string') {\n return loadExternalPlugin({ import_name: 'ckeditor5', import_as: pkg });\n }\n\n return loadExternalPlugin(pkg);\n }\n\n return Promise.all(imports.map(uncompressImport));\n}\n\n/**\n * Type definition for plugin raw descriptor\n */\nexport type AsyncImportRawDescription = {\n url?: string;\n import_name?: string;\n import_as?: string;\n window_name?: string;\n stylesheets?: string[];\n};\n","/**\n * Resolves element references in configuration object.\n * Looks for objects with { $element: \"selector\" } format and replaces them with actual DOM elements.\n *\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved element references\n */\nexport function resolveConfigElementReferences<T>(obj: T): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => resolveConfigElementReferences(item)) as T;\n }\n\n const anyObj = obj as any;\n\n if (anyObj.$element && typeof anyObj.$element === 'string') {\n const element = document.querySelector(anyObj.$element);\n\n if (!element) {\n console.warn(`Element not found for selector: ${anyObj.$element}`);\n }\n\n return (element || null) as T;\n }\n\n const result = Object.create(null);\n\n for (const [key, value] of Object.entries(obj)) {\n result[key] = resolveConfigElementReferences(value);\n }\n\n return result as T;\n}\n","/**\n * Generates a unique identifier string\n *\n * @returns Random string that can be used as unique identifier\n */\nexport function uid() {\n return Math.random().toString(36).substring(2);\n}\n","import type { ContextWatchdog } from 'ckeditor5';\n\nimport { execIfDOMReady, loadAsyncImports, resolveConfigElementReferences } from 'src/helpers';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorContextComponent extends HTMLElement {\n instance: ContextWatchdog | null = null;\n\n instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n #connectedEditors = new Set<CKEditorComponent>();\n\n static get observedAttributes() {\n return ['plugins', 'config'];\n }\n\n async connectedCallback() {\n try {\n execIfDOMReady(() => this.#initializeContext());\n }\n catch (error) {\n console.error('Failed to initialize context:', error);\n this.dispatchEvent(new CustomEvent('context-error', { detail: error }));\n }\n }\n\n async attributeChangedCallback(_: unknown, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null && oldValue !== newValue) {\n await this.#initializeContext();\n }\n }\n\n async disconnectedCallback() {\n if (this.instance) {\n await this.instance.destroy();\n this.instance = null;\n }\n }\n\n /**\n * Register editor component with this context\n *\n * @param editor - Editor component to register.\n */\n registerEditor(editor: CKEditorComponent) {\n this.#connectedEditors.add(editor);\n }\n\n /**\n * Unregister editor component from this context\n *\n * @param editor - Editor component to unregister\n */\n unregisterEditor(editor: CKEditorComponent) {\n this.#connectedEditors.delete(editor);\n }\n\n /**\n * Initialize CKEditor context with shared configuration\n *\n * @private\n */\n async #initializeContext() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers<ContextWatchdog>();\n\n await this.instance.destroy();\n\n this.instance = null;\n }\n\n // Broadcast context initialization event\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach:before', { detail: { element: this } }),\n );\n\n const { Context, ContextWatchdog } = await import('ckeditor5');\n const plugins = await this.#getPlugins();\n const config = this.#getConfig();\n\n // Broadcast context mounting event with configuration\n window.dispatchEvent(\n new CustomEvent('ckeditor:context:attach', { detail: { config, element: this } }),\n );\n\n this.instance = new ContextWatchdog(Context, {\n crashNumberLimit: 10,\n });\n\n await this.instance.create({\n ...config,\n plugins,\n });\n\n this.instance.on('itemError', (...args) => {\n console.error('Context item error:', ...args);\n });\n\n this.instancePromise.resolve(this.instance);\n this.dispatchEvent(new CustomEvent('context-ready', { detail: this.instance }));\n\n // Reinitialize connected editors.\n await Promise.all(\n [...this.#connectedEditors].map(editor => editor.reinitializeEditor()),\n );\n }\n\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n\n return loadAsyncImports(raw ? JSON.parse(raw) : []);\n }\n\n /**\n * Gets context configuration with resolved element references.\n *\n * @private\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n}\n\ncustomElements.define('ckeditor-context-component', CKEditorContextComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers/exec-if-dom-ready';\n\nexport class CKEditorEditableComponent extends HTMLElement {\n /**\n * List of attributes that trigger updates when changed\n *\n * @static\n * @returns {string[]} Array of attribute names to observe\n */\n static get observedAttributes() {\n return ['name'];\n }\n\n /**\n * Gets the name of this editable region\n */\n get name() {\n return this.getAttribute('name') || 'editable';\n }\n\n /**\n * Gets the actual editable DOM element.\n */\n get editableElement() {\n return this.querySelector('div')!;\n }\n\n /**\n * Lifecycle callback when element is added to DOM\n * Sets up the editable element and registers it with the parent editor\n */\n connectedCallback() {\n execIfDOMReady(() => {\n const editorComponent = this.#queryEditorElement();\n\n if (!editorComponent) {\n throw new Error('ckeditor-editable-component must be a child of ckeditor-component');\n }\n\n this.innerHTML = `<div>${this.innerHTML}</div>`;\n this.style.display = 'block';\n\n if (editorComponent.isDecoupled()) {\n editorComponent.runAfterEditorReady((editor) => {\n this.appendChild((editor.ui.view as any)[this.name].element);\n });\n }\n else {\n if (!this.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n\n editorComponent.editables![this.name] = this;\n }\n });\n }\n\n /**\n * Lifecycle callback for attribute changes\n * Handles name changes and propagates other attributes to editable element\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n if (oldValue === newValue) {\n return;\n }\n\n if (name === 'name') {\n if (!oldValue) {\n return;\n }\n\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n editorComponent.editables![newValue] = editorComponent.editables![oldValue]!;\n delete editorComponent.editables![oldValue];\n }\n }\n else {\n this.editableElement.setAttribute(name, newValue!);\n }\n }\n\n /**\n * Lifecycle callback when element is removed\n * Un-registers this editable from the parent editor\n */\n disconnectedCallback() {\n const editorComponent = this.#queryEditorElement();\n\n if (editorComponent) {\n delete editorComponent.editables![this.name];\n }\n }\n\n /**\n * Finds the parent editor component\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-editable-component', CKEditorEditableComponent);\n","import type { MultiRootEditor } from 'ckeditor5';\n\nimport type { CKEditorComponent } from './editor';\n\nexport class CKEditorMultiRootEditablesTracker {\n #editorElement: CKEditorComponent;\n #editables: Record<string, HTMLElement>;\n\n /**\n * Creates new tracker instance wrapped in a Proxy for dynamic property access\n *\n * @param editorElement - Parent editor component reference\n * @param initialEditables - Initial editable elements\n * @returns Proxy wrapping the tracker\n */\n constructor(\n editorElement: CKEditorComponent,\n initialEditables: Record<string, HTMLElement> = {},\n ) {\n this.#editorElement = editorElement;\n this.#editables = initialEditables;\n\n return new Proxy(this, {\n /**\n * Handles property access, returns class methods or editable elements\n *\n * @param target - The tracker instance\n * @param name - Property name being accessed\n */\n get(target: CKEditorMultiRootEditablesTracker, name: string) {\n if (typeof (target as any)[name] === 'function') {\n return (target as any)[name].bind(target);\n }\n\n return target.#editables[name];\n },\n\n /**\n * Handles setting new editable elements, triggers root attachment\n *\n * @param target - The tracker instance\n * @param name - Name of the editable root\n * @param element - Element to attach as editable\n */\n set(target: CKEditorMultiRootEditablesTracker, name: string, element: HTMLElement) {\n if (target.#editables[name] !== element) {\n void target.attachRoot(name, element);\n target.#editables[name] = element;\n }\n return true;\n },\n\n /**\n * Handles removing editable elements, triggers root detachment\n *\n * @param target - The tracker instance\n * @param name - Name of the root to remove\n */\n deleteProperty(target: CKEditorMultiRootEditablesTracker, name: string) {\n void target.detachRoot(name);\n delete target.#editables[name];\n\n return true;\n },\n });\n }\n\n /**\n * Attaches a new editable root to the editor.\n * Creates new editor root and binds UI elements.\n *\n * @param name - Name of the editable root\n * @param element - DOM element to use as editable\n * @returns Resolves when root is attached\n */\n async attachRoot(name: string, element: HTMLElement) {\n await this.detachRoot(name);\n\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const { ui, editing, model } = editor;\n\n editor.addRoot(name, {\n isUndoable: false,\n data: element.innerHTML,\n });\n\n const root = model.document.getRoot(name);\n\n if (ui.getEditableElement(name)) {\n editor.detachEditable(root!);\n }\n\n const editable = ui.view.createEditable(name, element);\n ui.addEditable(editable);\n editing.view.forceRender();\n });\n }\n\n /**\n * Detaches an editable root from the editor.\n * Removes editor root and cleans up UI bindings.\n *\n * @param name - Name of root to detach\n * @returns Resolves when root is detached\n */\n async detachRoot(name: string) {\n return this.#editorElement.runAfterEditorReady<MultiRootEditor>((editor) => {\n const root = editor.model.document.getRoot(name);\n\n if (root) {\n editor.detachEditable(root);\n editor.detachRoot(name, true);\n }\n });\n }\n\n /**\n * Gets all currently tracked editable elements\n *\n * @returns Map of all editable elements\n */\n getAll() {\n return this.#editables;\n }\n}\n","import type { Editor, EditorWatchdog, Watchdog } from 'ckeditor5';\n\nimport type { AsyncImportRawDescription } from '../../helpers';\nimport type { CKEditorContextComponent } from '../context';\nimport type { CKEditorEditableComponent } from '../editable';\n\nimport {\n execIfDOMReady,\n isSafeKey,\n loadAsyncCSS,\n loadAsyncImports,\n resolveConfigElementReferences,\n uid,\n} from '../../helpers';\nimport { CKEditorMultiRootEditablesTracker } from './multiroot-editables-tracker';\n\nexport class CKEditorComponent extends HTMLElement {\n instancePromise = Promise.withResolvers<Editor>();\n\n watchdog: Watchdog | null = null;\n\n instance: Editor | null = null;\n\n editables: Record<string, HTMLElement> | null = Object.create({});\n\n #initialHTML: string = '';\n\n #context: CKEditorContextComponent | null = null;\n\n #contextEditorId: string | null = null;\n\n #bundle: object | null = null;\n\n /**\n * List of attributes that trigger updates when changed.\n */\n static get observedAttributes() {\n return ['config', 'plugins', 'translations', 'type'];\n }\n\n /**\n * List of input attributes that trigger updates when changed.\n */\n static get inputAttributes() {\n return ['name', 'required', 'value'];\n }\n\n get oneditorchange() {\n return this.#getEventHandler('editorchange');\n }\n\n set oneditorchange(handler) {\n this.#setEventHandler('editorchange', handler);\n }\n\n get oneditorready() {\n return this.#getEventHandler('editorready');\n }\n\n set oneditorready(handler) {\n this.#setEventHandler('editorready', handler);\n }\n\n get oneditorerror() {\n return this.#getEventHandler('editorerror');\n }\n\n set oneditorerror(handler) {\n this.#setEventHandler('editorerror', handler);\n }\n\n /**\n * Gets event handler function from attribute or property\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @returns Event handler or null\n */\n #getEventHandler(name: string): Function | null {\n if (this.hasAttribute(`on${name}`)) {\n const handler = this.getAttribute(`on${name}`)!;\n\n if (!isSafeKey(handler)) {\n throw new Error(`Unsafe event handler attribute value: ${handler}`);\n }\n\n // eslint-disable-next-line no-new-func\n return (window as any)[handler] || new Function('event', handler);\n }\n return (this as any)[`#${name}Handler`];\n }\n\n /**\n * Sets event handler function\n *\n * @private\n * @param name - Event name without 'on' prefix\n * @param handler - Event handler\n */\n #setEventHandler(name: string, handler: Function | null) {\n if (typeof handler === 'string') {\n this.setAttribute(`on${name}`, handler);\n }\n else {\n this.removeAttribute(`on${name}`);\n (this as any)[`#${name}Handler`] = handler;\n }\n }\n\n /**\n * Lifecycle callback when element is connected to DOM\n * Initializes the editor when DOM is ready\n *\n * @protected\n */\n connectedCallback() {\n this.#context = this.closest('ckeditor-context-component');\n this.#initialHTML = this.innerHTML;\n\n try {\n execIfDOMReady(async () => {\n if (this.#context) {\n await this.#context.instancePromise.promise;\n this.#context.registerEditor(this);\n }\n\n await this.reinitializeEditor();\n });\n }\n catch (error) {\n console.error('Failed to initialize editor:', error);\n\n const event = new CustomEvent('editor-error', { detail: error });\n\n this.dispatchEvent(event);\n this.oneditorerror?.(event);\n }\n }\n\n /**\n * Handles attribute changes and reinitializes editor if needed\n *\n * @protected\n * @param name - Name of changed attribute\n * @param oldValue - Previous attribute value\n * @param newValue - New attribute value\n */\n async attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue !== null\n && oldValue !== newValue\n && CKEditorComponent.observedAttributes.includes(name) && this.isConnected) {\n await this.reinitializeEditor();\n }\n }\n\n /**\n * Lifecycle callback when element is removed from DOM\n * Destroys the editor instance\n * @protected\n */\n async disconnectedCallback() {\n if (this.#context) {\n this.#context.unregisterEditor(this);\n }\n\n try {\n await this.#destroy();\n }\n catch (error) {\n console.error('Failed to destroy editor:', error);\n }\n }\n\n /**\n * Runs a callback after the editor is ready. It waits for editor\n * initialization if needed.\n *\n * @param callback - Callback to run\n */\n runAfterEditorReady<E extends Editor>(callback: (editor: E) => void): Promise<void> {\n if (this.instance) {\n return Promise.resolve(callback(this.instance as unknown as E));\n }\n\n return this.instancePromise.promise.then(callback as unknown as any);\n }\n\n /**\n * Determines appropriate editor element tag based on editor type\n */\n get #editorElementTag() {\n switch (this.getAttribute('type')) {\n case 'ClassicEditor':\n return 'textarea';\n\n default:\n return 'div';\n }\n }\n\n /**\n * Gets the CKEditor context instance if available.\n */\n get #contextWatchdog() {\n return this.#context?.instance;\n }\n\n /**\n * Destroys the editor instance and watchdog if available\n */\n async #destroy() {\n if (this.#contextEditorId) {\n await this.#contextWatchdog!.remove(this.#contextEditorId);\n }\n\n await this.instance?.destroy();\n this.watchdog?.destroy();\n }\n\n /**\n * Gets editor configuration with resolved element references\n */\n #getConfig() {\n const config = JSON.parse(this.getAttribute('config') || '{}');\n\n return resolveConfigElementReferences(config);\n }\n\n /**\n * Creates a new CKEditor instance\n */\n async #initializeEditor(editablesOrContent: Record<string, HTMLElement | string> | CKEditorMultiRootEditablesTracker | string | HTMLElement) {\n await Promise.all([\n this.#ensureStylesheetsInjected(),\n this.#ensureWindowScriptsInjected(),\n ]);\n\n // Depending on the type of the editor the content supplied on the first\n // argument is different. For ClassicEditor it's a element or string, for MultiRootEditor\n // it's an object with editables, for DecoupledEditor it's string.\n let content: any = editablesOrContent;\n\n if (editablesOrContent instanceof CKEditorMultiRootEditablesTracker) {\n content = editablesOrContent.getAll();\n }\n else if (typeof editablesOrContent !== 'string') {\n content = (editablesOrContent as any)['main'];\n }\n\n // Broadcast editor initialization event. It's good time to load add inline window plugins.\n const beforeInitEventDetails = {\n ...content instanceof HTMLElement && { element: content },\n ...typeof content === 'string' && { data: content },\n ...content instanceof Object && { editables: content },\n };\n\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach:before', { detail: beforeInitEventDetails }),\n );\n\n // Start fetching constructor.\n const Editor = await this.#getEditorConstructor();\n const [plugins, translations] = await Promise.all([\n this.#getPlugins(),\n this.#getTranslations(),\n ]);\n\n const config = {\n ...this.#getConfig(),\n ...translations.length && {\n translations,\n },\n plugins,\n };\n\n // Broadcast editor mounting event. It's good time to map configuration.\n window.dispatchEvent(\n new CustomEvent('ckeditor:attach', { detail: { config, ...beforeInitEventDetails } }),\n );\n\n // Initialize watchdog if needed\n let watchdog: EditorWatchdog | null = null;\n let instance: Editor | null = null;\n let contextId: string | null = null;\n\n if (this.#context) {\n contextId = uid();\n\n await this.#contextWatchdog!.add({\n creator: (_element, _config) => Editor.create(_element, _config),\n id: contextId,\n sourceElementOrData: content,\n type: 'editor',\n config,\n });\n\n instance = this.#contextWatchdog!.getItem(contextId) as Editor;\n }\n else if (this.hasWatchdog()) {\n // Let's create use with plain watchdog.\n const { EditorWatchdog } = await import('ckeditor5');\n watchdog = new EditorWatchdog(Editor);\n\n await watchdog.create(content, config);\n\n instance = watchdog.editor;\n }\n else {\n // Let's create the editor without watchdog.\n instance = await Editor.create(content, config);\n }\n\n return {\n contextId,\n instance,\n watchdog,\n };\n }\n\n /**\n * Re-initializes the editor by destroying existing instance and creating new one\n *\n * @private\n * @returns {Promise<void>}\n */\n async reinitializeEditor() {\n if (this.instance) {\n this.instancePromise = Promise.withResolvers();\n\n await this.#destroy();\n\n this.instance = null;\n }\n\n this.style.display = 'block';\n\n if (!this.isMultiroot() && !this.isDecoupled()) {\n this.innerHTML = `<${this.#editorElementTag}>${this.#initialHTML}</${this.#editorElementTag}>`;\n this.#assignInputAttributes();\n }\n\n // Let's track changes in editables if it's a multiroot editor.\n if (this.isMultiroot()) {\n this.editables = new CKEditorMultiRootEditablesTracker(this, this.#queryEditables()) as unknown as Record<string, HTMLElement>;\n }\n else if (this.isDecoupled()) {\n this.editables = null;\n }\n else {\n this.editables = this.#queryEditables();\n }\n\n try {\n const { watchdog, instance, contextId } = await this.#initializeEditor(this.editables || this.#getConfig().initialData || '');\n\n this.watchdog = watchdog;\n this.instance = instance!;\n this.#contextEditorId = contextId;\n\n this.#setupContentSync();\n this.#setupEditableHeight();\n this.#setupDataChangeListener();\n\n this.instancePromise.resolve(this.instance!);\n\n // Broadcast editor ready event\n const event = new CustomEvent('editor-ready', { detail: this.instance });\n\n this.dispatchEvent(event);\n this.oneditorready?.(event);\n }\n catch (err) {\n this.instancePromise.reject(err);\n throw err;\n }\n }\n\n /**\n * Sets up data change listener that broadcasts content changes\n */\n #setupDataChangeListener() {\n const getRootContent = (rootName: string) => this.instance!.getData({ rootName });\n const getAllRoots = () =>\n this.instance?.model.document\n .getRootNames()\n .reduce((acc, rootName) => ({\n ...acc,\n [rootName]: getRootContent(rootName),\n }), {});\n\n this.instance?.model.document.on('change:data', () => {\n const event = new CustomEvent('editor-change', {\n detail: {\n editor: this.instance,\n data: getAllRoots(),\n },\n bubbles: true,\n });\n\n this.dispatchEvent(event);\n this.oneditorchange?.(event);\n });\n }\n\n /**\n * Checks if current editor is classic type\n */\n isClassic() {\n return this.getAttribute('type') === 'ClassicEditor';\n }\n\n /**\n * Checks if current editor is balloon type\n */\n isBallon() {\n return this.getAttribute('type') === 'BalloonEditor';\n }\n\n /**\n * Checks if current editor is multiroot type\n */\n isMultiroot() {\n return this.getAttribute('type') === 'MultiRootEditor';\n }\n\n /**\n * Checks if current editor is decoupled type\n */\n isDecoupled() {\n return this.getAttribute('type') === 'DecoupledEditor';\n }\n\n /**\n * Checks if current editor has watchdog enabled\n */\n hasWatchdog() {\n return this.getAttribute('watchdog') === 'true';\n }\n\n /**\n * Queries and validates editable elements\n */\n #queryEditables() {\n if (this.isDecoupled()) {\n return {};\n }\n\n if (this.isMultiroot()) {\n const editables = [...this.querySelectorAll('ckeditor-editable-component')] as CKEditorEditableComponent[];\n\n return editables.reduce((acc, element) => {\n if (!element.name) {\n throw new Error('Editable component missing required \"name\" attribute');\n }\n acc[element.name] = element;\n return acc;\n }, Object.create(null));\n }\n\n const mainEditable = this.querySelector(this.#editorElementTag);\n\n if (!mainEditable) {\n throw new Error(`No ${this.#editorElementTag} element found`);\n }\n\n return { main: mainEditable };\n }\n\n /**\n * Copies input-related attributes from component to the main editable element\n *\n * @private\n */\n #assignInputAttributes() {\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n for (const attr of CKEditorComponent.inputAttributes) {\n if (this.hasAttribute(attr)) {\n textarea.setAttribute(attr, this.getAttribute(attr)!);\n }\n }\n }\n\n /**\n * Sets up content sync between editor and textarea element.\n *\n * @private\n */\n #setupContentSync() {\n if (!this.instance) {\n return;\n }\n\n const textarea = this.querySelector('textarea');\n\n if (!textarea) {\n return;\n }\n\n // Initial sync\n const syncInput = () => {\n this.style.position = 'relative';\n\n textarea.innerHTML = '';\n textarea.value = this.instance!.getData();\n textarea.tabIndex = -1;\n\n Object.assign(textarea.style, {\n display: 'flex',\n position: 'absolute',\n bottom: '0',\n left: '50%',\n width: '1px',\n height: '1px',\n opacity: '0',\n pointerEvents: 'none',\n margin: '0',\n padding: '0',\n border: 'none',\n });\n };\n\n syncInput();\n\n // Listen for changes\n this.instance.model.document.on('change:data', () => {\n textarea.dispatchEvent(new Event('input', { bubbles: true }));\n textarea.dispatchEvent(new Event('change', { bubbles: true }));\n\n syncInput();\n });\n }\n\n /**\n * Sets up editable height for ClassicEditor\n *\n * @private\n */\n #setupEditableHeight() {\n if (!this.isClassic() && !this.isBallon()) {\n return;\n }\n\n const { instance } = this;\n const height = Number.parseInt(this.getAttribute('editable-height')!, 10);\n\n if (Number.isNaN(height)) {\n return;\n }\n\n instance!.editing.view.change((writer) => {\n writer.setStyle('height', `${height}px`, instance!.editing.view.document.getRoot()!);\n });\n }\n\n /**\n * Gets bundle JSON description from translations attribute\n */\n #getBundle(): BundleDescription {\n return this.#bundle ||= JSON.parse(this.getAttribute('bundle')!);\n }\n\n /**\n * Checks if all required stylesheets are injected. If not, inject.\n */\n async #ensureStylesheetsInjected() {\n await loadAsyncCSS(this.#getBundle()?.stylesheets || []);\n }\n\n /**\n * Checks if all required scripts are injected. If not, inject.\n */\n async #ensureWindowScriptsInjected() {\n const windowScripts = (this.#getBundle()?.scripts || []).filter(script => !!script.window_name);\n\n await loadAsyncImports(windowScripts);\n }\n\n /**\n * Loads translation modules\n */\n async #getTranslations() {\n const translations = this.#getBundle()?.scripts.filter(script => script.translation);\n\n return loadAsyncImports(translations);\n }\n\n /**\n * Loads plugin modules\n */\n async #getPlugins() {\n const raw = this.getAttribute('plugins');\n const items = raw ? JSON.parse(raw) : [];\n const mappedItems = items.map((item: any) =>\n typeof item === 'string'\n ? { import_name: 'ckeditor5', import_as: item }\n : item,\n );\n\n return loadAsyncImports(mappedItems);\n }\n\n /**\n * Gets editor constructor based on type attribute\n */\n async #getEditorConstructor() {\n const CKEditor = await import('ckeditor5');\n const editorType = this.getAttribute('type');\n\n if (!editorType || !Object.prototype.hasOwnProperty.call(CKEditor, editorType)) {\n throw new Error(`Invalid editor type: ${editorType}`);\n }\n\n return (CKEditor as any)[editorType] as EditorConstructor;\n }\n}\n\ntype EditorConstructor = {\n create: (...args: any[]) => Promise<Editor>;\n};\n\ntype BundleDescription = {\n stylesheets: string[];\n scripts: Array<AsyncImportRawDescription & {\n translation?: boolean;\n }>;\n};\n\ncustomElements.define('ckeditor-component', CKEditorComponent);\n","import type { CKEditorComponent } from './editor';\n\nimport { execIfDOMReady } from '../helpers';\n\nclass CKEditorUIPartComponent extends HTMLElement {\n /**\n * Lifecycle callback when element is added to DOM.\n * Adds the toolbar to the editor UI.\n */\n connectedCallback() {\n execIfDOMReady(async () => {\n const uiPart = this.getAttribute('name')!;\n const editor = await this.#queryEditorElement()!.instancePromise.promise;\n\n this.appendChild((editor.ui.view as any)[uiPart].element);\n });\n }\n\n /**\n * Finds the parent editor component.\n */\n #queryEditorElement(): CKEditorComponent | null {\n return this.closest('ckeditor-component') || document.body.querySelector('ckeditor-component');\n }\n}\n\ncustomElements.define('ckeditor-ui-part-component', CKEditorUIPartComponent);\n"],"names":["execIfDOMReady","callback","SCRIPT_LOAD_PROMISES","injectScript","url","promise","resolve","reject","script","isSafeKey","key","stylesheetExists","href","sheet","loadAsyncCSS","stylesheets","promises","link","loadAsyncImports","imports","loadExternalPlugin","import_name","import_as","window_name","isScriptPresent","module","imported","uncompressImport","pkg","resolveConfigElementReferences","obj","item","anyObj","element","result","value","uid","CKEditorContextComponent","#connectedEditors","#initializeContext","error","_","oldValue","newValue","editor","Context","ContextWatchdog","plugins","#getPlugins","config","#getConfig","args","raw","CKEditorEditableComponent","editorComponent","#queryEditorElement","name","CKEditorMultiRootEditablesTracker","#editorElement","#editables","editorElement","initialEditables","target","ui","editing","model","root","editable","CKEditorComponent","#initialHTML","#context","#contextEditorId","#bundle","#getEventHandler","handler","#setEventHandler","event","#destroy","#editorElementTag","#contextWatchdog","#initializeEditor","editablesOrContent","#ensureStylesheetsInjected","#ensureWindowScriptsInjected","content","beforeInitEventDetails","Editor","#getEditorConstructor","translations","#getTranslations","watchdog","instance","contextId","_element","_config","EditorWatchdog","#assignInputAttributes","#queryEditables","#setupContentSync","#setupEditableHeight","#setupDataChangeListener","err","getRootContent","rootName","getAllRoots","acc","mainEditable","textarea","attr","syncInput","height","writer","#getBundle","windowScripts","mappedItems","CKEditor","editorType","CKEditorUIPartComponent","uiPart"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAkB,QAAQ,EAAE,MAAM,WAAW,CAAC;AAgBlE,qBAAa,iBAAkB,SAAQ,WAAW;;IAChD,eAAe,+BAAmC;IAElD,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAEjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAAqB;IAUlE;;OAEG;IACH,MAAM,KAAK,kBAAkB,aAE5B;IAED;;OAEG;IACH,MAAM,KAAK,eAAe,aAEzB;IAED,IAAI,cAAc,oBAEjB;IAED,IAAI,cAAc,CAAC,OAAO,iBAAA,EAEzB;IAED,IAAI,aAAa,oBAEhB;IAED,IAAI,aAAa,CAAC,OAAO,iBAAA,EAExB;IAED,IAAI,aAAa,oBAEhB;IAED,IAAI,aAAa,CAAC,OAAO,iBAAA,EAExB;IAwCD;;;;;OAKG;IACH,iBAAiB;IAwBjB;;;;;;;OAOG;IACG,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ7F;;;;OAIG;IACG,oBAAoB;IAa1B;;;;;OAKG;IACH,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAkB,QAAQ,EAAE,MAAM,WAAW,CAAC;AAgBlE,qBAAa,iBAAkB,SAAQ,WAAW;;IAChD,eAAe,+BAAmC;IAElD,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAEjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAAqB;IAUlE;;OAEG;IACH,MAAM,KAAK,kBAAkB,aAE5B;IAED;;OAEG;IACH,MAAM,KAAK,eAAe,aAEzB;IAED,IAAI,cAAc,oBAEjB;IAED,IAAI,cAAc,CAAC,OAAO,iBAAA,EAEzB;IAED,IAAI,aAAa,oBAEhB;IAED,IAAI,aAAa,CAAC,OAAO,iBAAA,EAExB;IAED,IAAI,aAAa,oBAEhB;IAED,IAAI,aAAa,CAAC,OAAO,iBAAA,EAExB;IAwCD;;;;;OAKG;IACH,iBAAiB;IAwBjB;;;;;;;OAOG;IACG,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ7F;;;;OAIG;IACG,oBAAoB;IAa1B;;;;;OAKG;IACH,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA4InF;;;;;OAKG;IACG,kBAAkB;IA+ExB;;OAEG;IACH,SAAS;IAIT;;OAEG;IACH,QAAQ;IAIR;;OAEG;IACH,WAAW;IAIX;;OAEG;IACH,WAAW;IAIX;;OAEG;IACH,WAAW;CAwLZ"}
|
data/npm_package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ckeditor5-rails",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.0",
|
|
4
4
|
"description": "CKEditor 5 integration for Rails Framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"typecheck": "tsc --noEmit --pretty"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"ckeditor5": "^
|
|
33
|
-
"ckeditor5-premium-features": "^
|
|
32
|
+
"ckeditor5": "^47.6.1",
|
|
33
|
+
"ckeditor5-premium-features": "^47.6.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"typescript": "^5.5.4",
|
|
@@ -63,12 +63,16 @@ RSpec.describe 'CKEditor5 Types Integration', type: :feature, js: true do
|
|
|
63
63
|
});
|
|
64
64
|
JS
|
|
65
65
|
|
|
66
|
+
expect(page).to have_css('.ck-editor__editable', minimum: editables.size, wait: 10)
|
|
67
|
+
|
|
66
68
|
# Test each editable
|
|
67
69
|
expected_data = {}
|
|
68
70
|
editors.each_with_index do |editor, index|
|
|
69
71
|
editor.click
|
|
70
72
|
editor.send_keys([[:control, 'a'], :backspace])
|
|
73
|
+
|
|
71
74
|
content = "Content for #{editables[index]}"
|
|
75
|
+
|
|
72
76
|
editor.send_keys(content)
|
|
73
77
|
expected_data[editables[index]] = "<p>#{content}</p>"
|
|
74
78
|
end
|
|
@@ -152,7 +156,6 @@ RSpec.describe 'CKEditor5 Types Integration', type: :feature, js: true do
|
|
|
152
156
|
end
|
|
153
157
|
|
|
154
158
|
it 'handles dynamically added editables' do
|
|
155
|
-
# Set up event listener
|
|
156
159
|
page.execute_script(<<~JS)
|
|
157
160
|
window._newEditableEvents = [];
|
|
158
161
|
document.querySelector('ckeditor-component').addEventListener('editor-change', (e) => {
|
|
@@ -163,7 +166,6 @@ RSpec.describe 'CKEditor5 Types Integration', type: :feature, js: true do
|
|
|
163
166
|
});
|
|
164
167
|
JS
|
|
165
168
|
|
|
166
|
-
# Add new editable component
|
|
167
169
|
page.execute_script(<<~JS)
|
|
168
170
|
const container = document.querySelector('[data-testid="multiroot-editor"]');
|
|
169
171
|
const newEditable = document.createElement('ckeditor-editable-component');
|
|
@@ -171,14 +173,15 @@ RSpec.describe 'CKEditor5 Types Integration', type: :feature, js: true do
|
|
|
171
173
|
container.appendChild(newEditable);
|
|
172
174
|
JS
|
|
173
175
|
|
|
174
|
-
|
|
176
|
+
# Wait for the new editable to be fully initialized by CKEditor,
|
|
177
|
+
# not just present in the DOM — minimum: 3 because multiroot already has 2
|
|
178
|
+
expect(page).to have_css('.ck-editor__editable', minimum: 3, wait: 10)
|
|
175
179
|
|
|
176
|
-
# Find and interact with new editable
|
|
177
180
|
new_editable = find("[name='new-root']")
|
|
178
181
|
new_editable.click
|
|
182
|
+
new_editable.send_keys([[:control, 'a'], :backspace])
|
|
179
183
|
new_editable.send_keys('Content for new root')
|
|
180
184
|
|
|
181
|
-
# Verify the change event
|
|
182
185
|
eventually do
|
|
183
186
|
events = page.evaluate_script('window._newEditableEvents')
|
|
184
187
|
last_event = events.last
|
|
@@ -147,7 +147,7 @@ RSpec.describe CKEditor5::Rails::Presets::Manager do
|
|
|
147
147
|
it 'has default configuration' do
|
|
148
148
|
expect(manager.default.version).to eq(CKEditor5::Rails::DEFAULT_CKEDITOR_VERSION)
|
|
149
149
|
expect(manager.default.type).to eq(:classic)
|
|
150
|
-
expect(manager.default.automatic_upgrades?).to be
|
|
150
|
+
expect(manager.default.automatic_upgrades?).to be false
|
|
151
151
|
expect(manager.default.menubar?).to be true
|
|
152
152
|
expect(manager.default.config[:plugins]).not_to be_empty
|
|
153
153
|
expect(manager.default.config[:toolbar][:items]).not_to be_empty
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ckeditor5
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.36.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mateusz Bagiński
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2026-03-
|
|
12
|
+
date: 2026-03-14 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rails
|