ckeditor5 1.12.0 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c39a460f498306970334acf87d4bd8c66a24ddaf79ad0dd9f461ed5d9772de11
4
- data.tar.gz: b5a221dbe9dd9d47c649d1b8d78eda335fdeebe4fde6190db9f03cf3f3fe4aca
3
+ metadata.gz: a2d481ae5f7ed4d671e8d6ade94e9efa0ab5d0b4bba36f24b8052d84eadd21e9
4
+ data.tar.gz: 3d8ff1d8a23aadc4398e2439996d9a86aa792eec16e33a70837e731e68f6ba9f
5
5
  SHA512:
6
- metadata.gz: a7368d44b2ed0ce7416c8a4ed0052c9c15b343bf012e39fa24abd5761a61173c4ae95925061dce751c0b6419b19e1a69f2d98266f316b99d1c06479b1cad9b1c
7
- data.tar.gz: b0c6f01ac1d2efbc70f11a12997b6d48567293c13689e203ba29f9034dc233d25851e6d0c6bde29f382fbfafcb6f8630e4e51eb47db15922928eb20a199e3274
6
+ metadata.gz: a407f380c8f2295959533cd08966aace68f1d9d20208608a16269921ae167ba450e719663d918ff725ee10f0be6d020c2130d50873b51cc726b00bf4fa55b573
7
+ data.tar.gz: 37f51f50d80ce4e51aeed85188b7bf48963723b0b1cf004bc6faceb5ec561c85c79d00887ca50ce4fe2ed702468677718b35c7cdaceb7af9db10fed5ce088381
data/README.md CHANGED
@@ -62,10 +62,25 @@ In your view:
62
62
 
63
63
  Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
64
64
 
