primer_view_components 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/assets/styles/primer_view_components.css +2 -2
  6. data/app/assets/styles/primer_view_components.css.map +1 -1
  7. data/app/components/primer/alpha/action_list/heading.html.erb +1 -1
  8. data/app/components/primer/alpha/action_list/heading.rb +5 -3
  9. data/app/components/primer/alpha/action_list/item.html.erb +9 -0
  10. data/app/components/primer/alpha/action_list/item.rb +32 -11
  11. data/app/components/primer/alpha/action_list.css +1 -1
  12. data/app/components/primer/alpha/action_list.css.json +4 -41
  13. data/app/components/primer/alpha/action_list.css.map +1 -1
  14. data/app/components/primer/alpha/action_list.pcss +19 -20
  15. data/app/components/primer/alpha/action_list.rb +54 -6
  16. data/app/components/primer/alpha/action_menu/action_menu_element.d.ts +23 -0
  17. data/app/components/primer/alpha/action_menu/action_menu_element.js +165 -0
  18. data/app/components/primer/alpha/action_menu/action_menu_element.ts +168 -0
  19. data/app/components/primer/alpha/action_menu/list.rb +91 -0
  20. data/app/components/primer/alpha/action_menu.html.erb +26 -0
  21. data/app/components/primer/alpha/action_menu.rb +361 -0
  22. data/app/components/primer/alpha/auto_complete.css.json +0 -11
  23. data/app/components/primer/alpha/banner.css.json +0 -14
  24. data/app/components/primer/alpha/button_marketing.css.json +0 -10
  25. data/app/components/primer/alpha/dialog.css +1 -1
  26. data/app/components/primer/alpha/dialog.css.json +0 -65
  27. data/app/components/primer/alpha/dialog.css.map +1 -1
  28. data/app/components/primer/alpha/dialog.pcss +0 -4
  29. data/app/components/primer/alpha/dialog.rb +6 -2
  30. data/app/components/primer/alpha/dropdown/menu.rb +1 -1
  31. data/app/components/primer/alpha/dropdown.css.json +0 -21
  32. data/app/components/primer/alpha/layout.css.json +0 -27
  33. data/app/components/primer/alpha/menu.css.json +0 -11
  34. data/app/components/primer/alpha/modal_dialog.js +12 -0
  35. data/app/components/primer/alpha/modal_dialog.ts +17 -0
  36. data/app/components/primer/alpha/nav_list/item.rb +5 -0
  37. data/app/components/primer/alpha/overlay.css +1 -1
  38. data/app/components/primer/alpha/overlay.css.json +0 -3
  39. data/app/components/primer/alpha/overlay.css.map +1 -1
  40. data/app/components/primer/alpha/overlay.pcss +1 -0
  41. data/app/components/primer/alpha/overlay.rb +19 -19
  42. data/app/components/primer/alpha/segmented_control.css.json +0 -15
  43. data/app/components/primer/alpha/tab_nav.css.json +0 -10
  44. data/app/components/primer/alpha/text_field.css.json +0 -38
  45. data/app/components/primer/alpha/toggle_switch.css.json +0 -16
  46. data/app/components/primer/alpha/underline_nav.css.json +0 -13
  47. data/app/components/primer/beta/auto_complete/auto_complete.html.erb +1 -1
  48. data/app/components/primer/beta/auto_complete.rb +19 -1
  49. data/app/components/primer/beta/avatar.css.json +0 -14
  50. data/app/components/primer/beta/avatar_stack.css.json +0 -9
  51. data/app/components/primer/beta/blankslate.css.json +0 -12
  52. data/app/components/primer/beta/border_box.css.json +0 -32
  53. data/app/components/primer/beta/border_box.rb +3 -3
  54. data/app/components/primer/beta/breadcrumbs.css.json +0 -4
  55. data/app/components/primer/beta/button.css +1 -1
  56. data/app/components/primer/beta/button.css.json +0 -24
  57. data/app/components/primer/beta/button.css.map +1 -1
  58. data/app/components/primer/beta/button.pcss +5 -7
  59. data/app/components/primer/beta/counter.css.json +0 -6
  60. data/app/components/primer/beta/flash.css.json +0 -15
  61. data/app/components/primer/beta/label.css.json +0 -20
  62. data/app/components/primer/beta/link.css.json +0 -8
  63. data/app/components/primer/beta/popover.css.json +0 -18
  64. data/app/components/primer/beta/progress_bar.css.json +0 -6
  65. data/app/components/primer/beta/state.css.json +0 -10
  66. data/app/components/primer/beta/subhead.css.json +0 -8
  67. data/app/components/primer/beta/timeline_item.css.json +0 -9
  68. data/app/components/primer/beta/truncate.css.json +0 -6
  69. data/app/components/primer/focus_group.d.ts +19 -0
  70. data/app/components/primer/focus_group.js +144 -0
  71. data/app/components/primer/focus_group.ts +137 -0
  72. data/app/components/primer/icon_button.rb +1 -1
  73. data/app/components/primer/primer.d.ts +2 -0
  74. data/app/components/primer/primer.js +2 -0
  75. data/app/components/primer/primer.ts +2 -0
  76. data/app/components/primer/truncate.css.json +0 -7
  77. data/app/lib/primer/css/layout.css.json +0 -263
  78. data/app/lib/primer/css/utilities.css.json +0 -1636
  79. data/lib/primer/static/generate_arguments.rb +55 -0
  80. data/lib/primer/static/generate_audited_at.rb +17 -0
  81. data/lib/primer/static/generate_constants.rb +19 -0
  82. data/lib/primer/static/generate_info_arch.rb +156 -0
  83. data/lib/primer/static/generate_previews.rb +45 -0
  84. data/lib/primer/static/generate_statuses.rb +17 -0
  85. data/lib/primer/static.rb +72 -0
  86. data/lib/primer/view_components/linters/disallow_component_css_counter.rb +43 -4
  87. data/lib/primer/view_components/version.rb +1 -1
  88. data/lib/primer/view_components.rb +0 -48
  89. data/lib/primer/yard/component_manifest.rb +1 -0
  90. data/lib/primer/yard/component_ref.rb +14 -0
  91. data/lib/primer/yard/docs_helper.rb +3 -0
  92. data/lib/primer/yard/info_arch_docs_helper.rb +31 -0
  93. data/lib/primer/yard/legacy_gatsby_backend.rb +3 -35
  94. data/lib/primer/yard/registry.rb +2 -1
  95. data/lib/primer/yard.rb +1 -0
  96. data/lib/tasks/docs.rake +10 -12
  97. data/lib/tasks/static.rake +20 -28
  98. data/previews/primer/alpha/action_list_preview.rb +4 -1
  99. data/previews/primer/alpha/action_menu_preview/align_end.html.erb +6 -0
  100. data/previews/primer/alpha/action_menu_preview/content_labels.html.erb +9 -0
  101. data/previews/primer/alpha/action_menu_preview/opens_dialog.html.erb +21 -0
  102. data/previews/primer/alpha/action_menu_preview.rb +245 -0
  103. data/previews/primer/alpha/dialog_preview/body_has_scrollbar_overflow.html.erb +2 -2
  104. data/previews/primer/alpha/dialog_preview/custom_header.html.erb +3 -3
  105. data/previews/primer/alpha/dialog_preview/nested_dialog.html.erb +4 -4
  106. data/previews/primer/alpha/dialog_preview/test.html.erb +3 -3
  107. data/previews/primer/alpha/dialog_preview/with_footer.html.erb +3 -3
  108. data/previews/primer/alpha/dialog_preview/with_form.html.erb +1 -1
  109. data/previews/primer/alpha/dialog_preview/with_text_input.html.erb +2 -2
  110. data/previews/primer/alpha/dialog_preview.rb +7 -2
  111. data/previews/primer/beta/auto_complete_item_preview.rb +1 -0
  112. data/previews/primer/beta/auto_complete_preview.rb +36 -23
  113. data/static/arguments.json +3085 -1405
  114. data/static/audited_at.json +2 -0
  115. data/static/classes.json +576 -311
  116. data/static/constants.json +53 -2
  117. data/static/info_arch.json +8888 -0
  118. data/static/previews.json +226 -101
  119. data/static/statuses.json +2 -0
  120. metadata +28 -6
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+
5
+ require "json"
6
+
7
+ module Primer
8
+ module Static
9
+ # :nodoc:
10
+ module GenerateArguments
11
+ class << self
12
+ def call(view_context: self.view_context)
13
+ Primer::Component.descendants.sort_by(&:name).map do |component|
14
+ docs = registry.find(component)
15
+ ref = Primer::Yard::ComponentManifest.ref_for(component)
16
+
17
+ args = docs.params.map do |tag|
18
+ default_value = Primer::Yard::DocsHelper.pretty_default_value(tag, component)
19
+
20
+ {
21
+ "name" => tag.name,
22
+ "type" => tag.types.join(", "),
23
+ "default" => default_value,
24
+ "description" => view_context.render(inline: tag.text.squish)
25
+ }
26
+ end
27
+
28
+ {
29
+ "component" => docs.metadata[:title],
30
+ "status" => component.status.to_s,
31
+ "a11y_reviewed" => docs.metadata[:a11y_reviewed] == "true",
32
+ "short_name" => docs.short_name,
33
+ "source" => ref.source_url,
34
+ "lookbook" => ref.lookbook_url,
35
+ "parameters" => args
36
+ }
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def view_context
43
+ @view_context ||= ApplicationController.new.tap { |c| c.request = ActionDispatch::TestRequest.create }.view_context.tap do |vc|
44
+ vc.singleton_class.include(Primer::Yard::DocsHelper)
45
+ vc.singleton_class.include(Primer::ViewHelper)
46
+ end
47
+ end
48
+
49
+ def registry
50
+ @registry ||= Primer::Yard::Registry.make
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+ module Primer
5
+ module Static
6
+ # :nodoc:
7
+ module GenerateAuditedAt
8
+ class << self
9
+ def call
10
+ Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
11
+ mem[component.to_s] = component.audited_at.to_s
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+ module Primer
5
+ module Static
6
+ # :nodoc:
7
+ module GenerateConstants
8
+ class << self
9
+ def call
10
+ Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
11
+ mem[component.to_s] = component.constants(false).sort.each_with_object({}) do |constant, h|
12
+ h[constant] = component.const_get(constant)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+
5
+ require "json"
6
+
7
+ module Primer
8
+ module Static
9
+ # :nodoc:
10
+ module GenerateInfoArch
11
+ SKIP_METHODS = %i[call before_render].freeze
12
+
13
+ class << self
14
+ def call
15
+ components = Primer::Component.descendants.sort_by(&:name) - [Primer::BaseComponent]
16
+
17
+ component_docs = components.each_with_object({}) do |component, memo|
18
+ docs = registry.find(component)
19
+
20
+ preview_data = previews.find do |preview|
21
+ preview["component"] == docs.metadata[:title] &&
22
+ preview["status"] == component.status.to_s
23
+ end
24
+
25
+ arg_data = args.find do |component_args|
26
+ component_args["component"] == docs.metadata[:title] &&
27
+ component_args["status"] == component.status.to_s
28
+ end
29
+
30
+ slot_docs = docs.slot_methods.map do |slot_method|
31
+ param_tags = slot_method.tags(:param)
32
+
33
+ {
34
+ "name" => slot_method.name,
35
+ # rubocop:disable Style/IfUnlessModifier
36
+ "description" =>
37
+ if slot_method.base_docstring.to_s.present?
38
+ view_context.render(inline: slot_method.base_docstring)
39
+ end,
40
+ # rubocop:enable Style/IfUnlessModifier
41
+ "parameters" => serialize_params(param_tags, component)
42
+ }
43
+ end
44
+
45
+ mtds = docs.non_slot_methods.select do |mtd|
46
+ next false if mtd.base_docstring.to_s.blank?
47
+ next false if SKIP_METHODS.include?(mtd.name)
48
+
49
+ method_location, = mtd.files.first
50
+ class_location, = docs.docs.files.first
51
+
52
+ method_location == class_location
53
+ end
54
+
55
+ method_docs = mtds.map do |mtd|
56
+ param_tags = mtd.tags(:param)
57
+
58
+ {
59
+ "name" => mtd.name,
60
+ "description" => view_context.render(inline: mtd.base_docstring),
61
+ "parameters" => serialize_params(param_tags, component)
62
+ }
63
+ end
64
+
65
+ description =
66
+ if component == Primer::BaseComponent
67
+ docs.base_docstring
68
+ else
69
+ view_context.render(inline: docs.base_docstring)
70
+ end
71
+
72
+ memo[component] = {
73
+ "fully_qualified_name" => component.name,
74
+ "description" => description,
75
+ **arg_data,
76
+ "slots" => slot_docs,
77
+ "methods" => method_docs,
78
+ "previews" => (preview_data || {}).fetch("examples", []),
79
+ "subcomponents" => []
80
+ }
81
+ end
82
+
83
+ statuses = Primer::Status::Dsl::STATUSES.keys.map(&:to_s).map(&:capitalize)
84
+
85
+ Primer::Component.descendants.each do |component|
86
+ fq_class = component.name.to_s.split("::")
87
+ fq_class.shift # remove Primer::
88
+ status = fq_class.shift if statuses.include?(fq_class.first) # remove Status::
89
+
90
+ parent, *child = *fq_class
91
+
92
+ next if child.empty?
93
+
94
+ parent_class = Primer
95
+ parent_class = parent_class.const_get(status) if status
96
+ parent_class = parent_class.const_get(parent)
97
+
98
+ parent_docs = component_docs[parent_class]
99
+ next unless parent_docs
100
+
101
+ if (child_docs = component_docs.delete(component))
102
+ parent_docs["subcomponents"] << child_docs
103
+ end
104
+ end
105
+
106
+ component_docs.values + [system_args_docs]
107
+ end
108
+
109
+ private
110
+
111
+ def system_args_docs
112
+ docs = registry.find(Primer::BaseComponent)
113
+
114
+ {
115
+ component: "BaseComponent",
116
+ fully_qualified_name: "Primer::BaseComponent",
117
+ description_md: docs.base_docstring,
118
+ args_md: view_context.render(inline: docs.constructor.base_docstring)
119
+ }
120
+ end
121
+
122
+ def serialize_params(param_tags, component)
123
+ param_tags.map do |tag|
124
+ default_value = Primer::Yard::DocsHelper.pretty_default_value(tag, component)
125
+
126
+ {
127
+ "name" => tag.name,
128
+ "type" => tag.types&.join(", ") || "",
129
+ "default" => default_value,
130
+ "description" => view_context.render(inline: tag.text.squish)
131
+ }
132
+ end
133
+ end
134
+
135
+ def previews
136
+ @previews ||= JSON.parse(Static.read(:previews))
137
+ end
138
+
139
+ def args
140
+ @args ||= Primer::Static::GenerateArguments.call(view_context: view_context)
141
+ end
142
+
143
+ def view_context
144
+ @view_context ||= ApplicationController.new.tap { |c| c.request = ActionDispatch::TestRequest.create }.view_context.tap do |vc|
145
+ vc.singleton_class.include(Primer::Yard::InfoArchDocsHelper)
146
+ vc.singleton_class.include(Primer::ViewHelper)
147
+ end
148
+ end
149
+
150
+ def registry
151
+ @registry ||= Primer::Yard::Registry.make
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+
5
+ require "json"
6
+
7
+ module Primer
8
+ module Static
9
+ # :nodoc:
10
+ module GeneratePreviews
11
+ class << self
12
+ def call
13
+ Lookbook.previews.filter_map do |preview|
14
+ next if preview.preview_class.name.start_with?("Docs::")
15
+ next if preview.preview_class == Primer::Forms::FormsPreview
16
+
17
+ component = preview.components.first&.component_class
18
+
19
+ # rubocop:disable Style/IfUnlessModifier
20
+ unless component
21
+ raise "Could not determine which component `#{preview.preview_class}` is designed to preview. Please add a `@component` annotation."
22
+ end
23
+ # rubocop:enable Style/IfUnlessModifier
24
+
25
+ _, _, class_name = Primer::Yard::DocsHelper.status_module_and_short_name(component)
26
+
27
+ {
28
+ name: preview.name,
29
+ component: class_name,
30
+ status: component.status.to_s,
31
+ lookup_path: preview.lookup_path,
32
+ examples: preview.examples.map do |example|
33
+ {
34
+ inspect_path: example.url_path,
35
+ preview_path: example.url_path.sub("/inspect/", "/preview/"),
36
+ name: example.name
37
+ }
38
+ end
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+ module Primer
5
+ module Static
6
+ # :nodoc:
7
+ module GenerateStatuses
8
+ class << self
9
+ def call
10
+ Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
11
+ mem[component.to_s] = component.status.to_s
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+
5
+ require "json"
6
+
7
+ module Primer
8
+ # :nodoc:
9
+ module Static
10
+ DEFAULT_STATIC_PATH = File.expand_path("static").freeze
11
+
12
+ FILE_NAMES = {
13
+ statuses: "statuses.json",
14
+ constants: "constants.json",
15
+ audited_at: "audited_at.json",
16
+ arguments: "arguments.json",
17
+ previews: "previews.json",
18
+ info_arch: "info_arch.json"
19
+ }.freeze
20
+
21
+ # Returns a hash mapping component names to component statuses (alpha, beta, etc),
22
+ # sorted alphabetically by the component name.
23
+ def self.generate_statuses
24
+ Static::GenerateStatuses.call
25
+ end
26
+
27
+ # Returns a hash mapping component names to the date on which the component passed
28
+ # an accessibility audit.
29
+ def self.generate_audited_at
30
+ Static::GenerateAuditedAt.call
31
+ end
32
+
33
+ # Returns a hash mapping component names to an array of the constants defined inside
34
+ # the component's class.
35
+ def self.generate_constants
36
+ Static::GenerateConstants.call
37
+ end
38
+
39
+ # Returns an array of hashes, one per Primer component, that contains some metadata and
40
+ # a list of the arguments accepted by the component's constructor. Arguments are enumerated
41
+ # with their value, data type, and docstring.
42
+ def self.generate_arguments
43
+ Static::GenerateArguments.call
44
+ end
45
+
46
+ # Returns an array of hashes, one per Primer component, that contains some metadata and
47
+ # an array of all the component's previews. The preview data contains the Lookbook URL
48
+ # to each preview and its name.
49
+ def self.generate_previews
50
+ Static::GeneratePreviews.call
51
+ end
52
+
53
+ # Returns an array of hashes, one per Primer component, that contains all the data needed
54
+ # for the new primer.style docsite.
55
+ def self.generate_info_arch
56
+ Static::GenerateInfoArch.call
57
+ end
58
+
59
+ # Generates the requested stat hash and outputs it to a file.
60
+ def self.dump(stats)
61
+ File.open(File.join(DEFAULT_STATIC_PATH, FILE_NAMES[stats]), "w") do |f|
62
+ f.write(JSON.pretty_generate(send("generate_#{stats}")))
63
+ f.write($INPUT_RECORD_SEPARATOR)
64
+ end
65
+ end
66
+
67
+ # Returns the contents of the stat file.
68
+ def self.read(stats)
69
+ File.read(File.join(DEFAULT_STATIC_PATH, FILE_NAMES[stats]))
70
+ end
71
+ end
72
+ end
@@ -13,18 +13,57 @@ module ERBLint
13
13
  module Linters
14
14
  # Counts the number of times a class reserved for ViewComponents is used
15
15
  class DisallowComponentCssCounter < BaseLinter
16
+ CLASSES_COVERED_BY_OTHER_LINTERS =
17
+ BaseLinter.subclasses.reduce([]) do |html_classes, klass|
18
+ html_classes.concat(klass.const_get(:CLASSES))
19
+ end
20
+
16
21
  CLASSES = (
17
22
  JSON.parse(
18
23
  File.read(
19
24
  File.join(__dir__, "..", "..", "..", "..", "static", "classes.json")
20
25
  )
21
- ) - BaseLinter.subclasses.reduce([]) do |html_classes, klass|
22
- html_classes.concat(klass.const_get(:CLASSES))
26
+ ).reject do |html_class, _ruby_classes|
27
+ CLASSES_COVERED_BY_OTHER_LINTERS.include?(html_class)
23
28
  end
24
29
  ).freeze
