amber_extension_generator 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +185 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.solargraph.yml +20 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +20 -0
  8. data/Gemfile.lock +116 -0
  9. data/LICENSE +21 -0
  10. data/README.md +37 -0
  11. data/Rakefile +16 -0
  12. data/amber_extension_generator.gemspec +46 -0
  13. data/exe/amber_extension_generator +6 -0
  14. data/lib/amber_extension_generator/cli/args.rb +47 -0
  15. data/lib/amber_extension_generator/cli/gem_generator.rb +406 -0
  16. data/lib/amber_extension_generator/cli.rb +17 -0
  17. data/lib/amber_extension_generator/gem_name.rb +6 -0
  18. data/lib/amber_extension_generator/templates/assets/stylesheets/components.scss +2 -0
  19. data/lib/amber_extension_generator/templates/assets/stylesheets/main.scss.erb +6 -0
  20. data/lib/amber_extension_generator/templates/bin/dev.erb +10 -0
  21. data/lib/amber_extension_generator/templates/bin/generate.erb +142 -0
  22. data/lib/amber_extension_generator/templates/components/base_component.rb.erb +11 -0
  23. data/lib/amber_extension_generator/templates/components.rb +4 -0
  24. data/lib/amber_extension_generator/templates/rails_dummy/Gemfile.erb +33 -0
  25. data/lib/amber_extension_generator/templates/railtie.rb.erb +13 -0
  26. data/lib/amber_extension_generator/templates/templates/component.rb.tt +11 -0
  27. data/lib/amber_extension_generator/templates/templates/component_test.rb.tt +17 -0
  28. data/lib/amber_extension_generator/templates/templates/style.scss.tt +5 -0
  29. data/lib/amber_extension_generator/templates/templates/view.html.erb.tt +8 -0
  30. data/lib/amber_extension_generator/templates/test/component_test_case.rb +7 -0
  31. data/lib/amber_extension_generator/version.rb +6 -0
  32. data/lib/amber_extension_generator.rb +16 -0
  33. data/lib/dummy_rails_app_template.rb +61 -0
  34. metadata +127 -0
