ckeditor5 1.8.0 → 1.9.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 +43 -5
- data/lib/ckeditor5/rails/assets/webcomponent.mjs +246 -56
- data/lib/ckeditor5/rails/context/helpers.rb +13 -0
- data/lib/ckeditor5/rails/context/props.rb +30 -0
- data/lib/ckeditor5/rails/editor/helpers.rb +7 -14
- data/lib/ckeditor5/rails/helpers.rb +2 -0
- data/lib/ckeditor5/rails/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb520612d3f2847e8d70c48a8ffb3d1ad4be25800dd5f141a6948caf30b07978
|
4
|
+
data.tar.gz: 5f9850fb6a39774ab796f67b5dc95fa0ec1e6a5fe6f04fb3481f6ff17c76e026
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7057a3e537f5626b4754b815c1f418ddac64301350aa3b0299d5051dcda474a5f397018389a0e7c773bc1d15687043498a2bcd44518581e4233f8ab4ae85dc52
|
7
|
+
data.tar.gz: 0526b5810f411971ce3adafa1bad252eabaffc566f3d637b6585c2a16a6d6c938078e8b88ed88b34e610477c87c66f5dfc74d092fab2f46f183327f2fca9d287
|
data/README.md
CHANGED
@@ -101,6 +101,9 @@ Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
|
|
101
101
|
- [Inline editor 📝](#inline-editor-)
|
102
102
|
- [Balloon editor 🎈](#balloon-editor-)
|
103
103
|
- [Decoupled editor 🌐](#decoupled-editor-)
|
104
|
+
- [Using Context 📦](#using-context-)
|
105
|
+
- [Benefits of Using Context in Collaboration 🤝](#benefits-of-using-context-in-collaboration-)
|
106
|
+
- [Using Context in CKEditor 5 🔄](#using-context-in-ckeditor-5-)
|
104
107
|
- [How to access editor instance? 🤔](#how-to-access-editor-instance-)
|
105
108
|
- [Common Tasks and Solutions 💡](#common-tasks-and-solutions-)
|
106
109
|
- [Setting Editor Language 🌐](#setting-editor-language-)
|
@@ -184,9 +187,6 @@ Configuration of the editor can be complex, and it's recommended to use the [CKE
|
|
184
187
|
|
185
188
|
### Available Configuration Methods ⚙️
|
186
189
|
|
187
|
-
<details>
|
188
|
-
<summary>Expand to show available methods 📖</summary>
|
189
|
-
|
190
190
|
#### `cdn(cdn = nil, &block)` method
|
191
191
|
|
192
192
|
Defines the CDN to be used for CKEditor 5 assets. The example below shows how to set the CDN to `:jsdelivr`:
|
@@ -569,8 +569,6 @@ CKEditor5::Rails.configure do
|
|
569
569
|
end
|
570
570
|
```
|
571
571
|
|
572
|
-
</details>
|
573
|
-
|
574
572
|
## Including CKEditor 5 assets 📦
|
575
573
|
|
576
574
|
To include CKEditor 5 assets in your application, you can use the `ckeditor5_assets` helper method. This method takes the version of CKEditor 5 as an argument and includes the necessary resources of the editor. Depending on the specified configuration, it includes the JS and CSS assets from the official CKEditor 5 CDN or one of the popular CDNs.
|
@@ -965,6 +963,46 @@ If you want to use a decoupled editor, you can pass the `type` keyword argument
|
|
965
963
|
<% end %>
|
966
964
|
```
|
967
965
|
|
966
|
+
## Using Context 📦
|
967
|
+
|
968
|
+
Context CKEditor 5 is a feature that allows multiple editor instances to share a common configuration and state. This is particularly useful in collaborative environments where multiple users are editing different parts of the same document simultaneously. By using a shared context, all editor instances can synchronize their configurations, plugins, and other settings, ensuring a consistent editing experience across all users.
|
969
|
+
|
970
|
+
### Benefits of Using Context in Collaboration 🤝
|
971
|
+
|
972
|
+
1. **Consistency**: Ensures that all editor instances have the same configuration, plugins, and settings, providing a uniform editing experience.
|
973
|
+
2. **Synchronization**: Allows real-time synchronization of content and changes across multiple editor instances, making collaborative editing seamless.
|
974
|
+
3. **Resource Sharing**: Reduces the overhead of loading and initializing multiple editor instances by sharing common resources and configurations.
|
975
|
+
4. **Simplified Management**: Makes it easier to manage and update the configuration and state of multiple editor instances from a single point.
|
976
|
+
|
977
|
+
### Using Context in CKEditor 5 🔄
|
978
|
+
|
979
|
+
Format of the `ckeditor5_context` helper:
|
980
|
+
|
981
|
+
```erb
|
982
|
+
<%= ckeditor5_context config: { ...you context config... }, plugins: [ ...your context plugins... ] do %>
|
983
|
+
<%= ckeditor5_editor %>
|
984
|
+
<%= ckeditor5_editor %>
|
985
|
+
<% end %>
|
986
|
+
```
|
987
|
+
|
988
|
+
Example usage:
|
989
|
+
|
990
|
+
```erb
|
991
|
+
<!-- app/views/demos/index.html.erb -->
|
992
|
+
|
993
|
+
<% content_for :head do %>
|
994
|
+
<%= ckeditor5_assets preset: :ultrabasic %>
|
995
|
+
<% end %>
|
996
|
+
|
997
|
+
<%= ckeditor5_context do %>
|
998
|
+
<%= ckeditor5_editor initial_data: 'Hello World' %>
|
999
|
+
|
1000
|
+
<br>
|
1001
|
+
|
1002
|
+
<%= ckeditor5_editor initial_data: 'Hello World 2' %>
|
1003
|
+
<% end %>
|
1004
|
+
```
|
1005
|
+
|
968
1006
|
## How to access editor instance? 🤔
|
969
1007
|
|
970
1008
|
You can access the editor instance using plain HTML and JavaScript, as CKEditor 5 is a web component with defined `instance`, `instancePromise` and `editables` properties.
|
@@ -57,16 +57,30 @@ class CKEditorComponent extends HTMLElement {
|
|
57
57
|
/** @type {String} Initial HTML passed to component */
|
58
58
|
#initialHTML = '';
|
59
59
|
|
60
|
+
/** @type {CKEditorContextComponent|null} */
|
61
|
+
#context = null;
|
62
|
+
|
63
|
+
/** @type {String} ID of editor within context */
|
64
|
+
#contextEditorId = null;
|
65
|
+
|
60
66
|
/**
|
61
67
|
* Lifecycle callback when element is connected to DOM
|
62
68
|
* Initializes the editor when DOM is ready
|
63
69
|
* @protected
|
64
70
|
*/
|
65
71
|
connectedCallback() {
|
72
|
+
this.#context = this.closest('ckeditor-context-component');
|
66
73
|
this.#initialHTML = this.innerHTML;
|
67
74
|
|
68
75
|
try {
|
69
|
-
execIfDOMReady(() =>
|
76
|
+
execIfDOMReady(async () => {
|
77
|
+
if (this.#context) {
|
78
|
+
await this.#context.instancePromise.promise;
|
79
|
+
this.#context.registerEditor(this);
|
80
|
+
}
|
81
|
+
|
82
|
+
await this.reinitializeEditor();
|
83
|
+
});
|
70
84
|
} catch (error) {
|
71
85
|
console.error('Failed to initialize editor:', error);
|
72
86
|
this.dispatchEvent(new CustomEvent('editor-error', { detail: error }));
|
@@ -84,7 +98,7 @@ class CKEditorComponent extends HTMLElement {
|
|
84
98
|
if (oldValue !== null &&
|
85
99
|
oldValue !== newValue &&
|
86
100
|
CKEditorComponent.observedAttributes.includes(name) && this.isConnected) {
|
87
|
-
await this
|
101
|
+
await this.reinitializeEditor();
|
88
102
|
}
|
89
103
|
}
|
90
104
|
|
@@ -94,9 +108,12 @@ class CKEditorComponent extends HTMLElement {
|
|
94
108
|
* @protected
|
95
109
|
*/
|
96
110
|
async disconnectedCallback() {
|
111
|
+
if (this.#context) {
|
112
|
+
this.#context.unregisterEditor(this);
|
113
|
+
}
|
114
|
+
|
97
115
|
try {
|
98
|
-
await this
|
99
|
-
await this.watchdog?.destroy();
|
116
|
+
await this.#destroy();
|
100
117
|
} catch (error) {
|
101
118
|
console.error('Failed to destroy editor:', error);
|
102
119
|
}
|
@@ -119,6 +136,7 @@ class CKEditorComponent extends HTMLElement {
|
|
119
136
|
|
120
137
|
/**
|
121
138
|
* Determines appropriate editor element tag based on editor type
|
139
|
+
*
|
122
140
|
* @private
|
123
141
|
* @returns {string} HTML tag name to use
|
124
142
|
*/
|
@@ -133,57 +151,25 @@ class CKEditorComponent extends HTMLElement {
|
|
133
151
|
}
|
134
152
|
|
135
153
|
/**
|
136
|
-
*
|
137
|
-
* Looks for objects with { $element: "selector" } format and replaces them with actual elements.
|
154
|
+
* Gets the CKEditor context instance if available.
|
138
155
|
*
|
139
156
|
* @private
|
140
|
-
* @
|
141
|
-
* @returns {Object} Processed configuration object with resolved element references
|
157
|
+
* @returns {import('ckeditor5').ContextWatchdog|null}
|
142
158
|
*/
|
143
|
-
#
|
144
|
-
|
145
|
-
|
146
|
-
}
|
147
|
-
|
148
|
-
if (Array.isArray(obj)) {
|
149
|
-
return obj.map(item => this.#resolveElementReferences(item));
|
150
|
-
}
|
151
|
-
|
152
|
-
const result = Object.create(null);
|
153
|
-
|
154
|
-
for (const key of Object.getOwnPropertyNames(obj)) {
|
155
|
-
if (!isSafeKey(key)) {
|
156
|
-
console.warn(`Suspicious key "${key}" detected in config, skipping`);
|
157
|
-
continue;
|
158
|
-
}
|
159
|
-
|
160
|
-
const value = obj[key];
|
161
|
-
|
162
|
-
if (value && typeof value === 'object') {
|
163
|
-
if (value.$element) {
|
164
|
-
const selector = value.$element;
|
165
|
-
|
166
|
-
if (typeof selector !== 'string') {
|
167
|
-
console.warn(`Invalid selector type for "${key}", expected string`);
|
168
|
-
continue;
|
169
|
-
}
|
170
|
-
|
171
|
-
const element = document.querySelector(selector);
|
172
|
-
|
173
|
-
if (!element) {
|
174
|
-
console.warn(`Element not found for selector: ${selector}`);
|
175
|
-
}
|
159
|
+
get #contextWatchdog() {
|
160
|
+
return this.#context?.instance;
|
161
|
+
}
|
176
162
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
}
|
163
|
+
/**
|
164
|
+
* Destroys the editor instance and watchdog if available
|
165
|
+
*/
|
166
|
+
async #destroy() {
|
167
|
+
if (this.#contextEditorId) {
|
168
|
+
await this.#contextWatchdog.remove(this.#contextEditorId);
|
184
169
|
}
|
185
170
|
|
186
|
-
|
171
|
+
await this.instance?.destroy();
|
172
|
+
await this.watchdog?.destroy();
|
187
173
|
}
|
188
174
|
|
189
175
|
/**
|
@@ -195,7 +181,7 @@ class CKEditorComponent extends HTMLElement {
|
|
195
181
|
#getConfig() {
|
196
182
|
const config = JSON.parse(this.getAttribute('config') || '{}');
|
197
183
|
|
198
|
-
return
|
184
|
+
return resolveElementReferences(config);
|
199
185
|
}
|
200
186
|
|
201
187
|
/**
|
@@ -232,13 +218,27 @@ class CKEditorComponent extends HTMLElement {
|
|
232
218
|
plugins,
|
233
219
|
};
|
234
220
|
|
235
|
-
console.warn('Initializing CKEditor with:', { config, watchdog: this.hasWatchdog() });
|
221
|
+
console.warn('Initializing CKEditor with:', { config, watchdog: this.hasWatchdog(), context: this.#context });
|
236
222
|
|
237
223
|
// Initialize watchdog if needed
|
238
224
|
let watchdog = null;
|
239
225
|
let instance = null;
|
240
|
-
|
241
|
-
|
226
|
+
let contextId = null;
|
227
|
+
|
228
|
+
if (this.#context) {
|
229
|
+
contextId = uid();
|
230
|
+
|
231
|
+
await this.#contextWatchdog.add( {
|
232
|
+
creator: (_element, _config) => Editor.create(_element, _config),
|
233
|
+
id: contextId,
|
234
|
+
sourceElementOrData: content,
|
235
|
+
type: 'editor',
|
236
|
+
config,
|
237
|
+
} );
|
238
|
+
|
239
|
+
instance = this.#contextWatchdog.getItem(contextId);
|
240
|
+
} else if (this.hasWatchdog()) {
|
241
|
+
// Let's create use with plain watchdog.
|
242
242
|
const { EditorWatchdog } = await import('ckeditor5');
|
243
243
|
const watchdog = new EditorWatchdog(Editor);
|
244
244
|
|
@@ -246,12 +246,14 @@ class CKEditorComponent extends HTMLElement {
|
|
246
246
|
|
247
247
|
instance = watchdog.editor;
|
248
248
|
} else {
|
249
|
+
// Let's create the editor without watchdog.
|
249
250
|
instance = await Editor.create(content, config);
|
250
251
|
}
|
251
252
|
|
252
253
|
this.dispatchEvent(new CustomEvent('editor-ready', { detail: instance }));
|
253
254
|
|
254
255
|
return {
|
256
|
+
contextId,
|
255
257
|
instance,
|
256
258
|
watchdog,
|
257
259
|
};
|
@@ -263,11 +265,12 @@ class CKEditorComponent extends HTMLElement {
|
|
263
265
|
* @private
|
264
266
|
* @returns {Promise<void>}
|
265
267
|
*/
|
266
|
-
async
|
268
|
+
async reinitializeEditor() {
|
267
269
|
if (this.instance) {
|
268
270
|
this.instancePromise = Promise.withResolvers();
|
269
271
|
|
270
|
-
await this
|
272
|
+
await this.#destroy();
|
273
|
+
|
271
274
|
this.instance = null;
|
272
275
|
}
|
273
276
|
|
@@ -288,10 +291,11 @@ class CKEditorComponent extends HTMLElement {
|
|
288
291
|
}
|
289
292
|
|
290
293
|
try {
|
291
|
-
const { watchdog, instance } = await this.#initializeEditor(this.editables || this.#getConfig().initialData || '');
|
294
|
+
const { watchdog, instance, contextId } = await this.#initializeEditor(this.editables || this.#getConfig().initialData || '');
|
292
295
|
|
293
296
|
this.watchdog = watchdog;
|
294
297
|
this.instance = instance;
|
298
|
+
this.#contextEditorId = contextId;
|
295
299
|
|
296
300
|
this.#setupContentSync();
|
297
301
|
this.#setupEditableHeight();
|
@@ -511,6 +515,129 @@ class CKEditorComponent extends HTMLElement {
|
|
511
515
|
}
|
512
516
|
}
|
513
517
|
|
518
|
+
/**
|
519
|
+
* Custom element that provides shared CKEditor context for multiple editors.
|
520
|
+
*
|
521
|
+
* @extends HTMLElement
|
522
|
+
* @example
|
523
|
+
*
|
524
|
+
* <ckeditor-context-component plugins='[ ... ]'>
|
525
|
+
* <ckeditor-component type="ClassicEditor" config='{"toolbar": ["bold", "italic"]}'>
|
526
|
+
* <ckeditor-component type="ClassicEditor" config='{"toolbar": ["bold", "italic"]}'>
|
527
|
+
* </ckeditor-component>
|
528
|
+
*/
|
529
|
+
class CKEditorContextComponent extends HTMLElement {
|
530
|
+
static get observedAttributes() {
|
531
|
+
return ['plugins', 'config'];
|
532
|
+
}
|
533
|
+
|
534
|
+
/** @type {import('ckeditor5').Context|null} */
|
535
|
+
instance = null;
|
536
|
+
|
537
|
+
/** @type {Promise<import('ckeditor5').Context>} */
|
538
|
+
instancePromise = Promise.withResolvers();
|
539
|
+
|
540
|
+
/** @type {Set<CKEditorComponent>} */
|
541
|
+
#connectedEditors = new Set();
|
542
|
+
|
543
|
+
async connectedCallback() {
|
544
|
+
try {
|
545
|
+
execIfDOMReady(() => this.#initializeContext());
|
546
|
+
} catch (error) {
|
547
|
+
console.error('Failed to initialize context:', error);
|
548
|
+
this.dispatchEvent(new CustomEvent('context-error', { detail: error }));
|
549
|
+
}
|
550
|
+
}
|
551
|
+
|
552
|
+
async attributeChangedCallback(name, oldValue, newValue) {
|
553
|
+
if (oldValue !== null && oldValue !== newValue) {
|
554
|
+
await this.#initializeContext();
|
555
|
+
}
|
556
|
+
}
|
557
|
+
|
558
|
+
async disconnectedCallback() {
|
559
|
+
if (this.instance) {
|
560
|
+
await this.instance.destroy();
|
561
|
+
this.instance = null;
|
562
|
+
}
|
563
|
+
}
|
564
|
+
|
565
|
+
/**
|
566
|
+
* Register editor component with this context
|
567
|
+
*
|
568
|
+
* @param {CKEditorComponent} editor
|
569
|
+
*/
|
570
|
+
registerEditor(editor) {
|
571
|
+
this.#connectedEditors.add(editor);
|
572
|
+
}
|
573
|
+
|
574
|
+
/**
|
575
|
+
* Unregister editor component from this context
|
576
|
+
*
|
577
|
+
* @param {CKEditorComponent} editor
|
578
|
+
*/
|
579
|
+
unregisterEditor(editor) {
|
580
|
+
this.#connectedEditors.delete(editor);
|
581
|
+
}
|
582
|
+
|
583
|
+
/**
|
584
|
+
* Initialize CKEditor context with shared configuration
|
585
|
+
*
|
586
|
+
* @private
|
587
|
+
*/
|
588
|
+
async #initializeContext() {
|
589
|
+
if (this.instance) {
|
590
|
+
this.instancePromise = Promise.withResolvers();
|
591
|
+
|
592
|
+
await this.instance.destroy();
|
593
|
+
|
594
|
+
this.instance = null;
|
595
|
+
}
|
596
|
+
|
597
|
+
const { Context, ContextWatchdog } = await import('ckeditor5');
|
598
|
+
const plugins = await this.#getPlugins();
|
599
|
+
const config = this.#getConfig();
|
600
|
+
|
601
|
+
this.instance = new ContextWatchdog(Context, {
|
602
|
+
crashNumberLimit: 10
|
603
|
+
});
|
604
|
+
|
605
|
+
await this.instance.create({
|
606
|
+
...config,
|
607
|
+
plugins
|
608
|
+
});
|
609
|
+
|
610
|
+
this.instance.on('itemError', (...args) => {
|
611
|
+
console.error('Context item error:', ...args);
|
612
|
+
});
|
613
|
+
|
614
|
+
this.instancePromise.resolve(this.instance);
|
615
|
+
this.dispatchEvent(new CustomEvent('context-ready', { detail: this.instance }));
|
616
|
+
|
617
|
+
// Reinitialize connected editors.
|
618
|
+
await Promise.all(
|
619
|
+
[...this.#connectedEditors].map(editor => editor.reinitializeEditor())
|
620
|
+
);
|
621
|
+
}
|
622
|
+
|
623
|
+
async #getPlugins() {
|
624
|
+
const raw = this.getAttribute('plugins');
|
625
|
+
|
626
|
+
return loadAsyncImports(raw ? JSON.parse(raw) : []);
|
627
|
+
}
|
628
|
+
|
629
|
+
/**
|
630
|
+
* Gets context configuration with resolved element references.
|
631
|
+
*
|
632
|
+
* @private
|
633
|
+
*/
|
634
|
+
#getConfig() {
|
635
|
+
const config = JSON.parse(this.getAttribute('config') || '{}');
|
636
|
+
|
637
|
+
return resolveElementReferences(config);
|
638
|
+
}
|
639
|
+
}
|
640
|
+
|
514
641
|
/**
|
515
642
|
* Tracks and manages editable roots for CKEditor MultiRoot editor.
|
516
643
|
* Provides a proxy-based API for dynamically managing editable elements with automatic
|
@@ -894,6 +1021,69 @@ function isSafeKey(key) {
|
|
894
1021
|
key !== 'prototype';
|
895
1022
|
}
|
896
1023
|
|
1024
|
+
/**
|
1025
|
+
* Resolves element references in configuration object.
|
1026
|
+
* Looks for objects with { $element: "selector" } format and replaces them with actual elements.
|
1027
|
+
*
|
1028
|
+
* @param {Object} obj - Configuration object to process
|
1029
|
+
* @returns {Object} Processed configuration object with resolved element references
|
1030
|
+
*/
|
1031
|
+
function resolveElementReferences(obj) {
|
1032
|
+
if (!obj || typeof obj !== 'object') {
|
1033
|
+
return obj;
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
if (Array.isArray(obj)) {
|
1037
|
+
return obj.map(item => resolveElementReferences(item));
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
const result = Object.create(null);
|
1041
|
+
|
1042
|
+
for (const key of Object.getOwnPropertyNames(obj)) {
|
1043
|
+
if (!isSafeKey(key)) {
|
1044
|
+
console.warn(`Suspicious key "${key}" detected in config, skipping`);
|
1045
|
+
continue;
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
const value = obj[key];
|
1049
|
+
|
1050
|
+
if (value && typeof value === 'object') {
|
1051
|
+
if (value.$element) {
|
1052
|
+
const selector = value.$element;
|
1053
|
+
|
1054
|
+
if (typeof selector !== 'string') {
|
1055
|
+
console.warn(`Invalid selector type for "${key}", expected string`);
|
1056
|
+
continue;
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
const element = document.querySelector(selector);
|
1060
|
+
|
1061
|
+
if (!element) {
|
1062
|
+
console.warn(`Element not found for selector: ${selector}`);
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
result[key] = element || null;
|
1066
|
+
} else {
|
1067
|
+
result[key] = resolveElementReferences(value);
|
1068
|
+
}
|
1069
|
+
} else {
|
1070
|
+
result[key] = value;
|
1071
|
+
}
|
1072
|
+
}
|
1073
|
+
|
1074
|
+
return result;
|
1075
|
+
}
|
1076
|
+
|
1077
|
+
/**
|
1078
|
+
* Custom element that provides shared CKEditor context for multiple editors.
|
1079
|
+
*
|
1080
|
+
* @returns {String} unique id
|
1081
|
+
*/
|
1082
|
+
function uid() {
|
1083
|
+
return Math.random().toString(36).substring(2);
|
1084
|
+
}
|
1085
|
+
|
897
1086
|
customElements.define('ckeditor-component', CKEditorComponent);
|
898
1087
|
customElements.define('ckeditor-editable-component', CKEditorEditableComponent);
|
899
1088
|
customElements.define('ckeditor-ui-part-component', CKEditorUIPartComponent);
|
1089
|
+
customElements.define('ckeditor-context-component', CKEditorContextComponent);
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'props'
|
4
|
+
|
5
|
+
module CKEditor5::Rails::Context
|
6
|
+
module Helpers
|
7
|
+
def ckeditor5_context(**config, &block)
|
8
|
+
context_props = Props.new(config)
|
9
|
+
|
10
|
+
tag.send(:'ckeditor-context-component', **context_props.to_attributes, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CKEditor5::Rails
|
4
|
+
module Context
|
5
|
+
class Props
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_attributes
|
11
|
+
{
|
12
|
+
plugins: serialize_plugins,
|
13
|
+
config: serialize_config
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :config
|
20
|
+
|
21
|
+
def serialize_plugins
|
22
|
+
(config[:plugins] || []).map { |plugin| Editor::PropsPlugin.normalize(plugin).to_h }.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
def serialize_config
|
26
|
+
config.except(:plugins).to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -29,16 +29,13 @@ module CKEditor5::Rails
|
|
29
29
|
type ||= preset.type
|
30
30
|
|
31
31
|
validated_height = validate_editable_height(type, editable_height) || preset.editable_height
|
32
|
-
editor_props = Editor::Props.new(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
html_attributes.merge(validated_height ? { 'editable-height' => validated_height } : {}),
|
40
|
-
&block
|
41
|
-
)
|
32
|
+
editor_props = Editor::Props.new(controller_context, type, config, watchdog: watchdog)
|
33
|
+
|
34
|
+
tag_attributes = html_attributes
|
35
|
+
.merge(editor_props.to_attributes)
|
36
|
+
.merge(validated_height ? { 'editable-height' => validated_height } : {})
|
37
|
+
|
38
|
+
tag.send(:'ckeditor-component', **tag_attributes, &block)
|
42
39
|
end
|
43
40
|
|
44
41
|
def ckeditor5_editable(name = nil, **kwargs, &block)
|
@@ -91,10 +88,6 @@ module CKEditor5::Rails
|
|
91
88
|
raise PresetNotFoundError, "Preset #{preset} is not defined."
|
92
89
|
end
|
93
90
|
|
94
|
-
def render_editor_component(props, html_attributes, &block)
|
95
|
-
tag.send(:'ckeditor-component', **props.to_attributes, **html_attributes, &block)
|
96
|
-
end
|
97
|
-
|
98
91
|
def validate_editable_height(type, height)
|
99
92
|
return nil if height.nil?
|
100
93
|
|
@@ -3,11 +3,13 @@
|
|
3
3
|
require_relative 'cdn/helpers'
|
4
4
|
require_relative 'cloud/helpers'
|
5
5
|
require_relative 'editor/helpers'
|
6
|
+
require_relative 'context/helpers'
|
6
7
|
|
7
8
|
module CKEditor5::Rails
|
8
9
|
module Helpers
|
9
10
|
include Cdn::Helpers
|
10
11
|
include Cloud::Helpers
|
11
12
|
include Editor::Helpers
|
13
|
+
include Context::Helpers
|
12
14
|
end
|
13
15
|
end
|
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.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mateusz Bagiński
|
@@ -51,6 +51,8 @@ files:
|
|
51
51
|
- lib/ckeditor5/rails/cdn/helpers.rb
|
52
52
|
- lib/ckeditor5/rails/cdn/url_generator.rb
|
53
53
|
- lib/ckeditor5/rails/cloud/helpers.rb
|
54
|
+
- lib/ckeditor5/rails/context/helpers.rb
|
55
|
+
- lib/ckeditor5/rails/context/props.rb
|
54
56
|
- lib/ckeditor5/rails/editor/config_helpers.rb
|
55
57
|
- lib/ckeditor5/rails/editor/helpers.rb
|
56
58
|
- lib/ckeditor5/rails/editor/props.rb
|