ckeditor5 1.23.3 → 1.23.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ckeditor5/rails/assets/assets_bundle_html_serializer.rb +36 -17
- data/lib/ckeditor5/rails/assets/webcomponent_bundle.rb +32 -48
- data/lib/ckeditor5/rails/assets/webcomponents/components/editor.mjs +2 -6
- data/lib/ckeditor5/rails/assets/webcomponents/utils.mjs +1 -21
- data/lib/ckeditor5/rails/cdn/helpers.rb +5 -6
- data/lib/ckeditor5/rails/context/helpers.rb +2 -2
- data/lib/ckeditor5/rails/context/preset_builder.rb +1 -2
- data/lib/ckeditor5/rails/editor/helpers/editor_helpers.rb +4 -8
- data/lib/ckeditor5/rails/editor/props.rb +1 -1
- data/lib/ckeditor5/rails/editor/props_inline_plugin.rb +0 -29
- data/lib/ckeditor5/rails/hooks/importmap.rb +1 -0
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/spec/lib/ckeditor5/rails/assets/assets_bundle_hml_serializer_spec.rb +2 -2
- data/spec/lib/ckeditor5/rails/cdn/helpers_spec.rb +4 -0
- data/spec/lib/ckeditor5/rails/context/helpers_spec.rb +0 -13
- data/spec/lib/ckeditor5/rails/editor/helpers/editor_helpers_spec.rb +0 -50
- data/spec/lib/ckeditor5/rails/hooks/form_spec.rb +19 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f7600884a50bcb68e1f98db4063a3d885f9fbd4aa62b8ac6a793b8c5c4bc4af
|
4
|
+
data.tar.gz: e6a4f58340359d0c6c84fbd3e6aed0ce7bfe6cab733dc70b8e6640ed399cee3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 448bd74e867966489554bf08eb40ef2b43069ad9f2fd884aadbae94295b5fc819bdc20deceb037bcda3ed73e57c74754bc860b39ceb45ee43f5938e2a1bc457c
|
7
|
+
data.tar.gz: d0560e88dacdce2e9f73f2001f701077a67bf6724cbc008c844ff458e71c556b9e0c7e14406cd06b16f4fc8b322bf53cc38094b188dc08995b658674e0cd6c10
|
@@ -19,13 +19,24 @@ module CKEditor5::Rails::Assets
|
|
19
19
|
@lazy = lazy
|
20
20
|
end
|
21
21
|
|
22
|
-
def to_html
|
22
|
+
def to_html(nonce: nil)
|
23
23
|
tags = [
|
24
|
-
WebComponentBundle.instance.to_html
|
24
|
+
WebComponentBundle.instance.to_html(nonce: nonce)
|
25
25
|
]
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
unless lazy
|
28
|
+
tags.prepend(
|
29
|
+
preload_tags(nonce: nonce),
|
30
|
+
styles_tags(nonce: nonce),
|
31
|
+
window_scripts_tags(nonce: nonce)
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
if importmap
|
36
|
+
tags.prepend(
|
37
|
+
AssetsImportMap.new(bundle).to_html(nonce: nonce)
|
38
|
+
)
|
39
|
+
end
|
29
40
|
|
30
41
|
safe_join(tags)
|
31
42
|
end
|
@@ -40,34 +51,42 @@ module CKEditor5::Rails::Assets
|
|
40
51
|
|
41
52
|
private
|
42
53
|
|
43
|
-
def window_scripts_tags
|
44
|
-
|
45
|
-
tag.script(src: script.url, nonce:
|
46
|
-
end
|
54
|
+
def window_scripts_tags(nonce: nil)
|
55
|
+
scripts = bundle.scripts.filter_map do |script|
|
56
|
+
tag.script(src: script.url, nonce: nonce, crossorigin: 'anonymous') if script.window?
|
57
|
+
end
|
58
|
+
|
59
|
+
safe_join(scripts)
|
47
60
|
end
|
48
61
|
|
49
|
-
def styles_tags
|
50
|
-
|
51
|
-
tag.link(href: url, rel: 'stylesheet', crossorigin: 'anonymous')
|
52
|
-
end
|
62
|
+
def styles_tags(nonce: nil)
|
63
|
+
styles = bundle.stylesheets.map do |url|
|
64
|
+
tag.link(href: url, nonce: nonce, rel: 'stylesheet', crossorigin: 'anonymous')
|
65
|
+
end
|
66
|
+
|
67
|
+
safe_join(styles)
|
53
68
|
end
|
54
69
|
|
55
|
-
def preload_tags
|
56
|
-
|
70
|
+
def preload_tags(nonce: nil)
|
71
|
+
preloads = bundle.preloads.map do |preload|
|
57
72
|
if preload.is_a?(Hash) && preload[:as] && preload[:href]
|
58
73
|
tag.link(
|
59
74
|
**preload,
|
75
|
+
nonce: nonce,
|
60
76
|
crossorigin: 'anonymous'
|
61
77
|
)
|
62
78
|
else
|
63
79
|
tag.link(
|
64
80
|
href: preload,
|
65
81
|
rel: 'preload',
|
82
|
+
nonce: nonce,
|
66
83
|
as: self.class.url_resource_preload_type(preload),
|
67
84
|
crossorigin: 'anonymous'
|
68
85
|
)
|
69
86
|
end
|
70
|
-
end
|
87
|
+
end
|
88
|
+
|
89
|
+
safe_join(preloads)
|
71
90
|
end
|
72
91
|
end
|
73
92
|
|
@@ -90,11 +109,11 @@ module CKEditor5::Rails::Assets
|
|
90
109
|
{ imports: import_map }.to_json
|
91
110
|
end
|
92
111
|
|
93
|
-
def to_html
|
112
|
+
def to_html(nonce: nil)
|
94
113
|
tag.script(
|
95
114
|
to_json.html_safe,
|
96
115
|
type: 'importmap',
|
97
|
-
nonce:
|
116
|
+
nonce: nonce
|
98
117
|
)
|
99
118
|
end
|
100
119
|
|
@@ -3,54 +3,38 @@
|
|
3
3
|
require 'singleton'
|
4
4
|
require 'terser'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
inject_inline_code_signatures(content)
|
39
|
-
else
|
40
|
-
content
|
41
|
-
end
|
42
|
-
end.join("\n")
|
43
|
-
end
|
44
|
-
|
45
|
-
def inject_inline_code_signatures(content)
|
46
|
-
json_signatures = Editor::InlinePluginsSignaturesRegistry.instance.to_a.to_json
|
47
|
-
|
48
|
-
content.sub('__INLINE_CODE_SIGNATURES_PLACEHOLDER__', json_signatures)
|
49
|
-
end
|
50
|
-
|
51
|
-
def compress_source(code)
|
52
|
-
Terser.new(compress: true, mangle: true).compile(code).html_safe
|
53
|
-
end
|
6
|
+
module CKEditor5::Rails::Assets
|
7
|
+
class WebComponentBundle
|
8
|
+
include ActionView::Helpers::TagHelper
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
WEBCOMPONENTS_PATH = File.join(__dir__, 'webcomponents')
|
12
|
+
WEBCOMPONENTS_MODULES = [
|
13
|
+
'utils.mjs',
|
14
|
+
'components/editable.mjs',
|
15
|
+
'components/ui-part.mjs',
|
16
|
+
'components/editor.mjs',
|
17
|
+
'components/context.mjs'
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def source
|
21
|
+
@source ||= compress_source(raw_source)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_html(nonce: nil)
|
25
|
+
tag.script(source, type: 'module', nonce: nonce)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def raw_source
|
31
|
+
@raw_source ||= WEBCOMPONENTS_MODULES.map do |file|
|
32
|
+
File.read(File.join(WEBCOMPONENTS_PATH, file))
|
33
|
+
end.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def compress_source(code)
|
37
|
+
Terser.new(compress: true, mangle: true).compile(code).html_safe
|
54
38
|
end
|
55
39
|
end
|
56
40
|
end
|
@@ -568,14 +568,10 @@ class CKEditorComponent extends HTMLElement {
|
|
568
568
|
}
|
569
569
|
|
570
570
|
/**
|
571
|
-
* Gets bundle JSON description from translations attribute
|
572
|
-
*
|
573
|
-
* **warning**: It's present only if the editor is loaded lazily.
|
571
|
+
* Gets bundle JSON description from translations attribute
|
574
572
|
*/
|
575
573
|
#getBundle() {
|
576
|
-
return this.#bundle ||= JSON.parse(
|
577
|
-
this.getAttribute('bundle') || '{ "scripts": [], "stylesheets": [] }'
|
578
|
-
);
|
574
|
+
return this.#bundle ||= JSON.parse(this.getAttribute('bundle'));
|
579
575
|
}
|
580
576
|
|
581
577
|
|
@@ -20,22 +20,6 @@ function execIfDOMReady(callback) {
|
|
20
20
|
}
|
21
21
|
}
|
22
22
|
|
23
|
-
/**
|
24
|
-
* Verifies code signature using SHA-256 hash.
|
25
|
-
*
|
26
|
-
* @param {string} code - Source code to verify
|
27
|
-
* @returns {Promise<boolean>} True if code signature is valid
|
28
|
-
*/
|
29
|
-
async function verifyCodeSignature(code) {
|
30
|
-
const signature = await crypto.subtle
|
31
|
-
.digest('SHA-256', new TextEncoder().encode(code))
|
32
|
-
.then(hash => Array.from(new Uint8Array(hash))
|
33
|
-
.map(b => b.toString(16).padStart(2, '0'))
|
34
|
-
.join(''));
|
35
|
-
|
36
|
-
return __INLINE_CODE_SIGNATURES_PLACEHOLDER__.includes(signature);
|
37
|
-
}
|
38
|
-
|
39
23
|
/**
|
40
24
|
* Dynamically imports modules based on configuration
|
41
25
|
*
|
@@ -47,14 +31,10 @@ async function verifyCodeSignature(code) {
|
|
47
31
|
* @param {Object} imports[].window_name - Global window object name (for external type)
|
48
32
|
* @param {('inline'|'external')} imports[].type - Type of import
|
49
33
|
* @returns {Promise<Array<any>>} Array of loaded modules
|
50
|
-
* @throws {Error} When plugin loading fails
|
34
|
+
* @throws {Error} When plugin loading fails
|
51
35
|
*/
|
52
36
|
function loadAsyncImports(imports = []) {
|
53
37
|
const loadInlinePlugin = async ({ name, code }) => {
|
54
|
-
if (!await verifyCodeSignature(code)) {
|
55
|
-
throw new Error(`Invalid code signature for inline plugin "${name}"!`);
|
56
|
-
}
|
57
|
-
|
58
38
|
const module = await import(`data:text/javascript,${encodeURIComponent(code)}`);
|
59
39
|
|
60
40
|
if (!module.default) {
|
@@ -99,16 +99,15 @@ module CKEditor5::Rails
|
|
99
99
|
|
100
100
|
if importmap_available?
|
101
101
|
@__ckeditor_context = {
|
102
|
-
bundle: combined_bundle
|
103
|
-
lazy: true
|
102
|
+
bundle: combined_bundle
|
104
103
|
}
|
105
104
|
|
106
|
-
return Assets::WebComponentBundle.instance.to_html
|
105
|
+
return Assets::WebComponentBundle.instance.to_html(nonce: content_security_policy_nonce)
|
107
106
|
end
|
108
107
|
|
109
108
|
safe_join([
|
110
|
-
Assets::AssetsImportMap.new(combined_bundle).to_html,
|
111
|
-
Assets::WebComponentBundle.instance.to_html
|
109
|
+
Assets::AssetsImportMap.new(combined_bundle).to_html(nonce: content_security_policy_nonce),
|
110
|
+
Assets::WebComponentBundle.instance.to_html(nonce: content_security_policy_nonce)
|
112
111
|
])
|
113
112
|
end
|
114
113
|
|
@@ -183,7 +182,7 @@ module CKEditor5::Rails
|
|
183
182
|
lazy: lazy
|
184
183
|
)
|
185
184
|
|
186
|
-
html = serializer.to_html
|
185
|
+
html = serializer.to_html(nonce: content_security_policy_nonce)
|
187
186
|
|
188
187
|
if importmap_available?
|
189
188
|
@__ckeditor_context[:html_tags] = html
|
@@ -40,8 +40,8 @@ module CKEditor5::Rails::Context
|
|
40
40
|
# <% preset = ckeditor5_context_preset do
|
41
41
|
# plugins :Comments, :TrackChanges, :Collaboration # Shared functionality plugins
|
42
42
|
# end %>
|
43
|
-
def ckeditor5_context_preset(
|
44
|
-
PresetBuilder.new(
|
43
|
+
def ckeditor5_context_preset(&block)
|
44
|
+
PresetBuilder.new(&block)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -56,7 +56,7 @@ module CKEditor5::Rails
|
|
56
56
|
# <%= form_for @post do |f| %>
|
57
57
|
# <%= f.ckeditor5 :content, required: true %>
|
58
58
|
# <% end %>
|
59
|
-
def ckeditor5_editor( # rubocop:disable Metrics/ParameterLists
|
59
|
+
def ckeditor5_editor( # rubocop:disable Metrics/ParameterLists
|
60
60
|
preset: nil,
|
61
61
|
config: nil, extra_config: {}, type: nil,
|
62
62
|
initial_data: nil, watchdog: true,
|
@@ -78,9 +78,7 @@ module CKEditor5::Rails
|
|
78
78
|
|
79
79
|
editor_props = Editor::Props.new(
|
80
80
|
type, config,
|
81
|
-
|
82
|
-
# So web-component will be loaded from the CDN.
|
83
|
-
bundle: context[:lazy] ? context[:bundle] : nil,
|
81
|
+
bundle: context[:bundle],
|
84
82
|
watchdog: watchdog,
|
85
83
|
editable_height: editable_height || preset.editable_height
|
86
84
|
)
|
@@ -161,15 +159,13 @@ module CKEditor5::Rails
|
|
161
159
|
|
162
160
|
return {
|
163
161
|
bundle: create_preset_bundle(found_preset),
|
164
|
-
preset: found_preset
|
165
|
-
lazy: true
|
162
|
+
preset: found_preset
|
166
163
|
}
|
167
164
|
end
|
168
165
|
|
169
166
|
{
|
170
167
|
bundle: nil,
|
171
|
-
preset: Engine.default_preset
|
172
|
-
lazy: true
|
168
|
+
preset: Engine.default_preset
|
173
169
|
}
|
174
170
|
end
|
175
171
|
end
|
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'singleton'
|
4
|
-
require 'digest'
|
5
|
-
|
6
3
|
require_relative 'props_base_plugin'
|
7
4
|
|
8
5
|
module CKEditor5::Rails::Editor
|
@@ -14,8 +11,6 @@ module CKEditor5::Rails::Editor
|
|
14
11
|
|
15
12
|
@code = code
|
16
13
|
validate_code!
|
17
|
-
|
18
|
-
InlinePluginsSignaturesRegistry.instance.register(code)
|
19
14
|
end
|
20
15
|
|
21
16
|
def to_h
|
@@ -37,28 +32,4 @@ module CKEditor5::Rails::Editor
|
|
37
32
|
'Code must include `export default` that exports plugin definition!'
|
38
33
|
end
|
39
34
|
end
|
40
|
-
|
41
|
-
class InlinePluginsSignaturesRegistry
|
42
|
-
include Singleton
|
43
|
-
|
44
|
-
def initialize
|
45
|
-
@signatures = Set.new
|
46
|
-
end
|
47
|
-
|
48
|
-
def register(code)
|
49
|
-
signature = generate_signature(code)
|
50
|
-
@signatures.add(signature)
|
51
|
-
signature
|
52
|
-
end
|
53
|
-
|
54
|
-
def to_a
|
55
|
-
@signatures.to_a
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def generate_signature(code)
|
61
|
-
Digest::SHA256.hexdigest(code)
|
62
|
-
end
|
63
|
-
end
|
64
35
|
end
|
@@ -32,7 +32,7 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
describe '#to_html' do
|
35
|
-
subject(:html) { serializer.to_html }
|
35
|
+
subject(:html) { serializer.to_html(nonce: 'true') }
|
36
36
|
|
37
37
|
it 'includes window script tags' do
|
38
38
|
expect(html).to have_tag('script', with: {
|
@@ -240,7 +240,7 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsImportMap do
|
|
240
240
|
|
241
241
|
describe '#to_html' do
|
242
242
|
it 'generates script tag with import map' do
|
243
|
-
html = import_map.to_html
|
243
|
+
html = import_map.to_html(nonce: 'true')
|
244
244
|
expect(html).to have_tag('script', with: { type: 'importmap', nonce: 'true' }) do
|
245
245
|
with_text('{"imports":{"@ckeditor/module":"https://cdn.com/script2.js"}}')
|
246
246
|
end
|
@@ -107,18 +107,5 @@ RSpec.describe CKEditor5::Rails::Context::Helpers do
|
|
107
107
|
preset: :custom
|
108
108
|
)
|
109
109
|
end
|
110
|
-
|
111
|
-
it 'raises error when trying to define inline plugin' do
|
112
|
-
expect do
|
113
|
-
helper.ckeditor5_context_preset do
|
114
|
-
inline_plugin :TestPlugin, <<~JS
|
115
|
-
export default class TestPlugin { }
|
116
|
-
JS
|
117
|
-
end
|
118
|
-
end.to raise_error(
|
119
|
-
CKEditor5::Rails::Presets::Concerns::PluginMethods::DisallowedInlinePlugin,
|
120
|
-
'Inline plugins are not allowed here.'
|
121
|
-
)
|
122
|
-
end
|
123
110
|
end
|
124
111
|
end
|
@@ -58,7 +58,6 @@ RSpec.describe CKEditor5::Rails::Editor::Helpers::Editor do
|
|
58
58
|
result = helper.ckeditor5_context_or_fallback(:custom)
|
59
59
|
expect(result).to match({
|
60
60
|
bundle: 'custom-bundle',
|
61
|
-
lazy: true,
|
62
61
|
preset: custom_preset
|
63
62
|
})
|
64
63
|
end
|
@@ -72,33 +71,9 @@ RSpec.describe CKEditor5::Rails::Editor::Helpers::Editor do
|
|
72
71
|
result = helper.ckeditor5_context_or_fallback(nil)
|
73
72
|
expect(result).to match({
|
74
73
|
bundle: nil,
|
75
|
-
lazy: true,
|
76
74
|
preset: :default
|
77
75
|
})
|
78
76
|
end
|
79
|
-
|
80
|
-
it 'includes lazy flag in fallback context' do
|
81
|
-
allow(CKEditor5::Rails::Engine).to receive(:default_preset)
|
82
|
-
.and_return(:default)
|
83
|
-
|
84
|
-
result = helper.ckeditor5_context_or_fallback(nil)
|
85
|
-
expect(result[:lazy]).to be true
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'includes lazy flag in preset context' do
|
89
|
-
custom_preset = instance_double(CKEditor5::Rails::Presets::PresetBuilder)
|
90
|
-
|
91
|
-
allow(CKEditor5::Rails::Engine).to receive(:find_preset)
|
92
|
-
.with(:custom)
|
93
|
-
.and_return(custom_preset)
|
94
|
-
|
95
|
-
allow(helper).to receive(:create_preset_bundle)
|
96
|
-
.with(custom_preset)
|
97
|
-
.and_return('custom-bundle')
|
98
|
-
|
99
|
-
result = helper.ckeditor5_context_or_fallback(:custom)
|
100
|
-
expect(result[:lazy]).to be true
|
101
|
-
end
|
102
77
|
end
|
103
78
|
|
104
79
|
describe '#ckeditor5_editor' do
|
@@ -250,31 +225,6 @@ RSpec.describe CKEditor5::Rails::Editor::Helpers::Editor do
|
|
250
225
|
expect(helper.ckeditor5_editor(editable_height: 600)).to include('editable-height="600px"')
|
251
226
|
end
|
252
227
|
end
|
253
|
-
|
254
|
-
context 'when using bundles' do
|
255
|
-
let(:bundle) { 'test-bundle' }
|
256
|
-
let(:context) { { preset: :default, bundle: bundle, lazy: true } }
|
257
|
-
|
258
|
-
it 'uses bundle from context when lazy is true' do
|
259
|
-
expect(CKEditor5::Rails::Editor::Props).to receive(:new)
|
260
|
-
.with(anything, anything, hash_including(bundle: bundle))
|
261
|
-
.and_call_original
|
262
|
-
|
263
|
-
helper.ckeditor5_editor
|
264
|
-
end
|
265
|
-
|
266
|
-
context 'when lazy is false' do
|
267
|
-
let(:context) { { preset: :default, bundle: bundle, lazy: false } }
|
268
|
-
|
269
|
-
it 'does not use bundle from context' do
|
270
|
-
expect(CKEditor5::Rails::Editor::Props).to receive(:new)
|
271
|
-
.with(anything, anything, hash_including(bundle: nil))
|
272
|
-
.and_call_original
|
273
|
-
|
274
|
-
helper.ckeditor5_editor
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
278
228
|
end
|
279
229
|
|
280
230
|
describe '#ckeditor5_editable' do
|
@@ -7,7 +7,11 @@ RSpec.describe CKEditor5::Rails::Hooks::Form do
|
|
7
7
|
let(:post) { Post.new(content: 'Initial content') }
|
8
8
|
let(:builder) { described_class.new(:post, post, template) }
|
9
9
|
let(:template) do
|
10
|
-
|
10
|
+
Class.new(ActionView::Base) do
|
11
|
+
def content_security_policy_nonce
|
12
|
+
'test-nonce'
|
13
|
+
end
|
14
|
+
end.new(ActionView::LookupContext.new([]), {}, nil)
|
11
15
|
end
|
12
16
|
|
13
17
|
before do
|
@@ -18,10 +22,24 @@ RSpec.describe CKEditor5::Rails::Hooks::Form do
|
|
18
22
|
subject(:rendered_editor) { builder.build_editor(:content) }
|
19
23
|
|
20
24
|
it 'renders ckeditor element' do
|
25
|
+
bundle_json = {
|
26
|
+
scripts: [
|
27
|
+
{
|
28
|
+
import_name: 'ckeditor5',
|
29
|
+
url: 'https://cdn.jsdelivr.net/npm/ckeditor5@34.1.0/dist/browser/ckeditor5.js',
|
30
|
+
translation: false
|
31
|
+
}
|
32
|
+
],
|
33
|
+
stylesheets: [
|
34
|
+
'https://cdn.jsdelivr.net/npm/ckeditor5@34.1.0/dist/browser/ckeditor5.css'
|
35
|
+
]
|
36
|
+
}.to_json
|
37
|
+
|
21
38
|
attrs = {
|
22
39
|
name: 'post[content]',
|
23
40
|
id: 'post_content',
|
24
41
|
type: 'ClassicEditor',
|
42
|
+
bundle: bundle_json,
|
25
43
|
watchdog: 'true'
|
26
44
|
}
|
27
45
|
|
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.23.
|
4
|
+
version: 1.23.5
|
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-12-
|
12
|
+
date: 2024-12-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|