vite_ruby 2.0.0.beta.6 → 3.0.0

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: '0058a6fc7f925f10e97f390c028abbbecc2c4c9cc5e27f214cbcba826c42fe69'
4
- data.tar.gz: ebc2076502683d817f99c284fc2f6ec7adfa75dfd41f8f623a72e221cd56da5a
3
+ metadata.gz: '059c10492c1cc0b47f4347ef78f0de17c9220392611945ba189b5169c02729ba'
4
+ data.tar.gz: 534b84c6bd67bf9e7e0a74bec9ad8d277ebe37693829d3d995a26eba5b8ac2b2
5
5
  SHA512:
6
- metadata.gz: 728652c1e4f0884bde8a1823f9a70ffdf12ce509fdb8f7ae898133d8f9084cbcc1a0204da38212c8281f02e4e77f0ec8a481c85ce7e3f74be189965d34fbe791
7
- data.tar.gz: 6ed6080dcb36974a061d974188ede76c700b27e97a63ec5b357225acbd04dc5f555a13bc45f4790c73d9daba20c104181583f3a650a0fd7da6dc544c4b680b10
6
+ metadata.gz: e23a593394165dfea0f743fab1699535e9c1a531cde25cd53a85d19fb454795851fe85d83907d802d7dae6adbca25b449b0c7b6ab33b6530102fb49a5526aeb4
7
+ data.tar.gz: dcf237f94f9009a4427a27e807a66c3aae8a77b6ca39370a03c0f860d2d4b2d2bb4ecb93bc0f78f7a979c2105fe126c79c0297bdc32e24d7d88f860af2baf184
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # [3.0.0](https://github.com/ElMassimo/vite_ruby/compare/vite_ruby@1.2.20...vite_ruby@3.0.0) (2021-08-16)
2
+
3
+ See https://github.com/ElMassimo/vite_ruby/pull/116 for features and breaking changes.
4
+
1
5
  ## [1.2.20](https://github.com/ElMassimo/vite_ruby/compare/vite_ruby@1.2.18...vite_ruby@1.2.20) (2021-07-30)
2
6
 
3
7
 
data/default.vite.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "additionalInputGlobs": ["{assets,fonts,icons,images}/**/*"],
2
+ "additionalEntrypoints": ["~/{assets,fonts,icons,images}/**/*"],
3
3
  "assetHost": null,
4
4
  "assetsDir": "assets",
5
5
  "autoBuild": false,
@@ -10,6 +10,7 @@
10
10
  "publicDir": "public",
11
11
  "entrypointsDir": "entrypoints",
12
12
  "sourceCodeDir": "app/frontend",
13
+ "skipCompatibilityCheck": false,
13
14
  "host": "localhost",
14
15
  "https": null,
15
16
  "port": 3036,
data/lib/tasks/vite.rake CHANGED
@@ -40,13 +40,15 @@ namespace :vite do
40
40
  end
41
41
  end
42
42
 
