ckeditor5 1.16.0 → 1.16.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +66 -12
  3. data/lib/ckeditor5/rails/assets/assets_bundle.rb +1 -1
  4. data/lib/ckeditor5/rails/assets/webcomponents/components/context.mjs +0 -23
  5. data/lib/ckeditor5/rails/assets/webcomponents/components/editor.mjs +0 -24
  6. data/lib/ckeditor5/rails/assets/webcomponents/utils.mjs +10 -33
  7. data/lib/ckeditor5/rails/cdn/ckbox_bundle.rb +4 -4
  8. data/lib/ckeditor5/rails/cdn/ckeditor_bundle.rb +6 -6
  9. data/lib/ckeditor5/rails/context/helpers.rb +9 -3
  10. data/lib/ckeditor5/rails/context/preset_builder.rb +31 -0
  11. data/lib/ckeditor5/rails/context/preset_serializer.rb +30 -0
  12. data/lib/ckeditor5/rails/editor/props.rb +3 -16
  13. data/lib/ckeditor5/rails/editor/props_inline_plugin.rb +3 -6
  14. data/lib/ckeditor5/rails/editor/props_plugin.rb +4 -6
  15. data/lib/ckeditor5/rails/plugins/simple_upload_adapter.rb +2 -2
  16. data/lib/ckeditor5/rails/presets/concerns/configuration_methods.rb +21 -0
  17. data/lib/ckeditor5/rails/presets/concerns/plugin_methods.rb +29 -0
  18. data/lib/ckeditor5/rails/presets/preset_builder.rb +12 -33
  19. data/lib/ckeditor5/rails/version.rb +1 -1
  20. data/lib/ckeditor5/rails.rb +0 -1
  21. data/spec/e2e/features/context_spec.rb +36 -0
  22. data/spec/lib/ckeditor5/rails/assets/asset_bundle_hml_serializer_spec.rb +2 -2
  23. data/spec/lib/ckeditor5/rails/assets/assets_bundle_spec.rb +9 -7
  24. data/spec/lib/ckeditor5/rails/cdn/ckbox_bundle_spec.rb +1 -1
  25. data/spec/lib/ckeditor5/rails/context/helpers_spec.rb +49 -5
  26. data/spec/lib/ckeditor5/rails/context/preset_builder_spec.rb +85 -0
  27. data/spec/lib/ckeditor5/rails/context/{props_spec.rb → preset_serializer_spec.rb} +14 -21
  28. data/spec/lib/ckeditor5/rails/editor/props_spec.rb +0 -2
  29. metadata +12 -11
  30. data/lib/ckeditor5/rails/concerns/checksum.rb +0 -15
  31. data/lib/ckeditor5/rails/context/props.rb +0 -45
  32. data/lib/ckeditor5/rails/editor/props_base_plugin.rb +0 -19
  33. data/spec/lib/ckeditor5/rails/concerns/checksum_spec.rb +0 -50
  34. 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: e91fe2d11179c703901756efa978fcedcd3030d0381c4e550ab8c9c15ef73a19
4
- data.tar.gz: 4119948cdae51969b3d1e77801f20faecd81cfbf2755388fc444421e7da8bdb9
3
+ metadata.gz: 80773f82ac9fcdf35feac2e568206c4dd5dbd04240ae891b880549fc7192ef12
4
+ data.tar.gz: d4c4244344977827288691f7846bce8737c70d9df170aff1fa2fb52a3a400d1a
5
5
  SHA512:
6
- metadata.gz: d4f236d5bc883344daa8fa9bc0b7d55e3898360dd8fabfd48265bbd1eedf3c654e8ba6baf5b0a1ba5ffa215c6b2c14a60c02f7182b81885a875b0a4902f67746
7
- data.tar.gz: 593de9199583c1f22a38b9858967eca63b9c98eef8b7a6a1e5a06ccfa1df759424dab96ed88c1719614744b26c8a32920722156875ba748e66c80272eeb0fd78
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 Our Demos! 🎮 ✨
85
+ ## Try Demos! 🎮 ✨
86
86
 
