primer_view_components 0.0.42 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84c899ab3302b9bffbfe3f0d6471a732d3f457fa8f2eec84a3e7e4b9a9e003b0
4
- data.tar.gz: b3f96f4caf1154320ebe772c3696526901ad07b9cd0b2327383b94b995c8bac4
3
+ metadata.gz: 78f4fe987616d5ab746cbd6d6a0bc79ff62ecf33eb2365af3ade87a43461d35b
4
+ data.tar.gz: 2813cf307508ab9a413d98edbba54e1d7735dc86e853a42587487c7293d42571
5
5
  SHA512:
6
- metadata.gz: 9cab0b4a7016357d29d099e07ae047a335dc4e394422250cada38c4f861900433a639b20748ae239a0962eb49c4cb0b5a1279746bfab2c5713f51647834c6056
7
- data.tar.gz: 89e0b7c38eff95e73b6e0f829153b14033644bd74553fef7a784a9d25d16b7fd52aea7305e4163c1ef294a8a758c4278d24b5f25d6bb194be994f31dd07401e5
6
+ metadata.gz: 7b13c5c05eb27d2a635396d736daa1039024bef7ddb456d20ec037f2cf270e8cb157ebd40619ca8eed4523e9cde5af2d990b428dc2ff663a42faaf01070a48ef
7
+ data.tar.gz: c5e126fcf17bf04914a2ea054ca181991a8cb0fda5659753c4e03241e6dfcfe8a5e876b915033cfc69b11c10b3b7946403fdb86f1fca3161eb1278eae29d99ed
data/CHANGELOG.md CHANGED
@@ -2,6 +2,52 @@
2
2
 
3
3
  ## main
4
4
 
5
+ ## 0.0.43
6
+
7
+ * Upgrade primer/css to 17.2.1
8
+
9
+ *Jon Rohan*
10
+
11
+ ### New
12
+
13
+ * Add `clearfix` and `container` system arguments.
14
+
15
+ *Manuel Puyol*
16
+
17
+ ### Updates
18
+
19
+ * Promote `TabNav` component to beta.
20
+
21
+ *Manuel Puyol*
22
+
23
+ * Allow customizing `TabContainer` when using `TabNav` and `UnderlineNav` components.
24
+
25
+ *Manuel Puyol*
26
+
27
+ ### Breaking changes
28
+
29
+ * Restrict `col` system arguments to only accept values between 1 and 12.
30
+
31
+ *Manuel Puyol*
32
+
33
+ ### Misc
34
+
35
+ * Raise an error if `class` is used as a system argument.
36
+
37
+ *Manuel Puyol*
38
+
39
+ * Don't commit auto-generated component previews.
40
+
41
+ *Kate Higa*
42
+
43
+ * Provide linters for component migrations.
44
+
45
+ *Manuel Puyol*
46
+
47
+ * Update docs to accept multiline descriptions.
48
+
49
+ *Manuel Puyol*
50
+
5
51
  ## 0.0.42
6
52
 
7
53
  ### New
@@ -83,7 +83,9 @@ module Primer
83
83
  #
84
84
  # | Name | Type | Description |
85
85
  # | :- | :- | :- |
86
- # | `col` | Integer | Number of columns. |
86
+ # | `clearfix` | Boolean | Wether to assign the `clearfix` class. |
87
+ # | `col` | Integer | Number of columns. <%= one_of(Primer::Classify::Grid::COL_VALUES) %> |
88
+ # | `container` | Symbol | Size of the container. <%= one_of(Primer::Classify::Grid::CONTAINER_VALUES) %> |
87
89
  #
88
90
  # ## Layout
89
91
  #
@@ -148,6 +150,8 @@ module Primer
148
150
  @tag = tag
149
151
  @system_arguments = system_arguments
150
152
 
153
+ raise ArgumentError, "`class` is an invalid argument. Use `classes` instead." if system_arguments.key?(:class) && !Rails.env.production?
154
+
151
155
  @result = Primer::Classify.call(**@system_arguments.merge(classes: classes))
