ariadne_view_components 0.0.44-x86_64-darwin → 0.0.46-x86_64-darwin
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/CHANGELOG.md +13 -0
- data/app/lib/ariadne/action_view_extensions/form_helper.rb +30 -0
- data/app/lib/ariadne/audited/dsl.rb +32 -0
- data/app/lib/ariadne/class_name_helper.rb +22 -0
- data/app/lib/ariadne/fetch_or_fallback_helper.rb +110 -0
- data/app/lib/ariadne/form_builder.rb +74 -0
- data/app/lib/ariadne/icon_helper.rb +51 -0
- data/app/lib/ariadne/logger_helper.rb +23 -0
- data/app/lib/ariadne/status/dsl.rb +41 -0
- data/app/lib/ariadne/view_helper.rb +22 -0
- data/lib/ariadne/view_components/version.rb +1 -1
- metadata +10 -12
- data/lib/tasks/ariadne_view_components.rake +0 -48
- data/lib/tasks/build.rake +0 -30
- data/lib/tasks/coverage.rake +0 -20
- data/lib/tasks/docs.rake +0 -466
- data/lib/tasks/helpers/ast_processor.rb +0 -44
- data/lib/tasks/helpers/ast_traverser.rb +0 -77
- data/lib/tasks/static.rake +0 -15
- data/lib/tasks/test.rake +0 -19
- data/lib/yard/docs_helper.rb +0 -90
- data/lib/yard/renders_many_handler.rb +0 -19
- data/lib/yard/renders_one_handler.rb +0 -19
data/lib/tasks/docs.rake
DELETED
@@ -1,466 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "yard"
|
4
|
-
require "yard/renders_one_handler"
|
5
|
-
require "yard/renders_many_handler"
|
6
|
-
|
7
|
-
require "active_support/inflector"
|
8
|
-
require "fileutils"
|
9
|
-
|
10
|
-
namespace :docs do
|
11
|
-
desc "Rebuilds docs on change; run via the Procfile"
|
12
|
-
task :watch do
|
13
|
-
require "listen"
|
14
|
-
|
15
|
-
Rake::Task["docs:build"].execute
|
16
|
-
|
17
|
-
puts "Listening for changes to documentation..."
|
18
|
-
|
19
|
-
listener = Listen.to("app") do |modified, added, removed|
|
20
|
-
puts "modified absolute path: #{modified}"
|
21
|
-
puts "added absolute path: #{added}"
|
22
|
-
puts "removed absolute path: #{removed}"
|
23
|
-
|
24
|
-
if modified.length.nonzero?
|
25
|
-
changed = modified.dup.uniq
|
26
|
-
while (path = changed.shift)
|
27
|
-
puts "Reloading #{path}"
|
28
|
-
# reload constants (in case they changed)
|
29
|
-
load(path)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
Rake::Task["docs:build"].execute
|
34
|
-
end
|
35
|
-
listener.start # not blocking
|
36
|
-
sleep
|
37
|
-
end
|
38
|
-
|
39
|
-
# for classes in hashes
|
40
|
-
CLASS_MAPPINGS = '(?:\\S+|:\\"[\\S-]+\\"): \\"([\\S -]+)\\"'
|
41
|
-
# for classes in constants
|
42
|
-
CLASS_CONSTANT = '[A-Z_]+ = \\"([\\S -]+)\\"'
|
43
|
-
CLASS_REGEX = Regexp.new("(?:#{CLASS_MAPPINGS}|#{CLASS_CONSTANT})")
|
44
|
-
|
45
|
-
desc "Generate the documentation."
|
46
|
-
task :build do
|
47
|
-
registry = generate_yard_registry
|
48
|
-
|
49
|
-
puts "Converting YARD documentation to Markdown files."
|
50
|
-
|
51
|
-
# Rails controller for rendering arbitrary ERB
|
52
|
-
view_context = ApplicationController.new.tap { |c| c.request = ActionDispatch::TestRequest.create }.view_context
|
53
|
-
components = [
|
54
|
-
Ariadne::AvatarComponent,
|
55
|
-
Ariadne::AvatarStackComponent,
|
56
|
-
Ariadne::CommentComponent,
|
57
|
-
Ariadne::BodyComponent,
|
58
|
-
Ariadne::BlankslateComponent,
|
59
|
-
Ariadne::BaseButton,
|
60
|
-
Ariadne::ButtonComponent,
|
61
|
-
Ariadne::ContainerComponent,
|
62
|
-
Ariadne::ClipboardCopyComponent,
|
63
|
-
Ariadne::CounterComponent,
|
64
|
-
Ariadne::DetailsComponent,
|
65
|
-
Ariadne::DropdownComponent,
|
66
|
-
Ariadne::GridComponent,
|
67
|
-
Ariadne::FlashComponent,
|
68
|
-
Ariadne::FlexComponent,
|
69
|
-
Ariadne::FooterComponent,
|
70
|
-
Ariadne::HeaderComponent,
|
71
|
-
Ariadne::HeadingComponent,
|
72
|
-
Ariadne::HeroiconComponent,
|
73
|
-
Ariadne::ImageComponent,
|
74
|
-
Ariadne::InlineFlexComponent,
|
75
|
-
Ariadne::LinkComponent,
|
76
|
-
Ariadne::ListComponent,
|
77
|
-
Ariadne::NarrowContainerComponent,
|
78
|
-
Ariadne::PanelBarComponent,
|
79
|
-
Ariadne::PillComponent,
|
80
|
-
Ariadne::RichTextAreaComponent,
|
81
|
-
Ariadne::SlideoverComponent,
|
82
|
-
Ariadne::TabComponent,
|
83
|
-
Ariadne::TabContainerComponent,
|
84
|
-
Ariadne::TableNavComponent,
|
85
|
-
Ariadne::TabNavComponent,
|
86
|
-
Ariadne::Text,
|
87
|
-
Ariadne::TimeAgoComponent,
|
88
|
-
Ariadne::TimelineComponent,
|
89
|
-
Ariadne::TooltipComponent,
|
90
|
-
]
|
91
|
-
|
92
|
-
# TODO: Form is not in documentation
|
93
|
-
js_components = [
|
94
|
-
Ariadne::ClipboardCopyComponent,
|
95
|
-
Ariadne::RichTextAreaComponent,
|
96
|
-
Ariadne::SlideoverComponent,
|
97
|
-
Ariadne::TabContainerComponent,
|
98
|
-
Ariadne::TabNavComponent,
|
99
|
-
Ariadne::TimeAgoComponent,
|
100
|
-
Ariadne::TooltipComponent,
|
101
|
-
]
|
102
|
-
|
103
|
-
all_components = Ariadne::Component.descendants - [Ariadne::BaseComponent, Ariadne::Content] # TODO: why is `Ariadne::Content` not picked up?
|
104
|
-
components_needing_docs = all_components - components
|
105
|
-
|
106
|
-
args_for_components = []
|
107
|
-
classes_found_in_examples = []
|
108
|
-
|
109
|
-
errors = []
|
110
|
-
|
111
|
-
# Deletes docs before regenerating them, guaranteeing that we don't keep stale docs.
|
112
|
-
components_content_glob = File.join("docs", "content", "components", "**", "*.md")
|
113
|
-
FileUtils.rm_rf(components_content_glob)
|
114
|
-
|
115
|
-
components.sort_by(&:name).each do |component|
|
116
|
-
documentation = registry.get(component.name)
|
117
|
-
|
118
|
-
data = docs_metadata(component)
|
119
|
-
|
120
|
-
path = Pathname.new(data[:path])
|
121
|
-
path.dirname.mkpath unless path.dirname.exist?
|
122
|
-
File.open(path, "w") do |f|
|
123
|
-
f.puts("---")
|
124
|
-
f.puts("title: #{data[:title]}")
|
125
|
-
f.puts("componentId: #{data[:component_id]}")
|
126
|
-
f.puts("status: #{data[:status]}")
|
127
|
-
f.puts("source: #{data[:source]}")
|
128
|
-
f.puts("lookbook: #{data[:lookbook]}")
|
129
|
-
f.puts("---")
|
130
|
-
f.puts
|
131
|
-
f.puts("import Example from '#{data[:example_path]}'")
|
132
|
-
|
133
|
-
initialize_method = documentation.meths.find(&:constructor?)
|
134
|
-
|
135
|
-
if js_components.include?(component)
|
136
|
-
f.puts("import RequiresJSFlash from '#{data[:require_js_path]}'")
|
137
|
-
f.puts
|
138
|
-
f.puts("<RequiresJSFlash />")
|
139
|
-
end
|
140
|
-
|
141
|
-
f.puts
|
142
|
-
f.puts("<!-- Warning: AUTO-GENERATED file, do not edit. Add code comments to your Ruby instead <3 -->")
|
143
|
-
f.puts
|
144
|
-
f.puts(view_context.render(inline: documentation.base_docstring))
|
145
|
-
|
146
|
-
if documentation.tags(:deprecated).any?
|
147
|
-
f.puts
|
148
|
-
f.puts("## Deprecation")
|
149
|
-
documentation.tags(:deprecated).each do |tag|
|
150
|
-
f.puts
|
151
|
-
f.puts view_context.render(inline: tag.text)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
if documentation.tags(:accessibility).any?
|
156
|
-
f.puts
|
157
|
-
f.puts("## Accessibility")
|
158
|
-
documentation.tags(:accessibility).each do |tag|
|
159
|
-
f.puts
|
160
|
-
f.puts view_context.render(inline: tag.text)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
params = initialize_method.tags(:param)
|
165
|
-
|
166
|
-
errors << { component.name => { arguments: "No argument documentation found" } } if params.none?
|
167
|
-
|
168
|
-
f.puts
|
169
|
-
f.puts("## Arguments")
|
170
|
-
f.puts
|
171
|
-
f.puts("| Name | Type | Default | Description |")
|
172
|
-
f.puts("| :- | :- | :- | :- |")
|
173
|
-
|
174
|
-
documented_params = params.map(&:name)
|
175
|
-
component_params = component.instance_method(:initialize).parameters.map { |p| p.last.to_s }
|
176
|
-
|
177
|
-
if (documented_params & component_params).size != component_params.size
|
178
|
-
err = { arguments: {} }
|
179
|
-
(component_params - documented_params).each do |arg|
|
180
|
-
err[:arguments][arg] = "Not documented"
|
181
|
-
end
|
182
|
-
|
183
|
-
errors << { component.name => err }
|
184
|
-
end
|
185
|
-
|
186
|
-
args = []
|
187
|
-
params.each do |tag|
|
188
|
-
default_value = pretty_default_value(tag, component)
|
189
|
-
|
190
|
-
args << {
|
191
|
-
"name" => tag.name,
|
192
|
-
"type" => tag.types.join(", "),
|
193
|
-
"default" => default_value,
|
194
|
-
"description" => view_context.render(inline: tag.text.squish),
|
195
|
-
}
|
196
|
-
|
197
|
-
f.puts("| `#{tag.name}` | `#{tag.types.join(", ")}` | #{default_value} | #{view_context.render(inline: tag.text.squish)} |")
|
198
|
-
end
|
199
|
-
|
200
|
-
component_args = {
|
201
|
-
"component" => data[:title],
|
202
|
-
"source" => data[:source],
|
203
|
-
"parameters" => args,
|
204
|
-
}
|
205
|
-
|
206
|
-
args_for_components << component_args
|
207
|
-
|
208
|
-
# Slots V2 docs
|
209
|
-
slot_v2_methods = documentation.meths.select { |x| x[:renders_one] || x[:renders_many] }
|
210
|
-
|
211
|
-
if slot_v2_methods.any?
|
212
|
-
f.puts
|
213
|
-
f.puts("## Slots")
|
214
|
-
|
215
|
-
slot_v2_methods.each do |slot_documentation|
|
216
|
-
f.puts
|
217
|
-
f.puts("### `#{slot_documentation.name.to_s.capitalize}`")
|
218
|
-
|
219
|
-
if slot_documentation.base_docstring.to_s.present?
|
220
|
-
f.puts
|
221
|
-
f.puts(view_context.render(inline: slot_documentation.base_docstring))
|
222
|
-
end
|
223
|
-
|
224
|
-
param_tags = slot_documentation.tags(:param)
|
225
|
-
if param_tags.any?
|
226
|
-
f.puts
|
227
|
-
f.puts("| Name | Type | Default | Description |")
|
228
|
-
f.puts("| :- | :- | :- | :- |")
|
229
|
-
end
|
230
|
-
|
231
|
-
param_tags.each do |tag|
|
232
|
-
f.puts("| `#{tag.name}` | `#{tag.types.join(", ")}` | #{pretty_default_value(tag, component)} | #{view_context.render(inline: tag.text)} |")
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
example_tags = initialize_method.tags(:example)
|
238
|
-
|
239
|
-
if example_tags.any?
|
240
|
-
f.puts
|
241
|
-
f.puts("## Examples")
|
242
|
-
|
243
|
-
example_tags.each do |tag|
|
244
|
-
name, description, code = parse_example_tag(tag)
|
245
|
-
f.puts
|
246
|
-
f.puts("### #{name}")
|
247
|
-
if description
|
248
|
-
f.puts
|
249
|
-
f.puts(view_context.render(inline: description.squish))
|
250
|
-
end
|
251
|
-
f.puts
|
252
|
-
html = begin
|
253
|
-
view_context.render(inline: code)
|
254
|
-
rescue StandardError => e
|
255
|
-
raise StandardError, "Unexpected error with #{data[:title]}: #{e.message}"
|
256
|
-
end
|
257
|
-
html.scan(/class="([^"]*)"/) do |classnames|
|
258
|
-
classes_found_in_examples.concat(classnames[0].split.reject { |c| c.starts_with?("heroicon", "js") }.map { ".#{_1}" })
|
259
|
-
end
|
260
|
-
f.puts("<Example src=\"#{html.tr('"', "'").delete("\n")}\" />")
|
261
|
-
f.puts
|
262
|
-
f.puts("```erb")
|
263
|
-
f.puts(code.to_s)
|
264
|
-
f.puts("```")
|
265
|
-
end
|
266
|
-
else
|
267
|
-
errors << { component.name => { example: "No examples found" } } unless components_without_examples.include?(component)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
unless errors.empty?
|
273
|
-
puts "==============================================="
|
274
|
-
puts "===================== ERRORS =================="
|
275
|
-
puts "===============================================\n\n"
|
276
|
-
puts JSON.pretty_generate(errors)
|
277
|
-
puts "\n\n==============================================="
|
278
|
-
puts "==============================================="
|
279
|
-
puts "==============================================="
|
280
|
-
|
281
|
-
raise
|
282
|
-
end
|
283
|
-
|
284
|
-
File.open("static/classes.yml", "w") do |f|
|
285
|
-
non_ariadne_classes = classes_found_in_examples.reject { |c| c =~ /(?:ariadne|tiptap)/ }.uniq
|
286
|
-
if non_ariadne_classes.length.nonzero?
|
287
|
-
puts "==============================================="
|
288
|
-
puts "===================== ERRORS =================="
|
289
|
-
puts "===============================================\n\n"
|
290
|
-
puts "The following non-Ariadne classes were found: #{non_ariadne_classes.join(", ")}"
|
291
|
-
puts "\n\n==============================================="
|
292
|
-
puts "==============================================="
|
293
|
-
puts "==============================================="
|
294
|
-
|
295
|
-
raise
|
296
|
-
end
|
297
|
-
|
298
|
-
f.puts YAML.dump(classes_found_in_examples.uniq)
|
299
|
-
end
|
300
|
-
|
301
|
-
File.open("static/arguments.yml", "w") do |f|
|
302
|
-
f.puts YAML.dump(args_for_components)
|
303
|
-
end
|
304
|
-
|
305
|
-
puts "Markdown compiled."
|
306
|
-
|
307
|
-
if components_needing_docs.any?
|
308
|
-
puts "\nThe following components need documentation. Could you add it to them? \n* #{components_needing_docs.map(&:name).join("\n* ")}"
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
desc "Generate previews from documentation examples"
|
313
|
-
task :preview do
|
314
|
-
registry = generate_yard_registry
|
315
|
-
|
316
|
-
FileUtils.rm_rf("lookbook/test/components/previews/ariadne/docs/")
|
317
|
-
|
318
|
-
components = Ariadne::Component.descendants
|
319
|
-
|
320
|
-
components.each do |component|
|
321
|
-
documentation = registry.get(component.name)
|
322
|
-
short_name = component.name.gsub(/Ariadne|::/, "")
|
323
|
-
initialize_method = documentation.meths.find(&:constructor?)
|
324
|
-
|
325
|
-
next unless initialize_method&.tags(:example)&.any?
|
326
|
-
|
327
|
-
yard_example_tags = initialize_method.tags(:example)
|
328
|
-
|
329
|
-
path = Pathname.new("lookbook/test/components/previews/ariadne/docs/#{short_name.underscore}_preview.rb")
|
330
|
-
FileUtils.mkdir_p("lookbook/test/components/previews/ariadne/docs") unless path.dirname.exist?
|
331
|
-
|
332
|
-
File.open(path, "w") do |f|
|
333
|
-
f.puts("module Ariadne")
|
334
|
-
f.puts(" module Docs")
|
335
|
-
f.puts(" class #{short_name}Preview < ViewComponent::Preview")
|
336
|
-
|
337
|
-
yard_example_tags.each_with_index do |tag, index|
|
338
|
-
name, _, code = parse_example_tag(tag)
|
339
|
-
method_name = name.split("|").first.downcase.parameterize.underscore
|
340
|
-
f.puts(" def #{method_name}; end")
|
341
|
-
f.puts unless index == yard_example_tags.size - 1
|
342
|
-
path = Pathname.new("lookbook/test/components/previews/ariadne/docs/#{short_name.underscore}_preview/#{method_name}.html.erb")
|
343
|
-
FileUtils.mkdir_p("lookbook/test/components/previews/ariadne/docs/#{short_name.underscore}_preview") unless path.dirname.exist?
|
344
|
-
File.open(path, "w") do |view_file|
|
345
|
-
view_file.puts(code.to_s)
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
|
-
f.puts(" end")
|
350
|
-
f.puts(" end")
|
351
|
-
f.puts("end")
|
352
|
-
end
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
def generate_yard_registry
|
358
|
-
require "action_dispatch"
|
359
|
-
require_relative "../../app/lib/ariadne/view_helper"
|
360
|
-
require File.expand_path("./../../lookbook/config/environment.rb", __dir__)
|
361
|
-
|
362
|
-
YARD::Registry.yardoc_file = ".yardoc"
|
363
|
-
|
364
|
-
require "./app/components/ariadne/component.rb"
|
365
|
-
require "ariadne/view_components"
|
366
|
-
require "yard/docs_helper"
|
367
|
-
require "view_component/base"
|
368
|
-
require "view_component/test_helpers"
|
369
|
-
include(ViewComponent::TestHelpers)
|
370
|
-
include(Ariadne::ViewHelper)
|
371
|
-
include(YARD::DocsHelper)
|
372
|
-
|
373
|
-
Dir["./app/components/ariadne/**/*.rb"].sort.each do |file|
|
374
|
-
puts file
|
375
|
-
require file
|
376
|
-
end
|
377
|
-
|
378
|
-
YARD::Rake::YardocTask.new
|
379
|
-
|
380
|
-
# Custom tags for yard
|
381
|
-
YARD::Tags::Library.define_tag("Accessibility", :accessibility)
|
382
|
-
YARD::Tags::Library.define_tag("Deprecation", :deprecation)
|
383
|
-
YARD::Tags::Library.define_tag("Parameter", :param, :with_types_name_and_default)
|
384
|
-
|
385
|
-
puts "Building YARD documentation."
|
386
|
-
Rake::Task["yard"].execute
|
387
|
-
|
388
|
-
registry = YARD::RegistryStore.new
|
389
|
-
registry.load!(".yardoc")
|
390
|
-
registry
|
391
|
-
end
|
392
|
-
|
393
|
-
def parse_example_tag(tag)
|
394
|
-
name = tag.name
|
395
|
-
description = nil
|
396
|
-
code = nil
|
397
|
-
|
398
|
-
if tag.text.include?("@description")
|
399
|
-
splitted = tag.text.split(/@description|@code/)
|
400
|
-
description = splitted.second.gsub(/^[ \t]{2}/, "").strip
|
401
|
-
code = splitted.last.gsub(/^[ \t]{2}/, "").strip
|
402
|
-
else
|
403
|
-
code = tag.text
|
404
|
-
end
|
405
|
-
|
406
|
-
[name, description, code]
|
407
|
-
end
|
408
|
-
|
409
|
-
def pretty_default_value(tag, component)
|
410
|
-
params = tag.object.parameters.find { |param| [tag.name.to_s, "#{tag.name}:"].include?(param[0]) }
|
411
|
-
default = tag.defaults&.first || params&.second
|
412
|
-
|
413
|
-
return "N/A" unless default
|
414
|
-
|
415
|
-
constant_name = "#{component.name}::#{default}"
|
416
|
-
constant_value = default.safe_constantize || constant_name.safe_constantize
|
417
|
-
|
418
|
-
return pretty_value(default) if constant_value.nil?
|
419
|
-
|
420
|
-
pretty_value(constant_value)
|
421
|
-
end
|
422
|
-
|
423
|
-
def docs_metadata(component)
|
424
|
-
(status_module, component_name) = status_module_and_component_name(component)
|
425
|
-
status_path = status_module.nil? ? "" : "/"
|
426
|
-
status = component.status.to_s
|
427
|
-
|
428
|
-
{
|
429
|
-
title: component_name,
|
430
|
-
component_id: component_name.underscore,
|
431
|
-
status: status.capitalize,
|
432
|
-
source: source_url(component),
|
433
|
-
lookbook: lookbook_url(component),
|
434
|
-
path: "docs/content/components/#{status_path}#{component_name.underscore}.md",
|
435
|
-
example_path: example_path(component),
|
436
|
-
require_js_path: require_js_path(component),
|
437
|
-
}
|
438
|
-
end
|
439
|
-
|
440
|
-
def source_url(component)
|
441
|
-
path = component.name.split("::").map(&:underscore).join("/")
|
442
|
-
|
443
|
-
"https://github.com/yettoapp/ariadne/ruby/view_components/tree/main/app/components/#{path}.rb"
|
444
|
-
end
|
445
|
-
|
446
|
-
def lookbook_url(component)
|
447
|
-
path = component.name.split("::").map { |n| n.underscore.dasherize }.join("-")
|
448
|
-
|
449
|
-
"https://ariadne.style/view-components/lookbook/?path=/component/#{path}"
|
450
|
-
end
|
451
|
-
|
452
|
-
def example_path(component)
|
453
|
-
example_path = "../../src/@primer/gatsby-theme-doctocat/components/example"
|
454
|
-
example_path = "../#{example_path}" if status_module?(component)
|
455
|
-
example_path
|
456
|
-
end
|
457
|
-
|
458
|
-
def require_js_path(component)
|
459
|
-
require_js_path = "../../src/@primer/gatsby-theme-doctocat/components/requires-js-flash"
|
460
|
-
require_js_path = "../#{require_js_path}" if status_module?(component)
|
461
|
-
require_js_path
|
462
|
-
end
|
463
|
-
|
464
|
-
def status_module?(component)
|
465
|
-
["Alpha", "Beta"].intersect?(component.name.split("::"))
|
466
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "ast_traverser"
|
4
|
-
|
5
|
-
# :nodoc:
|
6
|
-
class AstProcessor
|
7
|
-
class << self
|
8
|
-
def increment(stats, component, arg_name, value)
|
9
|
-
stats[component][:arguments][arg_name][value] = 0 unless stats[component][:arguments][arg_name][value]
|
10
|
-
stats[component][:arguments][arg_name][value] += 1
|
11
|
-
end
|
12
|
-
|
13
|
-
def process_ast(ast, stats)
|
14
|
-
traverser = AstTraverser.new
|
15
|
-
traverser.walk(ast)
|
16
|
-
|
17
|
-
return if traverser.stats.empty?
|
18
|
-
|
19
|
-
traverser.stats.each do |component, component_info|
|
20
|
-
stats[component] ||= {
|
21
|
-
paths: [],
|
22
|
-
}
|
23
|
-
|
24
|
-
stats[component][:paths] << component_info[:path]
|
25
|
-
stats[component][:paths].uniq!
|
26
|
-
stats[component][:arguments] ||= {}
|
27
|
-
|
28
|
-
component_info[:arguments]&.each do |arg, value|
|
29
|
-
arg_name = arg.to_s
|
30
|
-
stats[component][:arguments][arg_name] ||= {}
|
31
|
-
|
32
|
-
# we want to count each class separately
|
33
|
-
if arg_name == "classes"
|
34
|
-
value.split.each do |val|
|
35
|
-
increment(stats, component, arg_name, val)
|
36
|
-
end
|
37
|
-
else
|
38
|
-
increment(stats, component, arg_name, value)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "ariadne/view_components/statuses"
|
4
|
-
require_relative "../../../app/lib/ariadne/view_helper"
|
5
|
-
|
6
|
-
# :nodoc:
|
7
|
-
class AstTraverser
|
8
|
-
include RuboCop::AST::Traversal
|
9
|
-
|
10
|
-
attr_reader :stats
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
@stats = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def on_send(node)
|
17
|
-
return super(node) unless component_node?(node)
|
18
|
-
|
19
|
-
name = component_name(node)
|
20
|
-
args = extract_arguments(node, name)
|
21
|
-
|
22
|
-
@stats[name] = { path: node.loc.expression.source_buffer.name }
|
23
|
-
@stats[name][:arguments] = args unless args.empty?
|
24
|
-
|
25
|
-
super(node) # recursively iterate over children
|
26
|
-
end
|
27
|
-
|
28
|
-
def view_helpers
|
29
|
-
@view_helpers ||= ::Ariadne::ViewHelper::HELPERS.keys.map { |key| "ariadne_#{key}".to_sym }
|
30
|
-
end
|
31
|
-
|
32
|
-
def component_node?(node)
|
33
|
-
view_helpers.include?(node.method_name) || (node.method_name == :new && !node.receiver.nil? && ::Ariadne::ViewComponents::STATUSES.key?(node.receiver.const_name))
|
34
|
-
end
|
35
|
-
|
36
|
-
def component_name(node)
|
37
|
-
return node.receiver.const_name if node.method_name == :new
|
38
|
-
|
39
|
-
helper_key = node.method_name.to_s.gsub("ariadne_", "").to_sym
|
40
|
-
Ariadne::ViewHelper::HELPERS[helper_key]
|
41
|
-
end
|
42
|
-
|
43
|
-
def extract_arguments(node, name)
|
44
|
-
args = node.arguments
|
45
|
-
res = {}
|
46
|
-
|
47
|
-
return res if args.empty?
|
48
|
-
|
49
|
-
kwargs = args.last
|
50
|
-
if kwargs.respond_to?(:pairs)
|
51
|
-
res = kwargs.pairs.each_with_object({}) do |pair, h|
|
52
|
-
h.merge!(extract_values(pair))
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Heroicon is the only component that accepts positional arguments.
|
57
|
-
res[:icon] = args.first.source if name == "Ariadne::HeroiconComponent" && args.size > 1
|
58
|
-
|
59
|
-
res
|
60
|
-
end
|
61
|
-
|
62
|
-
def extract_values(pair)
|
63
|
-
return { pair.key.value => pair.value.source } unless pair.value.type == :hash
|
64
|
-
|
65
|
-
flatten_pairs(pair, prefix: "#{pair.key.value}-")
|
66
|
-
end
|
67
|
-
|
68
|
-
def flatten_pairs(pair, prefix: "")
|
69
|
-
pair.value.pairs.each_with_object({}) do |value_pair, h|
|
70
|
-
if value_pair.value.type == :hash
|
71
|
-
h.merge!(flatten_pairs(value_pair, prefix: "#{prefix}#{value_pair.key.value}-"))
|
72
|
-
else
|
73
|
-
h["#{prefix}#{value_pair.key.value}"] = value_pair.value.source
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/tasks/static.rake
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
namespace :static do
|
4
|
-
desc "Generate static JSON mappings of components for easier loading"
|
5
|
-
task :dump do
|
6
|
-
require File.expand_path("./../../lookbook/config/environment.rb", __dir__)
|
7
|
-
require "ariadne/view_components"
|
8
|
-
# Loads all components for `.descendants` to work properly
|
9
|
-
Dir["./app/components/ariadne/**/*.rb"].sort.each { |file| require file }
|
10
|
-
|
11
|
-
Ariadne::ViewComponents.dump(:statuses)
|
12
|
-
Ariadne::ViewComponents.dump(:constants)
|
13
|
-
Ariadne::ViewComponents.dump(:audited_at)
|
14
|
-
end
|
15
|
-
end
|
data/lib/tasks/test.rake
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rake/testtask"
|
4
|
-
|
5
|
-
Rake::TestTask.new(:test) do |t|
|
6
|
-
ENV["TZ"] = "Asia/Yerevan"
|
7
|
-
|
8
|
-
t.libs << "test"
|
9
|
-
t.libs << "lib"
|
10
|
-
t.warning = false
|
11
|
-
t.test_files = FileList[ENV["TESTS"] || "test/**/*_test.rb"]
|
12
|
-
end
|
13
|
-
|
14
|
-
Rake::TestTask.new(:bench) do |t|
|
15
|
-
t.libs << "test"
|
16
|
-
t.test_files = FileList["test/benchmarks/**/bench_*.rb"]
|
17
|
-
t.verbose = true
|
18
|
-
t.warning = false
|
19
|
-
end
|