25
30
 
26
- TAGS = nil
27
- MESSAGE = "Primer ViewComponents defines some HTML classes with associated styles that should not be used outside those components. (These classes might have their styles changed or even disappear in the future.) Instead of using this class directly, please use its component if appropriate or define the styles you need some other way."
31
+ def run(processed_source)
32
+ @total_offenses = 0
33
+ @offenses_not_corrected = 0
34
+
35
+ processed_source
36
+ .parser
37
+ .nodes_with_type(:tag)
38
+ .each do |node|
39
+ tag = BetterHtml::Tree::Tag.from_node(node)
40
+
41
+ tag.attributes["class"]&.value&.split(/\s+/)&.each do |class_name|
42
+ if CLASSES.key? class_name
43
+ @total_offenses += 1
44
+ @offenses_not_corrected += 1
45
+ add_offense(
46
+ processed_source.to_source_range(tag.loc),
47
+ format_message(class_name)
48
+ )
49
+ end
50
+ end
51
+ end
52
+
53
+ counter_correct?(processed_source)
54
+
55
+ dump_data(processed_source) if ENV["DUMP_LINT_DATA"] == "1"
56
+ end
57
+
58
+ private
59
+
60
+ def format_message(class_name)
61
+ "DisallowComponentCssCounter:HTML class \"#{class_name}\" is reserved for Primer ViewComponents. It might disappear or have different styles in the future. You might want to use #{ruby_classes_sentence_string(class_name)} from Primer ViewComponents instead."
62
+ end
63
+
64
+ def ruby_classes_sentence_string(class_name)
65
+ CLASSES[class_name].to_sentence(last_word_connector: ", or ", two_words_connector: " or ")
66
+ end
28
67
  end
