ckeditor5 1.16.0 → 1.16.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +66 -12
- data/lib/ckeditor5/rails/assets/assets_bundle.rb +1 -1
- data/lib/ckeditor5/rails/assets/webcomponents/components/context.mjs +0 -23
- data/lib/ckeditor5/rails/assets/webcomponents/components/editor.mjs +0 -24
- data/lib/ckeditor5/rails/assets/webcomponents/utils.mjs +10 -33
- data/lib/ckeditor5/rails/cdn/ckbox_bundle.rb +4 -4
- data/lib/ckeditor5/rails/cdn/ckeditor_bundle.rb +6 -6
- data/lib/ckeditor5/rails/context/helpers.rb +9 -3
- data/lib/ckeditor5/rails/context/preset_builder.rb +31 -0
- data/lib/ckeditor5/rails/context/preset_serializer.rb +30 -0
- data/lib/ckeditor5/rails/editor/props.rb +3 -16
- data/lib/ckeditor5/rails/editor/props_inline_plugin.rb +3 -6
- data/lib/ckeditor5/rails/editor/props_plugin.rb +4 -6
- data/lib/ckeditor5/rails/plugins/simple_upload_adapter.rb +2 -2
- data/lib/ckeditor5/rails/presets/concerns/configuration_methods.rb +21 -0
- data/lib/ckeditor5/rails/presets/concerns/plugin_methods.rb +29 -0
- data/lib/ckeditor5/rails/presets/preset_builder.rb +12 -33
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/lib/ckeditor5/rails.rb +0 -1
- data/spec/e2e/features/context_spec.rb +36 -0
- data/spec/lib/ckeditor5/rails/assets/asset_bundle_hml_serializer_spec.rb +2 -2
- data/spec/lib/ckeditor5/rails/assets/assets_bundle_spec.rb +9 -7
- data/spec/lib/ckeditor5/rails/cdn/ckbox_bundle_spec.rb +1 -1
- data/spec/lib/ckeditor5/rails/context/helpers_spec.rb +49 -5
- data/spec/lib/ckeditor5/rails/context/preset_builder_spec.rb +85 -0
- data/spec/lib/ckeditor5/rails/context/{props_spec.rb → preset_serializer_spec.rb} +14 -21
- data/spec/lib/ckeditor5/rails/editor/props_spec.rb +0 -2
- metadata +12 -11
- data/lib/ckeditor5/rails/concerns/checksum.rb +0 -15
- data/lib/ckeditor5/rails/context/props.rb +0 -45
- data/lib/ckeditor5/rails/editor/props_base_plugin.rb +0 -19
- data/spec/lib/ckeditor5/rails/concerns/checksum_spec.rb +0 -50
- data/spec/lib/ckeditor5/rails/editor/props_base_plugin_spec.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80773f82ac9fcdf35feac2e568206c4dd5dbd04240ae891b880549fc7192ef12
|
4
|
+
data.tar.gz: d4c4244344977827288691f7846bce8737c70d9df170aff1fa2fb52a3a400d1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b681fd82436a62b4da89064979c02f4952ba1c210473b3d00791fe34627555e6df6761c4fb9cdbd49ea3258a3ce508c7c2c013ae4dccb56eb452848f936024a
|
7
|
+
data.tar.gz: 1c2170807abc784d8905b6817a8b1fb03c08d1f8ce3be48403923b96c255232c7acea65bacd417922e0014e5b18f7eb58dd6702837d0fc7bca3df936bee9774d
|
data/README.md
CHANGED
@@ -82,26 +82,26 @@ end
|
|
82
82
|
|
83
83
|
Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
|
84
84
|
|
85
|
-
## Try
|
85
|
+
## Try Demos! 🎮 ✨
|
86
86
|
|
87
|
-
|
87
|
+
Explore various editor configurations with the interactive [demo application](https://github.com/Mati365/ckeditor5-rails/tree/main/sandbox/app/views/demos). For additional inspiration, visit the official CKEditor 5 [examples](https://ckeditor.com/docs/ckeditor5/latest/examples/builds/classic-editor.html).
|
88
88
|
|
89
|
-
|
89
|
+
To run the demos locally, follow these steps:
|
90
90
|
|
91
91
|
```bash
|
92
|
-
bundle install # Install
|
93
|
-
bundle exec guard -g rails #
|
92
|
+
bundle install # Install dependencies
|
93
|
+
bundle exec guard -g rails # Start the server
|
94
94
|
```
|
95
95
|
|
96
|
-
|
96
|
+
Open [http://localhost:3000/](http://localhost:3000/) in a browser to start experimenting. Modify the code as needed.
|
97
97
|
|
98
|
-
|
98
|
+
For extending CKEditor's functionality, refer to the [plugins directory](https://github.com/Mati365/ckeditor5-rails/tree/main/lib/ckeditor5/rails/plugins) to create custom plugins. Community contributions are welcome.
|
99
99
|
|
100
100
|
## Table of Contents 📚
|
101
101
|
|
102
102
|
- [CKEditor 5 Rails Integration ✨](#ckeditor-5-rails-integration-)
|
103
103
|
- [Installation 🛠️](#installation-️)
|
104
|
-
- [Try
|
104
|
+
- [Try Demos! 🎮 ✨](#try-demos--)
|
105
105
|
- [Table of Contents 📚](#table-of-contents-)
|
106
106
|
- [Presets 🎨](#presets-)
|
107
107
|
- [Automatic upgrades 🔄](#automatic-upgrades-)
|
@@ -628,7 +628,7 @@ end
|
|
628
628
|
|
629
629
|
#### `inline_plugin(name, code)` method
|
630
630
|
|
631
|
-
Use with caution as this is an inline definition of the plugin code, and
|
631
|
+
⚠️ **Warning:** Use with caution as this is an inline definition of the plugin code, and it can potentially cause XSS vulnerabilities. Only use this method with static, trusted JavaScript code. The example below shows how to define a custom plugin that highlights the text:
|
632
632
|
|
633
633
|
```rb
|
634
634
|
# config/initializers/ckeditor5.rb
|
@@ -645,6 +645,8 @@ CKEditor5::Rails.configure do
|
|
645
645
|
}
|
646
646
|
|
647
647
|
init() {
|
648
|
+
const config = this.editor.config.get('myCustomPlugin') || {};
|
649
|
+
|
648
650
|
// ... Your plugin code
|
649
651
|
}
|
650
652
|
}
|
@@ -652,6 +654,23 @@ CKEditor5::Rails.configure do
|
|
652
654
|
end
|
653
655
|
```
|
654
656
|
|
657
|
+
To configure the custom plugin, use the `configure` method in your initializer. The example below shows how to configure the `myCustomPlugin`:
|
658
|
+
|
659
|
+
```rb
|
660
|
+
# config/initializers/ckeditor5.rb
|
661
|
+
|
662
|
+
CKEditor5::Rails.configure do
|
663
|
+
# ... other configuration
|
664
|
+
|
665
|
+
configure :myCustomPlugin, {
|
666
|
+
option1: 'value1',
|
667
|
+
option2: 'value2'
|
668
|
+
}
|
669
|
+
end
|
670
|
+
```
|
671
|
+
|
672
|
+
This approach is resistant to XSS attacks as it avoids inline JavaScript.
|
673
|
+
|
655
674
|
#### `simple_upload_adapter(url)` method
|
656
675
|
|
657
676
|
Defines the URL for the simple upload adapter. The default endpoint is `/uploads` and the method is `POST`. The example below shows how to set the URL to `/uploads`:
|
@@ -1129,16 +1148,18 @@ Format of the `ckeditor5_context` helper:
|
|
1129
1148
|
```erb
|
1130
1149
|
<!-- app/views/demos/index.html.erb -->
|
1131
1150
|
|
1132
|
-
<%= ckeditor5_context
|
1151
|
+
<%= ckeditor5_context @context_preset do %>
|
1133
1152
|
<%= ckeditor5_editor %>
|
1134
1153
|
<%= ckeditor5_editor %>
|
1135
1154
|
<% end %>
|
1136
1155
|
```
|
1137
1156
|
|
1138
|
-
The `ckeditor5_context` helper takes the
|
1157
|
+
The `ckeditor5_context` helper takes the context preset as an argument and renders the editor instances within the context. The context preset defines the shared configuration and state of the editor instances. It should be defined somewhere in controller.
|
1139
1158
|
|
1140
1159
|
### Example usage of `ckeditor5_context` helper 📝
|
1141
1160
|
|
1161
|
+
In your view:
|
1162
|
+
|
1142
1163
|
```erb
|
1143
1164
|
<!-- app/views/demos/index.html.erb -->
|
1144
1165
|
|
@@ -1146,7 +1167,7 @@ The `ckeditor5_context` helper takes the `config` and `plugins` keyword argument
|
|
1146
1167
|
<%= ckeditor5_assets preset: :ultrabasic %>
|
1147
1168
|
<% end %>
|
1148
1169
|
|
1149
|
-
<%= ckeditor5_context do %>
|
1170
|
+
<%= ckeditor5_context @context_preset do %>
|
1150
1171
|
<%= ckeditor5_editor initial_data: 'Hello World' %>
|
1151
1172
|
|
1152
1173
|
<br>
|
@@ -1155,6 +1176,39 @@ The `ckeditor5_context` helper takes the `config` and `plugins` keyword argument
|
|
1155
1176
|
<% end %>
|
1156
1177
|
```
|
1157
1178
|
|
1179
|
+
In your controller:
|
1180
|
+
|
1181
|
+
```rb
|
1182
|
+
# app/controllers/demos_controller.rb
|
1183
|
+
|
1184
|
+
class DemosController < ApplicationController
|
1185
|
+
def index
|
1186
|
+
@context_preset = ckeditor5_context_preset do
|
1187
|
+
# Syntax is identical to the `toolbar` method of the preset configuration.
|
1188
|
+
toolbar :bold, :italic
|
1189
|
+
|
1190
|
+
# It's possible to define plugins. Syntax is identical to the `plugins` method of the preset configuration.
|
1191
|
+
# Example:
|
1192
|
+
# plugin :Bold
|
1193
|
+
# inline_plugin :MyCustomPlugin, '...'
|
1194
|
+
end
|
1195
|
+
end
|
1196
|
+
end
|
1197
|
+
```
|
1198
|
+
|
1199
|
+
It's possible to omit the preset argument, in that case the empty preset will be used.
|
1200
|
+
|
1201
|
+
```erb
|
1202
|
+
<!-- app/views/demos/index.html.erb -->
|
1203
|
+
|
1204
|
+
<%= ckeditor5_context do %>
|
1205
|
+
<%= ckeditor5_editor %>
|
1206
|
+
<%= ckeditor5_editor %>
|
1207
|
+
<% end %>
|
1208
|
+
```
|
1209
|
+
|
1210
|
+
See demo for more details.
|
1211
|
+
|
1158
1212
|
## How to access editor instance? 🤔
|
1159
1213
|
|
1160
1214
|
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.
|
@@ -12,12 +12,7 @@ class CKEditorContextComponent extends HTMLElement {
|
|
12
12
|
/** @type {Set<CKEditorComponent>} */
|
13
13
|
#connectedEditors = new Set();
|
14
14
|
|
15
|
-
/** @type {String} Attributes checksum hash */
|
16
|
-
#integrity = '';
|
17
|
-
|
18
15
|
async connectedCallback() {
|
19
|
-
this.#integrity = this.getAttribute('integrity');
|
20
|
-
|
21
16
|
try {
|
22
17
|
execIfDOMReady(() => this.#initializeContext());
|
23
18
|
} catch (error) {
|
@@ -57,22 +52,6 @@ class CKEditorContextComponent extends HTMLElement {
|
|
57
52
|
this.#connectedEditors.delete(editor);
|
58
53
|
}
|
59
54
|
|
60
|
-
/**
|
61
|
-
* Validates editor configuration integrity hash to prevent attacks.
|
62
|
-
*/
|
63
|
-
async #validateIntegrity() {
|
64
|
-
const integrity = await calculateChecksum({
|
65
|
-
plugins: this.getAttribute('plugins'),
|
66
|
-
});
|
67
|
-
|
68
|
-
if (integrity !== this.#integrity) {
|
69
|
-
throw new Error(
|
70
|
-
'Configuration integrity check failed. It means that #integrity attributes mismatch from attributes passed to webcomponent. ' +
|
71
|
-
'This could be a security issue. Please check if you are passing correct attributes to the webcomponent.'
|
72
|
-
);
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
55
|
/**
|
77
56
|
* Initialize CKEditor context with shared configuration
|
78
57
|
*
|
@@ -87,8 +66,6 @@ class CKEditorContextComponent extends HTMLElement {
|
|
87
66
|
this.instance = null;
|
88
67
|
}
|
89
68
|
|
90
|
-
await this.#validateIntegrity();
|
91
|
-
|
92
69
|
const { Context, ContextWatchdog } = await import('ckeditor5');
|
93
70
|
const plugins = await this.#getPlugins();
|
94
71
|
const config = this.#getConfig();
|
@@ -40,9 +40,6 @@ class CKEditorComponent extends HTMLElement {
|
|
40
40
|
/** @type {String} ID of editor within context */
|
41
41
|
#contextEditorId = null;
|
42
42
|
|
43
|
-
/** @type {String} Attributes checksum hash */
|
44
|
-
#integrity = '';
|
45
|
-
|
46
43
|
/** @type {(event: CustomEvent) => void} Event handler for editor change */
|
47
44
|
get oneditorchange() {
|
48
45
|
return this.#getEventHandler('editorchange');
|
@@ -109,11 +106,9 @@ class CKEditorComponent extends HTMLElement {
|
|
109
106
|
/**
|
110
107
|
* Lifecycle callback when element is connected to DOM
|
111
108
|
* Initializes the editor when DOM is ready
|
112
|
-
*
|
113
109
|
* @protected
|
114
110
|
*/
|
115
111
|
connectedCallback() {
|
116
|
-
this.#integrity = this.getAttribute('integrity');
|
117
112
|
this.#context = this.closest('ckeditor-context-component');
|
118
113
|
this.#initialHTML = this.innerHTML;
|
119
114
|
|
@@ -233,23 +228,6 @@ class CKEditorComponent extends HTMLElement {
|
|
233
228
|
return resolveElementReferences(config);
|
234
229
|
}
|
235
230
|
|
236
|
-
/**
|
237
|
-
* Validates editor configuration integrity hash to prevent attacks.
|
238
|
-
*/
|
239
|
-
async #validateIntegrity() {
|
240
|
-
const integrity = await calculateChecksum({
|
241
|
-
translations: this.getAttribute('translations'),
|
242
|
-
plugins: this.getAttribute('plugins'),
|
243
|
-
});
|
244
|
-
|
245
|
-
if (integrity !== this.#integrity) {
|
246
|
-
throw new Error(
|
247
|
-
'Configuration integrity check failed. It means that #integrity attributes mismatch from attributes passed to webcomponent. ' +
|
248
|
-
'This could be a security issue. Please check if you are passing correct attributes to the webcomponent.'
|
249
|
-
);
|
250
|
-
}
|
251
|
-
}
|
252
|
-
|
253
231
|
/**
|
254
232
|
* Creates a new CKEditor instance
|
255
233
|
*
|
@@ -259,8 +237,6 @@ class CKEditorComponent extends HTMLElement {
|
|
259
237
|
* @throws {Error} When initialization fails
|
260
238
|
*/
|
261
239
|
async #initializeEditor(editablesOrContent) {
|
262
|
-
await this.#validateIntegrity();
|
263
|
-
|
264
240
|
const Editor = await this.#getEditorConstructor();
|
265
241
|
const [plugins, translations] = await Promise.all([
|
266
242
|
this.#getPlugins(),
|
@@ -66,18 +66,16 @@ function loadAsyncImports(imports = []) {
|
|
66
66
|
return imported;
|
67
67
|
};
|
68
68
|
|
69
|
-
return Promise.all(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
})
|
80
|
-
);
|
69
|
+
return Promise.all(imports.map(item => {
|
70
|
+
switch(item.type) {
|
71
|
+
case 'inline':
|
72
|
+
return loadInlinePlugin(item);
|
73
|
+
|
74
|
+
case 'external':
|
75
|
+
default:
|
76
|
+
return loadExternalPlugin(item);
|
77
|
+
}
|
78
|
+
}));
|
81
79
|
}
|
82
80
|
|
83
81
|
/**
|
@@ -155,24 +153,3 @@ function resolveElementReferences(obj) {
|
|
155
153
|
function uid() {
|
156
154
|
return Math.random().toString(36).substring(2);
|
157
155
|
}
|
158
|
-
|
159
|
-
/**
|
160
|
-
* Calculates checksum for an object.
|
161
|
-
*/
|
162
|
-
async function calculateChecksum(obj) {
|
163
|
-
const objCopy = { ...obj, checksum: undefined };
|
164
|
-
|
165
|
-
return sha256(JSON.stringify(objCopy));
|
166
|
-
}
|
167
|
-
|
168
|
-
/**
|
169
|
-
* Calculates SHA-256 hash for a string
|
170
|
-
*/
|
171
|
-
async function sha256(str) {
|
172
|
-
const buffer = new TextEncoder().encode(str);
|
173
|
-
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
|
174
|
-
|
175
|
-
return Array.from(new Uint8Array(hashBuffer))
|
176
|
-
.map(b => b.toString(16).padStart(2, '0'))
|
177
|
-
.join('');
|
178
|
-
}
|
@@ -20,11 +20,11 @@ module CKEditor5::Rails
|
|
20
20
|
|
21
21
|
def scripts
|
22
22
|
@scripts ||= [
|
23
|
-
Assets::
|
23
|
+
Assets::JSUrlImportMeta.new(
|
24
24
|
create_cdn_url('ckbox', version, 'ckbox.js'),
|
25
25
|
window_name: 'CKBox'
|
26
26
|
),
|
27
|
-
*
|
27
|
+
*translations_js_url_imports
|
28
28
|
]
|
29
29
|
end
|
30
30
|
|
@@ -46,11 +46,11 @@ module CKEditor5::Rails
|
|
46
46
|
'theme must be a string or symbol'
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
49
|
+
def translations_js_url_imports
|
50
50
|
translations.map do |lang|
|
51
51
|
url = create_cdn_url('ckbox', version, "translations/#{lang}.js")
|
52
52
|
|
53
|
-
Assets::
|
53
|
+
Assets::JSUrlImportMeta.new(url, window_name: 'CKBOX_TRANSLATIONS', translation: true)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -22,8 +22,8 @@ module CKEditor5::Rails
|
|
22
22
|
|
23
23
|
def scripts
|
24
24
|
@scripts ||= [
|
25
|
-
|
26
|
-
*
|
25
|
+
js_url_imports,
|
26
|
+
*translations_js_url_imports
|
27
27
|
]
|
28
28
|
end
|
29
29
|
|
@@ -35,18 +35,18 @@ module CKEditor5::Rails
|
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
-
def
|
39
|
-
Assets::
|
38
|
+
def js_url_imports
|
39
|
+
Assets::JSUrlImportMeta.new(
|
40
40
|
create_cdn_url(import_name, version, "#{import_name}.js"),
|
41
41
|
import_name: import_name
|
42
42
|
)
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
45
|
+
def translations_js_url_imports
|
46
46
|
translations.map do |lang|
|
47
47
|
url = create_cdn_url(import_name, version, "translations/#{lang}.js")
|
48
48
|
|
49
|
-
Assets::
|
49
|
+
Assets::JSUrlImportMeta.new(
|
50
50
|
url,
|
51
51
|
import_name: "#{import_name}/translations/#{lang}.js",
|
52
52
|
translation: true
|
@@ -1,13 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'preset_builder'
|
4
|
+
require_relative 'preset_serializer'
|
4
5
|
|
5
6
|
module CKEditor5::Rails::Context
|
6
7
|
module Helpers
|
7
|
-
def ckeditor5_context(
|
8
|
-
|
8
|
+
def ckeditor5_context(preset = nil, &block)
|
9
|
+
preset ||= PresetBuilder.new
|
10
|
+
context_props = PresetSerializer.new(preset)
|
9
11
|
|
10
12
|
tag.public_send(:'ckeditor-context-component', **context_props.to_attributes, &block)
|
11
13
|
end
|
14
|
+
|
15
|
+
def ckeditor5_context_preset(&block)
|
16
|
+
PresetBuilder.new(&block)
|
17
|
+
end
|
12
18
|
end
|
13
19
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../presets/concerns/configuration_methods'
|
4
|
+
require_relative '../presets/concerns/plugin_methods'
|
5
|
+
|
6
|
+
module CKEditor5::Rails
|
7
|
+
module Context
|
8
|
+
class PresetBuilder
|
9
|
+
include Presets::Concerns::ConfigurationMethods
|
10
|
+
include Presets::Concerns::PluginMethods
|
11
|
+
|
12
|
+
def initialize(&block)
|
13
|
+
@config = {
|
14
|
+
plugins: []
|
15
|
+
}
|
16
|
+
|
17
|
+
instance_eval(&block) if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize_copy(source)
|
21
|
+
super
|
22
|
+
|
23
|
+
@config = {
|
24
|
+
plugins: source.config[:plugins].map(&:dup)
|
25
|
+
}.merge(
|
26
|
+
source.config.except(:plugins).deep_dup
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CKEditor5::Rails
|
4
|
+
module Context
|
5
|
+
class PresetSerializer
|
6
|
+
def initialize(preset)
|
7
|
+
@preset = preset
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_attributes
|
11
|
+
{
|
12
|
+
plugins: serialize_plugins,
|
13
|
+
config: serialize_config
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
delegate :config, to: :@preset
|
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
|
@@ -5,8 +5,6 @@ require_relative 'editable_height_normalizer'
|
|
5
5
|
|
6
6
|
module CKEditor5::Rails::Editor
|
7
7
|
class Props
|
8
|
-
include CKEditor5::Rails::Concerns::Checksum
|
9
|
-
|
10
8
|
EDITOR_TYPES = {
|
11
9
|
classic: 'ClassicEditor',
|
12
10
|
inline: 'InlineEditor',
|
@@ -27,9 +25,8 @@ module CKEditor5::Rails::Editor
|
|
27
25
|
|
28
26
|
def to_attributes
|
29
27
|
{
|
30
|
-
**serialized_attributes,
|
31
28
|
type: EDITOR_TYPES[@type],
|
32
|
-
|
29
|
+
**serialized_attributes
|
33
30
|
}
|
34
31
|
end
|
35
32
|
|
@@ -41,24 +38,14 @@ module CKEditor5::Rails::Editor
|
|
41
38
|
|
42
39
|
attr_reader :controller_context, :watchdog, :type, :config, :editable_height
|
43
40
|
|
44
|
-
def integrity_checksum
|
45
|
-
unsafe_attributes = serialized_attributes.slice(:translations, :plugins)
|
46
|
-
|
47
|
-
calculate_object_checksum(unsafe_attributes)
|
48
|
-
end
|
49
|
-
|
50
41
|
def serialized_attributes
|
51
|
-
|
52
|
-
|
53
|
-
attributes = {
|
42
|
+
{
|
54
43
|
translations: serialize_translations,
|
55
44
|
plugins: serialize_plugins,
|
56
45
|
config: serialize_config,
|
57
46
|
watchdog: watchdog
|
58
47
|
}
|
59
|
-
|
60
|
-
attributes.merge!(editable_height ? { 'editable-height' => editable_height } : {})
|
61
|
-
@serialized_attributes = attributes
|
48
|
+
.merge(editable_height ? { 'editable-height' => editable_height } : {})
|
62
49
|
end
|
63
50
|
|
64
51
|
def serialize_translations
|
@@ -1,14 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'props_base_plugin'
|
4
|
-
|
5
3
|
module CKEditor5::Rails::Editor
|
6
|
-
class PropsInlinePlugin
|
7
|
-
attr_reader :code
|
4
|
+
class PropsInlinePlugin
|
5
|
+
attr_reader :name, :code
|
8
6
|
|
9
7
|
def initialize(name, code)
|
10
|
-
|
11
|
-
|
8
|
+
@name = name
|
12
9
|
@code = code
|
13
10
|
validate_code!
|
14
11
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'props_base_plugin'
|
4
|
-
|
5
3
|
module CKEditor5::Rails::Editor
|
6
|
-
class PropsPlugin
|
7
|
-
attr_reader :js_import_meta
|
4
|
+
class PropsPlugin
|
5
|
+
attr_reader :name, :js_import_meta
|
8
6
|
|
9
|
-
|
10
|
-
super(name)
|
7
|
+
delegate :to_h, to: :import_meta
|
11
8
|
|
9
|
+
def initialize(name, premium: false, **js_import_meta)
|
12
10
|
@name = name
|
13
11
|
@js_import_meta = if js_import_meta.empty?
|
14
12
|
{ import_name: premium ? 'ckeditor5-premium-features' : 'ckeditor5' }
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module CKEditor5::Rails::Plugins
|
4
4
|
class SimpleUploadAdapter < CKEditor5::Rails::Editor::PropsInlinePlugin
|
5
|
-
PLUGIN_CODE = <<~
|
5
|
+
PLUGIN_CODE = <<~JS
|
6
6
|
import { Plugin, FileRepository } from 'ckeditor5';
|
7
7
|
|
8
8
|
export default class SimpleUploadAdapter extends Plugin {
|
@@ -78,7 +78,7 @@ module CKEditor5::Rails::Plugins
|
|
78
78
|
});
|
79
79
|
}
|
80
80
|
}
|
81
|
-
|
81
|
+
JS
|
82
82
|
|
83
83
|
def initialize
|
84
84
|
super(:SimpleUploadAdapter, PLUGIN_CODE)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
module CKEditor5::Rails
|
6
|
+
module Presets
|
7
|
+
module Concerns
|
8
|
+
module ConfigurationMethods
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
attr_reader :config
|
13
|
+
end
|
14
|
+
|
15
|
+
def configure(key, value)
|
16
|
+
config[key] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CKEditor5::Rails
|
4
|
+
module Presets
|
5
|
+
module Concerns
|
6
|
+
module PluginMethods
|
7
|
+
def inline_plugin(name, code)
|
8
|
+
config[:plugins] << Editor::PropsInlinePlugin.new(name, code)
|
9
|
+
end
|
10
|
+
|
11
|
+
def plugin(name, **kwargs)
|
12
|
+
plugin_obj = PluginsBuilder.create_plugin(name, **kwargs)
|
13
|
+
config[:plugins] << plugin_obj
|
14
|
+
plugin_obj
|
15
|
+
end
|
16
|
+
|
17
|
+
def plugins(*names, **kwargs, &block)
|
18
|
+
config[:plugins] ||= []
|
19
|
+
|
20
|
+
names.each { |name| plugin(name, **kwargs) } unless names.empty?
|
21
|
+
|
22
|
+
builder = PluginsBuilder.new(config[:plugins])
|
23
|
+
builder.instance_eval(&block) if block_given?
|
24
|
+
builder
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|