primer_view_components 0.0.59 → 0.0.60

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -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/components/primer/alpha/border_box/header.html.erb +4 -0
  6. data/app/components/primer/alpha/border_box/header.rb +51 -0
  7. data/app/components/primer/alpha/tab_nav.rb +1 -2
  8. data/app/components/primer/base_component.rb +2 -2
  9. data/app/components/primer/beta/avatar.rb +18 -11
  10. data/app/components/primer/beta/breadcrumbs.rb +7 -0
  11. data/app/components/primer/border_box_component.rb +8 -12
  12. data/app/components/primer/clipboard_copy.html.erb +1 -1
  13. data/app/components/primer/component.rb +1 -0
  14. data/app/components/primer/label_component.rb +7 -7
  15. data/app/components/primer/markdown.rb +0 -10
  16. data/app/components/primer/spinner_component.html.erb +7 -4
  17. data/app/components/primer/timeline_item_component.rb +2 -2
  18. data/app/lib/primer/audited/dsl.rb +32 -0
  19. data/lib/primer/classify/cache.rb +0 -16
  20. data/lib/primer/classify/utilities.rb +13 -6
  21. data/lib/primer/classify/utilities.yml +199 -22
  22. data/lib/primer/classify.rb +2 -9
  23. data/lib/primer/view_components/engine.rb +6 -0
  24. data/lib/primer/view_components/linters/blankslate_component_migration_counter.rb +14 -0
  25. data/lib/primer/view_components/linters/subhead_component_migration_counter.rb +14 -0
  26. data/lib/primer/view_components/version.rb +1 -1
  27. data/lib/primer/view_components.rb +17 -29
  28. data/lib/rubocop/cop/primer/deprecated_arguments.rb +35 -1
  29. data/lib/rubocop/cop/primer/primer_octicon.rb +25 -4
  30. data/lib/tasks/docs.rake +2 -0
  31. data/lib/tasks/helpers/ast_processor.rb +44 -0
  32. data/lib/tasks/helpers/ast_traverser.rb +77 -0
  33. data/lib/tasks/primer_view_components.rake +47 -0
  34. data/lib/tasks/{constants.rake → static.rake} +5 -2
  35. data/lib/tasks/utilities.rake +40 -26
  36. data/static/arguments.yml +36 -5
  37. data/static/audited_at.json +61 -0
  38. data/static/classes.yml +3 -0
  39. data/static/constants.json +26 -0
  40. data/static/statuses.json +1 -0
  41. metadata +14 -7
  42. data/lib/primer/classify/grid.rb +0 -45
  43. data/lib/tasks/statuses.rake +0 -12
@@ -23,6 +23,30 @@
23
23
  :rotate:
24
24
  - anim-rotate
25
25
  :color:
26
+ :default:
27
+ - color-fg-default
28
+ :muted:
29
+ - color-fg-muted
30
+ :subtle:
31
+ - color-fg-subtle
32
+ :accent:
33
+ - color-fg-accent
34
+ :success:
35
+ - color-fg-success
36
+ :attention:
37
+ - color-fg-attention
38
+ :severe:
39
+ - color-fg-severe
40
+ :danger:
41
+ - color-fg-danger
42
+ :done:
43
+ - color-fg-done
44
+ :sponsors:
45
+ - color-fg-sponsors
46
+ :on_emphasis:
47
+ - color-fg-on-emphasis
48
+ :inherit:
49
+ - color-fg-inherit
26
50
  :text_primary:
27
51
  - color-text-primary
28
52
  :text_secondary:
@@ -55,24 +79,45 @@
55
79
  - color-icon-success
56
80
  :icon_warning:
57
81
  - color-icon-warning
58
- :border_color:
59
- :primary:
60
- - color-border-primary
61
- :secondary:
62
- - color-border-secondary
63
- :tertiary:
64
- - color-border-tertiary
65
- :inverse:
66
- - color-border-inverse
67
- :info:
68
- - color-border-info
82
+ :bg:
83
+ :default:
84
+ - color-bg-default
85
+ :overlay:
86
+ - color-bg-overlay
87
+ :inset:
88
+ - color-bg-inset
89
+ :subtle:
90
+ - color-bg-subtle
91
+ :emphasis:
92
+ - color-bg-emphasis
93
+ :accent:
94
+ - color-bg-accent
95
+ :accent_emphasis:
96
+ - color-bg-accent-emphasis
69
97
  :success:
70
- - color-border-success
98
+ - color-bg-success
99
+ :success_emphasis:
100
+ - color-bg-success-emphasis
101
+ :attention:
102
+ - color-bg-attention
103
+ :attention_emphasis:
104
+ - color-bg-attention-emphasis
105
+ :severe:
106
+ - color-bg-severe
107
+ :severe_emphasis:
108
+ - color-bg-severe-emphasis
71
109
  :danger:
72
- - color-border-danger
73
- :warning:
74
- - color-border-warning
75
- :bg:
110
+ - color-bg-danger
111
+ :danger_emphasis:
112
+ - color-bg-danger-emphasis
113
+ :done:
114
+ - color-bg-done
115
+ :done_emphasis:
116
+ - color-bg-done-emphasis
117
+ :sponsors:
118
+ - color-bg-sponsors
119
+ :sponsors_emphasis:
120
+ - color-bg-sponsors-emphasis
76
121
  :canvas:
77
122
  - color-bg-canvas
78
123
  :canvas_inverse:
@@ -85,24 +130,65 @@
85
130
  - color-bg-secondary
86
131
  :tertiary:
87
132
  - color-bg-tertiary
88
- :overlay:
89
- - color-bg-overlay
90
133
  :info:
91
134
  - color-bg-info
92
135
  :info_inverse:
93
136
  - color-bg-info-inverse
94
- :danger:
95
- - color-bg-danger
96
137
  :danger_inverse:
97
138
  - color-bg-danger-inverse
98
- :success:
99
- - color-bg-success
100
139
  :success_inverse:
101
140
  - color-bg-success-inverse
102
141
  :warning:
103
142
  - color-bg-warning
104
143
  :warning_inverse:
105
144
  - color-bg-warning-inverse
145
+ :border_color:
146
+ :default:
147
+ - color-border-default
148
+ :muted:
149
+ - color-border-muted
150
+ :subtle:
151
+ - color-border-subtle
152
+ :accent:
153
+ - color-border-accent
154
+ :accent_emphasis:
155
+ - color-border-accent-emphasis
156
+ :success:
157
+ - color-border-success
158
+ :success_emphasis:
159
+ - color-border-success-emphasis
160
+ :attention:
161
+ - color-border-attention
162
+ :attention_emphasis:
163
+ - color-border-attention-emphasis
164
+ :severe:
165
+ - color-border-severe
166
+ :severe_emphasis:
167
+ - color-border-severe-emphasis
168
+ :danger:
169
+ - color-border-danger
170
+ :danger_emphasis:
171
+ - color-border-danger-emphasis
172
+ :done:
173
+ - color-border-done
174
+ :done_emphasis:
175
+ - color-border-done-emphasis
176
+ :sponsors:
177
+ - color-border-sponsors
178
+ :sponsors_emphasis:
179
+ - color-border-sponsors-emphasis
180
+ :primary:
181
+ - color-border-primary
182
+ :secondary:
183
+ - color-border-secondary
184
+ :tertiary:
185
+ - color-border-tertiary
186
+ :inverse:
187
+ - color-border-inverse
188
+ :info:
189
+ - color-border-info
190
+ :warning:
191
+ - color-border-warning
106
192
  :position:
107
193
  :static:
108
194
  - position-static
@@ -147,6 +233,9 @@
147
233
  - v-align-text-bottom
148
234
  :baseline:
149
235
  - v-align-baseline
236
+ :clearfix:
237
+ true:
238
+ - clearfix
150
239
  :float:
151
240
  :left:
152
241
  - float-left
@@ -531,6 +620,8 @@
531
620
  - mb-md-n12
532
621
  - mb-lg-n12
533
622
  - mb-xl-n12
623
+ :auto:
624
+ - mb-auto
534
625
  :mr:
535
626
  0:
536
627
  - mr-0
@@ -610,6 +701,8 @@
610
701
  - mr-md-n6
611
702
  - mr-lg-n6
612
703
  - mr-xl-n6
704
+ :auto:
705
+ - mr-auto
613
706
  :ml:
614
707
  0:
615
708
  - ml-0
@@ -689,6 +782,8 @@
689
782
  - ml-md-n6
690
783
  - ml-lg-n6
691
784
  - ml-xl-n6
785
+ :auto:
786
+ - ml-auto
692
787
  :mx:
693
788
  0:
694
789
  - mx-0
@@ -1368,3 +1463,85 @@
1368
1463
  - hide-lg
1369
1464
  :xl:
1370
1465
  - hide-xl
1466
+ :container:
1467
+ :sm:
1468
+ - container-sm
1469
+ :md:
1470
+ - container-md
1471
+ :lg:
1472
+ - container-lg
1473
+ :xl:
1474
+ - container-xl
1475
+ :col:
1476
+ 1:
1477
+ - col-1
1478
+ - col-sm-1
1479
+ - col-md-1
1480
+ - col-lg-1
1481
+ - col-xl-1
1482
+ 2:
1483
+ - col-2
1484
+ - col-sm-2
1485
+ - col-md-2
1486
+ - col-lg-2
1487
+ - col-xl-2
1488
+ 3:
1489
+ - col-3
1490
+ - col-sm-3
1491
+ - col-md-3
1492
+ - col-lg-3
1493
+ - col-xl-3
1494
+ 4:
1495
+ - col-4
1496
+ - col-sm-4
1497
+ - col-md-4
1498
+ - col-lg-4
1499
+ - col-xl-4
1500
+ 5:
1501
+ - col-5
1502
+ - col-sm-5
1503
+ - col-md-5
1504
+ - col-lg-5
1505
+ - col-xl-5
1506
+ 6:
1507
+ - col-6
1508
+ - col-sm-6
1509
+ - col-md-6
1510
+ - col-lg-6
1511
+ - col-xl-6
1512
+ 7:
1513
+ - col-7
1514
+ - col-sm-7
1515
+ - col-md-7
1516
+ - col-lg-7
1517
+ - col-xl-7
1518
+ 8:
1519
+ - col-8
1520
+ - col-sm-8
1521
+ - col-md-8
1522
+ - col-lg-8
1523
+ - col-xl-8
1524
+ 9:
1525
+ - col-9
1526
+ - col-sm-9
1527
+ - col-md-9
1528
+ - col-lg-9
1529
+ - col-xl-9
1530
+ 10:
1531
+ - col-10
1532
+ - col-sm-10
1533
+ - col-md-10
1534
+ - col-lg-10
1535
+ - col-xl-10
1536
+ 11:
1537
+ - col-11
1538
+ - col-sm-11
1539
+ - col-md-11
1540
+ - col-lg-11
1541
+ - col-xl-11
1542
+ 12:
1543
+ - col-12
1544
+ - col-sm-12
1545
+ - col-md-12
1546
+ - col-lg-12
1547
+ - col-xl-12
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "classify/cache"
4
4
  require_relative "classify/flex"
5
- require_relative "classify/grid"
6
5
  require_relative "classify/utilities"
7
6
  require_relative "classify/validation"
8
7
 
@@ -14,10 +13,8 @@ module Primer
14
13
 
15
14
  TEXT_KEYS = %i[font_family font_style font_weight text_align text_transform].freeze
16
15
  BOX_SHADOW_KEY = :box_shadow
17
- CONTAINER_KEY = :container
18
16
 
19
17
  BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"].freeze
20
- RESPONSIVE_KEYS = ([Primer::Classify::Grid::COL_KEY] + Primer::Classify::Flex::RESPONSIVE_KEYS).freeze
21
18
 
22
19
  BOOLEAN_MAPPINGS = {
23
20
  underline: {
@@ -77,12 +74,10 @@ module Primer
77
74
  TYPOGRAPHY_KEYS +
78
75
  TEXT_KEYS +
79
76
  Primer::Classify::Flex::KEYS +
80
- Primer::Classify::Grid::KEYS +
81
77
  [
82
78
  BORDER_KEY,
83
79
  BORDER_RADIUS_KEY,
84
- BOX_SHADOW_KEY,
85
- CONTAINER_KEY
80
+ BOX_SHADOW_KEY
86
81
  ]
87
82
  ).freeze
88
83
 
@@ -143,7 +138,7 @@ module Primer
143
138
 
144
139
  styles_hash.each do |key, value|
145
140
  if value.is_a?(Array)
146
- raise ArgumentError, "#{key} does not support responsive values" unless RESPONSIVE_KEYS.include?(key) || Primer::Classify::Utilities.supported_key?(key)
141
+ raise ArgumentError, "#{key} does not support responsive values" unless Primer::Classify::Flex::RESPONSIVE_KEYS.include?(key) || Primer::Classify::Utilities.supported_key?(key)
147
142
 
148
143
  value.each_with_index do |val, index|
149
144
  extract_one_css_attr(classes, styles, key, val, BREAKPOINTS[index])
@@ -197,8 +192,6 @@ module Primer
197
192
  "rounded-#{val}"
198
193
  elsif Primer::Classify::Flex::KEYS.include?(key)
199
194
  Primer::Classify::Flex.classes(key, val, breakpoint)
200
- elsif Primer::Classify::Grid::KEYS.include?(key)
201
- Primer::Classify::Grid.classes(key, val, breakpoint)
202
195
  elsif TEXT_KEYS.include?(key)
203
196
  "text-#{val.to_s.dasherize}"
204
197
  elsif TYPOGRAPHY_KEYS.include?(key)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails/engine"
4
+ require "primer/classify/utilities"
4
5
 
5
6
  module Primer
6
7
  module ViewComponents
@@ -16,10 +17,15 @@ module Primer
16
17
 
17
18
  config.primer_view_components.force_system_arguments = false
18
19
  config.primer_view_components.silence_deprecations = false
20
+ config.primer_view_components.validate_class_names = !Rails.env.production?
19
21
 
20
22
  initializer "primer_view_components.assets" do |app|
21
23
  app.config.assets.precompile += %w[primer_view_components] if app.config.respond_to?(:assets)
22
24
  end
25
+
26
+ config.after_initialize do |app|
27
+ ::Primer::Classify::Utilities.validate_class_names = app.config.primer_view_components.delete(:validate_class_names)
28
+ end
23
29
  end
24
30
  end
25
31
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_linter"
4
+
5
+ module ERBLint
6
+ module Linters
7
+ # Counts the number of times a HTML Blankslate is used instead of the component.
8
+ class BlankslateComponentMigrationCounter < BaseLinter
9
+ MESSAGE = "We are migrating Blankslate to use [Primer::BlankslateComponent](https://primer.style/view-components/components/blankslate), please try to use that instead of raw HTML."
10
+ CLASSES = %w[blankslate].freeze
11
+ TAGS = %w[div].freeze
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_linter"
4
+
5
+ module ERBLint
6
+ module Linters
7
+ # Counts the number of times a HTML Subhead is used instead of the component.
8
+ class SubheadComponentMigrationCounter < BaseLinter
9
+ MESSAGE = "We are migrating Subhead to use [Primer::SubheadComponent](https://primer.style/view-components/components/subhead), please try to use that instead of raw HTML."
10
+ CLASSES = %w[Subhead].freeze
11
+ TAGS = %w[div].freeze
12
+ end
13
+ end
14
+ end
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 59
8
+ PATCH = 60
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
@@ -8,8 +8,11 @@ module Primer
8
8
  # :nodoc:
9
9
  module ViewComponents
10
10
  DEFAULT_STATIC_PATH = File.expand_path("static")
11
- DEFAULT_STATUS_FILE_NAME = "statuses.json"
12
- DEFAULT_CONSTANTS_FILE_NAME = "constants.json"
11
+ FILE_NAMES = {
12
+ statuses: "statuses.json",
13
+ constants: "constants.json",
14
+ audited_at: "audited_at.json"
15
+ }.freeze
13
16
 
14
17
  # generate_statuses returns a hash mapping component name to
15
18
  # the component's status sorted alphabetically by the component name.
@@ -19,25 +22,14 @@ module Primer
19
22
  end
20
23
  end
21
24
 
22
- # dump_statuses generates the status hash and then serializes
23
- # it as json at the given path
24
- def self.dump_statuses(path: DEFAULT_STATIC_PATH)
25
- require "json"
26
-
27
- statuses = generate_statuses
28
-
29
- File.open(File.join(path, DEFAULT_STATUS_FILE_NAME), "w") do |f|
30
- f.write(JSON.pretty_generate(statuses))
31
- f.write($INPUT_RECORD_SEPARATOR)
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
32
30
  end
33
31
  end
34
32
 
35
- # read_statuses returns a JSON string matching the output of
36
- # generate_statuses
37
- def self.read_statuses(path: DEFAULT_STATIC_PATH)
38
- File.read(File.join(path, DEFAULT_STATUS_FILE_NAME))
39
- end
40
-
41
33
  # generate_constants returns a hash mapping component name to
42
34
  # all of its constants.
43
35
  def self.generate_constants
@@ -48,23 +40,19 @@ module Primer
48
40
  end
49
41
  end
50
42
 
51
- # dump_constants generates the constants hash and then serializes
52
- # it as json at the given path
53
- def self.dump_constants(path: DEFAULT_STATIC_PATH)
43
+ # dump generates the requested stat hash and outputs it to a file.
44
+ def self.dump(stats)
54
45
  require "json"
55
46
 
56
- constants = generate_constants
57
-
58
- File.open(File.join(path, DEFAULT_CONSTANTS_FILE_NAME), "w") do |f|
59
- f.write(JSON.pretty_generate(constants))
47
+ File.open(File.join(DEFAULT_STATIC_PATH, FILE_NAMES[stats]), "w") do |f|
48
+ f.write(JSON.pretty_generate(send("generate_#{stats}")))
60
49
  f.write($INPUT_RECORD_SEPARATOR)
61
50
  end
62
51
  end
63
52
 
64
- # read_constants returns a JSON string matching the output of
65
- # generate_constants
66
- def self.read_constants(path: DEFAULT_STATIC_PATH)
67
- File.read(File.join(path, DEFAULT_CONSTANTS_FILE_NAME))
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]))
68
56
  end