29
68
  end
30
69
  end
@@ -6,7 +6,7 @@ module Primer
6
6
  module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 1
9
- PATCH = 4
9
+ PATCH = 6
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -7,54 +7,6 @@ require "primer/view_components/engine"
7
7
  module Primer
8
8
  # :nodoc:
9
9
  module ViewComponents
10
- DEFAULT_STATIC_PATH = File.expand_path("static")
11
- FILE_NAMES = {
12
- statuses: "statuses.json",
13
- constants: "constants.json",
14
- audited_at: "audited_at.json"
15
- }.freeze
16
-
17
- # generate_statuses returns a hash mapping component name to
18
- # the component's status sorted alphabetically by the component name.
19
- def self.generate_statuses
20
- Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
21
- mem[component.to_s] = component.status.to_s
22
- end
23
- end
24
-
25
- # generate_audited_at returns a hash mapping component name to
26
- # the day the component has passed an accessibility audit.
27
- def self.generate_audited_at
28
- Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
29
- mem[component.to_s] = component.audited_at.to_s
30
- end
31
- end
32
-
33
- # generate_constants returns a hash mapping component name to
34
- # all of its constants.
35
- def self.generate_constants
36
- Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
37
- mem[component.to_s] = component.constants(false).sort.each_with_object({}) do |constant, h|
38
- h[constant] = component.const_get(constant)
39
- end
40
- end
41
- end
42
-
43
- # dump generates the requested stat hash and outputs it to a file.
44
- def self.dump(stats)
45
- require "json"
46
-
47
- File.open(File.join(DEFAULT_STATIC_PATH, FILE_NAMES[stats]), "w") do |f|
48
- f.write(JSON.pretty_generate(send("generate_#{stats}")))
49
- f.write($INPUT_RECORD_SEPARATOR)
50
- end
51
- end
52
-
53
- # read returns a JSON string matching the output of the corresponding stat.
54
- def self.read(stats)
55
- File.read(File.join(DEFAULT_STATIC_PATH, FILE_NAMES[stats]))
56
- end
57
-
58
10
  # primer/view_components root directory.
