ckeditor5 1.14.1 → 1.15.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: a2d481ae5f7ed4d671e8d6ade94e9efa0ab5d0b4bba36f24b8052d84eadd21e9
4
- data.tar.gz: 3d8ff1d8a23aadc4398e2439996d9a86aa792eec16e33a70837e731e68f6ba9f
3
+ metadata.gz: a7d0dce96ea4b299699c42c1567c3f101a257c465a0e93b8856847fff94c6062
4
+ data.tar.gz: 9ca6f4faa82bc9f62efa91b65634b8b9a037ce7fda0bf99507cefc87fca8348b
5
5
  SHA512:
6
- metadata.gz: a407f380c8f2295959533cd08966aace68f1d9d20208608a16269921ae167ba450e719663d918ff725ee10f0be6d020c2130d50873b51cc726b00bf4fa55b573
7
- data.tar.gz: 37f51f50d80ce4e51aeed85188b7bf48963723b0b1cf004bc6faceb5ec561c85c79d00887ca50ce4fe2ed702468677718b35c7cdaceb7af9db10fed5ce088381
6
+ metadata.gz: c484342136c54b500b98e3615647f8c9c92c403d4af5569cadc910a520250f7767ccf020f9d697853fce9a9ae67a4bfa7dedb883b0691a6008f65b3b04c93190
7
+ data.tar.gz: f98cb8faacebed0f36ffda4a8523443f4307b138b20136e670ee9dc7894bd91d9889c9acc14f0abe736c34c7339d1ff664b9332f8cf22555348c8094cfa7b592
data/README.md CHANGED
@@ -28,7 +28,12 @@ In your config (the default config is defined [here](https://github.com/Mati365/
28
28
  # config/initializers/ckeditor5.rb
29
29
 
30
30
  CKEditor5::Rails.configure do
31
- version '43.3.0'
31
+ version '43.3.0' # 🔖 Specify the version of editor you want.
32
+ # ⚙️ Configuration includes:
33
+ # 📝 Classic editor build
34
+ # 🧩 Essential plugins (paragraphs, basic styles)
35
+ # 🎛️ Default toolbar layout
36
+ # 📜 GPL license
32
37
  end
33
38
  ```
34
39
 
@@ -54,38 +59,43 @@ In your view:
54
59
  <!-- app/views/demos/index.html.erb -->
55
60
 
56
61
  <% content_for :head do %>
62
+ <!-- 📦 Loads CKEditor assets via importmap based on initializer config -->
57
63
  <%= ckeditor5_assets %>
58
64
  <% end %>
59
65
 
66
+ <!-- 🖋️ Renders rich text editor interface using WebComponent -->
60
67
  <%= ckeditor5_editor %>
61
68
  ```
62
69
 
63
70
  Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
64
71
 
65
- ## Demos 🚀
72
+ ## Try Our Demos! 🎮 ✨
66
73
 
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).
74
+ 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! 💡
68
75
 
69
- In order to run all demos locally, you can clone the repository and run the following commands:
76
+ Ready to play with the demos locally? It's super easy! Just follow these steps: 🚀
70
77
 
71
78
  ```bash
72
- bundle install
73
- cd sandbox
74
- bundle exec rails server -p 3000
79
+ bundle install # Install all the goodies 📦
80
+ bundle exec guard -g rails # Fire up the server 🔥
75
81
  ```
76
82
 
77
- Then visit [http://localhost:3000/demos](http://localhost:3000/) to see the demos in action. 🚀
83
+ 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! 🎨
84
+
85
+ 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! ⭐
78
86
 
79
87
  ## Table of Contents 📚
80
88
 
81
89
  - [CKEditor 5 Rails Integration ✨](#ckeditor-5-rails-integration-)
82
90
  - [Installation 🛠️](#installation-️)
83
- - [Demos 🚀](#demos-)
91
+ - [Try Our Demos! 🎮 ✨](#try-our-demos--)
84
92
  - [Table of Contents 📚](#table-of-contents-)
85
93
  - [Presets 🎨](#presets-)
94
+ - [Automatic upgrades 🔄](#automatic-upgrades-)
86
95
  - [Available Configuration Methods ⚙️](#available-configuration-methods-️)
87
96
  - [`cdn(cdn = nil, &block)` method](#cdncdn--nil-block-method)
88
97
  - [`version(version)` method](#versionversion-method)
98
+ - [`automatic_upgrades(enabled: true)` method](#automatic_upgradesenabled-true-method)
89
99
  - [`gpl` method](#gpl-method)
90
100
  - [`license_key(key)` method](#license_keykey-method)
91
101
  - [`premium` method](#premium-method)
@@ -164,6 +174,11 @@ CKEditor5::Rails.configure do
164
174
  presets.define :blank_preset, inherit: false do
165
175
  version '44.0.0'
166
176
 
177
+ # It tells the integration to fetch the newest security patches and bug fixes.
178
+ # It may be disabled, but it's highly recommended to keep it enabled to avoid
179
+ # potential security issues.
180
+ automatic_upgrades
181
+
167
182
  gpl
168
183
  type :classic
169
184
 
@@ -208,6 +223,22 @@ end
208
223
 
209
224
  Configuration of the editor can be complex, and it's recommended to use the [CKEditor 5 online builder](https://ckeditor.com/ckeditor-5/online-builder/) to generate the configuration. It allows you to select the features you want to include and generate the configuration code in JavaScript format. Keep in mind that you need to convert the JavaScript configuration to Ruby format before using it in this gem.
210
225
 
226
+ ### Automatic upgrades 🔄
227
+
228
+ The gem includes a feature that automatically upgrades the CKEditor&nbsp;5 version when it's released. It's enabled by default for the `:default` preset. It means that the editor will automatically check the version of the editor during the initialization and upgrade it to the latest version if the new patch or minor version is released.
229
+
230
+ If you want to disable automatic upgrades, you can pass the `enabled: false` keyword argument to the `automatic_upgrades` method.
231
+
232
+ ```rb
233
+ # config/initializers/ckeditor5.rb
234
+
235
+ CKEditor5::Rails.configure do
236
+ # ... other configuration
237
+
238
+ automatic_upgrades enabled: false
239
+ end
240
+ ```
241
+
211
242
  ### Available Configuration Methods ⚙️
212
243
 
213
244
  #### `cdn(cdn = nil, &block)` method
@@ -254,6 +285,24 @@ CKEditor5::Rails.configure do
254
285
  end
255
286
  ```
256
287
 
288
+ #### `automatic_upgrades(enabled: true)` method
289
+
290
+ Defines if automatic upgrades should be enabled. It's enabled for the `:default` preset by default. The example below shows how to disable automatic upgrades:
291
+
292
+ ```rb
293
+ # config/initializers/ckeditor5.rb
294
+
295
+ CKEditor5::Rails.configure do
296
+ # ... other configuration
297
+
298
+ automatic_upgrades enabled: false
299
+ end
300
+ ```
301
+
302
+ It means that the editor will automatically upgrade to the latest version when the gem is updated. It'll upgrade the editor only if the new patch or minor version is released. If you want to disable automatic upgrades, you can pass the `enabled: false` keyword argument to the `automatic_upgrades` method.
303
+
304
+ Version is checked every nth day, where n is the number of days since the last check. Currently it's 4 days.
305
+
257
306
  #### `gpl` method
258
307
 
259
308
  Defines the license of CKEditor 5. The example below shows how to set the license to GPL:
@@ -76,6 +76,12 @@ module CKEditor5::Rails
76
76
  editor_config = config || preset.config
77
77
  editor_config = editor_config.deep_merge(extra_config)
78
78
  editor_config[:initialData] = initial_data if initial_data
79
+
80
+ if preset.automatic_upgrades? && editor_config[:version].present?
81
+ detected_version = VersionDetector.latest_safe_version(editor_config[:version])
82
+ editor_config[:version] = detected_version if detected_version
83
+ end
84
+
79
85
  editor_config
80
86
  end
81
87
 
@@ -36,6 +36,13 @@ module CKEditor5::Rails::Plugins
36
36
  xhr.open('POST', config.uploadUrl, true);
37
37
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
38
38
 
39
+ // Add CSRF token from meta tag
40
+ const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
41
+
42
+ if (csrfToken) {
43
+ xhr.setRequestHeader('X-CSRF-Token', csrfToken);
44
+ }
45
+
39
46
  xhr.upload.onprogress = (evt) => {
40
47
  if (evt.lengthComputable) {
41
48
  loader.uploadTotal = evt.total;
@@ -42,6 +42,7 @@ module CKEditor5::Rails::Presets
42
42
 
43
43
  def define_default_preset # rubocop:disable Metrics/MethodLength
44
44
  define :default do
45
+ automatic_upgrades
45
46
  gpl
46
47
  type :classic
47
48
  menubar
@@ -16,6 +16,7 @@ module CKEditor5::Rails
16
16
  @type = :classic
17
17
  @ckbox = nil
18
18
  @editable_height = nil
19
+ @automatic_upgrades = false
19
20
  @config = {
20
21
  plugins: [],
21
22
  toolbar: []
@@ -105,7 +106,20 @@ module CKEditor5::Rails
105
106
  def version(version = nil)
106
107
  return @version.to_s if version.nil?
107
108
 
108
- @version = Semver.new(version)
109
+ if @automatic_upgrades && version
110
+ detected = VersionDetector.latest_safe_version(version)
111
+ @version = Semver.new(detected || version)
112
+ else
113
+ @version = Semver.new(version)
114
+ end
115
+ end
116
+
117
+ def automatic_upgrades(enabled: true)
118
+ @automatic_upgrades = enabled
119
+ end
120
+
121
+ def automatic_upgrades?
122
+ @automatic_upgrades
109
123
  end
110
124
 
111
125
  def cdn(cdn = nil, &block)
@@ -1,18 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CKEditor5::Rails::Semver
4
- attr_reader :version
3
+ module CKEditor5
4
+ module Rails
5
+ class Semver
6
+ SEMVER_PATTERN = /\A\d+\.\d+\.\d+\z/
5
7
 
6
- alias to_s :version
8
+ attr_reader :major, :minor, :patch
7
9
 
8
- def initialize(version)
9
- @version = version.to_s
10
- validate!
11
- end
10
+ include Comparable
11
+
12
+ def initialize(version_string)
13
+ validate!(version_string)
14
+ @major, @minor, @patch = version_string.split('.').map(&:to_i)
15
+ end
16
+
17
+ def <=>(other)
18
+ return nil unless other.is_a?(Semver)
19
+
20
+ [major, minor, patch] <=> [other.major, other.minor, other.patch]
21
+ end
22
+
23
+ def safe_update?(other_version)
24
+ other = self.class.new(other_version)
25
+
26
+ return false if other.major != major
27
+ return true if other.minor > minor
28
+ return true if other.minor == minor && other.patch > patch
29
+
30
+ false
31
+ end
32
+
33
+ def version
34
+ "#{major}.#{minor}.#{patch}"
35
+ end
36
+
37
+ alias to_s :version
38
+
39
+ private
12
40
 
13
- private
41
+ def validate!(version_string)
42
+ return if version_string.is_a?(String) && version_string.match?(SEMVER_PATTERN)
14
43
 
15
- def validate!
16
- raise ArgumentError, 'invalid version format' unless version.match?(/\A\d+\.\d+\.\d+\z/)
44
+ raise ArgumentError, 'invalid version format'
45
+ end
46
+ end
17
47
  end
18
48
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CKEditor5
4
4
  module Rails
5
- VERSION = '1.14.1'
5
+ VERSION = '1.15.1'
6
6
  end
7
7
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'json'
5
+ require 'singleton'
6
+ require 'monitor'
7
+ require_relative 'semver'
8
+
9
+ module CKEditor5::Rails
10
+ class VersionDetector
11
+ include Singleton
12
+
13
+ NPM_PACKAGE = 'ckeditor5'
14
+ CACHE_DURATION = 345_600 # 4 days in seconds
15
+
16
+ class << self
17
+ delegate :latest_safe_version, to: :instance
18
+ end
19
+
20
+ def initialize
21
+ @cache = {}
22
+ @monitor = Monitor.new
23
+ end
24
+
25
+ def latest_safe_version(current_version)
26
+ @monitor.synchronize do
27
+ cache_key = "#{current_version}_latest"
28
+ return @cache[cache_key][:version] if valid_cache_entry?(cache_key)
29
+
30
+ version = find_latest_safe_version(current_version)
31
+ @cache[cache_key] = { version: version, timestamp: Time.now.to_i }
32
+ version
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def valid_cache_entry?(key)
39
+ entry = @cache[key]
40
+ entry && (Time.now.to_i - entry[:timestamp] < CACHE_DURATION)
41
+ end
42
+
43
+ def find_latest_safe_version(current_version)
44
+ versions = fetch_all_versions
45
+ return nil if versions.empty?
46
+
47
+ current_semver = Semver.new(current_version)
48
+ versions
49
+ .reject { |v| v.include?('nightly') || v.include?('dev') }
50
+ .select { |v| v.match?(Semver::SEMVER_PATTERN) }
51
+ .sort_by { |v| Semver.new(v) }
52
+ .reverse
53
+ .find { |v| current_semver.safe_update?(v) }
54
+ end
55
+
56
+ def fetch_all_versions
57
+ uri = URI("https://registry.npmjs.org/#{NPM_PACKAGE}")
58
+ response = fetch_with_timeout(uri)
59
+
60
+ if response.is_a?(Net::HTTPSuccess)
61
+ data = JSON.parse(response.body)
62
+ data['versions'].keys
63
+ else
64
+ warn 'Failed to fetch CKEditor versions'
65
+ []
66
+ end
67
+ rescue StandardError => e
68
+ warn "Error fetching versions: #{e.message}"
69
+ []
70
+ end
71
+
72
+ def fetch_with_timeout(uri)
73
+ http = Net::HTTP.new(uri.host, uri.port)
74
+ http.use_ssl = (uri.scheme == 'https')
75
+ http.open_timeout = 1
76
+ http.read_timeout = 1
77
+ http.get(uri.request_uri)
78
+ end
79
+ end
80
+ end
@@ -3,6 +3,7 @@
3
3
  module CKEditor5
4
4
  module Rails
5
5
  require_relative 'rails/version'
6
+ require_relative 'rails/version_detector'
6
7
  require_relative 'rails/semver'
7
8
  require_relative 'rails/assets/assets_bundle'
8
9
  require_relative 'rails/assets/assets_bundle_html_serializer'
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.14.1
4
+ version: 1.15.1
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-20 00:00:00.000000000 Z
12
+ date: 2024-11-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -74,6 +74,7 @@ files:
74
74
  - lib/ckeditor5/rails/presets/toolbar_builder.rb
75
75
  - lib/ckeditor5/rails/semver.rb
76
76
  - lib/ckeditor5/rails/version.rb
77
+ - lib/ckeditor5/rails/version_detector.rb
77
78
  - spec/lib/ckeditor5/rails/cdn/url_generator_spec.rb
78
79
  - spec/lib/ckeditor5/rails/semver_spec.rb
79
80
  - spec/spec_helper.rb