ckeditor5 1.6.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -3
- data/lib/ckeditor5/rails/assets/webcomponent.mjs +112 -13
- data/lib/ckeditor5/rails/editor/config_helpers.rb +9 -0
- data/lib/ckeditor5/rails/editor/helpers.rb +30 -1
- data/lib/ckeditor5/rails/presets/preset_builder.rb +9 -0
- data/lib/ckeditor5/rails/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18736efccfe3547f18ff9df5418fd5f93aafa426423c3ca8daca99de481c6c60
|
4
|
+
data.tar.gz: 6be07d38f24ba131e3a8444175b8416561706a97d74bd581d8568703ef3544f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c40e50c2093c7f8c311b8565a54ddc4835aba887ced1e36b4802c6681769a8f2e4f39812443e688f6e31ff4932eef76282664be82d7cdbb4b667c9febe76374f
|
7
|
+
data.tar.gz: f9a999fb8a325323e497b225f3c8bed54cc24befc5bcd2cc90a93a25dece1d539e5e33a34fbe2a4f9570e462527492e061819563b7fad19e61d24fae8a39953e
|
data/README.md
CHANGED
@@ -73,6 +73,7 @@ Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
|
|
73
73
|
- [`gpl` method](#gpl-method)
|
74
74
|
- [`license_key(key)` method](#license_keykey-method)
|
75
75
|
- [`premium` method](#premium-method)
|
76
|
+
- [`editable_height(height)` method](#editable_heightheight-method)
|
76
77
|
- [`translations(*languages)` method](#translationslanguages-method)
|
77
78
|
- [`ckbox` method](#ckbox-method)
|
78
79
|
- [`type(type)` method](#typetype-method)
|
@@ -83,6 +84,7 @@ Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
|
|
83
84
|
- [`plugin(name, premium:, import_name:)` method](#pluginname-premium-import_name-method)
|
84
85
|
- [`plugins(*names, **kwargs)` method](#pluginsnames-kwargs-method)
|
85
86
|
- [`inline_plugin(name, code)` method](#inline_pluginname-code-method)
|
87
|
+
- [`ckeditor5_element_ref(selector)` method](#ckeditor5_element_refselector-method)
|
86
88
|
- [Including CKEditor 5 assets 📦](#including-ckeditor-5-assets-)
|
87
89
|
- [Format 📝](#format-)
|
88
90
|
- [Using default preset](#using-default-preset)
|
@@ -271,6 +273,20 @@ CKEditor5::Rails.configure do
|
|
271
273
|
end
|
272
274
|
```
|
273
275
|
|
276
|
+
#### `editable_height(height)` method
|
277
|
+
|
278
|
+
Defines the height of the editor. The example below shows how to set the height to `300px`:
|
279
|
+
|
280
|
+
```rb
|
281
|
+
# config/initializers/ckeditor5.rb
|
282
|
+
|
283
|
+
CKEditor5::Rails.configure do
|
284
|
+
# ... other configuration
|
285
|
+
|
286
|
+
editable_height 300
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
274
290
|
#### `translations(*languages)` method
|
275
291
|
|
276
292
|
Defines the translations of CKEditor 5. You can pass the language codes as arguments. The example below shows how tell integration to fetch Polish and Spanish translations:
|
@@ -430,7 +446,9 @@ end
|
|
430
446
|
|
431
447
|
#### `configure(name, value)` method
|
432
448
|
|
433
|
-
Allows you to set custom configuration options. You can pass the name of the option and its value as arguments. The
|
449
|
+
Allows you to set custom configuration options. You can pass the name of the option and its value as arguments. The [`ckeditor5_element_ref(selector)` helper](#ckeditor5_element_refselector-method) allows you to reference DOM elements that will be used by the editor's features. It's particularly useful for features that need to check element presence or operate on specific DOM elements.
|
450
|
+
|
451
|
+
For example, you can use it to configure font family dropdown to show only fonts available in specific elements:
|
434
452
|
|
435
453
|
```rb
|
436
454
|
# config/initializers/ckeditor5.rb
|
@@ -438,8 +456,19 @@ Allows you to set custom configuration options. You can pass the name of the opt
|
|
438
456
|
CKEditor5::Rails.configure do
|
439
457
|
# ... other configuration
|
440
458
|
|
441
|
-
configure :
|
442
|
-
|
459
|
+
configure :fontFamily, {
|
460
|
+
supportAllValues: true,
|
461
|
+
options: [
|
462
|
+
'default',
|
463
|
+
'Arial, Helvetica, sans-serif',
|
464
|
+
'Courier New, Courier, monospace',
|
465
|
+
'Georgia, serif',
|
466
|
+
'Lucida Sans Unicode, Lucida Grande, sans-serif',
|
467
|
+
'Tahoma, Geneva, sans-serif',
|
468
|
+
'Times New Roman, Times, serif',
|
469
|
+
'Trebuchet MS, Helvetica, sans-serif',
|
470
|
+
'Verdana, Geneva, sans-serif'
|
471
|
+
]
|
443
472
|
}
|
444
473
|
end
|
445
474
|
```
|
@@ -523,6 +552,23 @@ CKEditor5::Rails.configure do
|
|
523
552
|
JS
|
524
553
|
end
|
525
554
|
```
|
555
|
+
|
556
|
+
#### `ckeditor5_element_ref(selector)` method
|
557
|
+
|
558
|
+
Defines a reference to a CKEditor 5 element. In other words, it allows you to reference DOM elements that will be used by the editor's features. It's particularly useful for features that need to check element presence or operate on specific DOM elements. The primary example is the `presence list` feature that requires a reference to the element that will be used to display the list.
|
559
|
+
|
560
|
+
```rb
|
561
|
+
# config/initializers/ckeditor5.rb
|
562
|
+
|
563
|
+
CKEditor5::Rails.configure do
|
564
|
+
# ... other configuration
|
565
|
+
|
566
|
+
configure :yourPlugin, {
|
567
|
+
element: ckeditor5_element_ref("body")
|
568
|
+
}
|
569
|
+
end
|
570
|
+
```
|
571
|
+
|
526
572
|
</details>
|
527
573
|
|
528
574
|
## Including CKEditor 5 assets 📦
|
@@ -808,6 +854,18 @@ If you want to override the configuration of the editor specified in default or
|
|
808
854
|
<%= ckeditor5_editor extra_config: { toolbar: [:Bold, :Italic] }, style: 'width: 600px' %>
|
809
855
|
```
|
810
856
|
|
857
|
+
It's possible to define the height of the editor by passing the `editable_height` keyword argument with the value in pixels:
|
858
|
+
|
859
|
+
```erb
|
860
|
+
<!-- app/views/demos/index.html.erb -->
|
861
|
+
|
862
|
+
<% content_for :head do %>
|
863
|
+
<%= ckeditor5_assets %>
|
864
|
+
<% end %>
|
865
|
+
|
866
|
+
<%= ckeditor5_editor editable_height: 300 %>
|
867
|
+
```
|
868
|
+
|
811
869
|
### Multiroot editor 🌳
|
812
870
|
|
813
871
|
The multiroot editor allows you to create an editor with multiple editable areas. It's useful when you want to create a CMS with multiple editable areas on a single page.
|
@@ -132,6 +132,72 @@ class CKEditorComponent extends HTMLElement {
|
|
132
132
|
}
|
133
133
|
}
|
134
134
|
|
135
|
+
/**
|
136
|
+
* Resolves element references in configuration object.
|
137
|
+
* Looks for objects with { $element: "selector" } format and replaces them with actual elements.
|
138
|
+
*
|
139
|
+
* @private
|
140
|
+
* @param {Object} obj - Configuration object to process
|
141
|
+
* @returns {Object} Processed configuration object with resolved element references
|
142
|
+
*/
|
143
|
+
#resolveElementReferences(obj) {
|
144
|
+
if (!obj || typeof obj !== 'object') {
|
145
|
+
return obj;
|
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
|
+
}
|
176
|
+
|
177
|
+
result[key] = element || null;
|
178
|
+
} else {
|
179
|
+
result[key] = this.#resolveElementReferences(value);
|
180
|
+
}
|
181
|
+
} else {
|
182
|
+
result[key] = value;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
return result;
|
187
|
+
}
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Gets editor configuration with resolved element references
|
191
|
+
*
|
192
|
+
* @private
|
193
|
+
* @returns {EditorConfig}
|
194
|
+
*/
|
195
|
+
#getConfig() {
|
196
|
+
const config = JSON.parse(this.getAttribute('config') || '{}');
|
197
|
+
|
198
|
+
return this.#resolveElementReferences(config);
|
199
|
+
}
|
200
|
+
|
135
201
|
/**
|
136
202
|
* Creates a new CKEditor instance
|
137
203
|
*
|
@@ -228,6 +294,7 @@ class CKEditorComponent extends HTMLElement {
|
|
228
294
|
this.instance = instance;
|
229
295
|
|
230
296
|
this.#setupContentSync();
|
297
|
+
this.#setupEditableHeight();
|
231
298
|
|
232
299
|
this.instancePromise.resolve(this.instance);
|
233
300
|
} catch (err) {
|
@@ -236,10 +303,18 @@ class CKEditorComponent extends HTMLElement {
|
|
236
303
|
}
|
237
304
|
}
|
238
305
|
|
306
|
+
/**
|
307
|
+
* Checks if current editor is classic type
|
308
|
+
*
|
309
|
+
* @returns {boolean}
|
310
|
+
*/
|
311
|
+
isClassic() {
|
312
|
+
return this.getAttribute('type') === 'ClassicEditor';
|
313
|
+
}
|
314
|
+
|
239
315
|
/**
|
240
316
|
* Checks if current editor is multiroot type
|
241
317
|
*
|
242
|
-
* @private
|
243
318
|
* @returns {boolean}
|
244
319
|
*/
|
245
320
|
isMultiroot() {
|
@@ -249,7 +324,6 @@ class CKEditorComponent extends HTMLElement {
|
|
249
324
|
/**
|
250
325
|
* Checks if current editor is decoupled type
|
251
326
|
*
|
252
|
-
* @private
|
253
327
|
* @returns {boolean}
|
254
328
|
*/
|
255
329
|
isDecoupled() {
|
@@ -259,23 +333,12 @@ class CKEditorComponent extends HTMLElement {
|
|
259
333
|
/**
|
260
334
|
* Checks if current editor has watchdog enabled
|
261
335
|
*
|
262
|
-
* @private
|
263
336
|
* @returns {boolean}
|
264
337
|
*/
|
265
338
|
hasWatchdog() {
|
266
339
|
return this.getAttribute('watchdog') === 'true';
|
267
340
|
}
|
268
341
|
|
269
|
-
/**
|
270
|
-
* Parses editor configuration from config attribute
|
271
|
-
*
|
272
|
-
* @private
|
273
|
-
* @returns {EditorConfig}
|
274
|
-
*/
|
275
|
-
#getConfig() {
|
276
|
-
return JSON.parse(this.getAttribute('config') || '{}');
|
277
|
-
}
|
278
|
-
|
279
342
|
/**
|
280
343
|
* Queries and validates editable elements
|
281
344
|
*
|
@@ -378,6 +441,28 @@ class CKEditorComponent extends HTMLElement {
|
|
378
441
|
});
|
379
442
|
}
|
380
443
|
|
444
|
+
/**
|
445
|
+
* Sets up editable height for ClassicEditor
|
446
|
+
*
|
447
|
+
* @private
|
448
|
+
*/
|
449
|
+
#setupEditableHeight() {
|
450
|
+
if (!this.isClassic()) {
|
451
|
+
return;
|
452
|
+
}
|
453
|
+
|
454
|
+
const { instance } = this;
|
455
|
+
const height = Number.parseInt(this.getAttribute('editable-height'), 10);
|
456
|
+
|
457
|
+
if (Number.isNaN(height)) {
|
458
|
+
return;
|
459
|
+
}
|
460
|
+
|
461
|
+
instance.editing.view.change((writer) => {
|
462
|
+
writer.setStyle('height', `${height}px`, instance.editing.view.document.getRoot());
|
463
|
+
});
|
464
|
+
}
|
465
|
+
|
381
466
|
/**
|
382
467
|
* Loads translation modules
|
383
468
|
*
|
@@ -795,6 +880,20 @@ function loadAsyncImports(imports = []) {
|
|
795
880
|
}));
|
796
881
|
}
|
797
882
|
|
883
|
+
|
884
|
+
/**
|
885
|
+
* Checks if a key is safe to use in configuration objects to prevent prototype pollution.
|
886
|
+
*
|
887
|
+
* @param {string} key - Key name to check
|
888
|
+
* @returns {boolean} True if key is safe to use.
|
889
|
+
*/
|
890
|
+
function isSafeKey(key) {
|
891
|
+
return typeof key === 'string' &&
|
892
|
+
key !== '__proto__' &&
|
893
|
+
key !== 'constructor' &&
|
894
|
+
key !== 'prototype';
|
895
|
+
}
|
896
|
+
|
798
897
|
customElements.define('ckeditor-component', CKEditorComponent);
|
799
898
|
customElements.define('ckeditor-editable-component', CKEditorEditableComponent);
|
800
899
|
customElements.define('ckeditor-ui-part-component', CKEditorUIPartComponent);
|
@@ -3,31 +3,42 @@
|
|
3
3
|
require_relative 'props_plugin'
|
4
4
|
require_relative 'props_inline_plugin'
|
5
5
|
require_relative 'props'
|
6
|
+
require_relative 'config_helpers'
|
6
7
|
|
7
8
|
module CKEditor5::Rails
|
8
9
|
module Editor::Helpers
|
10
|
+
include Editor::ConfigHelpers
|
11
|
+
|
9
12
|
class EditorContextError < StandardError; end
|
10
13
|
class PresetNotFoundError < ArgumentError; end
|
14
|
+
class InvalidEditableHeightError < ArgumentError; end
|
11
15
|
|
12
16
|
def ckeditor5_editor( # rubocop:disable Metrics/ParameterLists
|
13
17
|
config: nil, extra_config: {},
|
14
18
|
type: nil, preset: nil,
|
15
19
|
initial_data: nil, watchdog: true,
|
20
|
+
editable_height: nil,
|
16
21
|
**html_attributes, &block
|
17
22
|
)
|
18
23
|
validate_editor_input!(initial_data, block)
|
24
|
+
|
19
25
|
controller_context = validate_and_get_editor_context!
|
20
26
|
|
21
27
|
preset = resolve_editor_preset(preset || controller_context[:preset])
|
22
28
|
config = build_editor_config(preset, config, extra_config, initial_data)
|
23
29
|
type ||= preset.type
|
24
30
|
|
31
|
+
validated_height = validate_editable_height(type, editable_height) || preset.editable_height
|
25
32
|
editor_props = Editor::Props.new(
|
26
33
|
controller_context, type, config,
|
27
34
|
watchdog: watchdog
|
28
35
|
)
|
29
36
|
|
30
|
-
render_editor_component(
|
37
|
+
render_editor_component(
|
38
|
+
editor_props,
|
39
|
+
html_attributes.merge(validated_height ? { 'editable-height' => validated_height } : {}),
|
40
|
+
&block
|
41
|
+
)
|
31
42
|
end
|
32
43
|
|
33
44
|
def ckeditor5_editable(name = nil, **kwargs, &block)
|
@@ -83,5 +94,23 @@ module CKEditor5::Rails
|
|
83
94
|
def render_editor_component(props, html_attributes, &block)
|
84
95
|
tag.send(:'ckeditor-component', **props.to_attributes, **html_attributes, &block)
|
85
96
|
end
|
97
|
+
|
98
|
+
def validate_editable_height(type, height)
|
99
|
+
return nil if height.nil?
|
100
|
+
|
101
|
+
unless type == :classic
|
102
|
+
raise InvalidEditableHeightError,
|
103
|
+
'editable_height can be used only with ClassicEditor'
|
104
|
+
end
|
105
|
+
|
106
|
+
case height
|
107
|
+
when String, /^\d+px$/ then height
|
108
|
+
when Integer, /^\d+$/ then "#{height}px"
|
109
|
+
else
|
110
|
+
raise InvalidEditableHeightError,
|
111
|
+
"editable_height must be an integer representing pixels or string ending with 'px'\n" \
|
112
|
+
"(e.g. 500 or '500px'). Got: #{height.inspect}"
|
113
|
+
end
|
114
|
+
end
|
86
115
|
end
|
87
116
|
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module CKEditor5::Rails
|
4
4
|
module Presets
|
5
5
|
class PresetBuilder
|
6
|
+
include Editor::ConfigHelpers
|
7
|
+
|
6
8
|
attr_reader :config
|
7
9
|
|
8
10
|
def initialize
|
@@ -13,6 +15,7 @@ module CKEditor5::Rails
|
|
13
15
|
@license_key = nil
|
14
16
|
@type = :classic
|
15
17
|
@ckbox = nil
|
18
|
+
@editable_height = nil
|
16
19
|
@config = {
|
17
20
|
plugins: [],
|
18
21
|
toolbar: []
|
@@ -32,6 +35,12 @@ module CKEditor5::Rails
|
|
32
35
|
}
|
33
36
|
end
|
34
37
|
|
38
|
+
def editable_height(height = nil)
|
39
|
+
return @editable_height if height.nil?
|
40
|
+
|
41
|
+
@editable_height = height
|
42
|
+
end
|
43
|
+
|
35
44
|
def ckbox(version = nil, theme: :lark)
|
36
45
|
return @ckbox if version.nil?
|
37
46
|
|
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.8.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: 2024-11-
|
12
|
+
date: 2024-11-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -51,6 +51,7 @@ 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/editor/config_helpers.rb
|
54
55
|
- lib/ckeditor5/rails/editor/helpers.rb
|
55
56
|
- lib/ckeditor5/rails/editor/props.rb
|
56
57
|
- lib/ckeditor5/rails/editor/props_inline_plugin.rb
|