59
11
  def self.root
60
12
  Pathname(File.expand_path(File.join("..", ".."), __dir__))
@@ -65,6 +65,7 @@ module Primer
65
65
  Primer::Alpha::Tooltip => { js: true },
66
66
  Primer::Alpha::ToggleSwitch => { js: true },
67
67
  Primer::Alpha::Overlay => { js: true },
68
+ Primer::Alpha::ActionMenu => { js: true },
68
69
 
69
70
  # Examples can be seen in the NavList docs
70
71
  Primer::Alpha::NavList => { js: true },
@@ -34,6 +34,20 @@ module Primer
34
34
  def form_component?
35
35
  @attrs.fetch(:form_component, ATTR_DEFAULTS[:form_component])
36
36
  end
37
+
38
+ def source_url
39
+ @source_url ||= begin
40
+ path = klass.name.split("::").map(&:underscore).join("/")
41
+ "https://github.com/primer/view_components/tree/main/app/components/#{path}.rb"
42
+ end
43
+ end
44
+
45
+ def lookbook_url
46
+ @lookbook_url ||= begin
47
+ path = klass.name.underscore.gsub("_component", "")
48
+ "https://primer.style/view-components/lookbook/inspect/#{path}/default/"
49
+ end
50
+ end
37
51
  end
