primer_view_components 0.1.3 → 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 +22 -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/forms/select_form.rb +2 -2
- data/app/lib/primer/css/layout.css.json +0 -263
- data/app/lib/primer/css/utilities.css.json +0 -1636
- data/lib/primer/classify/utilities.yml +60 -0
- data/lib/primer/forms/form_control.html.erb +1 -1
- data/lib/primer/forms/form_control.rb +5 -1
- data/lib/primer/forms/multi.html.erb +6 -8
- data/lib/primer/forms/text_field.html.erb +15 -17
- 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/custom_utilities.yml +60 -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
@@ -1606,45 +1606,105 @@
|
|
1606
1606
|
:border:
|
1607
1607
|
:left:
|
1608
1608
|
- border-left
|
1609
|
+
- border-sm-left
|
1610
|
+
- border-md-left
|
1611
|
+
- border-lg-left
|
1612
|
+
- border-xl-left
|
1609
1613
|
:top:
|
1610
1614
|
- border-top
|
1615
|
+
- border-sm-top
|
1616
|
+
- border-md-top
|
1617
|
+
- border-lg-top
|
1618
|
+
- border-xl-top
|
1611
1619
|
:bottom:
|
1612
1620
|
- border-bottom
|
1621
|
+
- border-sm-bottom
|
1622
|
+
- border-md-bottom
|
1623
|
+
- border-lg-bottom
|
1624
|
+
- border-xl-bottom
|
1613
1625
|
:right:
|
1614
1626
|
- border-right
|
1627
|
+
- border-sm-right
|
1628
|
+
- border-md-right
|
1629
|
+
- border-lg-right
|
1630
|
+
- border-xl-right
|
1615
1631
|
:y:
|
1616
1632
|
- border-y
|
1617
1633
|
:x:
|
1618
1634
|
- border-x
|
1619
1635
|
true:
|
1620
1636
|
- border
|
1637
|
+
- border-sm
|
1638
|
+
- border-md
|
1639
|
+
- border-lg
|
1640
|
+
- border-xl
|
1621
1641
|
0:
|
1622
1642
|
- border-0
|
1643
|
+
- border-sm-0
|
1644
|
+
- border-md-0
|
1645
|
+
- border-lg-0
|
1646
|
+
- border-xl-0
|
1623
1647
|
false:
|
1624
1648
|
- border-0
|
1649
|
+
- border-sm-0
|
1650
|
+
- border-md-0
|
1651
|
+
- border-lg-0
|
1652
|
+
- border-xl-0
|
1625
1653
|
:dashed:
|
1626
1654
|
- border-dashed
|
1627
1655
|
:border_top:
|
1628
1656
|
0:
|
1629
1657
|
- border-top-0
|
1658
|
+
- border-sm-top-0
|
1659
|
+
- border-md-top-0
|
1660
|
+
- border-lg-top-0
|
1661
|
+
- border-xl-top-0
|
1630
1662
|
:border_bottom:
|
1631
1663
|
0:
|
1632
1664
|
- border-bottom-0
|
1665
|
+
- border-sm-bottom-0
|
1666
|
+
- border-md-bottom-0
|
1667
|
+
- border-lg-bottom-0
|
1668
|
+
- border-xl-bottom-0
|
1633
1669
|
:border_left:
|
1634
1670
|
0:
|
1635
1671
|
- border-left-0
|
1672
|
+
- border-sm-left-0
|
1673
|
+
- border-md-left-0
|
1674
|
+
- border-lg-left-0
|
1675
|
+
- border-xl-left-0
|
1636
1676
|
:border_right:
|
1637
1677
|
0:
|
1638
1678
|
- border-right-0
|
1679
|
+
- border-sm-right-0
|
1680
|
+
- border-md-right-0
|
1681
|
+
- border-lg-right-0
|
1682
|
+
- border-xl-right-0
|
1639
1683
|
:border_radius:
|
1640
1684
|
0:
|
1641
1685
|
- rounded-0
|
1686
|
+
- rounded-sm-0
|
1687
|
+
- rounded-md-0
|
1688
|
+
- rounded-lg-0
|
1689
|
+
- rounded-xl-0
|
1642
1690
|
1:
|
1643
1691
|
- rounded-1
|
1692
|
+
- rounded-sm-1
|
1693
|
+
- rounded-md-1
|
1694
|
+
- rounded-lg-1
|
1695
|
+
- rounded-xl-1
|
1644
1696
|
2:
|
1645
1697
|
- rounded-2
|
1698
|
+
- rounded-sm-2
|
1699
|
+
- rounded-md-2
|
1700
|
+
- rounded-lg-2
|
1701
|
+
- rounded-xl-2
|
1646
1702
|
3:
|
1647
1703
|
- rounded-3
|
1704
|
+
- rounded-sm-3
|
1705
|
+
- rounded-md-3
|
1706
|
+
- rounded-lg-3
|
1707
|
+
- rounded-xl-3
|
1648
1708
|
:justify_content:
|
1649
1709
|
:flex_start:
|
1650
1710
|
- flex-justify-start
|
@@ -6,11 +6,15 @@ module Primer
|
|
6
6
|
class FormControl < BaseComponent
|
7
7
|
delegate :builder, :form, to: :@input
|
8
8
|
|
9
|
-
def initialize(input:)
|
9
|
+
def initialize(input:, tag: :div, **system_arguments)
|
10
10
|
@input = input
|
11
|
+
@tag = tag
|
11
12
|
@input.add_label_classes("FormControl-label")
|
12
13
|
@form_group_arguments = {
|
14
|
+
**system_arguments,
|
13
15
|
class: class_names(
|
16
|
+
system_arguments[:class],
|
17
|
+
system_arguments[:classes],
|
14
18
|
"FormControl",
|
15
19
|
"width-full",
|
16
20
|
"FormControl--fullWidth" => @input.full_width?
|
@@ -1,9 +1,7 @@
|
|
1
|
-
<%=
|
2
|
-
<%=
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
</primer-multi-input>
|
8
|
-
<% end %>
|
1
|
+
<%= render(FormControl.new(input: @input, **@input.input_arguments)) do %>
|
2
|
+
<primer-multi-input data-name="<%= @input.name %>">
|
3
|
+
<% @input.inputs.each do |child_input| %>
|
4
|
+
<%= render(child_input.to_component) %>
|
5
|
+
<% end %>
|
6
|
+
</primer-multi-input>
|
9
7
|
<% end %>
|
@@ -1,19 +1,17 @@
|
|
1
|
-
|
2
|
-
<%=
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
<%=
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
</button>
|
16
|
-
<% end %>
|
1
|
+
<%= render(FormControl.new(input: @input, tag: :"primer-text-field")) do %>
|
2
|
+
<%= content_tag(:div, **@field_wrap_arguments) do %>
|
3
|
+
<% if @input.leading_visual %>
|
4
|
+
<span class="FormControl-input-leadingVisualWrap">
|
5
|
+
<%= render(Primer::Beta::Octicon.new(**@input.leading_visual)) %>
|
6
|
+
</span>
|
7
|
+
<% end %>
|
8
|
+
<%= render Primer::ConditionalWrapper.new(condition: @input.auto_check_src, tag: "auto-check", csrf: auto_check_authenticity_token, src: @input.auto_check_src) do %>
|
9
|
+
<%= builder.text_field(@input.name, **@input.input_arguments) %>
|
10
|
+
<% end %>
|
11
|
+
<% if @input.show_clear_button? %>
|
12
|
+
<button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="Clear" data-action="click:primer-text-field#clearContents">
|
13
|
+
<%= render(Primer::Beta::Octicon.new(icon: :"x-circle-fill")) %>
|
14
|
+
</button>
|
17
15
|
<% end %>
|
18
16
|
<% end %>
|
19
|
-
|
17
|
+
<% end %>
|
@@ -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
|