ckeditor5 1.26.2 → 1.27.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +65 -0
- data/lib/ckeditor5/rails/editor/helpers/config_helpers.rb +14 -0
- data/lib/ckeditor5/rails/engine.rb +1 -1
- data/lib/ckeditor5/rails/plugins/custom_translations_loader.rb +97 -0
- data/lib/ckeditor5/rails/plugins.rb +1 -0
- data/lib/ckeditor5/rails/presets/preset_builder.rb +41 -8
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/spec/e2e/features/ajax_form_integration_spec.rb +1 -1
- data/spec/e2e/features/editor_types_spec.rb +3 -3
- data/spec/e2e/features/form_integration_spec.rb +1 -1
- data/spec/lib/ckeditor5/rails/presets/preset_builder_spec.rb +56 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93b0f87e014924cf2ba04dc4d8ce96afef84152c4c8fc7bdebf5a736db864b95
|
4
|
+
data.tar.gz: 02b97648d5c94907741382795721e5944ecc0752c3b2792cfe0c7455c482f81f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 992f3a903d5bd123e91b572f0d0154c42044f90768264fe07a5c61d343431921ed3a45515f8f74ad48a68a0870876e9f73184cdc14266f4c0e43a4f393306a93
|
7
|
+
data.tar.gz: 64a1063477787141603fd850b6de704223c15b8dd6dbedcd713ea4a5ae69fb1ebf630ba1eaef9fc245a95272f4b32b40618065e04e0c69d72b8536677ef107bd
|
data/README.md
CHANGED
@@ -149,7 +149,9 @@ For extending CKEditor's functionality, refer to the [plugins directory](https:/
|
|
149
149
|
- [`simple_upload_adapter(url)` method](#simple_upload_adapterurl-method)
|
150
150
|
- [`special_characters(&block)` method](#special_charactersblock-method)
|
151
151
|
- [`wproofreader(version: nil, cdn: nil, **config)` method](#wproofreaderversion-nil-cdn-nil-config-method)
|
152
|
+
- [`custom_translations(lang_code = nil, translations = {})` method](#custom_translationslang_code--nil-translations---method)
|
152
153
|
- [Controller / View helpers 📦](#controller--view-helpers-)
|
154
|
+
- [`ckeditor5_translation_ref(key)` method](#ckeditor5_translation_refkey-method)
|
153
155
|
- [`ckeditor5_element_ref(selector)` method](#ckeditor5_element_refselector-method)
|
154
156
|
- [`ckeditor5_preset(name = nil, &block)` method](#ckeditor5_presetname--nil-block-method)
|
155
157
|
- [Including CKEditor 5 assets 📦](#including-ckeditor-5-assets-)
|
@@ -1197,8 +1199,71 @@ For more info about the WProofreader plugin, check the [official documentation](
|
|
1197
1199
|
|
1198
1200
|
</details>
|
1199
1201
|
|
1202
|
+
#### `custom_translations(lang_code = nil, translations = {})` method
|
1203
|
+
|
1204
|
+
<details>
|
1205
|
+
<summary>Define custom translations for CKEditor components and UI</summary>
|
1206
|
+
|
1207
|
+
<br />
|
1208
|
+
|
1209
|
+
Allows setting custom translations for editor components, UI elements, and headings. The translations are applied globally since they override the global translation object.
|
1210
|
+
|
1211
|
+
> [!NOTE]
|
1212
|
+
> This helper allows overriding builtin translations of the editor, but translations are overridden globally, as the CKEditor 5 uses a single translation object for all instances of the editor. It's recommended to use the `ckeditor5_translation_ref` helper to reference the translations in the configuration.
|
1213
|
+
|
1214
|
+
```rb
|
1215
|
+
# config/initializers/ckeditor5.rb
|
1216
|
+
|
1217
|
+
CKEditor5::Rails.configure do
|
1218
|
+
# ... other configuration
|
1219
|
+
|
1220
|
+
custom_translations :en, {
|
1221
|
+
'Heading 1': 'Your custom translation value'
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
configure :heading, {
|
1225
|
+
options: [
|
1226
|
+
{ model: 'heading1', title: ckeditor5_translation_ref('Heading 1') },
|
1227
|
+
# ...
|
1228
|
+
]
|
1229
|
+
}
|
1230
|
+
end
|
1231
|
+
```
|
1232
|
+
|
1233
|
+
</details>
|
1234
|
+
|
1200
1235
|
### Controller / View helpers 📦
|
1201
1236
|
|
1237
|
+
#### `ckeditor5_translation_ref(key)` method
|
1238
|
+
|
1239
|
+
<details>
|
1240
|
+
<summary>Defines a reference to a CKEditor 5 translation</summary>
|
1241
|
+
|
1242
|
+
<br />
|
1243
|
+
|
1244
|
+
Allows you to reference CKEditor 5 translations in the configuration. It's particularly useful when you want to use custom translations in the editor configuration.
|
1245
|
+
|
1246
|
+
```rb
|
1247
|
+
# config/initializers/ckeditor5.rb
|
1248
|
+
|
1249
|
+
CKEditor5::Rails.configure do
|
1250
|
+
# ... other configuration
|
1251
|
+
|
1252
|
+
custom_translations :en, {
|
1253
|
+
'Heading 1': 'Your custom translation value'
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
configure :heading, {
|
1257
|
+
options: [
|
1258
|
+
{ model: 'heading1', title: ckeditor5_translation_ref('Heading 1') },
|
1259
|
+
# ...
|
1260
|
+
]
|
1261
|
+
}
|
1262
|
+
end
|
1263
|
+
```
|
1264
|
+
|
1265
|
+
</details>
|
1266
|
+
|
1202
1267
|
#### `ckeditor5_element_ref(selector)` method
|
1203
1268
|
|
1204
1269
|
<details>
|
@@ -17,6 +17,20 @@ module CKEditor5::Rails::Editor::Helpers
|
|
17
17
|
{ '$element': selector }
|
18
18
|
end
|
19
19
|
|
20
|
+
# Creates a reference to a translation key that will be used by CKEditor.
|
21
|
+
# This helper creates a special object that CKEditor recognizes as a translation reference.
|
22
|
+
#
|
23
|
+
# @param key [String] The translation key to reference
|
24
|
+
# @return [Hash] A hash with the translation reference in CKEditor's format
|
25
|
+
#
|
26
|
+
# @example Referencing a translation in plugin configuration
|
27
|
+
# configure :toolbar, {
|
28
|
+
# placeholder: ckeditor5_translation_ref("editor.placeholder")
|
29
|
+
# }
|
30
|
+
def ckeditor5_translation_ref(key)
|
31
|
+
{ '$translation': key }
|
32
|
+
end
|
33
|
+
|
20
34
|
# Creates or retrieves a preset configuration for CKEditor.
|
21
35
|
# When called with a name, finds and returns an existing preset.
|
22
36
|
# When called with a block, creates a new preset with the given configuration.
|
@@ -78,7 +78,7 @@ module CKEditor5::Rails
|
|
78
78
|
:type, :menubar, :plugins, :plugin, :inline_plugin,
|
79
79
|
:toolbar, :block_toolbar, :balloon_toolbar,
|
80
80
|
:language, :ckbox, :configure, :automatic_upgrades, :simple_upload_adapter,
|
81
|
-
:editable_height, :wproofreader, to: :default_preset
|
81
|
+
:editable_height, :wproofreader, :custom_translations, to: :default_preset
|
82
82
|
|
83
83
|
def initialize(configuration)
|
84
84
|
@configuration = configuration
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../editor/props_inline_plugin'
|
4
|
+
|
5
|
+
module CKEditor5::Rails::Plugins
|
6
|
+
class CustomTranslationsLoader < CKEditor5::Rails::Editor::PropsInlinePlugin
|
7
|
+
def initialize(translations) # rubocop:disable Metrics/MethodLength
|
8
|
+
code = <<~JS.freeze
|
9
|
+
const { Plugin } = await import('ckeditor5');
|
10
|
+
|
11
|
+
function resolveTranslationReferences(uiLanguage, config, visited = new WeakSet()) {
|
12
|
+
if (!config || typeof config !== 'object') {
|
13
|
+
return config;
|
14
|
+
}
|
15
|
+
|
16
|
+
if (visited.has(config)) {
|
17
|
+
return config;
|
18
|
+
}
|
19
|
+
|
20
|
+
visited.add(config);
|
21
|
+
|
22
|
+
if (Array.isArray(config)) {
|
23
|
+
config.forEach((item, index) => {
|
24
|
+
config[index] = resolveTranslationReferences(uiLanguage, item, visited);
|
25
|
+
});
|
26
|
+
|
27
|
+
return config;
|
28
|
+
}
|
29
|
+
|
30
|
+
for (const key of Object.getOwnPropertyNames(config)) {
|
31
|
+
const value = config[key];
|
32
|
+
|
33
|
+
if (value && typeof value === 'object') {
|
34
|
+
if (value.$translation) {
|
35
|
+
const translationKey = value.$translation;
|
36
|
+
const translations = window.CKEDITOR_TRANSLATIONS?.[uiLanguage];
|
37
|
+
|
38
|
+
if (!translations?.dictionary[translationKey]) {
|
39
|
+
console.warn(`Translation not found for key: ${translationKey}`);
|
40
|
+
}
|
41
|
+
|
42
|
+
config[key] = translations?.dictionary[translationKey] || translationKey;
|
43
|
+
} else {
|
44
|
+
resolveTranslationReferences(uiLanguage, value, visited);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
return config;
|
50
|
+
}
|
51
|
+
|
52
|
+
return class CustomTranslationsLoader extends Plugin {
|
53
|
+
static CUSTOM_TRANSLATIONS = Object.create( #{translations.to_json} );
|
54
|
+
|
55
|
+
static get pluginName() {
|
56
|
+
return 'CustomTranslationsLoader';
|
57
|
+
}
|
58
|
+
|
59
|
+
constructor( editor ) {
|
60
|
+
super( editor );
|
61
|
+
|
62
|
+
const { locale, config } = this.editor;
|
63
|
+
|
64
|
+
this.#extendPack();
|
65
|
+
resolveTranslationReferences(locale.uiLanguage, config._config)
|
66
|
+
}
|
67
|
+
|
68
|
+
#extendPack() {
|
69
|
+
const { uiLanguage } = this.editor.locale;
|
70
|
+
const translations = this.#translations;
|
71
|
+
|
72
|
+
if (!window.CKEDITOR_TRANSLATIONS) {
|
73
|
+
window.CKEDITOR_TRANSLATIONS = {};
|
74
|
+
}
|
75
|
+
|
76
|
+
if (!window.CKEDITOR_TRANSLATIONS[uiLanguage]) {
|
77
|
+
window.CKEDITOR_TRANSLATIONS[uiLanguage] = { dictionary: {} };
|
78
|
+
}
|
79
|
+
|
80
|
+
Object.entries(translations).forEach(([key, value]) => {
|
81
|
+
window.CKEDITOR_TRANSLATIONS[uiLanguage].dictionary[key] = value;
|
82
|
+
});
|
83
|
+
}
|
84
|
+
|
85
|
+
get #translations() {
|
86
|
+
const { uiLanguage } = this.editor.locale;
|
87
|
+
|
88
|
+
return CustomTranslationsLoader.CUSTOM_TRANSLATIONS[uiLanguage];
|
89
|
+
}
|
90
|
+
}
|
91
|
+
JS
|
92
|
+
|
93
|
+
super(:CustomTranslationsLoader, code)
|
94
|
+
compress!
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -9,6 +9,7 @@ end
|
|
9
9
|
require_relative 'plugins/simple_upload_adapter'
|
10
10
|
require_relative 'plugins/wproofreader'
|
11
11
|
require_relative 'plugins/special_characters_bootstrap'
|
12
|
+
require_relative 'plugins/custom_translations_loader'
|
12
13
|
|
13
14
|
# Plugin patches and fixes
|
14
15
|
require_relative 'plugins/patches/fix_color_picker_race_condition'
|
@@ -6,7 +6,7 @@ require_relative 'special_characters_builder'
|
|
6
6
|
|
7
7
|
module CKEditor5::Rails
|
8
8
|
module Presets
|
9
|
-
class PresetBuilder
|
9
|
+
class PresetBuilder # rubocop:disable Metrics/ClassLength
|
10
10
|
include Editor::Helpers::Config
|
11
11
|
include Concerns::ConfigurationMethods
|
12
12
|
include Concerns::PluginMethods
|
@@ -27,6 +27,7 @@ module CKEditor5::Rails
|
|
27
27
|
@ckbox = nil
|
28
28
|
@editable_height = nil
|
29
29
|
@automatic_upgrades = false
|
30
|
+
@custom_translations = {}
|
30
31
|
@config = {
|
31
32
|
plugins: [],
|
32
33
|
toolbar: []
|
@@ -35,6 +36,12 @@ module CKEditor5::Rails
|
|
35
36
|
instance_eval(&block) if block_given?
|
36
37
|
end
|
37
38
|
|
39
|
+
def deconstruct_keys(keys)
|
40
|
+
keys.index_with do |key|
|
41
|
+
public_send(key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
38
45
|
# @example Copy preset and modify it
|
39
46
|
# original = PresetBuilder.new
|
40
47
|
# copied = original.initialize_copy(original)
|
@@ -43,6 +50,7 @@ module CKEditor5::Rails
|
|
43
50
|
|
44
51
|
@translations = source.translations.dup
|
45
52
|
@ckbox = source.ckbox.dup if source.ckbox
|
53
|
+
@custom_translations = source.custom_translations.deep_dup
|
46
54
|
@config = {
|
47
55
|
plugins: source.config[:plugins].map(&:dup),
|
48
56
|
toolbar: deep_copy_toolbar(source.config[:toolbar])
|
@@ -63,12 +71,6 @@ module CKEditor5::Rails
|
|
63
71
|
license_key == 'GPL'
|
64
72
|
end
|
65
73
|
|
66
|
-
def deconstruct_keys(keys)
|
67
|
-
keys.index_with do |key|
|
68
|
-
public_send(key)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
74
|
# Create a new preset by overriding current configuration
|
73
75
|
# @example Override existing preset
|
74
76
|
# preset.override do
|
@@ -199,7 +201,7 @@ module CKEditor5::Rails
|
|
199
201
|
# Apply integration patches for the current version
|
200
202
|
# @return [void]
|
201
203
|
def apply_integration_patches
|
202
|
-
patch_plugin
|
204
|
+
patch_plugin(Plugins::Patches::FixColorPickerRaceCondition.new)
|
203
205
|
end
|
204
206
|
|
205
207
|
# Enable or disable automatic version upgrades
|
@@ -333,6 +335,37 @@ module CKEditor5::Rails
|
|
333
335
|
config[:language].present?
|
334
336
|
end
|
335
337
|
|
338
|
+
# Configure custom translations for the editor
|
339
|
+
# @param lang_code [Symbol] Language code for translations (e.g. :en, :pl)
|
340
|
+
# @param translations [Hash] A hash containing translations in format { key => translation }
|
341
|
+
# @example Add multiple translations
|
342
|
+
# custom_translations :en, {
|
343
|
+
# 'my.button': 'My Button'
|
344
|
+
# }
|
345
|
+
# custom_translations :pl, {
|
346
|
+
# 'my.button': 'Mój przycisk'
|
347
|
+
# }
|
348
|
+
# @example Use translations in configuration with ckeditor5_translation_ref
|
349
|
+
# custom_translations :en, {
|
350
|
+
# 'custom.heading': 'Custom Section'
|
351
|
+
# }
|
352
|
+
#
|
353
|
+
# configure :heading, {
|
354
|
+
# options: [
|
355
|
+
# { model: 'heading1', title: ckeditor5_translation_ref('custom.heading') }
|
356
|
+
# ]
|
357
|
+
# }
|
358
|
+
# @return [void]
|
359
|
+
def custom_translations(lang_code = nil, translations = {})
|
360
|
+
return @custom_translations if lang_code.blank?
|
361
|
+
|
362
|
+
@custom_translations[lang_code.to_sym] ||= {}
|
363
|
+
@custom_translations[lang_code.to_sym].merge!(translations)
|
364
|
+
|
365
|
+
plugins.remove(:CustomTranslationsLoader)
|
366
|
+
plugins.prepend(Plugins::CustomTranslationsLoader.new(@custom_translations))
|
367
|
+
end
|
368
|
+
|
336
369
|
# Configure editor language
|
337
370
|
# @param ui [Symbol, nil] UI language code
|
338
371
|
# @param content [Symbol] Content language code
|
@@ -8,7 +8,7 @@ RSpec.describe 'AJAX Form Integration', type: :feature, js: true do
|
|
8
8
|
setup_form_tracking(page)
|
9
9
|
end
|
10
10
|
|
11
|
-
shared_examples 'an ajax form with CKEditor' do |form_testid, editor_testid, submit_testid, response_id|
|
11
|
+
shared_examples 'an ajax form with CKEditor' do |form_testid, editor_testid, submit_testid, response_id|
|
12
12
|
let(:form) { find("[data-testid='#{form_testid}']") }
|
13
13
|
let(:editor) { find("[data-testid='#{editor_testid}']") }
|
14
14
|
let(:editable) { editor.find('.ck-editor__editable') }
|
@@ -44,10 +44,10 @@ RSpec.describe 'CKEditor5 Types Integration', type: :feature, js: true do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
shared_examples 'a multiroot editor that fires change events' do |path, editables|
|
47
|
+
shared_examples 'a multiroot editor that fires change events' do |path, editables|
|
48
48
|
before { visit path }
|
49
49
|
|
50
|
-
it 'sends properly change events with proper payload for editables' do
|
50
|
+
it 'sends properly change events with proper payload for editables' do
|
51
51
|
editors = editables.map do |name|
|
52
52
|
find("[data-testid='#{name}-editable']")
|
53
53
|
end
|
@@ -151,7 +151,7 @@ RSpec.describe 'CKEditor5 Types Integration', type: :feature, js: true do
|
|
151
151
|
expect(page).to have_css('.ck-toolbar', count: 1)
|
152
152
|
end
|
153
153
|
|
154
|
-
it 'handles dynamically added editables' do
|
154
|
+
it 'handles dynamically added editables' do
|
155
155
|
# Set up event listener
|
156
156
|
page.execute_script(<<~JS)
|
157
157
|
window._newEditableEvents = [];
|
@@ -8,7 +8,7 @@ RSpec.describe 'Form Integration', type: :feature, js: true do
|
|
8
8
|
setup_form_tracking(page)
|
9
9
|
end
|
10
10
|
|
11
|
-
shared_examples 'a form with CKEditor' do |form_testid, editor_testid, submit_testid|
|
11
|
+
shared_examples 'a form with CKEditor' do |form_testid, editor_testid, submit_testid|
|
12
12
|
let(:form) { find("[data-testid='#{form_testid}']") }
|
13
13
|
let(:editor) { find("[data-testid='#{editor_testid}']") }
|
14
14
|
let(:editable) { editor.find('.ck-editor__editable') }
|
@@ -494,6 +494,61 @@ RSpec.describe CKEditor5::Rails::Presets::PresetBuilder do
|
|
494
494
|
end
|
495
495
|
end
|
496
496
|
|
497
|
+
describe '#custom_translations' do
|
498
|
+
it 'returns empty hash when called without arguments' do
|
499
|
+
expect(builder.custom_translations).to eq({})
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'stores translations for a language' do
|
503
|
+
translations = { 'my.button': 'My Button' }
|
504
|
+
builder.custom_translations(:en, translations)
|
505
|
+
expect(builder.custom_translations).to eq({ en: translations })
|
506
|
+
end
|
507
|
+
|
508
|
+
it 'merges translations for the same language' do
|
509
|
+
builder.custom_translations(:en, { 'button.one': 'One' })
|
510
|
+
builder.custom_translations(:en, { 'button.two': 'Two' })
|
511
|
+
|
512
|
+
expect(builder.custom_translations[:en]).to eq({
|
513
|
+
'button.one': 'One',
|
514
|
+
'button.two': 'Two'
|
515
|
+
})
|
516
|
+
end
|
517
|
+
|
518
|
+
it 'handles multiple languages' do
|
519
|
+
builder.custom_translations(:en, { 'button': 'Button' })
|
520
|
+
builder.custom_translations(:pl, { 'button': 'Przycisk' })
|
521
|
+
|
522
|
+
expect(builder.custom_translations).to eq({
|
523
|
+
en: { button: 'Button' },
|
524
|
+
pl: { button: 'Przycisk' }
|
525
|
+
})
|
526
|
+
end
|
527
|
+
|
528
|
+
it 'normalizes language codes to symbols' do
|
529
|
+
builder.custom_translations('EN', { 'button': 'Button' })
|
530
|
+
expect(builder.custom_translations.keys).to eq([:EN])
|
531
|
+
end
|
532
|
+
|
533
|
+
it 'adds and replaces CustomTranslationsLoader plugin' do
|
534
|
+
translations = { 'my.button': 'My Button' }
|
535
|
+
|
536
|
+
expect do
|
537
|
+
builder.custom_translations(:en, translations)
|
538
|
+
end.to change { builder.config[:plugins].count }.by(1)
|
539
|
+
|
540
|
+
plugin = builder.config[:plugins].first
|
541
|
+
expect(plugin).to be_a(CKEditor5::Rails::Plugins::CustomTranslationsLoader)
|
542
|
+
|
543
|
+
# Adding more translations should replace the plugin
|
544
|
+
expect do
|
545
|
+
builder.custom_translations(:pl, { 'my.button': 'Mój przycisk' })
|
546
|
+
end.not_to(change { builder.config[:plugins].count })
|
547
|
+
|
548
|
+
expect(builder.config[:plugins].first).to be_a(CKEditor5::Rails::Plugins::CustomTranslationsLoader)
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
497
552
|
describe '#deep_copy_toolbar' do
|
498
553
|
context 'with array toolbar' do
|
499
554
|
it 'returns duplicated array' do
|
@@ -552,7 +607,7 @@ RSpec.describe CKEditor5::Rails::Presets::PresetBuilder do
|
|
552
607
|
expect { builder.special_characters }.not_to raise_error
|
553
608
|
end
|
554
609
|
|
555
|
-
it 'configures special characters with groups and items' do
|
610
|
+
it 'configures special characters with groups and items' do
|
556
611
|
builder.special_characters do
|
557
612
|
group 'Emoji', label: 'Emoticons' do
|
558
613
|
item 'smiley', '😊'
|
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.
|
4
|
+
version: 1.27.0
|
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: 2025-02-
|
12
|
+
date: 2025-02-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- lib/ckeditor5/rails/hooks/importmap.rb
|
91
91
|
- lib/ckeditor5/rails/hooks/simple_form.rb
|
92
92
|
- lib/ckeditor5/rails/plugins.rb
|
93
|
+
- lib/ckeditor5/rails/plugins/custom_translations_loader.rb
|
93
94
|
- lib/ckeditor5/rails/plugins/patches/fix_color_picker_race_condition.rb
|
94
95
|
- lib/ckeditor5/rails/plugins/simple_upload_adapter.rb
|
95
96
|
- lib/ckeditor5/rails/plugins/special_characters_bootstrap.rb
|