ckeditor5 1.12.0 → 1.14.1

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: 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