@@ -0,0 +1,406 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ require 'rainbow/refinement'
6
+ require 'cli/ui'
7
+ require 'tty-command'
8
+ require 'erb'
9
+
10
+ using ::Rainbow
11
+
12
+ module ::AmberExtensionGenerator
13
+ module CLI
14
+ # Generates a new extension gem
15
+ class GemGenerator
16
+ class << self
17
+ # @param args [::AmberExtensionGenerator::CLI::Args]
18
+ # @return [void]
19
+ def call(args)
20
+ new(args).call
21
+ end
22
+ end
23
+
24
+ # @param args [::AmberExtensionGenerator::CLI::Args]
25
+ def initialize(args)
26
+ @args = args
27
+ end
28
+
29
+ # @return [void]
30
+ def call
31
+ ::CLI::UI::StdoutRouter.enable
32
+ generate_amber_gem
33
+ puts
34
+ generate_rails_dummy_app
35
+ end
36
+
37
+ private
38
+
39
+ # @return [void]
40
+ def generate_amber_gem
41
+ ::CLI::UI::Frame.open 'Create gem', color: :green do # rubocop:disable Metrics/BlockLength
42
+ ::CLI::UI::Frame.open 'Generate gem with bundler' do
43
+ syscall "bundle gem #{root_path} --linter=rubocop --ci=github --test=minitest", input: "y\n"
44
+ end
45
+
46
+ ::CLI::UI::Frame.open 'Patch gem' do
47
+ template 'components/base_component.rb.erb', gem_entry_folder_path / 'components' / 'base_component.rb'
48
+
49
+ copy 'components.rb', gem_entry_folder_path / 'components.rb'
50
+ template 'railtie.rb.erb', gem_entry_folder_path / 'railtie.rb'
51
+
52
+ substitute gem_entry_file_path, /^end/, <<~RUBY.chomp
53
+ end
54
+
55
+ require 'pathname'
56
+ require_relative '#{gem_entry_folder_path.basename}/railtie' if defined?(::Rails::Railtie)
57
+ require_relative '#{gem_entry_folder_path.basename}/components'
58
+
59
+ # Override this if you want to have a different name for the
60
+ # base component of your gem
61
+ #{root_module_name}::ABSTRACT_COMPONENT = #{root_module_name}::BaseComponent
62
+ #{root_module_name}::ROOT_PATH = ::Pathname.new ::File.expand_path('#{relative_path_to_root}', __dir__)
63
+ RUBY
64
+
65
+ create '.rubocop.yml', ::File.read(ROOT_GEM_PATH / '.rubocop.yml')
66
+
67
+ template 'bin/generate.erb', 'bin/generate'
68
+ template 'bin/dev.erb', 'bin/dev'
69
+ make_executable 'bin/generate'
70
+ make_executable 'bin/dev'
71
+
72
+ make_dir 'assets/stylesheets'
73
+ template 'assets/stylesheets/main.scss.erb', main_stylesheet_path
74
+ copy 'assets/stylesheets/components.scss', stylesheet_dir_path / 'components.scss'
75
+
76
+ make_dir 'templates'
77
+ copy 'templates/component.rb.tt'
78
+ copy 'templates/style.scss.tt'
79
+ copy 'templates/view.html.erb.tt'
80
+ copy 'templates/component_test.rb.tt'
81
+
82
+ substitute "#{gem_name}.gemspec", /^end/, <<~RUBY.chomp
83
+ # ignore the dummy Rails app when building the gem
84
+ spec.files.reject! { _1.match(/^#{rails_dummy_path}/) }
85
+ spec.add_dependency 'amber_component'
86
+ spec.add_development_dependency 'thor'
87
+ spec.add_development_dependency 'sassc'
88
+ end
89
+ RUBY
90
+
91
+ copy 'test/component_test_case.rb'
92
+ substitute 'Rakefile', /test_\*\.rb/, '*_test.rb'
93
+ inner_module_name = gem_name.split('-').last
94
+ move gem_test_folder_path.parent / "test_#{inner_module_name}.rb",
95
+ gem_test_folder_path.parent / "#{inner_module_name}_test.rb"
96
+
97
+ append 'test/test_helper.rb',
98
+ "require_relative 'component_test_case'\n"
99
+ end
100
+ end
101
+ end
102
+
103
+ # @return [void]
104
+ def generate_rails_dummy_app
105
+ ::CLI::UI::Frame.open 'Rails dummy app', color: :magenta do
106
+ unless syscall? 'gem list -i rails'
107
+ ::CLI::UI::Frame.open 'Install Rails' do
108
+ syscall 'gem install rails'
109
+ syscall 'gem install sqlite3'
110
+ end
111
+ end
112
+
113
+ ::CLI::UI::Frame.open 'Generate app' do
114
+ syscall "rails new #{root_path / rails_dummy_path} -m #{rails_template_path}",
115
+ env: { GEM_NAME: gem_name },
116
+ input: "y\n"
117
+ end
118
+
119
+ ::CLI::UI::Frame.open 'Patch app' do
120
+ append rails_dummy_path / 'Gemfile', template_content('rails_dummy/Gemfile.erb')
121
+
122
+ if exist?(rails_dummy_path / 'app' / 'assets' / 'stylesheets' / 'application.css')
123
+ move rails_dummy_path / 'app' / 'assets' / 'stylesheets' / 'application.css',
124
+ rails_dummy_path / 'app' / 'assets' / 'stylesheets' / 'application.scss'
125
+
126
+ append rails_dummy_path / 'app' / 'assets' / 'stylesheets' / 'application.scss', <<~SCSS
127
+ @import "#{gem_name_path}";
128
+ SCSS
129
+ else
130
+ append rails_dummy_path / 'app' / 'assets' / 'stylesheets' / 'application.sass.scss', <<~SCSS
131
+ @import "#{gem_name_path}";
132
+ SCSS
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ # @return [String]
139
+ def relative_path_to_root
140
+ (['..'] * root_module_name.split('::').length).join('/')
141
+ end
142
+
143
+ # Performs a shell command with a PTY,
144
+ # captures its output and logs it to this process's STDOUT.
145
+ #
146
+ # @param command [String]
147
+ # @param env [Hash{Symbol => String}] Environment variables
148
+ # @param input [String, nil] Input to the process
149
+ # @return [String] STDOUT
150
+ def syscall(command, env: {}, input: nil)
151
+ cmd = ::TTY::Command.new(color: true, printer: :quiet)
152
+ cmd.run!(command, pty: true, input: input, env: env)
153
+ end
154
+
155
+ # Performs a quiet shell command (without logging to STDOUT)
156
+ # and returns the process's exit status as a `Boolean`.
157
+ #
158
+ # @param command [String]
159
+ # @param env [Hash{Symbol => String}] Environment variables
160
+ # @param input [String, nil] Input to the process
161
+ # @return [Boolean] whether the command was successful
162
+ def syscall?(command, env: {}, input: nil)
163
+ cmd = ::TTY::Command.new(printer: :null)
164
+ !cmd.run!(command, input: input, env: env).failure?
165
+ end
166
+
167
+ # Make a file in the newly generated gem executable.
168
+ #
169
+ # @param path [String, Pathname]
170
+ # @return [void]
171
+ def make_executable(path)
172
+ ::FileUtils.chmod 'ugo+x', root_path / path
173
+ end
174
+
175
+ # Relative path to the main entry file of the generated gem.
176
+ #
177
+ # @return [Pathname]
178
+ def gem_entry_file_path
179
+ gem_entry_folder_path.sub_ext('.rb')
180
+ end
181
+
182
+ # Relative path to the main folder of the generated gem.
183
+ #
184
+ # @return [Pathname]
185
+ def gem_entry_folder_path
186
+ ::Pathname.new('lib') / gem_name_path
187
+ end
188
+
189
+ # Relative path to the test folder of the generated gem.
190
+ #
191
+ # @return [Pathname]
192
+ def gem_test_folder_path
193
+ ::Pathname.new('test') / gem_name_path
194
+ end
195
+
196
+ # @return [Pathname]
197
+ def gem_name_path
198
+ @gem_name_path ||= ::Pathname.new gem_name.gsub('-', '/')
199
+ end
200
+
201
+ # Name of the generated gem.
202
+ #
203
+ # @return [String]
204
+ def gem_name
205
+ @gem_name ||= root_path.basename.to_s
206
+ end
207
+
208
+ # Relative path to the stylesheet directory of the generated gem.
209
+ #
210
+ # @return [Pathname]
211
+ def stylesheet_dir_path
212
+ ::Pathname.new('assets') / 'stylesheets' / gem_name_path
213
+ end
214
+
215
+ # Relative path to the main stylesheet file of the generated gem.
216
+ #
217
+ # @return [Pathname]
218
+ def main_stylesheet_path
219
+ stylesheet_dir_path.sub_ext '.scss'
220
+ end
221
+
222
+ # @return [Pathname]
223
+ def rails_dummy_path
224
+ ::Pathname.new 'dummy_app'
225
+ end
226
+
227
+ # Path to the root folder of the generated gem.
228
+ #
229
+ # @return [Pathname]
230
+ def root_path
231
+ @args.gem_path
232
+ end
233
+
234
+ # @return [Pathname]
235
+ def rails_template_path
236
+ ROOT_GEM_PATH / 'lib' / 'dummy_rails_app_template.rb'
237
+ end
238
+
239
+ # Check whether the given file/directory exists
240
+ # in the generated gem.
241
+ #
242
+ # @param path [String, Pathname]
243
+ # @return [Boolean]
244
+ def exist?(path)
245
+ (root_path / path).exist?
246
+ end
247
+
248
+ # Create a directory in the generated gem
249
+ # if it doesn't exist already.
250
+ #
251
+ # @param path [String, Pathname]
252
+ # @return [void]
253
+ def make_dir(path)
254
+ dir_path = root_path / path
255
+ ::FileUtils.mkdir_p dir_path unless dir_path.exist?
256
+ end
257
+ alias mkdir make_dir
258
+
259
+ # @param string [String, Symbol]
260
+ # @return [String]
261
+ def action_message(string)
262
+ "#{string.to_s.rjust(12, ' ')} "
263
+ end
264
+
265
+ # Parse a template file from this gem using ERB and
266
+ # and copy it to the newly generated gem.
267
+ #
268
+ # @param template_path [String, Pathname]
269
+ # @param target_path [String, Pathname]
270
+ # @return [void]
271
+ def template(template_path, target_path)
272
+ create target_path, template_content(template_path)
273
+ end
274
+
275
+ # Copy a file from this gem's template folder to
276
+ # the newly generated gem.
277
+ #
278
+ # @param source_path [String, Pathname]
279
+ # @param target_path [String, Pathname]
280
+ # @return [void]
281
+ def copy(source_path, target_path = source_path, recursive: false)
282
+ print action_message(__method__).green
283
+ puts target_path
284
+
285
+ source = TEMPLATES_FOLDER_PATH / source_path
286
+ target = root_path / target_path
287
+ ::FileUtils.mkdir_p(target.dirname) unless target.dirname.directory?
288
+ return ::FileUtils.cp_r source, target if recursive
289
+
290
+ ::FileUtils.cp source, target
291
+ end
292
+
293
+ # Move a file inside the generated gem.
294
+ #
295
+ # @param source_path [String, Pathname]
296
+ # @param target_path [String, Pathname]
297
+ # @return [void]
298
+ def move(source_path, target_path)
299
+ print action_message(__method__).yellow
300
+ puts "#{source_path} -> #{target_path}"
301
+
302
+ source = root_path / source_path
303
+ target = root_path / target_path
304
+ ::FileUtils.move source, target
305
+ end
306
+
307
+ # Read and parse a template with ERB and
308
+ # return the result as a `String`.
309
+ #
310
+ # @param path [String, Pathname]
311
+ # @return [String] Parsed content of the template
312
+ def template_content(path)
313
+ template_path = TEMPLATES_FOLDER_PATH / path
314
+ ::ERB.new(template_path.read).result(binding)
315
+ end
316
+
317
+ # Create a new file with the specified content
318
+ # in the newly generated gem.
319
+ #
320
+ # @param file_path [String, Pathname]
321
+ # @param content [String]
322
+ def create(file_path, content)
323
+ print action_message(__method__).green
324
+ puts file_path
325
+
326
+ path = root_path / file_path
327
+ ::FileUtils.mkdir_p(path.dirname) unless path.dirname.directory?
328
+
329
+ path.write(content)
330
+ end
331
+
332
+ # Substitute a part of a certain file in the generated gem.
333
+ #
334
+ # @param file_path [String, Pathname]
335
+ # @param regexp [Regexp]
336
+ # @param replacement [String]
337
+ # @return [void]
338
+ def substitute(file_path, regexp, replacement)
339
+ print action_message(:gsub).yellow
340
+ puts file_path
341
+
342
+ path = root_path / file_path
343
+ file_content = path.read
344
+ raise "Cannot substitute #{path} because #{regexp.inspect} was not found" unless file_content.match?(regexp)
345
+
346
+ path.write file_content.sub(regexp, replacement)
347
+ end
348
+
349
+ # Prepend some content to a file in the generated gem.
350
+ #
351
+ # @param file_path [String, Pathname]
352
+ # @param content [String]
353
+ # @return [void]
354
+ def prepend(file_path, content)
355
+ print action_message(__method__).yellow
356
+ puts file_path
357
+
358
+ # @type [Pathname]
359
+ path = root_path / file_path
360
+ current_content = ::File.read path
361
+ ::File.open(path, 'w') do |f|
362
+ f.write(content)
363
+ f.write(current_content)
364
+ end
365
+ end
366
+
367
+ # Append some content to a file in the generated gem.
368
+ #
369
+ # @param file_path [String, Pathname]
370
+ # @param content[String]
371
+ # @return [void]
372
+ def append(file_path, content)
373
+ print action_message(__method__).yellow
374
+ puts file_path
375
+
376
+ # @type [Pathname]
377
+ path = root_path / file_path
378
+ ::File.open(path, 'a') { _1.write(content) }
379
+ end
380
+
381
+ # Name of the root module of the generated gem.
382
+ #
383
+ # @return [String]
384
+ def root_module_name
385
+ camelize(gem_name_path)
386
+ end
387
+
388
+ # @param string [String]
389
+ # @param uppercase_first_letter [Boolean]
390
+ # @return [String]
391
+ def camelize(string, uppercase_first_letter: true)
392
+ string = string.to_s
393
+ string = if uppercase_first_letter
394
+ string.sub(/^[a-z\d]*/, &:capitalize)
395
+ else
396
+ string.sub(/^(?:(?=\b|[A-Z_])|\w)/, &:downcase)
397
+ end
398
+
399
+ string.gsub!(%r{(?:_|(/))([a-z\d]*)}) do
400
+ "#{::Regexp.last_match(1)}#{::Regexp.last_match(2).capitalize}"
401
+ end
402
+ string.gsub('/', '::')
403
+ end
404
+ end
405
+ end
406
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+
5
+ module ::AmberExtensionGenerator
6
+ # Contains all code which interacts with the terminal.
7
+ module CLI
8
+ class << self
9
+ def run
10
+ GemGenerator.call Args.parse
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ require_relative 'cli/args'
17
+ require_relative 'cli/gem_generator'
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ::AmberExtensionGenerator
4
+ # @return [String]
5
+ GEM_NAME = 'amber_extension_generator'
6
+ end
@@ -0,0 +1,2 @@
1
+ // This file imports all of your components' stylesheets
2
+
@@ -0,0 +1,6 @@
1
+ // This is the main entry point for all your styles.
2
+ // This file will be imported by the users of this gem,
3
+ // so every stylesheet required by this gem should
4
+ // be imported here.
5
+
6
+ @import "<%= gem_name_path.basename %>/components";
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+
3
+ BIN_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
4
+
5
+ echo "╔════════════════════════════════════╗"
6
+ echo "║ Starting the development Rails App ║"
7
+ echo "╚════════════════════════════════════╝"
8
+ echo
9
+
10
+ $BIN_DIR/../<%= rails_dummy_path %>/bin/rails server
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'thor'
5
+ require 'pathname'
6
+ require 'fileutils'
7
+
8
+ require_relative '../<%= gem_entry_folder_path %>'
9
+
10
+ class ::GenerateCommand < ::Thor
11
+ include ::Thor::Actions
12
+
13
+ # @return [Module]
14
+ LIBRARY_MODULE = <%= root_module_name %>
15
+ # @return [String]
16
+ LIBRARY_NAME = '<%= gem_name %>'
17
+ # @return [Pathname]
18
+ ROOT_PATH = ::Pathname.new ::File.expand_path('..', __dir__)
19
+ # @return [Pathname]
20
+ GEM_ENTRY_FOLDER_PATH = ::Pathname.new '<%= gem_entry_folder_path %>'
21
+
22
+ class << self
23
+ # Define the generator's root folder
24
+ #
25
+ # @return [String]
26
+ def source_root
27
+ ::File.expand_path('..', __dir__)
28
+ end
29
+ end
30
+
31
+ desc 'component NAME', 'Generate a new component with the specified NAME'
32
+
33
+ # @param name [String]
34
+ # @return [void]
35
+ def component(name)
36
+ name = snake_case(name)
37
+ name = "#{name}_component" unless name.end_with? '_component'
38
+ @name = name
39
+
40
+ template 'templates/component.rb.tt', component_path
41
+ component_assets_path.mkdir unless component_assets_path.exist?
42
+
43
+ template 'templates/view.html.erb.tt', component_assets_path / 'view.html.erb'
44
+ template 'templates/style.scss.tt', component_assets_path / 'style.scss'
45
+ template 'templates/component_test.rb.tt', component_test_file_path
46
+
47
+ append_file main_components_stylesheet_path, %(\n@import "../../../#{component_assets_path}/style.scss";)
48
+ end
49
+
50
+ private
51
+
52
+ # @return [Pathname]
53
+ def component_test_file_path
54
+ components_test_folder_path / "#{@name}_test.rb"
55
+ end
56
+
57
+ # @return [Pathname]
58
+ def main_components_stylesheet_path
59
+ ROOT_PATH / 'assets' / 'stylesheets' / library_relative_path / 'components.scss'
60
+ end
61
+
62
+ # @return [Pathname]
63
+ def components_test_folder_path
64
+ ROOT_PATH / 'test' / library_relative_path / 'components'
65
+ end
66
+
67
+ # @return [Pathname]
68
+ def library_relative_path
69
+ @library_relative_path ||= ::Pathname.new LIBRARY_NAME.gsub('-', '/')
70
+ end
71
+
72
+ # @return [Pathname]
73
+ def component_assets_path
74
+ @component_assets_path ||= GEM_ENTRY_FOLDER_PATH / 'components' / @name
75
+ end
76
+
77
+ # @return [Pathname]
78
+ def component_path
79
+ @component_path ||= GEM_ENTRY_FOLDER_PATH / 'components' / file_name
80
+ end
81
+
82
+ # @return [String]
83
+ def full_class_name
84
+ "#{LIBRARY_MODULE}::#{class_name}"
85
+ end
86
+
87
+ # @return [String]
88
+ def component_css_class
89
+ "#{LIBRARY_NAME}--#{@name}"
90
+ end
91
+
92
+ # @return [String]
93
+ def class_name
94
+ @class_name ||= camelize(@name)
95
+ end
96
+
97
+ # @return [String]
98
+ def file_name
99
+ @file_name ||= "#{@name}.rb"
100
+ end
101
+
102
+ # @return [Class]
103
+ def abstract_component
104
+ LIBRARY_MODULE::ABSTRACT_COMPONENT
105
+ end
106
+
107
+ # Converts a string to camel/Pascal Case.
108
+ #
109
+ # camelize('some_snake_case') #=> "SomeSnakeCase"
110
+ # camelize('some/snake_case') #=> "Some::SnakeCase"
111
+ #
112
+ # @param string [String]
113
+ # @param uppercase_first_letter [Boolean]
114
+ # @return [String]
115
+ def camelize(string, uppercase_first_letter: true)
116
+ string = if uppercase_first_letter
117
+ string.sub(/^[a-z\d]*/, &:capitalize)
118
+ else
119
+ string.sub(/^(?:(?=\b|[A-Z_])|\w)/, &:downcase)
120
+ end
121
+
122
+ string.gsub!(%r{(?:_|(/))([a-z\d]*)}) do
123
+ "#{::Regexp.last_match(1)}#{::Regexp.last_match(2).capitalize}"
124
+ end
125
+ string.gsub('/', '::')
126
+ end
127
+
128
+ # Converts a string in PascalCase or camelCase to snake_case.
129
+ #
130
+ # snake_case('SomePascalCase') => "some_pascal_case"
131
+ # snake_case('Some::PascalCase') => "some/pascal_case"
132
+ #
133
+ # @param string [String]
134
+ # @return [String]
135
+ def snake_case(string)
136
+ string.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
137
+ .gsub(%r{::_|/_}, '/')
138
+ .downcase
139
+ end
140
+ end
141
+
142
+ ::GenerateCommand.start
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'amber_component'
4
+
5
+ module <%= root_module_name %>
6
+ # Abstract class which should serve as a superclass
7
+ # for all components.
8
+ #
9
+ # @abstract Subclass to create a new component.
10
+ class BaseComponent < ::AmberComponent::Base; end
11
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'components/base_component'
4
+ ::Dir[::File.expand_path('components/**/*.rb', __dir__)].sort.each { require_relative _1 }
@@ -0,0 +1,33 @@
1
+ # === GEM AUTO-RELOADING ===
2
+
3
+ class ::ExtensionGem
4
+ # @return [String] Name of the gem.
5
+ attr_reader :name
6
+ # @return [Pathname] Path to the gem.
7
+ attr_reader :path
8
+ # @return [Array<Symbol>] Top-level constants defined by the gem.
9
+ attr_reader :constants
10
+ # @return [String]
11
+ attr_reader :require_path
12
+
13
+ # @param name [String]
14
+ # @param path [String, Pathname]
15
+ # @param constants [Array<Symbol>]
16
+ # @param require_path [String, nil]
17
+ def initialize(name:, path:, constants:, require_path: nil)
18
+ @name = name
19
+ @path = ::File.expand_path(path, __dir__)
20
+ @constants = constants
21
+ @require_path = require_path || @name.gsub('-', '/')
22
+ end
23
+ end
24
+
25
+ # @return [ExtensionGem]
26
+ ::AMBER_EXTENSION_GEM = ::ExtensionGem.new(
27
+ name: "<%= gem_name %>",
28
+ path: '..',
29
+ constants: %i[<%= root_module_name %>].freeze
30
+ )
31
+ gem ::AMBER_EXTENSION_GEM.name, path: ::AMBER_EXTENSION_GEM.path
32
+
33
+ # === END GEM AUTO-RELOADING ===
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= root_module_name %>
4
+ # Class which hooks into Rails
5
+ # and configures the application.
6
+ class Railtie < ::Rails::Railtie
7
+ initializer '<%= gem_name %>.assets' do |app|
8
+ (ROOT_PATH / 'assets').each_child do |asset_dir|
9
+ app.config.assets.paths << asset_dir.to_s
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= full_class_name %> < <%= abstract_component %>
4
+ # Props that your component accepts
5
+ prop :description, type: ::String, default: -> { 'Default Description' }
6
+
7
+ after_initialize do
8
+ # some initialization
9
+ @time = ::Time.now
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class <%= full_class_name %>Test < ::ComponentTestCase
6
+ # For a full list of available assertions see
7
+ # https://rubydoc.info/github/jnicklas/capybara/Capybara/Node/Matchers
8
+
9
+ # def test_returns_correct_html
10
+ # render do
11
+ # <%= full_class_name %>.call
12
+ # end
13
+ #
14
+ # assert_text 'Hello from <%= full_class_name %>'
15
+ # assert_selector "div.<%= component_css_class %> p", text: 'Default Description'
16
+ # end
17
+ end