ckeditor5 1.19.5 → 1.20.0
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 +4 -4
- data/Gemfile +5 -2
- data/README.md +2 -0
- data/lib/ckeditor5/rails/assets/assets_bundle_html_serializer.rb +43 -25
- data/lib/ckeditor5/rails/cdn/helpers.rb +81 -2
- data/lib/ckeditor5/rails/context/helpers.rb +28 -0
- data/lib/ckeditor5/rails/context/preset_builder.rb +33 -0
- data/lib/ckeditor5/rails/editor/helpers/config_helpers.rb +39 -0
- data/lib/ckeditor5/rails/editor/helpers/editor_helpers.rb +73 -13
- data/lib/ckeditor5/rails/engine.rb +11 -3
- data/lib/ckeditor5/rails/hooks/form.rb +44 -0
- data/lib/ckeditor5/rails/hooks/importmap.rb +58 -0
- data/lib/ckeditor5/rails/hooks/simple_form.rb +42 -0
- data/lib/ckeditor5/rails/presets/concerns/configuration_methods.rb +45 -0
- data/lib/ckeditor5/rails/presets/concerns/plugin_methods.rb +54 -0
- data/lib/ckeditor5/rails/presets/manager.rb +49 -0
- data/lib/ckeditor5/rails/presets/plugins_builder.rb +32 -0
- data/lib/ckeditor5/rails/presets/preset_builder.rb +117 -0
- data/lib/ckeditor5/rails/presets/toolbar_builder.rb +33 -0
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/spec/e2e/features/editor_types_spec.rb +1 -1
- data/spec/e2e/spec_helper.rb +2 -7
- data/spec/lib/ckeditor5/rails/assets/{asset_bundle_hml_serializer_spec.rb → assets_bundle_hml_serializer_spec.rb} +58 -15
- data/spec/lib/ckeditor5/rails/cdn/helpers_spec.rb +41 -5
- data/spec/lib/ckeditor5/rails/engine_spec.rb +32 -0
- data/spec/lib/ckeditor5/rails/hooks/importmap_spec.rb +131 -0
- metadata +7 -4
data/spec/e2e/spec_helper.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'capybara'
|
4
4
|
require 'capybara/rspec'
|
5
5
|
require 'capybara/cuprite'
|
6
|
+
require 'rspec/retry'
|
6
7
|
|
7
8
|
ENV['RAILS_ENV'] ||= 'test'
|
8
9
|
|
@@ -40,16 +41,10 @@ Capybara.server = :webrick
|
|
40
41
|
Capybara.default_driver = :cuprite
|
41
42
|
Capybara.javascript_driver = :cuprite
|
42
43
|
|
43
|
-
require 'rspec/retry'
|
44
|
-
|
45
44
|
RSpec.configure do |config|
|
46
|
-
config.verbose_retry = true
|
47
|
-
|
48
45
|
config.around :each, :js do |example|
|
49
|
-
example.run_with_retry retry:
|
46
|
+
example.run_with_retry retry: 4, retry_wait: 5, default_sleep_interval: 2
|
50
47
|
end
|
51
|
-
|
52
|
-
config.profile_examples = 10
|
53
48
|
end
|
54
49
|
|
55
50
|
Dir[File.expand_path('support/**/*.rb', __dir__)].each { |f| require f }
|
@@ -42,6 +42,13 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer do
|
|
42
42
|
})
|
43
43
|
end
|
44
44
|
|
45
|
+
it 'should not include importmap if not requested' do
|
46
|
+
serializer = described_class.new(bundle, importmap: false)
|
47
|
+
html = serializer.to_html
|
48
|
+
|
49
|
+
expect(html).not_to have_tag('script', with: { type: 'importmap' })
|
50
|
+
end
|
51
|
+
|
45
52
|
it 'includes import map' do
|
46
53
|
expect(html).to have_tag('script', with: { type: 'importmap' }) do
|
47
54
|
with_text(%r{"@ckeditor/script2":"https://cdn\.com/script2\.js"})
|
@@ -131,13 +138,6 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer do
|
|
131
138
|
nonce: 'true'
|
132
139
|
})
|
133
140
|
end
|
134
|
-
|
135
|
-
it 'memoizes scripts import map' do
|
136
|
-
first_call = serializer.send(:scripts_import_map_tag)
|
137
|
-
second_call = serializer.send(:scripts_import_map_tag)
|
138
|
-
|
139
|
-
expect(first_call.object_id).to eq(second_call.object_id)
|
140
|
-
end
|
141
141
|
end
|
142
142
|
|
143
143
|
describe '.url_resource_preload_type' do
|
@@ -153,17 +153,60 @@ RSpec.describe CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer do
|
|
153
153
|
expect(described_class.url_resource_preload_type('file.unknown')).to eq('fetch')
|
154
154
|
end
|
155
155
|
end
|
156
|
+
end
|
156
157
|
|
157
|
-
|
158
|
-
|
158
|
+
RSpec.describe CKEditor5::Rails::Assets::AssetsImportMap do
|
159
|
+
let(:scripts) do
|
160
|
+
[
|
161
|
+
CKEditor5::Rails::Assets::JSUrlImportMeta.new(
|
162
|
+
'https://cdn.com/script1.js',
|
163
|
+
window_name: 'WindowScript'
|
164
|
+
),
|
165
|
+
CKEditor5::Rails::Assets::JSUrlImportMeta.new(
|
166
|
+
'https://cdn.com/script2.js',
|
167
|
+
import_name: '@ckeditor/module'
|
168
|
+
),
|
169
|
+
CKEditor5::Rails::Assets::JSUrlImportMeta.new(
|
170
|
+
'https://cdn.com/script3.js',
|
171
|
+
import_name: 'https://example.com/module'
|
172
|
+
)
|
173
|
+
]
|
174
|
+
end
|
175
|
+
|
176
|
+
let(:bundle) { CKEditor5::Rails::Assets::AssetsBundle.new(scripts: scripts) }
|
177
|
+
subject(:import_map) { described_class.new(bundle) }
|
178
|
+
|
179
|
+
describe '#to_json' do
|
180
|
+
it 'includes only ESM scripts without URL-like imports' do
|
181
|
+
json = JSON.parse(import_map.to_json)
|
182
|
+
expect(json['imports']).to eq({
|
183
|
+
'@ckeditor/module' => 'https://cdn.com/script2.js'
|
184
|
+
})
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe '#to_html' do
|
189
|
+
it 'generates script tag with import map' do
|
190
|
+
html = import_map.to_html
|
191
|
+
expect(html).to have_tag('script', with: { type: 'importmap', nonce: 'true' }) do
|
192
|
+
with_text('{"imports":{"@ckeditor/module":"https://cdn.com/script2.js"}}')
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
159
196
|
|
197
|
+
describe '#looks_like_url? (private)' do
|
160
198
|
it 'returns false for invalid URIs' do
|
161
|
-
expect(
|
162
|
-
expect(
|
163
|
-
expect(
|
164
|
-
expect(
|
165
|
-
expect(
|
166
|
-
expect(
|
199
|
+
expect(import_map.send(:looks_like_url?, '@ckeditor/foo')).to be false
|
200
|
+
expect(import_map.send(:looks_like_url?, 'http')).to be false
|
201
|
+
expect(import_map.send(:looks_like_url?, 'invalid')).to be false
|
202
|
+
expect(import_map.send(:looks_like_url?, 'http://[invalid')).to be false
|
203
|
+
expect(import_map.send(:looks_like_url?, "http://example.com\nmalicious")).to be false
|
204
|
+
expect(import_map.send(:looks_like_url?, 'http://<invalid>')).to be false
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'returns true for valid HTTP(S) URLs' do
|
208
|
+
expect(import_map.send(:looks_like_url?, 'http://example.com')).to be true
|
209
|
+
expect(import_map.send(:looks_like_url?, 'https://cdn.com/script.js')).to be true
|
167
210
|
end
|
168
211
|
end
|
169
212
|
end
|
@@ -3,7 +3,16 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
6
|
-
let(:test_class)
|
6
|
+
let(:test_class) do
|
7
|
+
Class.new do
|
8
|
+
include CKEditor5::Rails::Cdn::Helpers
|
9
|
+
|
10
|
+
def importmap_rendered?
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
let(:helper) { test_class.new }
|
8
17
|
let(:preset) do
|
9
18
|
CKEditor5::Rails::Presets::PresetBuilder.new do
|
@@ -32,10 +41,6 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
|
32
41
|
|
33
42
|
describe '#ckeditor5_assets' do
|
34
43
|
context 'with valid preset' do
|
35
|
-
it 'returns serialized bundle html' do
|
36
|
-
expect(helper.ckeditor5_assets(preset: :default)).to eq(bundle_html)
|
37
|
-
end
|
38
|
-
|
39
44
|
it 'creates base bundle' do
|
40
45
|
expect(CKEditor5::Rails::Cdn::CKEditorBundle).to receive(:new)
|
41
46
|
.with(
|
@@ -218,6 +223,37 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
|
218
223
|
.to raise_error(ArgumentError, /forgot to define version/)
|
219
224
|
end
|
220
225
|
end
|
226
|
+
|
227
|
+
context 'when Rails.application.importmap is defined' do
|
228
|
+
before do
|
229
|
+
allow(helper).to receive(:importmap_available?).and_return(true)
|
230
|
+
allow(helper).to receive(:importmap_rendered?).and_return(false)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'returns nil and stores html tags in context' do
|
234
|
+
result = helper.ckeditor5_assets(preset: :default)
|
235
|
+
expect(result).to be_nil
|
236
|
+
expect(context[:html_tags]).to eq(bundle_html)
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'raise exception if importmap_rendered?' do
|
240
|
+
allow(helper).to receive(:importmap_rendered?).and_return(true)
|
241
|
+
expect { helper.ckeditor5_assets(preset: :default) }
|
242
|
+
.to raise_error(CKEditor5::Rails::Cdn::Helpers::ImportmapAlreadyRenderedError)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context 'when importmap_available? is true returns html' do
|
247
|
+
before do
|
248
|
+
allow(helper).to receive(:importmap_available?).and_return(nil)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'returns html directly' do
|
252
|
+
result = helper.ckeditor5_assets(preset: :default)
|
253
|
+
expect(result).to eq(bundle_html)
|
254
|
+
expect(context[:html_tags]).to be_nil
|
255
|
+
end
|
256
|
+
end
|
221
257
|
end
|
222
258
|
|
223
259
|
describe 'cdn helper methods' do
|
@@ -102,5 +102,37 @@ RSpec.describe CKEditor5::Rails::Engine do
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
105
|
+
|
106
|
+
describe 'importmap initializer' do
|
107
|
+
context 'when Importmap is defined' do
|
108
|
+
module Importmap # rubocop:disable Lint/ConstantDefinitionInBlock
|
109
|
+
module ImportmapTagsHelper; end
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'prepends CKEditor5 importmap helper' do
|
113
|
+
initializer = described_class.initializers.find { |i| i.name == 'ckeditor5.importmap' }
|
114
|
+
initializer.run(Rails.application)
|
115
|
+
|
116
|
+
expect(Importmap::ImportmapTagsHelper.ancestors)
|
117
|
+
.to include(CKEditor5::Rails::Hooks::Importmap::ImportmapTagsHelper)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when Importmap is not defined' do
|
122
|
+
before do
|
123
|
+
@importmap = Importmap if defined?(Importmap)
|
124
|
+
Object.send(:remove_const, :Importmap) if defined?(Importmap)
|
125
|
+
end
|
126
|
+
|
127
|
+
after do
|
128
|
+
Object.const_set(:Importmap, @importmap) if @importmap
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'does not raise error' do
|
132
|
+
initializer = described_class.initializers.find { |i| i.name == 'ckeditor5.importmap' }
|
133
|
+
expect { initializer.run(Rails.application) }.not_to raise_error
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
105
137
|
end
|
106
138
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe CKEditor5::Rails::Hooks::Importmap::ImportmapTagsHelper do
|
6
|
+
let(:test_class) do
|
7
|
+
Class.new do
|
8
|
+
include ActionView::Helpers::TagHelper
|
9
|
+
include CKEditor5::Rails::Hooks::Importmap::ImportmapTagsHelper
|
10
|
+
|
11
|
+
def javascript_importmap_module_preload_tags(*)
|
12
|
+
'<script type="modulepreload">preload</script>'
|
13
|
+
end
|
14
|
+
|
15
|
+
def javascript_import_module_tag(*)
|
16
|
+
'<script type="module">import</script>'
|
17
|
+
end
|
18
|
+
|
19
|
+
def javascript_inline_importmap_tag(json)
|
20
|
+
"<script type=\"importmap\">#{json}</script>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:helper) { test_class.new }
|
26
|
+
let(:importmap) { double('Importmap', to_json: '{"imports":{}}') }
|
27
|
+
|
28
|
+
before do
|
29
|
+
allow(Rails.application).to receive(:importmap).and_return(importmap)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#javascript_importmap_tags' do
|
33
|
+
context 'without CKEditor context' do
|
34
|
+
it 'generates basic importmap tags' do
|
35
|
+
result = helper.javascript_importmap_tags
|
36
|
+
|
37
|
+
expect(result).to include('modulepreload')
|
38
|
+
expect(result).to include('module')
|
39
|
+
expect(helper).to be_importmap_rendered
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with CKEditor context' do
|
44
|
+
let(:bundle) do
|
45
|
+
CKEditor5::Rails::Assets::AssetsBundle.new(
|
46
|
+
scripts: [
|
47
|
+
CKEditor5::Rails::Assets::JSUrlImportMeta.new(
|
48
|
+
'https://cdn.com/script.js',
|
49
|
+
import_name: '@ckeditor/module'
|
50
|
+
)
|
51
|
+
]
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
let(:html_tags) { '<script src="ckeditor.js"></script>' }
|
56
|
+
|
57
|
+
before do
|
58
|
+
helper.instance_variable_set(:@__ckeditor_context, {
|
59
|
+
bundle: bundle,
|
60
|
+
html_tags: html_tags
|
61
|
+
})
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'merges CKEditor importmap with base importmap' do
|
65
|
+
result = CGI.unescapeHTML(helper.javascript_importmap_tags)
|
66
|
+
|
67
|
+
expect(result).to include('@ckeditor/module')
|
68
|
+
expect(result).to include('https://cdn.com/script.js')
|
69
|
+
expect(result).to include(html_tags)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'handles invalid JSON gracefully' do
|
73
|
+
allow(importmap).to receive(:to_json).and_return('invalid json')
|
74
|
+
|
75
|
+
expect(Rails.logger).to receive(:error).with(/Failed to merge import maps/)
|
76
|
+
helper.javascript_importmap_tags
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'processes importmap in correct order when context is present' do
|
80
|
+
html = CGI.unescapeHTML(helper.javascript_importmap_tags)
|
81
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
82
|
+
scripts = doc.css('script')
|
83
|
+
|
84
|
+
expect(scripts[0]['type']).to eq('importmap')
|
85
|
+
expect(scripts[1]['type']).to eq('modulepreload')
|
86
|
+
expect(scripts[2]['type']).to eq('module')
|
87
|
+
expect(scripts[3]['src']).to eq('ckeditor.js')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'adds inline importmap when context is missing' do
|
91
|
+
helper.instance_variable_set(:@__ckeditor_context, nil)
|
92
|
+
html = CGI.unescapeHTML(helper.javascript_importmap_tags)
|
93
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
94
|
+
scripts = doc.css('script')
|
95
|
+
|
96
|
+
expect(scripts[0]['type']).to eq('importmap')
|
97
|
+
expect(doc.css('script[src="ckeditor.js"]')).to be_empty
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#importmap_rendered?' do
|
103
|
+
it 'returns false by default' do
|
104
|
+
expect(helper).not_to be_importmap_rendered
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'returns true after rendering importmap' do
|
108
|
+
helper.javascript_importmap_tags
|
109
|
+
expect(helper).to be_importmap_rendered
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#merge_import_maps_json (private)' do
|
114
|
+
it 'correctly merges two valid import maps' do
|
115
|
+
map_a = '{"imports":{"a":"1"}}'
|
116
|
+
map_b = '{"imports":{"b":"2"}}'
|
117
|
+
|
118
|
+
result = JSON.parse(helper.send(:merge_import_maps_json, map_a, map_b))
|
119
|
+
expect(result['imports']).to eq('a' => '1', 'b' => '2')
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns second map when first is invalid' do
|
123
|
+
map_a = 'invalid json'
|
124
|
+
map_b = '{"imports":{"b":"2"}}'
|
125
|
+
|
126
|
+
expect(Rails.logger).to receive(:error).with(/Failed to merge import maps/)
|
127
|
+
result = helper.send(:merge_import_maps_json, map_a, map_b)
|
128
|
+
expect(result).to eq(map_b)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
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.
|
4
|
+
version: 1.20.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: 2024-
|
12
|
+
date: 2024-12-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/ckeditor5/rails/engine.rb
|
71
71
|
- lib/ckeditor5/rails/helpers.rb
|
72
72
|
- lib/ckeditor5/rails/hooks/form.rb
|
73
|
+
- lib/ckeditor5/rails/hooks/importmap.rb
|
73
74
|
- lib/ckeditor5/rails/hooks/simple_form.rb
|
74
75
|
- lib/ckeditor5/rails/plugins/simple_upload_adapter.rb
|
75
76
|
- lib/ckeditor5/rails/plugins/wproofreader.rb
|
@@ -89,7 +90,7 @@ files:
|
|
89
90
|
- spec/e2e/spec_helper.rb
|
90
91
|
- spec/e2e/support/eventually.rb
|
91
92
|
- spec/e2e/support/form_helpers.rb
|
92
|
-
- spec/lib/ckeditor5/rails/assets/
|
93
|
+
- spec/lib/ckeditor5/rails/assets/assets_bundle_hml_serializer_spec.rb
|
93
94
|
- spec/lib/ckeditor5/rails/assets/assets_bundle_spec.rb
|
94
95
|
- spec/lib/ckeditor5/rails/cdn/ckbox_bundle_spec.rb
|
95
96
|
- spec/lib/ckeditor5/rails/cdn/ckeditor_bundle_spec.rb
|
@@ -108,6 +109,7 @@ files:
|
|
108
109
|
- spec/lib/ckeditor5/rails/editor/props_spec.rb
|
109
110
|
- spec/lib/ckeditor5/rails/engine_spec.rb
|
110
111
|
- spec/lib/ckeditor5/rails/hooks/form_spec.rb
|
112
|
+
- spec/lib/ckeditor5/rails/hooks/importmap_spec.rb
|
111
113
|
- spec/lib/ckeditor5/rails/hooks/simple_form_spec.rb
|
112
114
|
- spec/lib/ckeditor5/rails/plugins/wproofreader_spec.rb
|
113
115
|
- spec/lib/ckeditor5/rails/presets/manager_spec.rb
|
@@ -154,7 +156,7 @@ test_files:
|
|
154
156
|
- spec/e2e/spec_helper.rb
|
155
157
|
- spec/e2e/support/eventually.rb
|
156
158
|
- spec/e2e/support/form_helpers.rb
|
157
|
-
- spec/lib/ckeditor5/rails/assets/
|
159
|
+
- spec/lib/ckeditor5/rails/assets/assets_bundle_hml_serializer_spec.rb
|
158
160
|
- spec/lib/ckeditor5/rails/assets/assets_bundle_spec.rb
|
159
161
|
- spec/lib/ckeditor5/rails/cdn/ckbox_bundle_spec.rb
|
160
162
|
- spec/lib/ckeditor5/rails/cdn/ckeditor_bundle_spec.rb
|
@@ -173,6 +175,7 @@ test_files:
|
|
173
175
|
- spec/lib/ckeditor5/rails/editor/props_spec.rb
|
174
176
|
- spec/lib/ckeditor5/rails/engine_spec.rb
|
175
177
|
- spec/lib/ckeditor5/rails/hooks/form_spec.rb
|
178
|
+
- spec/lib/ckeditor5/rails/hooks/importmap_spec.rb
|
176
179
|
- spec/lib/ckeditor5/rails/hooks/simple_form_spec.rb
|
177
180
|
- spec/lib/ckeditor5/rails/plugins/wproofreader_spec.rb
|
178
181
|
- spec/lib/ckeditor5/rails/presets/manager_spec.rb
|