ckeditor5 1.16.1 → 1.16.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95f068ef75561d88a26a68c5aafa6e6f86b55405984e83bf35909085f288f9ba
4
- data.tar.gz: d72e733641c5ac8c4f9d1e20731d54ffd2c0e4d88bc3b82618eb62b8c2820049
3
+ metadata.gz: 80773f82ac9fcdf35feac2e568206c4dd5dbd04240ae891b880549fc7192ef12
4
+ data.tar.gz: d4c4244344977827288691f7846bce8737c70d9df170aff1fa2fb52a3a400d1a
5
5
  SHA512:
6
- metadata.gz: 31fb63fa1ac20061e1c28150178b7b8f92ca54e99073f2e180a7823d7f76f58c75a9f55e70b9a6f729d9715389b1a349305027e6d6c0c56bb2f7539d1a6bc0ad
7
- data.tar.gz: 4019ffcc8e326be64930092815d5ff68436e4c242a67853adf735b4667aa7bec624df66fe9614d0f7e4bb00c67c2c0cf0e1195c43647d397b9f99ab8a0637479
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
@@ -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
@@ -2,9 +2,9 @@
2
2
 
3
3
  module CKEditor5::Rails
4
4
  module Context
5
- class Props
6
- def initialize(config)
7
- @config = config
5
+ class PresetSerializer
6
+ def initialize(preset)
7
+ @preset = preset
8
8
  end
9
9
 
10
10
  def to_attributes
@@ -16,7 +16,7 @@ module CKEditor5::Rails
16
16
 
17
17
  private
18
18
 
19
- attr_reader :config
19
+ delegate :config, to: :@preset
20
20
 
21
21
  def serialize_plugins
22
22
  (config[:plugins] || []).map { |plugin| Editor::PropsPlugin.normalize(plugin).to_h }.to_json
@@ -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
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'concerns/configuration_methods'
4
+ require_relative 'concerns/plugin_methods'
5
+
3
6
  module CKEditor5::Rails
4
7
  module Presets
5
8
  class PresetBuilder
6
9
  include Editor::Helpers::Config
7
-
8
- attr_reader :config
10
+ include Concerns::ConfigurationMethods
11
+ include Concerns::PluginMethods
9
12
 
10
13
  def initialize(&block)
11
14
  @version = nil
@@ -46,10 +49,6 @@ module CKEditor5::Rails
46
49
  license_key == 'GPL'
47
50
  end
48
51
 
49
- def menubar?
50
- @config.dig(:menuBar, :isVisible) || false
51
- end
52
-
53
52
  def to_h_with_overrides(**overrides)