69
57
  end
70
58
  end
@@ -46,6 +46,18 @@ module RuboCop
46
46
  yellow: "bg: :warning_inverse",
47
47
  red_light: "bg: :danger",
48
48
  red: "bg: :danger_inverse",
49
+ canvas: "bg: :default",
50
+ canvas_inverse: "bg: :emphasis",
51
+ canvas_inset: "bg: :inset",
52
+ primary: "bg: :default",
53
+ secondary: "bg: :subtle",
54
+ tertiary: "bg: :subtle",
55
+ info: "bg: :accent",
56
+ info_inverse: "bg: :accent_emphasis",
57
+ danger_inverse: "bg: :danger_emphasis",
58
+ success_inverse: "bg: :success_emphasis",
59
+ warning: "bg: :attention",
60
+ warning_inverse: "bg: :attention_emphasis",
49
61
  gray_0: nil,
50
62
  gray_1: nil,
51
63
  gray_2: nil,
@@ -140,9 +152,31 @@ module RuboCop
140
152
  green: "border_color: :success",
141
153
  yellow: "border_color: :warning",
142
154
  red: "border_color: :danger",
143
- white: "border_color: :inverse"
155
+ white: "border_color: :inverse",
156
+ primary: "border_color: :default",
157
+ secondary: "border_color: :muted",
158
+ tertiary: "border_color: :default",
159
+ inverse: nil,
160
+ info: "border_color: :accent_emphasis",
161
+ warning: "border_color: :attention_emphasis"
144
162
  },