43
- if Rake::Task.task_defined?('assets:precompile')
44
- Rake::Task['assets:precompile'].enhance do |task|
45
- prefix = task.name.split(/#|assets:precompile/).first
46
- Rake::Task["#{ prefix }vite:build"].invoke
43
+ unless ENV['VITE_RUBY_SKIP_ASSETS_PRECOMPILE_EXTENSION'] == 'true'
44
+ if Rake::Task.task_defined?('assets:precompile')
45
+ Rake::Task['assets:precompile'].enhance do |task|
46
+ prefix = task.name.split(/#|assets:precompile/).first
47
+ Rake::Task["#{ prefix }vite:build"].invoke
48
+ end
49
+ else
50
+ Rake::Task.define_task('assets:precompile' => ['vite:install_dependencies', 'vite:build'])
47
51
  end
48
- else
49
- Rake::Task.define_task('assets:precompile' => ['vite:install_dependencies', 'vite:build'])
50
52
  end
51
53
 
52
54
  # Any prerequisite task that installs packages should also install build dependencies.
data/lib/vite_ruby.rb CHANGED
@@ -23,9 +23,7 @@ class ViteRuby
23
23
  COMPANION_LIBRARIES = {
24
24
  'vite_rails' => 'rails',
25
25
  'vite_hanami' => 'hanami',
26
- 'vite_roda' => 'roda',
27
26
  'vite_padrino' => 'padrino',
28
- 'vite_sinatra' => 'sinatra',
29
27
  'jekyll-vite' => 'jekyll',
30
28
  'vite_rails_legacy' => 'rails',
31
29
  }
@@ -3,16 +3,22 @@
3
3
  require 'time'
4
4
 
5
5
  # Internal: Value object with information about the last build.
6
- ViteRuby::Build = Struct.new(:success, :timestamp, :digest, :current_digest) do
6
+ ViteRuby::Build = Struct.new(:success, :timestamp, :vite_ruby, :digest, :current_digest) do
7
7
  # Internal: Combines information from a previous build with the current digest.
8
8
  def self.from_previous(attrs, current_digest)
9
- new(attrs['success'], attrs['timestamp'] || 'never', attrs['digest'] || 'none', current_digest)
9
+ new(
10
+ attrs['success'],
11
+ attrs['timestamp'] || 'never',
12
+ attrs['vite_ruby'] || 'unknown',
13
+ attrs['digest'] || 'none',
14
+ current_digest,
15
+ )
10
16
  end
11
17
 
12
18
  # Internal: A build is considered stale when watched files have changed since
13
19
  # the last build, or when a certain time has ellapsed in case of failure.
14
20
  def stale?
15
- digest != current_digest || retry_failed?
21
+ digest != current_digest || retry_failed? || vite_ruby != ViteRuby::VERSION
16
22
  end
17
23
 
18
24
  # Internal: A build is considered fresh if watched files have not changed, or
@@ -31,7 +37,12 @@ ViteRuby::Build = Struct.new(:success, :timestamp, :digest, :current_digest) do
31
37
 
32
38
  # Internal: Returns a new build with the specified result.
33
39
  def with_result(success)
34
- self.class.new(success, Time.now.strftime('%F %T'), current_digest)
40
+ self.class.new(
41
+ success,
42
+ Time.now.strftime('%F %T'),
43
+ ViteRuby::VERSION,
44
+ current_digest,
45
+ )
35
46
  end
36
47
 
37
48
  # Internal: Returns a JSON string with the metadata of the build.
@@ -57,7 +57,7 @@ private
57
57
  # changes, and skip Vite builds if no files have changed.
58
58
  def watched_files_digest
59
59
  Dir.chdir File.expand_path(config.root) do
60
- files = Dir[*watched_paths].reject { |f| File.directory?(f) }
60
+ files = Dir[*config.watched_paths].reject { |f| File.directory?(f) }
61
61
  file_ids = files.sort.map { |f| "#{ File.basename(f) }/#{ Digest::SHA1.file(f).hexdigest }" }
62
62
  Digest::SHA1.hexdigest(file_ids.join('/'))
63
63
  end
@@ -88,22 +88,4 @@ private
88
88
  logger.error '❌ Check that vite and vite-plugin-ruby are in devDependencies and have been installed. ' if stderr.include?('ERR! canceled')
89
89
  end
90
90
  end
91
-
92
- # Internal: Files and directories that should be watched for changes.
93
- #
94
- # NOTE: You can specify additional ones in vite.json using "watchAdditionalPaths": [...]
95
- def watched_paths
96
- [
97
- *config.watch_additional_paths,
98
- "#{ config.source_code_dir }/**/*",
99
- 'yarn.lock',
100
- 'package-lock.json',
101
- 'pnpm-lock.yaml',
102
- 'package.json',
103
- 'vite.config.ts',
104
- 'vite.config.js',
105
- 'windi.config.ts',
106
- config.config_path,
107
- ].freeze
108
- end
109
91
  end
@@ -24,7 +24,7 @@ module ViteRuby::CLI::FileUtils
24
24
  # @api private
25
25
  def cp(source, destination)
26
26
  mkdir_p(destination)
27
- FileUtils.cp(source, destination)
27
+ FileUtils.cp(source, destination) unless File.exist?(destination)
28
28
  end
29
29
 
30
30
  # Adds a new line at the bottom of the file.
@@ -32,10 +32,10 @@ module ViteRuby::CLI::FileUtils
32
32
  # @since 1.2.11
33
33
  # @api private
34
34
  def append(path, contents)
35
- mkdir_p(path)
35
+ content = read_lines(path)
36
+ return if content.join.include?(contents)
36
37
 
37
- content = File.readlines(path)
38
- content << "\n" unless content.last.end_with?("\n")
38
+ content << "\n" unless content.last&.end_with?("\n")
39
39
  content << "#{ contents }\n"
40
40
 
41
41
  write(path, content)
@@ -46,7 +46,7 @@ module ViteRuby::CLI::FileUtils
46
46
  # @since 1.2.11
47
47
  # @api private
48
48
  def replace_first_line(path, target, replacement)
49
- content = File.readlines(path)
49
+ content = read_lines(path)
50
50
  content[index(content, path, target)] = "#{ replacement }\n"
51
51
 
52
52
  write(path, content)
@@ -86,6 +86,11 @@ module ViteRuby::CLI::FileUtils
86
86
  Pathname.new(path).dirname.mkpath
87
87
  end
88
88
 
89
+ # Returns an array with lines in the specified file, empty if it doesn't exist.
90
+ def read_lines(path)
91
+ File.exist?(path) ? File.readlines(path) : []
92
+ end
93
+
89
94
  # @since 1.2.11
90
95
  # @api private
91
96
  def index(content, path, target)
@@ -103,7 +108,9 @@ module ViteRuby::CLI::FileUtils
103
108
  # @since 1.2.11
104
109
  # @api private
105
110
  def _inject_line_before(path, target, contents, finder)
106
- content = File.readlines(path)
111
+ content = read_lines(path)
112
+ return if content.join.include?(contents)
113
+
107
114
  i = finder.call(content, path, target)
108
115
 
109
116
  content.insert(i, "#{ contents }\n")
@@ -113,7 +120,9 @@ module ViteRuby::CLI::FileUtils
113
120
  # @since 1.2.11
114
121
  # @api private
115
122
  def _inject_line_after(path, target, contents, finder)
116
- content = File.readlines(path)
123
+ content = read_lines(path)
124
+ return if content.join.include?(contents)
125
+
117
126
  i = finder.call(content, path, target)
118
127
 
119
128
  content.insert(i + 1, "#{ contents }\n")
@@ -71,6 +71,7 @@ private
71
71
  # Internal: Creates the Vite and vite-plugin-ruby configuration files.
72
72
  def create_configuration_files
73
73
  copy_template 'config/vite.config.ts', to: root.join('vite.config.ts')
74
+ append root.join('Procfile.dev'), 'vite: bin/vite dev'
74
75
  setup_app_files
75
76
  ViteRuby.reload_with(config_path: config.config_path)
76
77
  end
@@ -79,13 +80,8 @@ private
79
80
  def install_js_dependencies
80
81
  package_json = root.join('package.json')
81
82
  write(package_json, '{}') unless package_json.exist?
82
-
83
- Dir.chdir(root) do
84
- deps = js_dependencies.join(' ')
85
- _, stderr, status = ViteRuby::IO.capture("npx --package @antfu/ni -- ni -D #{ deps }", stdin_data: "\n")
86
- _, stderr, = ViteRuby::IO.capture("yarn add -D #{ deps }") unless status.success?
87
- say("Could not install JS dependencies.\n", stderr) unless stderr.to_s.empty?
88
- end
83
+ deps = js_dependencies.join(' ')
84
+ run_with_capture("#{ npm_install } -D #{ deps }", stdin_data: "\n")
89
85
  end
90
86
 
91
87
  # Internal: Adds compilation output dirs to git ignore.
@@ -114,8 +110,18 @@ private
114
110
  end
115
111
 
116
112
  def run_with_capture(*args, **options)
117
- _, stderr, status = ViteRuby::IO.capture(*args, **options)
118
- say(err) unless status.success? || stderr.to_s.empty?
113
+ Dir.chdir(root) do
114
+ _, stderr, status = ViteRuby::IO.capture(*args, **options)
115
+ say(stderr) unless status.success? || stderr.to_s.empty?
116
+ end
117
+ end
118
+
119
+ # Internal: Support all popular package managers.
120
+ def npm_install
121
+ return 'yarn add' if root.join('yarn.lock').exist?
122
+ return 'pnpm install' if root.join('pnpm-lock.yaml').exist?
123
+
124
+ 'npm install'
119
125
  end
120
126
 
121
127
  # Internal: Avoid printing warning about missing vite.json, we will create one.
@@ -5,10 +5,7 @@ class ViteRuby::CLI::UpgradePackages < ViteRuby::CLI::Install
5
5
 
6
6
  def call(**)
7
7
  say 'Upgrading npm packages'
8
-
9
- Dir.chdir(root) do
10
- deps = js_dependencies.join(' ')
11
- run_with_capture("npx --package @antfu/ni -- ni -D #{ deps }")
12
- end
8
+ deps = js_dependencies.join(' ')
9
+ run_with_capture("#{ npm_install } -D #{ deps }")
13
10
  end
14
11
  end
@@ -108,6 +108,8 @@ class ViteRuby::Commands
108
108
  packages = `npm ls vite vite-plugin-ruby`
109
109
  packages_msg = packages.include?('vite@') ? "installed packages:\n#{ packages }" : '❌ Check that vite and vite-plugin-ruby have been added as development dependencies and installed.'
110
110
  $stdout.puts packages_msg
111
+
112
+ ViteRuby::CompatibilityCheck.verify_plugin_version(config.root)
111
113
  end
112
114
  end
113
115
 
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ # Internal: Verifies that the installed vite-plugin-ruby version is compatible
6
+ # with the current version of vite_ruby.
7
+ #
8
+ # This helps to prevent more subtle runtime errors if there is a mismatch in the
9
+ # manifest schema.
10
+ module ViteRuby::CompatibilityCheck
11
+ class << self
12
+ # Public: Attempt to verify that the vite-plugin-ruby version is compatible.
13
+ def verify_plugin_version(root)
14
+ package = JSON.parse(root.join('package.json').read) rescue {}
15
+ requirement = package.dig('devDependencies', 'vite-plugin-ruby') ||
16
+ package.dig('dependencies', 'vite-plugin-ruby')
17
+
18
+ raise_unless_satisfied(requirement, ViteRuby::DEFAULT_PLUGIN_VERSION)
19
+ end
20
+
21
+ # Internal: Notifies the user of a possible incompatible plugin.
22
+ def raise_unless_satisfied(npm_req, ruby_req)
23
+ unless compatible_plugin?(npm_req, ruby_req)
24
+ raise ArgumentError, <<~ERROR
25
+ vite-plugin-ruby@#{ npm_req } might not be compatible with vite_ruby-#{ ViteRuby::VERSION }
26
+
27
+ You may disable this check if needed: https://vite-ruby.netlify.app/config/#skipCompatibilityCheck
28
+
29
+ You may upgrade both by running:
30
+
31
+ bundle exec vite upgrade
32
+ ERROR
33
+ end
34
+ end
35
+
36
+ # Internal: Returns true unless the check is performed and does not meet the
37
+ # requirement.
38
+ def compatible_plugin?(npm_req, ruby_req)
39
+ npm_req, ruby_req = [npm_req, ruby_req]
40
+ .map { |req| Gem::Requirement.new(req.sub('^', '~>')) }
41
+
42
+ current_version = npm_req.requirements.first.second
43
+
44
+ ruby_req.satisfied_by?(current_version)
45
+ rescue StandardError
46
+ true
47
+ end
48
+ end
49
+ end
@@ -52,6 +52,18 @@ class ViteRuby::Config
52
52
  end.merge(ViteRuby.env)
53
53
  end
54
54
 
55
+ # Internal: Files and directories that should be watched for changes.
56
+ def watched_paths
57
+ [
58
+ *(watch_additional_paths + additional_entrypoints).reject { |dir|
59
+ dir.start_with?('~/') || dir.start_with?(source_code_dir)
60
+ },
61
+ "#{ source_code_dir }/**/*",
62
+ config_path,
63
+ *DEFAULT_WATCHED_PATHS,
64
+ ].freeze
65
+ end
66
+
55
67
  private
56
68
 
57
69
  # Internal: Coerces all the configuration values, in case they were passed
@@ -61,7 +73,7 @@ private
61
73
  config['port'] = config['port'].to_i
62
74
  config['root'] = Pathname.new(config['root'])
63
75
  config['build_cache_dir'] = config['root'].join(config['build_cache_dir'])
64
- coerce_booleans(config, 'auto_build', 'hide_build_console_output', 'https')
76
+ coerce_booleans(config, 'auto_build', 'hide_build_console_output', 'https', 'skip_compatibility_check')
65
77
  end
66
78
 
67
79
  # Internal: Coerces configuration options to boolean.
@@ -71,6 +83,7 @@ private
71
83
 
72
84
  def initialize(attrs)
73
85
  @config = attrs.tap { |config| coerce_values(config) }.freeze
86
+ ViteRuby::CompatibilityCheck.verify_plugin_version(root) unless skip_compatibility_check
74
87
  end
75
88
 
76
89
  class << self
@@ -134,7 +147,7 @@ private
134
147
  multi_env_config.fetch('all', {})
135
148
  .merge(multi_env_config.fetch(mode, {}))
136
149
  rescue Errno::ENOENT => error
137
- warn "Check that your vite.json configuration file is available in the load path:\n\n\t#{ error.message }\n\n"
150
+ $stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{ error.message }\n\n"
138
151
  {}
139
152
  end
140
153
  end
@@ -143,11 +156,24 @@ private
143
156
  DEFAULT_CONFIG = load_json("#{ __dir__ }/../../default.vite.json").freeze
144
157
 
145
158
  # Internal: Configuration options that can not be provided as env vars.
146
- NOT_CONFIGURABLE_WITH_ENV = %w[additional_input_globs watch_additional_paths].freeze
159
+ NOT_CONFIGURABLE_WITH_ENV = %w[additional_entrypoints watch_additional_paths].freeze
147
160
 
148
161
  # Internal: Configuration options that can be provided as env vars.
149
162
  CONFIGURABLE_WITH_ENV = (DEFAULT_CONFIG.keys + %w[mode root] - NOT_CONFIGURABLE_WITH_ENV).freeze
150
163
 
164
+ # Internal: If any of these files is modified the build won't be skipped.
165
+ DEFAULT_WATCHED_PATHS = %w[
166
+ package-lock.json
167
+ package.json
168
+ pnpm-lock.yaml
169
+ postcss.config.js
170
+ tailwind.config.js
171
+ vite.config.js
172
+ vite.config.ts
173
+ windi.config.ts
174
+ yarn.lock
175
+ ].freeze
176
+
151
177
  public
152
178
 
153
179
  # Define getters for the configuration options.
@@ -85,6 +85,9 @@ protected
85
85
 
86
86
  private
87
87
 
88
+ # Internal: The prefix used by Vite.js to request files with an absolute path.
89
+ FS_PREFIX = '/@fs/'
90
+
88
91
  extend Forwardable
89
92
 
90
93
  def_delegators :@vite_ruby, :config, :builder, :dev_server_running?
@@ -135,7 +138,9 @@ private
135
138
  def resolve_references(manifest)
136
139
  manifest.each_value do |entry|
137
140
  entry['file'] = prefix_vite_asset(entry['file'])
138
- entry['css'] = entry['css'].map { |path| prefix_vite_asset(path) } if entry['css']
141
+ %w[css assets].each do |key|
142
+ entry[key] = entry[key].map { |path| prefix_vite_asset(path) } if entry[key]
143
+ end
139
144
  entry['imports']&.map! { |name| manifest.fetch(name) }
140
145
  end
141
146
  end
@@ -143,13 +148,26 @@ private
143
148
  # Internal: Resolves the manifest entry name for the specified resource.
144
149
  def resolve_entry_name(name, type: nil)
145
150
  name = with_file_extension(name.to_s, type)
146
- name = name[1..-1] if name.start_with?('/')
147
151
 
148
- # Prefix scripts and stylesheets with the entrypoints dir.
149
- if (type || File.dirname(name) == '.') && !name.start_with?(config.entrypoints_dir)
150
- File.join(config.entrypoints_dir, name)
152
+ raise ArgumentError, "Asset names can not be relative. Found: #{ name }" if name.start_with?('.') && !name.include?('legacy-polyfills')
153
+
154
+ # Explicit path, relative to the source_code_dir.
155
+ name.sub(%r{^~/(.+)$}) { return Regexp.last_match(1) }
156
+
157
+ # Explicit path, relative to the project root.
158
+ name.sub(%r{^/(.+)$}) { return resolve_absolute_entry(Regexp.last_match(1)) }
159
+
160
+ # Sugar: Prefix with the entrypoints dir if the path is not nested.
161
+ name.include?('/') ? name : File.join(config.entrypoints_dir, name)
162
+ end
163
+
164
+ # Internal: Entry names in the manifest are relative to the Vite.js.
165
+ # During develoment, files outside the root must be requested explicitly.
166
+ def resolve_absolute_entry(name)
167
+ if dev_server_running?
168
+ File.join(FS_PREFIX, config.root, name)
151
169
  else
152
- name
170
+ config.root.join(name).relative_path_from(config.vite_root_dir).to_s
153
171
  end
154
172
  end
155
173
 
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ViteRuby
4
- VERSION = '2.0.0.beta.6'
4
+ VERSION = '3.0.0'
5
5
 
6
6
  # Internal: Versions used by default when running `vite install`.
7
- DEFAULT_VITE_VERSION = '^2.5.0-beta.2'
8
- DEFAULT_PLUGIN_VERSION = '^3.0.0-beta.2'
7
+ DEFAULT_VITE_VERSION = '^2.5.0'
8
+ DEFAULT_PLUGIN_VERSION = '^3.0.0'
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vite_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta.6
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Máximo Mussini
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-13 00:00:00.000000000 Z
11
+ date: 2021-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-cli
@@ -184,6 +184,7 @@ files:
184
184
  - lib/vite_ruby/cli/version.rb
185
185
  - lib/vite_ruby/cli/vite.rb
186
186
  - lib/vite_ruby/commands.rb
187
+ - lib/vite_ruby/compatibility_check.rb
187
188
  - lib/vite_ruby/config.rb
188
189
  - lib/vite_ruby/dev_server_proxy.rb
189
190
  - lib/vite_ruby/error.rb
@@ -200,8 +201,8 @@ homepage: https://github.com/ElMassimo/vite_ruby
200
201
  licenses:
201
202
  - MIT
202
203
  metadata:
203
- source_code_uri: https://github.com/ElMassimo/vite_ruby/tree/vite_ruby@2.0.0.beta.6/vite_ruby
204
- changelog_uri: https://github.com/ElMassimo/vite_ruby/blob/vite_ruby@2.0.0.beta.6/vite_ruby/CHANGELOG.md
204
+ source_code_uri: https://github.com/ElMassimo/vite_ruby/tree/vite_ruby@3.0.0/vite_ruby
205
+ changelog_uri: https://github.com/ElMassimo/vite_ruby/blob/vite_ruby@3.0.0/vite_ruby/CHANGELOG.md
205
206
  post_install_message: "Thanks for installing Vite Ruby!\n\nIf you upgraded the gem
206
207
  manually, please run:\n\tbundle exec vite upgrade"
207
208
  rdoc_options: []
@@ -214,9 +215,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
214
215
  version: '2.4'
215
216
  required_rubygems_version: !ruby/object:Gem::Requirement
216
217
  requirements:
217
- - - ">"
218
+ - - ">="
218
219
  - !ruby/object:Gem::Version
219
- version: 1.3.1
220
+ version: '0'
220
221
  requirements: []
221
222
  rubygems_version: 3.1.4
222
223
  signing_key: