primer_view_components 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +2 -2
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/action_list/heading.html.erb +1 -1
- data/app/components/primer/alpha/action_list/heading.rb +5 -3
- data/app/components/primer/alpha/action_list/item.html.erb +9 -0
- data/app/components/primer/alpha/action_list/item.rb +31 -10
- data/app/components/primer/alpha/action_list.css +1 -1
- data/app/components/primer/alpha/action_list.css.json +4 -41
- data/app/components/primer/alpha/action_list.css.map +1 -1
- data/app/components/primer/alpha/action_list.pcss +19 -20
- data/app/components/primer/alpha/action_list.rb +54 -6
- data/app/components/primer/alpha/action_menu/action_menu_element.d.ts +22 -0
- data/app/components/primer/alpha/action_menu/action_menu_element.js +139 -0
- data/app/components/primer/alpha/action_menu/action_menu_element.ts +137 -0
- data/app/components/primer/alpha/action_menu/list.rb +81 -0
- data/app/components/primer/alpha/action_menu.html.erb +26 -0
- data/app/components/primer/alpha/action_menu.rb +322 -0
- data/app/components/primer/alpha/auto_complete.css.json +0 -11
- data/app/components/primer/alpha/banner.css.json +0 -14
- data/app/components/primer/alpha/button_marketing.css.json +0 -10
- data/app/components/primer/alpha/dialog.css.json +0 -63
- data/app/components/primer/alpha/dialog.rb +6 -2
- data/app/components/primer/alpha/dropdown.css.json +0 -21
- data/app/components/primer/alpha/layout.css.json +0 -27
- data/app/components/primer/alpha/menu.css.json +0 -11
- data/app/components/primer/alpha/nav_list/item.rb +5 -0
- data/app/components/primer/alpha/overlay.css +1 -1
- data/app/components/primer/alpha/overlay.css.json +0 -3
- data/app/components/primer/alpha/overlay.css.map +1 -1
- data/app/components/primer/alpha/overlay.pcss +1 -0
- data/app/components/primer/alpha/overlay.rb +14 -18
- data/app/components/primer/alpha/segmented_control.css.json +0 -15
- data/app/components/primer/alpha/tab_nav.css.json +0 -10
- data/app/components/primer/alpha/text_field.css.json +0 -38
- data/app/components/primer/alpha/toggle_switch.css.json +0 -16
- data/app/components/primer/alpha/underline_nav.css.json +0 -13
- data/app/components/primer/beta/avatar.css.json +0 -14
- data/app/components/primer/beta/avatar_stack.css.json +0 -9
- data/app/components/primer/beta/blankslate.css.json +0 -12
- data/app/components/primer/beta/border_box.css.json +0 -32
- data/app/components/primer/beta/border_box.rb +3 -3
- data/app/components/primer/beta/breadcrumbs.css.json +0 -4
- data/app/components/primer/beta/button.css +1 -1
- data/app/components/primer/beta/button.css.json +0 -22
- data/app/components/primer/beta/button.css.map +1 -1
- data/app/components/primer/beta/button.pcss +3 -3
- data/app/components/primer/beta/counter.css.json +0 -6
- data/app/components/primer/beta/flash.css.json +0 -15
- data/app/components/primer/beta/label.css.json +0 -20
- data/app/components/primer/beta/link.css.json +0 -8
- data/app/components/primer/beta/popover.css.json +0 -18
- data/app/components/primer/beta/progress_bar.css.json +0 -6
- data/app/components/primer/beta/state.css.json +0 -10
- data/app/components/primer/beta/subhead.css.json +0 -8
- data/app/components/primer/beta/timeline_item.css.json +0 -9
- data/app/components/primer/beta/truncate.css.json +0 -6
- data/app/components/primer/focus_group.d.ts +19 -0
- data/app/components/primer/focus_group.js +144 -0
- data/app/components/primer/focus_group.ts +137 -0
- data/app/components/primer/icon_button.rb +1 -1
- data/app/components/primer/primer.d.ts +2 -0
- data/app/components/primer/primer.js +2 -0
- data/app/components/primer/primer.ts +2 -0
- data/app/components/primer/truncate.css.json +0 -7
- data/app/lib/primer/css/layout.css.json +0 -263
- data/app/lib/primer/css/utilities.css.json +0 -1636
- data/lib/primer/static/generate_arguments.rb +55 -0
- data/lib/primer/static/generate_audited_at.rb +17 -0
- data/lib/primer/static/generate_constants.rb +19 -0
- data/lib/primer/static/generate_info_arch.rb +156 -0
- data/lib/primer/static/generate_previews.rb +45 -0
- data/lib/primer/static/generate_statuses.rb +17 -0
- data/lib/primer/static.rb +72 -0
- data/lib/primer/view_components/linters/disallow_component_css_counter.rb +43 -4
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/primer/view_components.rb +0 -48
- data/lib/primer/yard/component_manifest.rb +1 -0
- data/lib/primer/yard/component_ref.rb +14 -0
- data/lib/primer/yard/docs_helper.rb +3 -0
- data/lib/primer/yard/info_arch_docs_helper.rb +31 -0
- data/lib/primer/yard/legacy_gatsby_backend.rb +3 -35
- data/lib/primer/yard/registry.rb +2 -1
- data/lib/primer/yard.rb +1 -0
- data/lib/tasks/docs.rake +10 -12
- data/lib/tasks/static.rake +20 -28
- data/previews/primer/alpha/action_list_preview.rb +4 -1
- data/previews/primer/alpha/action_menu_preview/align_end.html.erb +6 -0
- data/previews/primer/alpha/action_menu_preview/opens_dialog.html.erb +21 -0
- data/previews/primer/alpha/action_menu_preview.rb +238 -0
- data/previews/primer/alpha/dialog_preview/body_has_scrollbar_overflow.html.erb +2 -2
- data/previews/primer/alpha/dialog_preview/custom_header.html.erb +3 -3
- data/previews/primer/alpha/dialog_preview/nested_dialog.html.erb +4 -4
- data/previews/primer/alpha/dialog_preview/test.html.erb +3 -3
- data/previews/primer/alpha/dialog_preview/with_footer.html.erb +3 -3
- data/previews/primer/alpha/dialog_preview/with_form.html.erb +1 -1
- data/previews/primer/alpha/dialog_preview/with_text_input.html.erb +2 -2
- data/previews/primer/alpha/dialog_preview.rb +7 -2
- data/previews/primer/beta/auto_complete_item_preview.rb +1 -0
- data/static/arguments.json +3078 -1404
- data/static/audited_at.json +2 -0
- data/static/classes.json +576 -311
- data/static/constants.json +42 -2
- data/static/info_arch.json +8859 -0
- data/static/previews.json +221 -101
- data/static/statuses.json +2 -0
- metadata +23 -2
@@ -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
|
-
)
|
22
|
-
|
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
|
-
|
27
|
-
|
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
|
@@ -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
|
@@ -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
|
46
|
-
lookbook: lookbook_url
|
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
|
-
|
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)
|
data/lib/primer/yard/registry.rb
CHANGED
@@ -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
|
46
|
+
constructor&.tags(:param) || []
|
46
47
|
end
|
47
48
|
|
48
49
|
def slot_methods
|