87
- Want to see some cool examples? We've got you covered! Check out our interactive [demo application](https://github.com/Mati365/ckeditor5-rails/tree/main/sandbox/app/views/demos) packed with various editor configurations. You can also explore official CKEditor 5 [examples](https://ckeditor.com/docs/ckeditor5/latest/examples/builds/classic-editor.html) for more inspiration! 💡
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
- Ready to play with the demos locally? It's super easy! Just follow these steps: 🚀
89
+ To run the demos locally, follow these steps:
90
90
 
91
91
  ```bash
92
- bundle install # Install all the goodies 📦
93
- bundle exec guard -g rails # Fire up the server 🔥
92
+ bundle install # Install dependencies
93
+ bundle exec guard -g rails # Start the server
94
94
  ```
95
95
 
96
- Now the fun part - open [http://localhost:3000/](http://localhost:3000/) in your browser and start experimenting! 🎯 Feel free to tweak the code and make it your own! 🎨
96
+ Open [http://localhost:3000/](http://localhost:3000/) in a browser to start experimenting. Modify the code as needed.
97
97
 
98
- Want to extend CKEditor's functionality? Check out our [plugins directory](https://github.com/Mati365/ckeditor5-rails/tree/main/lib/ckeditor5/rails/plugins) and create your own awesome plugins! 🔌 We love community contributions - your plugin could be the next great addition to our ecosystem! ⭐
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 Our Demos! 🎮 ✨](#try-our-demos--)
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 you can define a custom class or function for the plugin here. The example below shows how to define a custom plugin that highlights the text:
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 config: { ... }, plugins: [ ... ] do %>
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 `config` and `plugins` keyword arguments. The `config` keyword argument allows you to define the shared configuration of the editor instances, while the `plugins` keyword argument allows you to define the shared plugins. Format of these arguments is the same as in the `ckeditor5_editor` helper.
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.
@@ -38,7 +38,7 @@ module CKEditor5::Rails::Assets
38
38
  end
39
39
  end
40
40
 
41
- class JSExportsMeta
41
+ class JSUrlImportMeta
42
42
  attr_reader :url, :import_meta
43
43
 
44
44
  delegate :esm?, :window?, :import_name, :window_name, :import_as, :to_h, to: :import_meta
@@ -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
- imports.map(async (item) => {
71
- switch(item.type) {
72
- case 'inline':
73
- return loadInlinePlugin(item);
74
-
75
- case 'external':
76
- default:
77
- return loadExternalPlugin(item);
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::JSExportsMeta.new(
23
+ Assets::JSUrlImportMeta.new(
24
24
  create_cdn_url('ckbox', version, 'ckbox.js'),
25
25
  window_name: 'CKBox'
26
26
  ),
27
- *translations_js_exports_meta
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 translations_js_exports_meta
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::JSExportsMeta.new(url, window_name: 'CKBOX_TRANSLATIONS', translation: true)
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
- js_exports_meta,
26
- *translations_js_exports_meta
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 js_exports_meta
39
- Assets::JSExportsMeta.new(
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 translations_js_exports_meta
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::JSExportsMeta.new(
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 'props'
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(**config, &block)
8
- context_props = Props.new(config)
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
- integrity: integrity_checksum
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
- return @serialized_attributes if defined?(@serialized_attributes)
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 < PropsBasePlugin
7
- attr_reader :code
4
+ class PropsInlinePlugin
5
+ attr_reader :name, :code
8
6
 
9
7
  def initialize(name, code)
10
- super(name)
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 < PropsBasePlugin
7
- attr_reader :js_import_meta
4
+ class PropsPlugin
5
+ attr_reader :name, :js_import_meta
8
6
 
9
- def initialize(name, premium: false, **js_import_meta)
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 = <<~JAVASCRIPT
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
- JAVASCRIPT
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