38
52
  end
39
53
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  # :nocov:
4
4
  module Primer
5
+ # :nodoc:
5
6
  module Yard
6
7
  # Helper methods to use for yard documentation
7
8
  module DocsHelper
@@ -90,6 +91,8 @@ module Primer
90
91
  end
91
92
  end
92
93
  end
94
+
95
+ DocsHelper.extend(DocsHelper)
93
96
  end
94
97
  end
95
98
  # :nocov:
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+ module Primer
5
+ module Yard
6
+ # Helper methods to use for info arch yard documentation
7
+ module InfoArchDocsHelper
8
+ include DocsHelper
9
+
10
+ def link_to_component(component)
11
+ "{{#link_to_component}}#{component}{{/link_to_component}}"
12
+ end
13
+
14
+ def link_to_system_arguments_docs
15
+ "{{link_to_system_arguments_docs}}"
16
+ end
17
+
18
+ def link_to_typography_docs
19
+ "{{link_to_typography_docs}}"
20
+ end
21
+
22
+ def link_to_accessibility
23
+ "{{link_to_accessibility}}"
24
+ end
25
+
26
+ def link_to_octicons
27
+ "{{link_to_octicons}}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -33,7 +33,6 @@ module Primer
33
33
  end
34
34
 
35
35
  def generate