54
53
  {
55
54
  version: overrides.fetch(:version, version),
@@ -144,16 +143,16 @@ module CKEditor5::Rails
144
143
  @type = type
145
144
  end
146
145
 
147
- def configure(key, value)
148
- @config[key] = value
149
- end
150
-
151
146
  def menubar(visible: true)
152
- @config[:menuBar] = {
147
+ config[:menuBar] = {
153
148
  isVisible: visible
154
149
  }
155
150
  end
156
151
 
152
+ def menubar?
153
+ config.dig(:menuBar, :isVisible) || false
154
+ end
155
+
157
156
  def toolbar(*items, should_group_when_full: true, &block)
158
157
  if @config[:toolbar].blank? || !items.empty?
159
158
  @config[:toolbar] = {
@@ -167,30 +166,10 @@ module CKEditor5::Rails
167
166
  builder
168
167
  end
169
168
 
170
- def inline_plugin(name, code)
171
- @config[:plugins] << Editor::PropsInlinePlugin.new(name, code)
172
- end
173
-
174
- def plugin(name, **kwargs)
175
- plugin_obj = PluginsBuilder.create_plugin(name, **kwargs)
176
- @config[:plugins] << plugin_obj
177
- plugin_obj
178
- end
179
-
180
- def plugins(*names, **kwargs, &block)
181
- @config[:plugins] ||= []
182
-
183
- names.each { |name| plugin(name, **kwargs) } unless names.empty?
184
-
185
- builder = PluginsBuilder.new(@config[:plugins])
186
- builder.instance_eval(&block) if block_given?
187
- builder
188
- end
189
-
190
169
  def language(ui = nil, content: ui) # rubocop:disable Naming/MethodParameterName
191
- return @config[:language] if ui.nil?
170
+ return config[:language] if ui.nil?
192
171
 
193
- @config[:language] = {
172
+ config[:language] = {
194
173
  ui: ui,
195
174
  content: content
196
175
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  module CKEditor5
4
4
  module Rails
5
- VERSION = '1.16.1'
5
+ VERSION = '1.16.2'
6
6
 
7
7
  DEFAULT_CKEDITOR_VERSION = '43.3.1'
8
8
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'e2e/spec_helper'
4
+
5
+ RSpec.describe 'CKEditor5 Context Integration', type: :feature, js: true do
6
+ before { visit 'context' }
7
+
8
+ it 'initializes context with multiple editors' do
9
+ expect(page).to have_css('.ck-editor__editable', count: 2, wait: 10)
10
+ end
11
+
12
+ it 'initializes the magic context plugin' do
13
+ eventually do
14
+ plugin_exists = page.evaluate_script('window.MagicContextPlugin !== undefined')
15
+ expect(plugin_exists).to be true
16
+ end
17
+ end
18
+
19
+ it 'allows editing content in context editors' do
20
+ editors = all('.ck-editor__editable')
21
+
22
+ # Test first editor
23
+ editors[0].click
24
+ editors[0].send_keys([[:control, 'a'], :backspace])
25
+ editors[0].send_keys('Modified Context Item 1')
26
+
27
+ # Test second editor
28
+ editors[1].click
29
+ editors[1].send_keys([[:control, 'a'], :backspace])
30
+ editors[1].send_keys('Modified Context Item 2')
31
+
32
+ # Verify content
33
+ expect(editors[0].text).to eq('Modified Context Item 1')
34
+ expect(editors[1].text).to eq('Modified Context Item 2')
35
+ end
36
+ end
@@ -19,11 +19,11 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer do
19
19
 
20
20
  let(:scripts) do
21
21
  [
22
- CKEditor5::Rails::Assets::JSExportsMeta.new(
22
+ CKEditor5::Rails::Assets::JSUrlImportMeta.new(
23
23
  'https://cdn.com/script1.js',
24
24
  window_name: 'CKEditor5'
25
25
  ),
26
- CKEditor5::Rails::Assets::JSExportsMeta.new(
26
+ CKEditor5::Rails::Assets::JSUrlImportMeta.new(
27
27
  'https://cdn.com/script2.js',
28
28
  import_name: '@ckeditor/script2'
29
29
  )
@@ -35,8 +35,10 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundle do
35
35
 
36
36
  describe '#translations_scripts' do
37
37
  let(:bundle) { concrete_class.new }
38
- let(:translation_script) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, translation?: true) }
39
- let(:regular_script) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, translation?: false) }
38
+ let(:translation_script) do
39
+ instance_double(CKEditor5::Rails::Assets::JSUrlImportMeta, translation?: true)
40
+ end
41
+ let(:regular_script) { instance_double(CKEditor5::Rails::Assets::JSUrlImportMeta, translation?: false) }
40
42
 
41
43
  before do
42
44
  allow(bundle).to receive(:scripts).and_return([translation_script, regular_script])
@@ -48,8 +50,8 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundle do
48
50
  end
49
51
 
50
52
  describe '#<<' do
51
- let(:script1) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta) }
52
- let(:script2) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta) }
53
+ let(:script1) { instance_double(CKEditor5::Rails::Assets::JSUrlImportMeta) }
54
+ let(:script2) { instance_double(CKEditor5::Rails::Assets::JSUrlImportMeta) }
53
55
  let(:stylesheet1) { '/path/to/style1.css' }
54
56
  let(:stylesheet2) { '/path/to/style2.css' }
55
57
 
@@ -101,8 +103,8 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundle do
101
103
  end
102
104
 
103
105
  describe '#preloads' do
104
- let(:script1) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, url: '/js/script1.js') }
105
- let(:script2) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, url: '/js/script2.js') }
106
+ let(:script1) { instance_double(CKEditor5::Rails::Assets::JSUrlImportMeta, url: '/js/script1.js') }
107
+ let(:script2) { instance_double(CKEditor5::Rails::Assets::JSUrlImportMeta, url: '/js/script2.js') }
106
108
  let(:stylesheet1) { '/css/style1.css' }
107
109
  let(:stylesheet2) { '/css/style2.css' }
108
110
 
@@ -136,7 +138,7 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundle do
136
138
  end
137
139
  end
138
140
 