152
156
 
153
157
  @system_arguments[:"data-view-component"] = true
@@ -1,3 +1,4 @@
1
+ <%# erblint:counter ButtonComponentMigrationCounter 1 %>
1
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
3
  <% if spinner.present? %>
3
4
  <%= spinner %>
@@ -23,56 +23,74 @@ module Primer
23
23
  # description: "Description",
24
24
  # ) %>
25
25
  #
26
- # @example Icon|Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
27
- # <%= render Primer::BlankslateComponent.new(
28
- # icon: :globe,
29
- # title: "Title",
30
- # description: "Description",
31
- # ) %>
26
+ # @example Icon
27
+ # @description
28
+ # Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
29
+ # @code
30
+ # <%= render Primer::BlankslateComponent.new(
31
+ # icon: :globe,
32
+ # title: "Title",
33
+ # description: "Description",
34
+ # ) %>
32
35
  #
33
- # @example Loading|Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
34
- # <%= render Primer::BlankslateComponent.new(
35
- # title: "Title",
36
- # description: "Description",
37
- # ) do |component| %>
38
- # <% component.spinner(size: :large) %>
39
- # <% end %>
36
+ # @example Loading
37
+ # @description
38
+ # Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
39
+ # @code
40
+ # <%= render Primer::BlankslateComponent.new(
41
+ # title: "Title",
42
+ # description: "Description",
43
+ # ) do |component| %>
44
+ # <% component.spinner(size: :large) %>
45
+ # <% end %>
40
46
  #
41
- # @example Custom content|Pass custom content as a block in place of `description`.
42
- # <%= render Primer::BlankslateComponent.new(
43
- # title: "Title",
44
- # ) do %>
45
- # <em>Your custom content here</em>
46
- # <% end %>
47
+ # @example Custom content
48
+ # @description
49
+ # Pass custom content as a block in place of `description`.
50
+ # @code
51
+ # <%= render Primer::BlankslateComponent.new(
52
+ # title: "Title",
53
+ # ) do %>
54
+ # <em>Your custom content here</em>
55
+ # <% end %>
47
56
  #
48
- # @example Action button|Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
49
- # <%= render Primer::BlankslateComponent.new(
50
- # icon: :book,
51
- # title: "Welcome to the mona wiki!",
52
- # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
57
+ # @example Action button
58
+ # @description
59
+ # Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
60
+ # @code
61
+ # <%= render Primer::BlankslateComponent.new(
62
+ # icon: :book,
63
+ # title: "Welcome to the mona wiki!",
64
+ # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
53
65
  #
54
- # button_text: "Create the first page",
55
- # button_url: "https://github.com/monalisa/mona/wiki/_new",
56
- # ) %>
66
+ # button_text: "Create the first page",
67
+ # button_url: "https://github.com/monalisa/mona/wiki/_new",
68
+ # ) %>
57
69
  #
58
- # @example Link|Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
59
- # <%= render Primer::BlankslateComponent.new(
60
- # icon: :book,
61
- # title: "Welcome to the mona wiki!",
62
- # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
63
- # link_text: "Learn more about wikis",
64
- # link_url: "https://docs.github.com/en/github/building-a-strong-community/about-wikis",
65
- # ) %>
70
+ # @example Link
71
+ # @description
72
+ # Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
73
+ # @code
74
+ # <%= render Primer::BlankslateComponent.new(
75
+ # icon: :book,
76
+ # title: "Welcome to the mona wiki!",
77
+ # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
78
+ # link_text: "Learn more about wikis",
79
+ # link_url: "https://docs.github.com/en/github/building-a-strong-community/about-wikis",
80
+ # ) %>
66
81
  #