65
+ ## Demos 🚀
66
+
67
+ Interested in more advanced configuration? Visit the demos in the [demo application](https://github.com/Mati365/ckeditor5-rails/tree/main/sandbox/app/views/demos) or take a look at official CKEditor 5 [examples](https://ckeditor.com/docs/ckeditor5/latest/examples/builds/classic-editor.html).
68
+
69
+ In order to run all demos locally, you can clone the repository and run the following commands:
70
+
71
+ ```bash
72
+ bundle install
73
+ cd sandbox
74
+ bundle exec rails server -p 3000
75
+ ```
76
+
77
+ Then visit [http://localhost:3000/demos](http://localhost:3000/) to see the demos in action. 🚀
78
+
65
79
  ## Table of Contents 📚
66
80
 
67
81
  - [CKEditor 5 Rails Integration ✨](#ckeditor-5-rails-integration-)
68
82
  - [Installation 🛠️](#installation-️)
83
+ - [Demos 🚀](#demos-)
69
84
  - [Table of Contents 📚](#table-of-contents-)
70
85
  - [Presets 🎨](#presets-)
71
86
  - [Available Configuration Methods ⚙️](#available-configuration-methods-️)
@@ -85,9 +100,10 @@ Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
85
100
  - [`plugin(name, premium:, import_name:)` method](#pluginname-premium-import_name-method)
86
101
  - [`plugins(*names, **kwargs)` method](#pluginsnames-kwargs-method)
87
102
  - [`inline_plugin(name, code)` method](#inline_pluginname-code-method)
103
+ - [`simple_upload_adapter(url)` method](#simple_upload_adapterurl-method)
88
104
  - [Controller / View helpers 📦](#controller--view-helpers-)
89
105
  - [`ckeditor5_element_ref(selector)` method](#ckeditor5_element_refselector-method)
90
- - [`ckeditor5_preset(&block)` method](#ckeditor5_presetblock-method)
106
+ - [`ckeditor5_preset(&block)` method](#ckeditor5_presetblock-method)
91
107
  - [Including CKEditor 5 assets 📦](#including-ckeditor-5-assets-)
92
108
  - [Format 📝](#format-)
93
109
  - [Using default preset](#using-default-preset)
@@ -534,6 +550,20 @@ CKEditor5::Rails.configure do
534
550
  end
535
551
  ```
536
552
 
553
+ Methods such as `remove`, `append`, and `prepend` can be used to modify the plugins configuration. To remove a plugin, you can use the `remove` method with the plugin name as an argument:
554
+
555
+ ```rb
556
+ # config/initializers/ckeditor5.rb
557
+
558
+ CKEditor5::Rails.configure do
559
+ # ... other configuration
560
+
561
+ plugins do
562
+ remove :Heading
563
+ end
564
+ end
565
+ ```
566
+
537
567
  #### `inline_plugin(name, code)` method
538
568
 
539
569
  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:
@@ -560,6 +590,21 @@ CKEditor5::Rails.configure do
560
590
  end
561
591
  ```
562
592
 
593
+ #### `simple_upload_adapter(url)` method
594
+
595
+ 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`:
596
+
597
+ ```rb
598
+ # config/initializers/ckeditor5.rb
599
+
600
+ CKEditor5::Rails.configure do
601
+ # ... other configuration
602
+
603
+ simple_upload_adapter
604
+ # or: simple_upload_adapter '/uploads'
605
+ end
606
+ ```
607
+
563
608
  ### Controller / View helpers 📦
564
609
 
565
610
  #### `ckeditor5_element_ref(selector)` method
@@ -578,7 +623,7 @@ CKEditor5::Rails.configure do
578
623
  end
579
624
  ```
580
625
 
581
- ### `ckeditor5_preset(&block)` method
626
+ #### `ckeditor5_preset(&block)` method
582
627
 
583
628
  The `ckeditor5_preset` method allows you to define a custom preset in your application controller. It may be useful when you want to define a preset based on the current user or request.
584
629
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module CKEditor5::Rails::Editor
4
4
  class PropsInlinePlugin
5
+ attr_reader :name, :code
6
+
5
7
  def initialize(name, code)
6
8
  @name = name
7
9
  @code = code
@@ -18,8 +20,6 @@ module CKEditor5::Rails::Editor
18
20
 
19
21
  private
20
22
 
21
- attr_reader :name, :code
22
-
23
23
  def validate_code!
24
24
  raise ArgumentError, 'Code must be a String' unless code.is_a?(String)
25
25
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module CKEditor5::Rails::Editor
4
4
  class PropsPlugin
5
+ attr_reader :name, :js_import_meta
6
+
5
7
  delegate :to_h, to: :import_meta
6
8
 
7
9
  def initialize(name, premium: false, **js_import_meta)
@@ -30,9 +32,5 @@ module CKEditor5::Rails::Editor
30
32
  meta.merge!({ type: :external })
31
33
  meta
32
34
  end
33
-
34
- private
35
-
36
- attr_reader :name, :js_import_meta
37
35
  end
38
36
  end
@@ -4,6 +4,7 @@ require 'rails/engine'
4
4
 
5
5
  require_relative 'presets/manager'
6
6
  require_relative 'hooks/form'
7
+ require_relative 'plugins/simple_upload_adapter'
7
8
 
8
9
  module CKEditor5::Rails
9
10
  class Engine < ::Rails::Engine
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5::Rails::Plugins
4
+ class SimpleUploadAdapter < CKEditor5::Rails::Editor::PropsInlinePlugin
5
+ PLUGIN_CODE = <<~JAVASCRIPT
6
+ import { Plugin, FileRepository } from 'ckeditor5';
7
+
8
+ export default class SimpleUploadAdapter extends Plugin {
9
+ static get requires() {
10
+ return [FileRepository];
11
+ }
12
+
13
+ static get pluginName() {
14
+ return 'SimpleUploadAdapter';
15
+ }
16
+
17
+ init() {
18
+ const fileRepository = this.editor.plugins.get(FileRepository);
19
+ const config = this.editor.config.get('simpleUpload');
20
+
21
+ if (!config || !config.uploadUrl) {
22
+ console.warn('Upload URL is not configured');
23
+ return;
24
+ }
25
+
26
+ fileRepository.createUploadAdapter = (loader) => ({
27
+ async upload() {
28
+ try {
29
+ const file = await loader.file;
30
+ const formData = new FormData();
31
+ formData.append('upload', file);
32
+
33
+ return new Promise((resolve, reject) => {
34
+ const xhr = new XMLHttpRequest();
35
+
36
+ xhr.open('POST', config.uploadUrl, true);
37
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
38
+
39
+ xhr.upload.onprogress = (evt) => {
40
+ if (evt.lengthComputable) {
41
+ loader.uploadTotal = evt.total;
42
+ loader.uploaded = evt.loaded;
43
+ }
44
+ };
45
+
46
+ xhr.onload = () => {
47
+ if (xhr.status >= 200 && xhr.status < 300) {
48
+ const data = JSON.parse(xhr.response);
49
+ resolve({ default: data.url });
50
+ } else {
51
+ reject(`Upload failed: ${xhr.statusText}`);
52
+ }
53
+ };
54
+
55
+ xhr.onerror = () => reject('Upload failed');
56
+ xhr.onabort = () => reject('Upload aborted');
57
+
58
+ xhr.send(formData);
59
+ this._xhr = xhr;
60
+ });
61
+ } catch (error) {
62
+ throw error;
63
+ }
64
+ },
65
+
66
+ abort() {
67
+ if (this._xhr) {
68
+ this._xhr.abort();
69
+ }
70
+ }
71
+ });
72
+ }
73
+ }
74
+ JAVASCRIPT
75
+
76
+ def initialize
77
+ super(:SimpleUpload, PLUGIN_CODE)
78
+ end
79
+ end
80
+ end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'preset_builder'
4
3
  require_relative 'toolbar_builder'
4
+ require_relative 'plugins_builder'
5
+ require_relative 'preset_builder'
5
6
 
6
7
  module CKEditor5::Rails::Presets
7
8
  class Manager
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5::Rails
4
+ class Presets::PluginsBuilder
5
+ attr_reader :plugins
6
+
7
+ def initialize(plugins)
8
+ @plugins = plugins
9
+ end
10
+
11
+ def self.create_plugin(name, **kwargs)
12
+ if name.is_a?(Editor::PropsInlinePlugin) || name.is_a?(Editor::PropsPlugin)
13
+ name
14
+ else
15
+ Editor::PropsPlugin.new(name, **kwargs)
16
+ end
17
+ end
18
+
19
+ def remove(*names)
20
+ names.each { |name| plugins.delete_if { |plugin| plugin.name == name } }
21
+ end
22
+
23
+ def prepend(*names, before: nil, **kwargs)
24
+ new_plugins = names.map { |name| self.class.create_plugin(name, **kwargs) }
25
+
26
+ if before
27
+ index = plugins.index { |p| p.name == before }
28
+ raise ArgumentError, "Plugin '#{before}' not found" unless index
29
+
30
+ plugins.insert(index, *new_plugins)
31
+ else
32
+ plugins.insert(0, *new_plugins)
33
+ end
34
+ end
35
+
36
+ def append(*names, after: nil, **kwargs)
37
+ new_plugins = names.map { |name| self.class.create_plugin(name, **kwargs) }
38
+
39
+ if after
40
+ index = plugins.index { |p| p.name == after }
41
+ raise ArgumentError, "Plugin '#{after}' not found" unless index
42
+
43
+ plugins.insert(index + 1, *new_plugins)
44
+ else
45
+ plugins.push(*new_plugins)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -24,6 +24,19 @@ module CKEditor5::Rails
24
24
  instance_eval(&block) if block_given?
25
25
  end
26
26
 
27
+ def initialize_copy(source)
28
+ super
29
+
30
+ @translations = source.translations.dup
31
+ @ckbox = source.ckbox.dup if source.ckbox
32
+ @config = {
33
+ plugins: source.config[:plugins].map(&:dup),
34
+ toolbar: deep_copy_toolbar(source.config[:toolbar])
35
+ }.merge(
36
+ source.config.except(:plugins, :toolbar).deep_dup
37
+ )
38
+ end
39
+
27
40
  def premium?
28
41
  @premium
29
42
  end
@@ -137,7 +150,7 @@ module CKEditor5::Rails
137
150
 
138
151
  return unless block
139
152
 
140
- builder = ToolbarBuilder.new(@config[:toolbar])
153
+ builder = ArrayBuilder.new(@config[:toolbar][:items])
141
154
  builder.instance_eval(&block)
142
155
  end
143
156
 
@@ -146,11 +159,21 @@ module CKEditor5::Rails
146
159
  end
147
160
 
148
161
  def plugin(name, **kwargs)
149
- @config[:plugins] << Editor::PropsPlugin.new(name, **kwargs)
162
+ plugin_obj = PluginsBuilder.create_plugin(name, **kwargs)
163
+
164
+ @config[:plugins] << plugin_obj
165
+ plugin_obj
150
166
  end
151
167
 
152
- def plugins(*names, **kwargs)
153
- names.each { |name| plugin(name, **kwargs) }
168
+ def plugins(*names, **kwargs, &block)
169
+ @config[:plugins] ||= []
170
+
171
+ names.each { |name| plugin(name, **kwargs) } unless names.empty?
172
+
173
+ return unless block
174
+
175
+ builder = PluginsBuilder.new(@config[:plugins])
176
+ builder.instance_eval(&block)
154
177
  end
155
178
 
156
179
  def language(ui = nil, content: ui) # rubocop:disable Naming/MethodParameterName
@@ -161,6 +184,27 @@ module CKEditor5::Rails
161
184
  content: content
162
185
  }
163
186
  end
187
+
188
+ def simple_upload_adapter(upload_url = '/uploads')
189
+ plugins do
190
+ remove(:Base64UploadAdapter)
191
+ end
192
+
193
+ plugin(Plugins::SimpleUploadAdapter.new)
194
+ configure(:simpleUpload, { uploadUrl: upload_url })
195
+ end
196
+
197
+ private
198
+
199
+ def deep_copy_toolbar(toolbar)
200
+ return toolbar.dup if toolbar.is_a?(Array)
201
+ return {} if toolbar.nil?
202
+
203
+ {
204
+ items: toolbar[:items].dup,
205
+ shouldNotGroupWhenFull: toolbar[:shouldNotGroupWhenFull]
206
+ }
207
+ end
164
208
  end
165
209
  end
166
210
  end
@@ -2,12 +2,10 @@
2
2
 
3
3
  module CKEditor5::Rails::Presets
4
4
  class ToolbarBuilder
5
- def initialize(toolbar_config)
6
- @toolbar_config = toolbar_config
7
- end
5
+ attr_reader :items
8
6
 
9
- def items
10
- @toolbar_config[:items]
7
+ def initialize(items)
8
+ @items = items
11
9
  end
12
10
 
13
11
  def remove(*removed_items)
@@ -17,7 +15,7 @@ module CKEditor5::Rails::Presets
17
15
  def prepend(*prepended_items, before: nil)
18
16
  if before
19
17
  index = items.index(before)
20
- raise ArgumentError, "Item '#{before}' not found in toolbar" unless index
18
+ raise ArgumentError, "Item '#{before}' not found in array" unless index
21
19
 
22
20
  items.insert(index, *prepended_items)
23
21
  else
@@ -28,7 +26,7 @@ module CKEditor5::Rails::Presets
28
26
  def append(*appended_items, after: nil)
29
27
  if after
30
28
  index = items.index(after)
31
- raise ArgumentError, "Item '#{after}' not found in toolbar" unless index
29
+ raise ArgumentError, "Item '#{after}' not found in array" unless index
32
30
 
33
31
  items.insert(index + 1, *appended_items)
34
32
  else
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CKEditor5
4
4
  module Rails
5
- VERSION = '1.12.0'
5
+ VERSION = '1.14.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ckeditor5
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 1.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Bagiński
@@ -67,7 +67,9 @@ files:
67
67
  - lib/ckeditor5/rails/helpers.rb
68
68
  - lib/ckeditor5/rails/hooks/form.rb
69
69
  - lib/ckeditor5/rails/hooks/simple_form.rb
70
+ - lib/ckeditor5/rails/plugins/simple_upload_adapter.rb
70
71
  - lib/ckeditor5/rails/presets/manager.rb
72
+ - lib/ckeditor5/rails/presets/plugins_builder.rb
71
73
  - lib/ckeditor5/rails/presets/preset_builder.rb
72
74
  - lib/ckeditor5/rails/presets/toolbar_builder.rb
73
75
  - lib/ckeditor5/rails/semver.rb