36
- args_for_components = []
37
36
  errors = []
38
37
 
39
38
  each_component do |component_ref|
@@ -42,8 +41,8 @@ module Primer
42
41
  status_path = docs.status_module.nil? ? "" : "#{docs.status_module}/"
43
42
 
44
43
  metadata = docs.metadata.merge(
45
- source: source_url(component),
46
- lookbook: lookbook_url(component),
44
+ source: component_ref.source_url,
45
+ lookbook: component_ref.lookbook_url,
47
46
  path: "docs/content/components/#{status_path}#{docs.short_name.downcase}.md",
48
47
  example_path: example_path(component),
49
48
  require_js_path: require_js_path(component)
@@ -113,30 +112,11 @@ module Primer
113
112
  errors << { component.name => err }
114
113
  end
115
114
 
116
- args = []
117
115
  docs.params.each do |tag|
118
116
  default_value = pretty_default_value(tag, component)
119
-
120
- args << {
121
- "name" => tag.name,
122
- "type" => tag.types.join(", "),
123
- "default" => default_value,
124
- "description" => view_context.render(inline: tag.text.squish)
125
- }
126
-
127
117
  f.puts("| `#{tag.name}` | `#{tag.types.join(', ')}` | #{default_value} | #{view_context.render(inline: tag.text.squish)} |")
128
118
  end
129
119
 
130
- component_args = {
131
- "component" => metadata[:title],
132
- "status" => component.status.to_s,
133
- "source" => metadata[:source],
134
- "lookbook" => metadata[:lookbook],
135
- "parameters" => args
136
- }
137
-
138
- args_for_components << component_args
139
-
140
120
  if docs.slot_methods.any?
141
121
  f.puts
142
122
  f.puts("## Slots")
@@ -190,7 +170,7 @@ module Primer
190
170
  f.puts(view_context.render(inline: system_args_docs.constructor.base_docstring))
191
171
  end
192
172
 
193
- [args_for_components, errors]
173
+ errors
194
174
  end
195
175
 
196
176
  private
@@ -220,18 +200,6 @@ module Primer
220
200
  manifest.each(&block)
221
201
  end
222
202
 
223
- def source_url(component)
224
- path = component.name.split("::").map(&:underscore).join("/")
225
-
226
- "https://github.com/primer/view_components/tree/main/app/components/#{path}.rb"
227
- end
228
-
229
- def lookbook_url(component)
230
- path = component.name.underscore.gsub("_component", "")
231
-
232
- "https://primer.style/view-components/lookbook/inspect/#{path}/default/"
233
- end
234
-
235
203
  def example_path(component)
236
204
  example_path = "../../src/@primer/gatsby-theme-doctocat/components/example"
237
205
  example_path = "../#{example_path}" if status_module?(component)
@@ -28,6 +28,7 @@ module Primer
28
28
 
29
29
  {
30
30
  title: class_name,
31
+ class_name: class_name,
31
32
  component_id: short_name.underscore,
32
33
  status: status.capitalize,
33
34
  status_module: status_module,
@@ -42,7 +43,7 @@ module Primer
42
43
  end
43
44
 
44
45
  def params
45
- constructor.tags(:param)
46
+ constructor&.tags(:param) || []
46
47
  end
47
48
 
48
49
  def slot_methods