ckeditor5 1.28.1 → 1.29.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/README.md +8 -9
- data/lib/ckeditor5/rails/editor/props_inline_plugin.rb +15 -14
- data/lib/ckeditor5/rails/editor/props_patch_plugin.rb +0 -2
- data/lib/ckeditor5/rails/plugins/custom_translations_loader.rb +2 -3
- data/lib/ckeditor5/rails/plugins/simple_upload_adapter.rb +2 -3
- data/lib/ckeditor5/rails/plugins/special_characters_bootstrap.rb +2 -3
- data/lib/ckeditor5/rails/plugins/wproofreader.rb +2 -3
- data/lib/ckeditor5/rails/presets/concerns/plugin_methods.rb +22 -3
- data/lib/ckeditor5/rails/presets/manager.rb +6 -1
- data/lib/ckeditor5/rails/presets/preset_builder.rb +12 -8
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/spec/lib/ckeditor5/rails/cdn/helpers_spec.rb +8 -2
- data/spec/lib/ckeditor5/rails/context/preset_builder_spec.rb +18 -0
- data/spec/lib/ckeditor5/rails/editor/props_inline_plugin_spec.rb +28 -0
- data/spec/lib/ckeditor5/rails/presets/preset_builder_spec.rb +2 -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: 256f9adbf5e78de031f065ddb9b752cfbf10cd3dac9e684e6d18058fef7f6576
|
4
|
+
data.tar.gz: 6049c1d13ba8366999c877b926676414426938377163e921b957f252372c32a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f66a5c790311abf91166063825f3b7c6b3708d2f472748538b77abce68c56f42038bc163a133d989358d27a57370bac89db0ee77d6da0dd8b64bb62b6922263a
|
7
|
+
data.tar.gz: af90ae4ff64f99b2d8c5bc6f04baede52d7351f4bfa3e62e88125311806ceb66147caefb454e374f891b6ed7383943414c75e81b391aacf2e9f05131963f6dd3
|
data/README.md
CHANGED
@@ -146,10 +146,10 @@ For extending CKEditor's functionality, refer to the [plugins directory](https:/
|
|
146
146
|
- [`inline_plugin(name, code)` method](#inline_pluginname-code-method)
|
147
147
|
- [`external_plugin(name, script:, import_as: nil, window_name: nil, stylesheets: [])` method](#external_pluginname-script-import_as-nil-window_name-nil-stylesheets--method)
|
148
148
|
- [`patch_plugin(plugin)`](#patch_pluginplugin)
|
149
|
-
- [`simple_upload_adapter(url)` method](#simple_upload_adapterurl-method)
|
150
|
-
- [`special_characters(&block)` method](#
|
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)
|
149
|
+
- [`simple_upload_adapter(url, compress: true)` method](#simple_upload_adapterurl-compress-true-method)
|
150
|
+
- [`special_characters(compress: true, &block)` method](#special_characterscompress-true-block-method)
|
151
|
+
- [`wproofreader(version: nil, cdn: nil, compress: true, **config)` method](#wproofreaderversion-nil-cdn-nil-compress-true-config-method)
|
152
|
+
- [`custom_translations(lang_code = nil, translations = {}, compress: true)` method](#custom_translationslang_code--nil-translations---compress-true-method)
|
153
153
|
- [Controller / View helpers 📦](#controller--view-helpers-)
|
154
154
|
- [`ckeditor5_translation_ref(key)` method](#ckeditor5_translation_refkey-method)
|
155
155
|
- [`ckeditor5_element_ref(selector)` method](#ckeditor5_element_refselector-method)
|
@@ -1031,13 +1031,12 @@ class YourPatch < CKEditor5::Rails::Editor::PropsPatchPlugin
|
|
1031
1031
|
|
1032
1032
|
def initialize
|
1033
1033
|
super(:YourPatch, PLUGIN_CODE, min_version: nil, max_version: '45.0.0')
|
1034
|
-
compress!
|
1035
1034
|
end
|
1036
1035
|
end
|
1037
1036
|
```
|
1038
1037
|
</details>
|
1039
1038
|
|
1040
|
-
#### `simple_upload_adapter(url)` method
|
1039
|
+
#### `simple_upload_adapter(url, compress: true)` method
|
1041
1040
|
|
1042
1041
|
<details>
|
1043
1042
|
<summary>Configure server-side image upload endpoint</summary>
|
@@ -1060,7 +1059,7 @@ end
|
|
1060
1059
|
```
|
1061
1060
|
</details>
|
1062
1061
|
|
1063
|
-
#### `special_characters(&block)` method
|
1062
|
+
#### `special_characters(compress: true, &block)` method
|
1064
1063
|
|
1065
1064
|
<details>
|
1066
1065
|
<summary>Configure special characters plugin</summary>
|
@@ -1106,7 +1105,7 @@ For more info about the special characters plugin, check the [official documenta
|
|
1106
1105
|
|
1107
1106
|
</details>
|
1108
1107
|
|
1109
|
-
#### `wproofreader(version: nil, cdn: nil, **config)` method
|
1108
|
+
#### `wproofreader(version: nil, cdn: nil, compress: true, **config)` method
|
1110
1109
|
|
1111
1110
|
<details>
|
1112
1111
|
<summary>Configure WProofreader plugin</summary>
|
@@ -1160,7 +1159,7 @@ For more info about the WProofreader plugin, check the [official documentation](
|
|
1160
1159
|
|
1161
1160
|
</details>
|
1162
1161
|
|
1163
|
-
#### `custom_translations(lang_code = nil, translations = {})` method
|
1162
|
+
#### `custom_translations(lang_code = nil, translations = {}, compress: true)` method
|
1164
1163
|
|
1165
1164
|
<details>
|
1166
1165
|
<summary>Define custom translations for CKEditor components and UI</summary>
|
@@ -4,17 +4,20 @@ require_relative 'props_base_plugin'
|
|
4
4
|
|
5
5
|
module CKEditor5::Rails::Editor
|
6
6
|
class PropsInlinePlugin < PropsBasePlugin
|
7
|
-
attr_reader :code
|
7
|
+
attr_reader :code, :compress
|
8
8
|
|
9
|
-
def initialize(name, code)
|
9
|
+
def initialize(name, code, compress: true)
|
10
10
|
super(name)
|
11
11
|
|
12
12
|
raise ArgumentError, 'Code must be a String' unless code.is_a?(String)
|
13
13
|
|
14
|
-
@code = "(async () => { #{code
|
14
|
+
@code = "(async () => { #{code} })()"
|
15
|
+
@compress = compress
|
15
16
|
end
|
16
17
|
|
17
|
-
def
|
18
|
+
def try_compress!
|
19
|
+
return unless @compress
|
20
|
+
|
18
21
|
@code = Terser.new(compress: false, mangle: true).compile(@code)
|
19
22
|
end
|
20
23
|
|
@@ -33,19 +36,17 @@ module CKEditor5::Rails::Editor
|
|
33
36
|
end
|
34
37
|
|
35
38
|
def to_html(nonce: nil)
|
36
|
-
code =
|
37
|
-
|
38
|
-
tag.script(code.html_safe, type: 'module', nonce: nonce)
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def wrap_with_handlers(code)
|
44
|
-
<<~JS
|
39
|
+
code = <<~JS
|
45
40
|
window.addEventListener('ckeditor:request-cjs-plugin:#{@plugin.name}', () => {
|
46
|
-
|
41
|
+
try {
|
42
|
+
window['#{@plugin.name}'] = #{@plugin.code};
|
43
|
+
} catch(e) {
|
44
|
+
console.error('Error initializing CKEditor plugin #{@plugin.name}:', e);
|
45
|
+
}
|
47
46
|
}, { once: true });
|
48
47
|
JS
|
48
|
+
|
49
|
+
tag.script(code.html_safe, nonce: nonce)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
@@ -12,8 +12,6 @@ module CKEditor5::Rails::Editor
|
|
12
12
|
|
13
13
|
@min_version = min_version && CKEditor5::Rails::Semver.new(min_version)
|
14
14
|
@max_version = max_version && CKEditor5::Rails::Semver.new(max_version)
|
15
|
-
|
16
|
-
compress!
|
17
15
|
end
|
18
16
|
|
19
17
|
def self.applicable_for_version?(editor_version, min_version: nil, max_version: nil)
|
@@ -4,7 +4,7 @@ require_relative '../editor/props_inline_plugin'
|
|
4
4
|
|
5
5
|
module CKEditor5::Rails::Plugins
|
6
6
|
class CustomTranslationsLoader < CKEditor5::Rails::Editor::PropsInlinePlugin
|
7
|
-
def initialize(translations) # rubocop:disable Metrics/MethodLength
|
7
|
+
def initialize(translations, **kwargs) # rubocop:disable Metrics/MethodLength
|
8
8
|
code = <<~JS.freeze
|
9
9
|
const { Plugin } = await import('ckeditor5');
|
10
10
|
|
@@ -90,8 +90,7 @@ module CKEditor5::Rails::Plugins
|
|
90
90
|
}
|
91
91
|
JS
|
92
92
|
|
93
|
-
super(:CustomTranslationsLoader, code)
|
94
|
-
compress!
|
93
|
+
super(:CustomTranslationsLoader, code, **kwargs)
|
95
94
|
end
|
96
95
|
end
|
97
96
|
end
|
@@ -12,6 +12,7 @@ module CKEditor5::Rails
|
|
12
12
|
class MissingInlinePluginError < StandardError; end
|
13
13
|
class UnsupportedESModuleError < StandardError; end
|
14
14
|
class InvalidPatchPluginError < ArgumentError; end
|
15
|
+
class CompressionDisabledError < StandardError; end
|
15
16
|
|
16
17
|
included do
|
17
18
|
attr_reader :disallow_inline_plugin_compression
|
@@ -35,6 +36,7 @@ module CKEditor5::Rails
|
|
35
36
|
#
|
36
37
|
# @param name [Symbol] Plugin name
|
37
38
|
# @param code [String] JavaScript code defining the plugin
|
39
|
+
# @param compress [Boolean] Whether to compress the code (default: true)
|
38
40
|
# @example Define custom highlight plugin
|
39
41
|
# inline_plugin :MyCustomPlugin, <<~JS
|
40
42
|
# const { Plugin } = await import( 'ckeditor5' );
|
@@ -49,7 +51,7 @@ module CKEditor5::Rails
|
|
49
51
|
# }
|
50
52
|
# }
|
51
53
|
# JS
|
52
|
-
def inline_plugin(name, code)
|
54
|
+
def inline_plugin(name, code, compress: true)
|
53
55
|
if code.match?(/export default/)
|
54
56
|
raise UnsupportedESModuleError,
|
55
57
|
'Inline plugins must not use ES module syntax!' \
|
@@ -61,8 +63,8 @@ module CKEditor5::Rails
|
|
61
63
|
'Plugin code must return a class that extends Plugin!'
|
62
64
|
end
|
63
65
|
|
64
|
-
|
65
|
-
plugin.compress
|
66
|
+
compress = false if @disallow_inline_plugin_compression
|
67
|
+
plugin = Editor::PropsInlinePlugin.new(name, code, compress: compress)
|
66
68
|
|
67
69
|
register_plugin(plugin)
|
68
70
|
end
|
@@ -121,6 +123,23 @@ module CKEditor5::Rails
|
|
121
123
|
builder
|
122
124
|
end
|
123
125
|
|
126
|
+
# Compresses inline plugins to reduce bundle size
|
127
|
+
#
|
128
|
+
# @raise [CompressionDisabledError] If inline plugin compression is disabled
|
129
|
+
# @example Compress inline plugins
|
130
|
+
# try_compress_inline_plugins!
|
131
|
+
# @return [void]
|
132
|
+
# @note This method is called automatically when defining a preset
|
133
|
+
def try_compress_inline_plugins!
|
134
|
+
raise CompressionDisabledError if @disallow_inline_plugin_compression
|
135
|
+
|
136
|
+
config[:plugins].each do |plugin|
|
137
|
+
next unless plugin.is_a?(Editor::PropsInlinePlugin)
|
138
|
+
|
139
|
+
plugin.try_compress!
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
124
143
|
private
|
125
144
|
|
126
145
|
# Register a plugin in the editor configuration.
|
@@ -40,6 +40,8 @@ module CKEditor5::Rails::Presets
|
|
40
40
|
end
|
41
41
|
|
42
42
|
preset.instance_eval(&block)
|
43
|
+
preset.try_compress_inline_plugins!
|
44
|
+
|
43
45
|
@presets[name] = preset
|
44
46
|
end
|
45
47
|
|
@@ -54,7 +56,10 @@ module CKEditor5::Rails::Presets
|
|
54
56
|
# end
|
55
57
|
# end
|
56
58
|
def override(name, &block)
|
57
|
-
@presets[name]
|
59
|
+
preset = @presets[name]
|
60
|
+
|
61
|
+
preset.instance_eval(&block)
|
62
|
+
preset.try_compress_inline_plugins!
|
58
63
|
end
|
59
64
|
|
60
65
|
alias extend override
|
@@ -328,6 +328,7 @@ module CKEditor5::Rails
|
|
328
328
|
# Configure custom translations for the editor
|
329
329
|
# @param lang_code [Symbol] Language code for translations (e.g. :en, :pl)
|
330
330
|
# @param translations [Hash] A hash containing translations in format { key => translation }
|
331
|
+
# @param compress [Boolean] Whether to compress the translations
|
331
332
|
# @example Add multiple translations
|
332
333
|
# custom_translations :en, {
|
333
334
|
# 'my.button': 'My Button'
|
@@ -346,14 +347,14 @@ module CKEditor5::Rails
|
|
346
347
|
# ]
|
347
348
|
# }
|
348
349
|
# @return [void]
|
349
|
-
def custom_translations(lang_code = nil, translations = {})
|
350
|
+
def custom_translations(lang_code = nil, translations = {}, compress: true)
|
350
351
|
return @custom_translations if lang_code.blank?
|
351
352
|
|
352
353
|
@custom_translations[lang_code.to_sym] ||= {}
|
353
354
|
@custom_translations[lang_code.to_sym].merge!(translations)
|
354
355
|
|
355
356
|
plugins.remove(:CustomTranslationsLoader)
|
356
|
-
plugins.prepend(Plugins::CustomTranslationsLoader.new(@custom_translations))
|
357
|
+
plugins.prepend(Plugins::CustomTranslationsLoader.new(@custom_translations, compress: compress))
|
357
358
|
end
|
358
359
|
|
359
360
|
# Configure editor language
|
@@ -381,34 +382,37 @@ module CKEditor5::Rails
|
|
381
382
|
|
382
383
|
# Configure simple upload adapter
|
383
384
|
# @param upload_url [String] Upload endpoint URL
|
385
|
+
# @param compress [Boolean] Enable compression
|
384
386
|
# @example Enable upload adapter
|
385
387
|
# simple_upload_adapter '/uploads'
|
386
|
-
def simple_upload_adapter(upload_url = '/uploads')
|
388
|
+
def simple_upload_adapter(upload_url = '/uploads', compress: true)
|
387
389
|
plugins do
|
388
390
|
remove(:Base64UploadAdapter)
|
389
391
|
end
|
390
392
|
|
391
|
-
plugin(Plugins::SimpleUploadAdapter.new)
|
393
|
+
plugin(Plugins::SimpleUploadAdapter.new(compress: compress))
|
392
394
|
configure(:simpleUpload, { uploadUrl: upload_url })
|
393
395
|
end
|
394
396
|
|
395
397
|
# Configure WProofreader plugin
|
396
398
|
# @param version [String, nil] Plugin version
|
397
399
|
# @param cdn [String, nil] CDN URL
|
400
|
+
# @param compress [Boolean] Enable compression
|
398
401
|
# @param config [Hash] Plugin configuration
|
399
402
|
# @example Basic configuration
|
400
403
|
# wproofreader serviceId: 'your-service-ID',
|
401
404
|
# srcUrl: 'https://svc.webspellchecker.net/spellcheck31/wscbundle/wscbundle.js'
|
402
|
-
def wproofreader(version: nil, cdn: nil, **config)
|
405
|
+
def wproofreader(version: nil, cdn: nil, compress: true, **config)
|
403
406
|
configure :wproofreader, config
|
404
407
|
plugins do
|
405
|
-
prepend(Plugins::WProofreaderSync.new)
|
408
|
+
prepend(Plugins::WProofreaderSync.new(compress: compress))
|
406
409
|
append(Plugins::WProofreader.new(version: version, cdn: cdn))
|
407
410
|
end
|
408
411
|
end
|
409
412
|
|
410
413
|
# Configure special characters plugin
|
411
414
|
#
|
415
|
+
# @param compress [Boolean] Enable compression
|
412
416
|
# @yield Block for configuring special characters
|
413
417
|
# @example Basic configuration with block
|
414
418
|
# special_characters do
|
@@ -434,14 +438,14 @@ module CKEditor5::Rails
|
|
434
438
|
# item 'heart', '❤️'
|
435
439
|
# end
|
436
440
|
# end
|
437
|
-
def special_characters(&block)
|
441
|
+
def special_characters(compress: true, &block)
|
438
442
|
builder = SpecialCharactersBuilder.new
|
439
443
|
builder.instance_eval(&block) if block_given?
|
440
444
|
|
441
445
|
plugins do
|
442
446
|
append(:SpecialCharacters)
|
443
447
|
builder.packs_plugins.each { |pack| append(pack) }
|
444
|
-
prepend(Plugins::SpecialCharactersBootstrap.new)
|
448
|
+
prepend(Plugins::SpecialCharactersBootstrap.new(compress: compress))
|
445
449
|
end
|
446
450
|
|
447
451
|
configure(:specialCharactersBootstrap, builder.to_h)
|
@@ -361,7 +361,7 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
|
361
361
|
|
362
362
|
describe '#ckeditor5_inline_plugins_tags' do
|
363
363
|
let(:preset) do
|
364
|
-
CKEditor5::Rails::Presets::PresetBuilder.new do
|
364
|
+
preset = CKEditor5::Rails::Presets::PresetBuilder.new do
|
365
365
|
inline_plugin 'Plugin1', <<~JAVASCRIPT
|
366
366
|
const { Plugin } = await import( 'ckeditor5' );
|
367
367
|
|
@@ -382,10 +382,13 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
|
382
382
|
}
|
383
383
|
JAVASCRIPT
|
384
384
|
end
|
385
|
+
|
386
|
+
preset.try_compress_inline_plugins!
|
387
|
+
preset
|
385
388
|
end
|
386
389
|
|
387
390
|
let(:another_preset) do
|
388
|
-
CKEditor5::Rails::Presets::PresetBuilder.new do
|
391
|
+
preset = CKEditor5::Rails::Presets::PresetBuilder.new do
|
389
392
|
inline_plugin 'Plugin3', <<~JAVASCRIPT
|
390
393
|
const { Plugin } = await import( 'ckeditor5' );
|
391
394
|
|
@@ -396,6 +399,9 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
|
396
399
|
}
|
397
400
|
JAVASCRIPT
|
398
401
|
end
|
402
|
+
|
403
|
+
preset.try_compress_inline_plugins!
|
404
|
+
preset
|
399
405
|
end
|
400
406
|
|
401
407
|
before do
|
@@ -83,6 +83,24 @@ RSpec.describe CKEditor5::Rails::Context::PresetBuilder do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
describe 'try_compress_inline_plugins!' do
|
87
|
+
let(:plugin_code) do
|
88
|
+
<<~JAVASCRIPT
|
89
|
+
const { Plugin } = await import( 'ckeditor5' );
|
90
|
+
|
91
|
+
return class Abc extends Plugin {}
|
92
|
+
JAVASCRIPT
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'raises CompressionDisabledError when compression is disabled' do
|
96
|
+
builder.instance_variable_set(:@disallow_inline_plugin_compression, true)
|
97
|
+
|
98
|
+
expect do
|
99
|
+
builder.try_compress_inline_plugins!
|
100
|
+
end.to raise_error(CKEditor5::Rails::Presets::Concerns::PluginMethods::CompressionDisabledError)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
86
104
|
describe '#inline_plugin' do
|
87
105
|
let(:plugin_code) do
|
88
106
|
<<~JAVASCRIPT
|
@@ -26,6 +26,34 @@ RSpec.describe CKEditor5::Rails::Editor::PropsInlinePlugin do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
describe '#try_compress!' do
|
30
|
+
let(:plugin) { described_class.new(:CustomPlugin, valid_code) }
|
31
|
+
let(:compiled_code) { '(async()=>{const compressed_code})()' }
|
32
|
+
let(:terser_instance) { instance_double('Terser') }
|
33
|
+
|
34
|
+
context 'when compression is enabled' do
|
35
|
+
it 'compresses the code using Terser' do
|
36
|
+
expect(Terser).to receive(:new).with(compress: false, mangle: true).and_return(terser_instance)
|
37
|
+
expect(terser_instance).to receive(:compile).with(plugin.code).and_return(compiled_code)
|
38
|
+
|
39
|
+
plugin.try_compress!
|
40
|
+
expect(plugin.code).to eq(compiled_code)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when compression is disabled' do
|
45
|
+
let(:plugin) { described_class.new(:CustomPlugin, valid_code, compress: false) }
|
46
|
+
let(:original_code) { plugin.code.dup }
|
47
|
+
|
48
|
+
it 'does not modify the code' do
|
49
|
+
expect(Terser).not_to receive(:new)
|
50
|
+
|
51
|
+
plugin.try_compress!
|
52
|
+
expect(plugin.code).to eq(original_code)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
29
57
|
describe '#to_h' do
|
30
58
|
it 'returns correct hash representation' do
|
31
59
|
plugin = described_class.new(:CustomPlugin, valid_code)
|
@@ -280,7 +280,8 @@ RSpec.describe CKEditor5::Rails::Presets::PresetBuilder do
|
|
280
280
|
end
|
281
281
|
|
282
282
|
it 'adds inline plugin to configuration' do
|
283
|
-
builder.inline_plugin(:CustomPlugin, plugin_code)
|
283
|
+
builder.inline_plugin(:CustomPlugin, plugin_code, compress: true)
|
284
|
+
builder.try_compress_inline_plugins!
|
284
285
|
|
285
286
|
plugin = builder.config[:plugins].first
|
286
287
|
expect(plugin).to be_a(CKEditor5::Rails::Editor::PropsInlinePlugin)
|
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.29.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-03-
|
12
|
+
date: 2025-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|