145
163
  color: {
164
+ text_primary: "color: :default",
165
+ text_secondary: "color: :muted",
166
+ text_tertiary: "color: :muted",
167
+ text_link: "color: :accent",
168
+ text_success: "color: :success",
169
+ text_warning: "color: :attention",
170
+ text_danger: "color: :danger",
171
+ text_inverse: "color: :on_emphasis",
172
+ text_white: "color: :on_emphasis",
173
+ icon_primary: "color: :default",
174
+ icon_secondary: "color: :muted",
175
+ icon_tertiary: "color: :muted",
176
+ icon_info: "color: :accent",
177
+ icon_danger: "color: :danger",
178
+ icon_success: "color: :success",
179
+ icon_warning: "color: :attention",
146
180
  blue: "color: :text_link",
147
181
  gray_dark: "color: :text_primary",
148
182
  gray: "color: :text_secondary",
@@ -29,7 +29,8 @@ module RuboCop
29
29
 
30
30
  SIZE_ATTRIBUTES = %w[height width size].freeze
31
31
  STRING_ATTRIBUTES = %w[aria- data-].freeze
32
- VALID_ATTRIBUTES = [*SIZE_ATTRIBUTES, *STRING_ATTRIBUTES, "class"].freeze
32
+ REST_ATTRIBUTES = %w[title].freeze
33
+ VALID_ATTRIBUTES = [*SIZE_ATTRIBUTES, *STRING_ATTRIBUTES, *REST_ATTRIBUTES, "class"].freeze
33
34
 
34
35
  STRING_ATTRIBUTE_REGEX = Regexp.union(STRING_ATTRIBUTES).freeze
35
36
  ATTRIBUTE_REGEX = Regexp.union(VALID_ATTRIBUTES).freeze
@@ -74,7 +75,9 @@ module RuboCop
74
75
  # Converting arguments for the component
75
76
  classes = classes(kwargs)
76
77
  size_attributes = transform_sizes(kwargs)
77
- args = arguments_as_string(node, size_attributes, classes)
78
+ rest_attributes = rest_args(kwargs)
79
+
80
+ args = arguments_as_string(node, size_attributes, rest_attributes, classes)
78
81
  if node.dot?
79
82
  corrector.replace(node.loc.expression, "#{node.receiver.source}.primer_octicon(#{args})")
80
83
  else
@@ -99,6 +102,14 @@ module RuboCop
99
102
  end
100
103
  end
101
104
 
105
+ def rest_args(kwargs)
106
+ kwargs.pairs.each_with_object({}) do |pair, h|
107
+ next unless REST_ATTRIBUTES.include?(pair.key.value.to_s)
108
+
109
+ h[pair.key.value] = pair.value.source
110
+ end
111
+ end
112
+
102
113
  def octicon_size_attributes(kwargs)
103
114
  kwargs.pairs.each_with_object({}) do |pair, h|
104
115
  next unless SIZE_ATTRIBUTES.include?(pair.key.value.to_s)
@@ -125,18 +136,28 @@ module RuboCop
125
136
  class_arg.value.value
126
137
  end
127
138
 
128
- def arguments_as_string(node, size_attributes, classes)
139
+ def arguments_as_string(node, size_attributes, rest_attributes, classes)
129
140
  args = icon(node.arguments.first)
130
141
  size_args = size_attributes_to_string(size_attributes)
131
142
  string_args = string_args_to_string(node)
143
+ rest_args = rest_args_to_string(rest_attributes)
132
144
 
133
- args = "#{args}, #{size_attributes_to_string(size_attributes)}" if size_args.present?
145
+ args = "#{args}, #{size_args}" if size_args.present?
146
+ args = "#{args}, #{rest_args}" if rest_args.present?
134
147
  args = "#{args}, #{utilities_args(classes)}" if classes.present?
135
148
  args = "#{args}, #{string_args}" if string_args.present?
136
149
 
137
150
  args
138
151
  end
139
152
 
153
+ def rest_args_to_string(attrs)
154
+ return if attrs.blank?
155
+
156
+ attrs.map do |key, value|
157
+ "#{key}: #{value}"
158
+ end.join(", ")
159
+ end
160
+
140
161
  def utilities_args(classes)
141
162
  args = ::Primer::Classify::Utilities.classes_to_hash(classes)
142
163
 
data/lib/tasks/docs.rake CHANGED
@@ -27,6 +27,7 @@ namespace :docs do
27
27
  # Rails controller for rendering arbitrary ERB
28
28
  view_context = ApplicationController.new.tap { |c| c.request = ActionDispatch::TestRequest.create }.view_context
29
29
  components = [
30
+ Primer::Alpha::BorderBox::Header,
30
31
  Primer::Image,
31
32
  Primer::LocalTime,
32
33
  Primer::OcticonSymbolsComponent,
@@ -75,6 +76,7 @@ namespace :docs do
75
76
  Primer::Truncate,
76
77
  Primer::Beta::Truncate,
77
78
  Primer::Alpha::UnderlineNav,
79
+ Primer::Alpha::UnderlinePanels,
78
80
  Primer::Alpha::TabNav,
79
81
  Primer::Alpha::TabPanels
80
82
  ]
@@ -0,0 +1,44 @@
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