139
- RSpec.describe CKEditor5::Rails::Assets::JSExportsMeta do
141
+ RSpec.describe CKEditor5::Rails::Assets::JSUrlImportMeta do
140
142
  let(:url) { '/path/to/script.js' }
141
143
 
142
144
  describe '#initialize' do
@@ -36,7 +36,7 @@ RSpec.describe CKEditor5::Rails::Cdn::CKBoxBundle do
36
36
 
37
37
  describe '#scripts' do
38
38
  it 'returns array with main script' do
39
- expect(bundle.scripts.first).to be_a(CKEditor5::Rails::Assets::JSExportsMeta)
39
+ expect(bundle.scripts.first).to be_a(CKEditor5::Rails::Assets::JSUrlImportMeta)
40
40
  expect(bundle.scripts.first.url).to include('ckbox.js')
41
41
  expect(bundle.scripts.first.window_name).to eq('CKBox')
42
42
  end
@@ -14,7 +14,28 @@ RSpec.describe CKEditor5::Rails::Context::Helpers do
14
14
  let(:helper) { test_class.new }
15
15
 
16
16
  describe '#ckeditor5_context' do
17
- it 'creates context component with default attributes' do
17
+ let(:empty_preset) { CKEditor5::Rails::Context::PresetBuilder.new }
18
+
19
+ let(:custom_preset) do
20
+ CKEditor5::Rails::Context::PresetBuilder.new do
21
+ configure :preset, :custom
22
+ end
23
+ end
24
+
25
+ let(:cdn_preset) do
26
+ CKEditor5::Rails::Context::PresetBuilder.new do
27
+ configure :cdn, :jsdelivr
28
+ end
29
+ end
30
+
31
+ let(:complex_preset) do
32
+ CKEditor5::Rails::Context::PresetBuilder.new do
33
+ configure :preset, :custom
34
+ configure :cdn, :jsdelivr
35
+ end
36
+ end
37
+
38
+ it 'is optional to pass a preset' do
18
39
  expect(helper.ckeditor5_context).to have_tag(
19
40
  'ckeditor-context-component',
20
41
  with: {
@@ -24,8 +45,18 @@ RSpec.describe CKEditor5::Rails::Context::Helpers do
24
45
  )
25
46
  end
26
47
 
48
+ it 'creates context component with default attributes' do
49
+ expect(helper.ckeditor5_context(empty_preset)).to have_tag(
50
+ 'ckeditor-context-component',
51
+ with: {
52
+ plugins: '[]',
53
+ config: '{}'
54
+ }
55
+ )
56
+ end
57
+
27
58
  it 'creates context component with preset configuration' do
28
- expect(helper.ckeditor5_context(preset: :custom)).to have_tag(
59
+ expect(helper.ckeditor5_context(custom_preset)).to have_tag(
29
60
  'ckeditor-context-component',
30
61
  with: {
31
62
  plugins: '[]',
@@ -35,7 +66,7 @@ RSpec.describe CKEditor5::Rails::Context::Helpers do
35
66
  end
36
67
 
37
68
  it 'creates context component with cdn configuration' do
38
- expect(helper.ckeditor5_context(cdn: :jsdelivr)).to have_tag(
69
+ expect(helper.ckeditor5_context(cdn_preset)).to have_tag(
39
70
  'ckeditor-context-component',
40
71
  with: {
41
72
  plugins: '[]',
@@ -45,7 +76,7 @@ RSpec.describe CKEditor5::Rails::Context::Helpers do
45
76
  end
46
77
 
47
78
  it 'creates context component with multiple configurations' do
48
- result = helper.ckeditor5_context(preset: :custom, cdn: :jsdelivr)
79
+ result = helper.ckeditor5_context(complex_preset)
49
80
 
50
81
  expect(result).to have_tag(
51
82
  'ckeditor-context-component',
@@ -57,11 +88,24 @@ RSpec.describe CKEditor5::Rails::Context::Helpers do
57
88
  end
58
89
 
59
90
  it 'accepts block content' do
60
- result = helper.ckeditor5_context { 'Content' }
91
+ result = helper.ckeditor5_context(empty_preset) { 'Content' }
61
92
 
62
93
  expect(result).to have_tag('ckeditor-context-component') do
63
94
  with_text 'Content'
64
95
  end
65
96
  end
66
97
  end
98
+
99
+ describe '#ckeditor5_context_preset' do
100
+ it 'creates a new preset builder' do
101
+ preset = helper.ckeditor5_context_preset do
102
+ configure :preset, :custom
103
+ end
104
+
105
+ expect(preset.config).to eq(
106
+ plugins: [],
107
+ preset: :custom
108
+ )
109
+ end
110
+ end
67
111
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe CKEditor5::Rails::Context::PresetBuilder do
6
+ subject(:builder) { described_class.new }
7
+
8
+ describe '#initialize' do
9
+ it 'creates empty config with plugins array' do
10
+ expect(builder.config).to eq({ plugins: [] })
11
+ end
12
+
13
+ it 'accepts configuration block' do
14
+ builder = described_class.new do
15
+ configure :language, 'en'
16
+ end
17
+
18
+ expect(builder.config[:language]).to eq('en')
19
+ end
20
+ end
21
+
22
+ describe '#initialize_copy' do
23
+ let(:original) do
24
+ described_class.new do
25
+ configure :language, 'en'
26
+ plugin 'Test'
27
+ end
28
+ end
29
+
30
+ it 'creates deep copy of config' do
31
+ copy = original.dup
32
+
33
+ expect(copy.config).not_to be(original.config)
34
+ expect(copy.config[:plugins]).not_to be(original.config[:plugins])
35
+ expect(copy.config[:plugins].first).not_to be(original.config[:plugins].first)
36
+ end
37
+ end
38
+
39
+ describe '#configure' do
40
+ it 'sets config value' do
41
+ builder.configure(:toolbar, { items: ['bold'] })
42
+ expect(builder.config[:toolbar]).to eq({ items: ['bold'] })
43
+ end
44
+ end
45
+
46
+ describe '#plugin' do
47
+ it 'adds normalized plugin to config' do
48
+ plugin = builder.plugin('Test')
49
+
50
+ expect(builder.config[:plugins]).to include(plugin)
51
+ expect(plugin).to be_a(CKEditor5::Rails::Editor::PropsPlugin)
52
+ end
53
+
54
+ it 'accepts plugin options' do
55
+ plugin = builder.plugin('Test', premium: true)
56
+
57
+ expect(plugin.js_import_meta[:import_name]).to eq('ckeditor5-premium-features')
58
+ end
59
+ end
60
+
61
+ describe '#plugins' do
62
+ it 'adds multiple plugins at once' do
63
+ builder.plugins('Test1', 'Test2')
64
+
65
+ expect(builder.config[:plugins].map(&:name)).to eq(%w[Test1 Test2])
66
+ end
67
+
68
+ it 'accepts block for complex configuration' do
69
+ builder.plugins do
70
+ append 'Test1'
71
+ append 'Test2', premium: true
72
+ end
73
+
74
+ expect(builder.config[:plugins].map(&:name)).to eq(%w[Test1 Test2])
75
+ end
76
+
77
+ it 'accepts both arguments and block' do
78
+ builder.plugins('Test1') do
79
+ append 'Test2'
80
+ end
81
+
82
+ expect(builder.config[:plugins].map(&:name)).to eq(%w[Test1 Test2])
83
+ end
84
+ end
85
+ end
@@ -2,28 +2,27 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe CKEditor5::Rails::Context::Props do
6
- let(:config) do
7
- {
8
- plugins: [
9
- CKEditor5::Rails::Editor::PropsPlugin.new('Plugin1', import_name: '@ckeditor/plugin1'),
10
- CKEditor5::Rails::Editor::PropsInlinePlugin.new('plugin2', 'export default class Plugin2 {}')
11
- ],
12
- toolbar: { items: %w[bold italic] },
13
- language: 'en'
14
- }
5
+ RSpec.describe CKEditor5::Rails::Context::PresetSerializer do
6
+ let(:preset) do
7
+ CKEditor5::Rails::Context::PresetBuilder.new do
8
+ plugin 'Plugin1', import_name: '@ckeditor/plugin1'
9
+ inline_plugin 'plugin2', 'export default class Plugin2 {}'
10
+
11
+ configure :toolbar, { items: %w[bold italic] }
12
+ configure :language, 'en'
13
+ end
15
14
  end
16
15
 
17
- subject(:props) { described_class.new(config) }
16
+ subject(:serializer) { described_class.new(preset) }
18
17
 
19
18
  describe '#initialize' do
20
- it 'accepts a config hash' do
21
- expect { described_class.new({}) }.not_to raise_error
19
+ it 'accepts a preset instance' do
20
+ expect { described_class.new(preset) }.not_to raise_error
22
21
  end
23
22
  end
24
23
 
25
24
  describe '#to_attributes' do
26
- subject(:attributes) { props.to_attributes }
25
+ subject(:attributes) { serializer.to_attributes }
27
26
 
28
27
  it 'returns a hash with plugins and config keys' do
29
28
  expect(attributes).to be_a(Hash)
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.16.1
4
+ version: 1.16.2
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-22 00:00:00.000000000 Z
12
+ date: 2024-11-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -56,7 +56,8 @@ files:
56
56
  - lib/ckeditor5/rails/cdn/helpers.rb
57
57
  - lib/ckeditor5/rails/cdn/url_generator.rb
58
58
  - lib/ckeditor5/rails/context/helpers.rb
59
- - lib/ckeditor5/rails/context/props.rb
59
+ - lib/ckeditor5/rails/context/preset_builder.rb
60
+ - lib/ckeditor5/rails/context/preset_serializer.rb
60
61
  - lib/ckeditor5/rails/editor/editable_height_normalizer.rb
61
62
  - lib/ckeditor5/rails/editor/helpers.rb
62
63
  - lib/ckeditor5/rails/editor/helpers/config_helpers.rb
@@ -69,6 +70,8 @@ files:
69
70
  - lib/ckeditor5/rails/hooks/form.rb
70
71
  - lib/ckeditor5/rails/hooks/simple_form.rb
71
72
  - lib/ckeditor5/rails/plugins/simple_upload_adapter.rb
73
+ - lib/ckeditor5/rails/presets/concerns/configuration_methods.rb
74
+ - lib/ckeditor5/rails/presets/concerns/plugin_methods.rb
72
75
  - lib/ckeditor5/rails/presets/manager.rb
73
76
  - lib/ckeditor5/rails/presets/plugins_builder.rb
74
77
  - lib/ckeditor5/rails/presets/preset_builder.rb
@@ -76,6 +79,7 @@ files:
76
79
  - lib/ckeditor5/rails/semver.rb
77
80
  - lib/ckeditor5/rails/version.rb
78
81
  - lib/ckeditor5/rails/version_detector.rb
82
+ - spec/e2e/features/context_spec.rb
79
83
  - spec/e2e/features/editor_types_spec.rb
80
84
  - spec/e2e/features/form_integration_spec.rb
81
85
  - spec/e2e/spec_helper.rb
@@ -88,7 +92,8 @@ files:
88
92
  - spec/lib/ckeditor5/rails/cdn/helpers_spec.rb
89
93
  - spec/lib/ckeditor5/rails/cdn/url_generator_spec.rb
90
94
  - spec/lib/ckeditor5/rails/context/helpers_spec.rb
91
- - spec/lib/ckeditor5/rails/context/props_spec.rb
95
+ - spec/lib/ckeditor5/rails/context/preset_builder_spec.rb
96
+ - spec/lib/ckeditor5/rails/context/preset_serializer_spec.rb
92
97
  - spec/lib/ckeditor5/rails/editor/editable_height_normalizer_spec.rb
93
98
  - spec/lib/ckeditor5/rails/editor/helpers/config_helpers_spec.rb
94
99
  - spec/lib/ckeditor5/rails/editor/helpers/editor_helpers_spec.rb
@@ -131,6 +136,7 @@ signing_key:
131
136
  specification_version: 4
132
137
  summary: CKEditor 5 for Rails
133
138
  test_files:
139
+ - spec/e2e/features/context_spec.rb
134
140
  - spec/e2e/features/editor_types_spec.rb
135
141
  - spec/e2e/features/form_integration_spec.rb
136
142
  - spec/e2e/spec_helper.rb
@@ -143,7 +149,8 @@ test_files:
143
149
  - spec/lib/ckeditor5/rails/cdn/helpers_spec.rb
144
150
  - spec/lib/ckeditor5/rails/cdn/url_generator_spec.rb
145
151
  - spec/lib/ckeditor5/rails/context/helpers_spec.rb
146
- - spec/lib/ckeditor5/rails/context/props_spec.rb
152
+ - spec/lib/ckeditor5/rails/context/preset_builder_spec.rb
153
+ - spec/lib/ckeditor5/rails/context/preset_serializer_spec.rb
147
154
  - spec/lib/ckeditor5/rails/editor/editable_height_normalizer_spec.rb
148
155
  - spec/lib/ckeditor5/rails/editor/helpers/config_helpers_spec.rb
149
156
  - spec/lib/ckeditor5/rails/editor/helpers/editor_helpers_spec.rb