67
- # @example Variations|There are a few variations of how the Blankslate appears: `narrow` adds a maximum width, `large` increases the font size, and `spacious` adds extra padding.
68
- # <%= render Primer::BlankslateComponent.new(
69
- # icon: :book,
70
- # title: "Welcome to the mona wiki!",
71
- # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
72
- # narrow: true,
73
- # large: true,
74
- # spacious: true,
75
- # ) %>
82
+ # @example Variations
83
+ # @description
84
+ # There are a few variations of how the Blankslate appears: `narrow` adds a maximum width, `large` increases the font size, and `spacious` adds extra padding.
85
+ # @code
86
+ # <%= render Primer::BlankslateComponent.new(
87
+ # icon: :book,
88
+ # title: "Welcome to the mona wiki!",
89
+ # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
90
+ # narrow: true,
91
+ # large: true,
92
+ # spacious: true,
93
+ # ) %>
76
94
  #
77
95
  # @param title [String] Text that appears in a larger bold font.
78
96
  # @param title_tag [Symbol] HTML tag to use for title.
@@ -1,4 +1,4 @@
1
- <%= wrapper do %>
1
+ <%= wrapper(**@wrapper_arguments) do %>
2
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
3
3
  <%= extra if @align == :left %>
4
4
 
@@ -5,6 +5,8 @@ module Primer
5
5
  class TabNavComponent < Primer::Component
6
6
  include Primer::TabbedComponentHelper
7
7
 
8
+ status :beta
9
+
8
10
  DEFAULT_EXTRA_ALIGN = :left
9
11
  EXTRA_ALIGN_OPTIONS = [DEFAULT_EXTRA_ALIGN, :right].freeze
10
12
 
@@ -102,15 +104,31 @@ module Primer
102
104
  # <% end %>
103
105
  # <% end %>
104
106
  #
107
+ # @example Customizing the body
108
+ # <%= render(Primer::TabNavComponent.new(label: "Default", body_arguments: { classes: "custom-class", border: true, border_color: :info })) do |c| %>
109
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
110
+ # <% c.tab(href: "#") { "Tab 2" } %>
111
+ # <% c.tab(href: "#") { "Tab 3" } %>
112
+ # <% end %>
113
+ #
114
+ # @example Customizing the wrapper
115
+ # <%= render(Primer::TabNavComponent.new(label: "Default", wrapper_arguments: { classes: "custom-class", border: true, border_color: :info })) do |c| %>
116
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
117
+ # <% c.tab(href: "#") { "Tab 2" } %>
118
+ # <% c.tab(href: "#") { "Tab 3" } %>
119
+ # <% end %>
120
+ #
105
121
  # @param label [String] Used to set the `aria-label` on the top level `<nav>` element.
106
122
  # @param with_panel [Boolean] Whether the TabNav should navigate through pages or panels.
107
123
  # @param body_arguments [Hash] <%= link_to_system_arguments_docs %> for the body wrapper.
124
+ # @param wrapper_arguments [Hash] <%= link_to_system_arguments_docs %> for the `TabContainer` wrapper. Only applies if `with_panel` is `true`.
108
125
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
109
- def initialize(label:, with_panel: false, body_arguments: {}, **system_arguments)
126
+ def initialize(label:, with_panel: false, body_arguments: {}, wrapper_arguments: {}, **system_arguments)
110
127
  @align = DEFAULT_EXTRA_ALIGN
111
128
  @with_panel = with_panel
112
129
  @system_arguments = system_arguments
113
130
  @body_arguments = body_arguments
131
+ @wrapper_arguments = wrapper_arguments
114
132
 
115
133
  @system_arguments[:tag] ||= :div
116
134
  @system_arguments[:classes] = class_names(
@@ -1,4 +1,4 @@
1
- <%= wrapper do %>
1
+ <%= wrapper(**@wrapper_arguments) do %>
2
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
3
3
  <% if @align == :right %>
4
4
  <%= actions %>
@@ -116,14 +116,30 @@ module Primer
116
116
  # <% end %>
117
117
  # <% end %>
118
118
  #
119
+ # @example Customizing the body
120
+ # <%= render(Primer::UnderlineNavComponent.new(label: "Default", body_arguments: { tag: :ul, classes: "custom-class", border: true, border_color: :info })) do |c| %>
121
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
122
+ # <% c.tab(href: "#") { "Tab 2" } %>
123
+ # <% c.tab(href: "#") { "Tab 3" } %>
124
+ # <% end %>
125
+ #
126
+ # @example Customizing the wrapper
127
+ # <%= render(Primer::UnderlineNavComponent.new(label: "Default", wrapper_arguments: { classes: "custom-class", border: true, border_color: :info })) do |c| %>
128
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
129
+ # <% c.tab(href: "#") { "Tab 2" } %>
130
+ # <% c.tab(href: "#") { "Tab 3" } %>
131
+ # <% end %>
132
+ #
119
133
  # @param label [String] The `aria-label` on top level `<nav>` element.
120
134
  # @param with_panel [Boolean] Whether the TabNav should navigate through pages or panels.
121
135
  # @param align [Symbol] <%= one_of(Primer::UnderlineNavComponent::ALIGN_OPTIONS) %> - Defaults to <%= Primer::UnderlineNavComponent::ALIGN_DEFAULT %>
122
136
  # @param body_arguments [Hash] <%= link_to_system_arguments_docs %> for the body wrapper.
137
+ # @param wrapper_arguments [Hash] <%= link_to_system_arguments_docs %> for the `TabContainer` wrapper. Only applies if `with_panel` is `true`.
123
138
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
124
- def initialize(label:, with_panel: false, align: ALIGN_DEFAULT, body_arguments: { tag: BODY_TAG_DEFAULT }, **system_arguments)
139
+ def initialize(label:, with_panel: false, align: ALIGN_DEFAULT, body_arguments: { tag: BODY_TAG_DEFAULT }, wrapper_arguments: {}, **system_arguments)
125
140
  @with_panel = with_panel
126
141
  @align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
142
+ @wrapper_arguments = wrapper_arguments
127
143
 
128
144
  @system_arguments = system_arguments
129
145
  @system_arguments[:tag] = navigation_tag(with_panel)
@@ -7,7 +7,7 @@ module Primer
7
7
  SPACING_KEYS = Primer::Classify::Spacing::KEYS
8
8
 
9
9
  # Keys where we can simply translate { key: value } into ".key-value"
10
- CONCAT_KEYS = SPACING_KEYS + %i[hide position v float col text box_shadow].freeze
10
+ CONCAT_KEYS = SPACING_KEYS + %i[hide position v float text box_shadow].freeze
11
11
 
12
12
  INVALID_CLASS_NAME_PREFIXES =
13
13
  (["bg-", "color-", "text-", "d-", "v-align-", "wb-", "box-shadow-"] + CONCAT_KEYS.map { |k| "#{k}-" }).freeze
@@ -22,9 +22,10 @@ module Primer
22
22
  BOX_SHADOW_KEY = :box_shadow
23
23
  VISIBILITY_KEY = :visibility
24
24
  ANIMATION_KEY = :animation
25
+ CONTAINER_KEY = :container
25
26
 
26
27
  BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"].freeze
27
- RESPONSIVE_KEYS = ([DISPLAY_KEY, :col, :float] + SPACING_KEYS + Primer::Classify::Flex::RESPONSIVE_KEYS).freeze
28
+ RESPONSIVE_KEYS = ([DISPLAY_KEY, :float, Primer::Classify::Grid::COL_KEY] + SPACING_KEYS + Primer::Classify::Flex::RESPONSIVE_KEYS).freeze
28
29
 
29
30
  BOOLEAN_MAPPINGS = {
30
31
  underline: {
@@ -84,6 +85,7 @@ module Primer
84
85
  TYPOGRAPHY_KEYS +
85
86
  TEXT_KEYS +
86
87
  Primer::Classify::Flex::KEYS +
88
+ Primer::Classify::Grid::KEYS +
87
89
  [
88
90
  BORDER_KEY,
89
91
  BORDER_COLOR_KEY,
@@ -97,7 +99,8 @@ module Primer
97
99
  HEIGHT_KEY,
98
100
  BOX_SHADOW_KEY,
99
101
  VISIBILITY_KEY,
100
- ANIMATION_KEY
102
+ ANIMATION_KEY,
103
+ CONTAINER_KEY
101
104
  ]
102
105
  ).freeze
103
106
 
@@ -206,6 +209,8 @@ module Primer
206
209
  memo[:classes] << "rounded-#{val}"
207
210
  elsif Primer::Classify::Flex::KEYS.include?(key)
208
211
  memo[:classes] << Primer::Classify::Flex.classes(key, val, breakpoint)
212
+ elsif Primer::Classify::Grid::KEYS.include?(key)
213
+ memo[:classes] << Primer::Classify::Grid.classes(key, val, breakpoint)
209
214
  elsif key == WIDTH_KEY || key == HEIGHT_KEY
210
215
  if val == :fit
211
216
  memo[:classes] << "#{key}-#{val}"
@@ -54,6 +54,21 @@ module Primer
54
54
  values: Primer::Classify::Flex::ALIGN_ITEMS_VALUES
55
55
  )
56
56
 
57
+ preload(
58
+ keys: Primer::Classify::Grid::CONTAINER_KEY,
59
+ values: Primer::Classify::Grid::CONTAINER_VALUES
60
+ )
61
+
62
+ preload(
63
+ keys: Primer::Classify::Grid::CLEARFIX_KEY,
64
+ values: [true]
65
+ )
66
+
67
+ preload(
68
+ keys: Primer::Classify::Grid::COL_KEY,
69
+ values: Primer::Classify::Grid::COL_VALUES
70
+ )
71
+
57
72
  preload(
58
73
  keys: Primer::Classify::DISPLAY_KEY,
59
74
  values: [:flex, :block, :inline_block, :inline_flex, :none, :table, :table_cell]
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ class Classify
5
+ # Handler for PrimerCSS grid classes.
6
+ class Grid
7
+ extend Primer::FetchOrFallbackHelper
8
+
9
+ CONTAINER_KEY = :container
10
+ CONTAINER_VALUES = [:xl, :lg, :md, :sm].freeze
11
+
12
+ CLEARFIX_KEY = :clearfix
13
+ CLEARFIX_VALUES = [true, false].freeze
14
+
15
+ COL_KEY = :col
16
+ COL_VALUES = (1..12).to_a.freeze
17
+
18
+ KEYS = [CONTAINER_KEY, CLEARFIX_KEY, COL_KEY].freeze
19
+
20
+ class << self
21
+ def classes(key, value, breakpoint)
22
+ send(key, value, breakpoint)
23
+ end
24
+
25
+ private
26
+
27
+ def container(value, _breakpoint)
28
+ val = fetch_or_fallback(CONTAINER_VALUES, value)
29
+
30
+ "container-#{val}"
31
+ end
32
+
33
+ def clearfix(value, _breakpoint)
34
+ "clearfix" if fetch_or_fallback(CLEARFIX_VALUES, value)
35
+ end
36
+
37
+ def col(value, breakpoint)
38
+ val = fetch_or_fallback(COL_VALUES, value.to_i)
39
+
40
+ "col#{breakpoint}-#{val}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -20,10 +20,10 @@ module Primer
20
20
  with_panel ? :div : :nav
21
21
  end
22
22
 
23
- def wrapper
23
+ def wrapper(**system_arguments)
24
24
  return yield unless @with_panel
25
25
 
26
- render Primer::TabContainerComponent.new do
26
+ render Primer::TabContainerComponent.new(**system_arguments) do
27
27
  yield
28
28
  end
29
29
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.join(__dir__, "linters", "*.rb")].sort.each { |file| require file }
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "helpers"
4
+
5
+ module ERBLint
6
+ module Linters
7
+ # Counts the number of times a HTML button is used instead of the component.
8
+ class ButtonComponentMigrationCounter < Linter
9
+ include Helpers
10
+
11
+ TAGS = %w[button summary a].freeze
12
+ CLASS = "btn"
13
+ MESSAGE = "We are migrating buttons to use [Primer::ButtonComponent](https://primer.style/view-components/components/button), please try to use that instead of raw HTML."
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "helpers"
4
+
5
+ module ERBLint
6
+ module Linters
7
+ # Counts the number of times a HTML flash is used instead of the component.
8
+ class FlashComponentMigrationCounter < Linter
9
+ include Helpers
10
+
11
+ TAGS = %w[div].freeze
12
+ CLASS = "flash"
13
+ MESSAGE = "We are migrating flashes to use [Primer::FlashComponent](https://primer.style/view-components/components/flash), please try to use that instead of raw HTML."
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "openssl"
5
+
6
+ module ERBLint
7
+ module Linters
8
+ # Helper methods for linting ERB.
9
+ module Helpers
10
+ def self.included(base)
11
+ base.include(LinterRegistry)
12
+
13
+ define_method "run" do |processed_source|
14
+ tags(processed_source).each do |tag|
15
+ next if tag.closing?
16
+ next unless self.class::TAGS&.include?(tag.name)
17
+
18
+ classes = tag.attributes["class"]&.value&.split(" ")
19
+
20
+ next unless !self.class::CLASS || classes&.include?(self.class::CLASS)
21
+
22
+ generate_offense(self.class, processed_source, tag, self.class::MESSAGE)
23
+ end
24
+
25
+ counter_correct?(processed_source)
26
+ end
27
+
28
+ define_method "autocorrect" do |processed_source, offense|
29
+ return unless offense.context
30
+
31
+ lambda do |corrector|
32
+ if processed_source.file_content.include?("erblint:counter #{self.class.name.demodulize}")
33
+ # update the counter if exists
34
+ corrector.replace(offense.source_range, offense.context)
35
+ else
36
+ # add comment with counter if none
37
+ corrector.insert_before(processed_source.source_buffer.source_range, "#{offense.context}\n")
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def tags(processed_source)
46
+ processed_source.parser.nodes_with_type(:tag).map { |tag_node| BetterHtml::Tree::Tag.from_node(tag_node) }
47
+ end
48
+
49
+ def counter_correct?(processed_source)
50
+ comment_node = nil
51
+ expected_count = 0
52
+ rule_name = self.class.name.match(/:?:?(\w+)\Z/)[1]
53
+ offenses_count = @offenses.length
54
+
55
+ processed_source.parser.ast.descendants(:erb).each do |node|
56
+ indicator_node, _, code_node, = *node
57
+ indicator = indicator_node&.loc&.source
58
+ comment = code_node&.loc&.source&.strip
59
+
60
+ if indicator == "#" && comment.start_with?("erblint:count") && comment.match(rule_name)
61
+ comment_node = code_node
62
+ expected_count = comment.match(/\s(\d+)\s?$/)[1].to_i
63
+ end
64
+ end
65
+
66
+ if offenses_count.zero?
67
+ add_offense(processed_source.to_source_range(comment_node.loc), "Unused erblint:count comment for #{rule_name}") if comment_node
68
+ return
69
+ end
70
+
71
+ first_offense = @offenses[0]
72
+
73
+ if comment_node.nil?
74
+ add_offense(processed_source.to_source_range(first_offense.source_range), "#{rule_name}: If you must, add <%# erblint:counter #{rule_name} #{offenses_count} %> to bypass this check.", "<%# erblint:counter #{rule_name} #{offenses_count} %>")
75
+ else
76
+ clear_offenses
77
+ add_offense(processed_source.to_source_range(comment_node.loc), "Incorrect erblint:counter number for #{rule_name}. Expected: #{expected_count}, actual: #{offenses_count}.", " erblint:counter #{rule_name} #{offenses_count} ") if expected_count != offenses_count
78
+ end
79
+ end
80
+
81
+ def generate_offense(klass, processed_source, tag, message = nil, replacement = nil)
82
+ message ||= klass::MESSAGE
83
+ klass_name = klass.name.split("::")[-1]
84
+ offense = ["#{klass_name}:#{message}", tag.node.loc.source].join("\n")
85
+ add_offense(processed_source.to_source_range(tag.loc), offense, replacement)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 42
8
+ PATCH = 43
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
data/lib/tasks/docs.rake CHANGED
@@ -20,32 +20,12 @@ namespace :docs do
20
20
  end
21
21
 
22
22
  task :build do
23
- require File.expand_path("./../../demo/config/environment.rb", __dir__)
24
- require "primer/view_components"
25
- require "yard/docs_helper"
26
- require "view_component/test_helpers"
27
- include ViewComponent::TestHelpers
28
- include Primer::ViewHelper
29
- include YARD::DocsHelper
30
-
31
- Dir["./app/components/primer/**/*.rb"].sort.each { |file| require file }
32
-
33
- YARD::Rake::YardocTask.new
34
-
35
- # Custom tags for yard
36
- YARD::Tags::Library.define_tag("Accessibility", :accessibility)
37
- YARD::Tags::Library.define_tag("Deprecation", :deprecation)
38
-
39
- puts "Building YARD documentation."
40
- Rake::Task["yard"].execute
23
+ registry = generate_yard_registry
41
24
 
42
25
  puts "Converting YARD documentation to Markdown files."
43
26
 
44
27
  # Rails controller for rendering arbitrary ERB
45
28
  view_context = ApplicationController.new.tap { |c| c.request = ActionDispatch::TestRequest.create }.view_context
46
-
47
- registry = YARD::RegistryStore.new
48
- registry.load!(".yardoc")
49
29
  components = [
50
30
  Primer::Image,
51
31
  Primer::LocalTime,
@@ -172,7 +152,18 @@ namespace :docs do
172
152
  end
173
153
 
174
154
  initialize_method.tags(:example).each do |tag|
175
- (name, description) = tag.name.split("|")
155
+ name = tag.name
156
+ description = nil
157
+ code = nil
158
+
159
+ if tag.text.include?("@description")
160
+ splitted = tag.text.split(/@description|@code/)
161
+ description = splitted.second.gsub(/^[ \t]{2}/, "").strip
162
+ code = splitted.last.gsub(/^[ \t]{2}/, "").strip
163
+ else
164
+ code = tag.text
165
+ end
166
+
176
167
  f.puts
177
168
  f.puts("### #{name}")
178
169
  if description
@@ -180,14 +171,14 @@ namespace :docs do
180
171
  f.puts(description)
181
172
  end
182
173
  f.puts
183
- html = view_context.render(inline: tag.text)
174
+ html = view_context.render(inline: code)
184
175
  html.scan(/class="([^"]*)"/) do |classnames|
185
176
  classes_found_in_examples.concat(classnames[0].split(" ").reject { |c| c.starts_with?("octicon", "js", "my-") }.map { ".#{_1}"})
186
177
  end
187
178
  f.puts("<Example src=\"#{html.tr('"', "\'").delete("\n")}\" />")
188
179
  f.puts
189
180
  f.puts("```erb")
190
- f.puts(tag.text.to_s)
181
+ f.puts(code.to_s)
191
182
  f.puts("```")
192
183
  end
193
184
 
@@ -302,6 +293,22 @@ namespace :docs do
302
293
 
303
294
  puts "Markdown compiled."
304
295
 
296
+ if components_without_examples.any?
297
+ puts
298
+ puts "The following components have no examples defined: #{components_without_examples.map(&:name).join(', ')}. Consider adding an example?"
299
+ end
300
+
301
+ if components_needing_docs.any?
302
+ puts
303
+ puts "The following components needs docs. Care to contribute them? #{components_needing_docs.map(&:name).join(', ')}"
304
+ end
305
+ end
306
+
307
+ task :preview do
308
+ registry = generate_yard_registry
309
+
310
+ components = Primer::Component.descendants
311
+
305
312
  # Generate previews from documentation examples
306
313
  components.each do |component|
307
314
  documentation = registry.get(component.name)
@@ -336,15 +343,30 @@ namespace :docs do
336
343
  f.puts("end")
337
344
  end
338
345
  end
346
+ end
339
347
 
340
- if components_without_examples.any?
341
- puts
342
- puts "The following components have no examples defined: #{components_without_examples.map(&:name).join(', ')}. Consider adding an example?"
343
- end
348
+ def generate_yard_registry
349
+ require File.expand_path("./../../demo/config/environment.rb", __dir__)
350
+ require "primer/view_components"
351
+ require "yard/docs_helper"
352
+ require "view_component/test_helpers"
353
+ include ViewComponent::TestHelpers
354
+ include Primer::ViewHelper
355
+ include YARD::DocsHelper
344
356
 
345
- if components_needing_docs.any?
346
- puts
347
- puts "The following components needs docs. Care to contribute them? #{components_needing_docs.map(&:name).join(', ')}"
348
- end
357
+ Dir["./app/components/primer/**/*.rb"].sort.each { |file| require file }
358
+
359
+ YARD::Rake::YardocTask.new
360
+
361
+ # Custom tags for yard
362
+ YARD::Tags::Library.define_tag("Accessibility", :accessibility)
363
+ YARD::Tags::Library.define_tag("Deprecation", :deprecation)
364
+
365
+ puts "Building YARD documentation."
366
+ Rake::Task["yard"].execute
367
+
368
+ registry = YARD::RegistryStore.new
369
+ registry.load!(".yardoc")
370
+ registry
349
371
  end
350
372
  end
data/static/statuses.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "Primer::StateComponent": "beta",
44
44
  "Primer::SubheadComponent": "beta",
45
45
  "Primer::TabContainerComponent": "alpha",
46
- "Primer::TabNavComponent": "alpha",
46
+ "Primer::TabNavComponent": "beta",
47
47
  "Primer::TextComponent": "beta",
48
48
  "Primer::TimeAgoComponent": "beta",
49
49
  "Primer::TimelineItemComponent": "beta",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primer_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.42
4
+ version: 0.0.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-25 00:00:00.000000000 Z
11
+ date: 2021-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -142,6 +142,20 @@ dependencies:
142
142
  - - '='
143
143
  - !ruby/object:Gem::Version
144
144
  version: '0.13'
145
+ - !ruby/object:Gem::Dependency
146
+ name: erb_lint
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
145
159
  - !ruby/object:Gem::Dependency
146
160
  name: listen
147
161
  requirement: !ruby/object:Gem::Requirement
@@ -444,6 +458,7 @@ files:
444
458
  - app/lib/primer/classify/functional_border_colors.rb
445
459
  - app/lib/primer/classify/functional_colors.rb
446
460
  - app/lib/primer/classify/functional_text_colors.rb
461
+ - app/lib/primer/classify/grid.rb
447
462
  - app/lib/primer/classify/spacing.rb
448
463
  - app/lib/primer/fetch_or_fallback_helper.rb
449
464
  - app/lib/primer/join_style_arguments_helper.rb
@@ -454,6 +469,10 @@ files:
454
469
  - app/lib/primer/view_helper.rb
455
470
  - lib/primer/view_components.rb
456
471
  - lib/primer/view_components/engine.rb
472
+ - lib/primer/view_components/linters.rb
473
+ - lib/primer/view_components/linters/button_component_migration_counter.rb
474
+ - lib/primer/view_components/linters/flash_component_migration_counter.rb
475
+ - lib/primer/view_components/linters/helpers.rb
457
476
  - lib/primer/view_components/version.rb
458
477
  - lib/tasks/coverage.rake
459
478
  - lib/tasks/docs.rake