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 +4 -4
- data/CHANGELOG.md +46 -0
- data/app/components/primer/base_component.rb +5 -1
- data/app/components/primer/blankslate_component.html.erb +1 -0
- data/app/components/primer/blankslate_component.rb +62 -44
- data/app/components/primer/tab_nav_component.html.erb +1 -1
- data/app/components/primer/tab_nav_component.rb +19 -1
- data/app/components/primer/underline_nav_component.html.erb +1 -1
- data/app/components/primer/underline_nav_component.rb +17 -1
- data/app/lib/primer/classify.rb +8 -3
- data/app/lib/primer/classify/cache.rb +15 -0
- data/app/lib/primer/classify/grid.rb +45 -0
- data/app/lib/primer/tabbed_component_helper.rb +2 -2
- data/lib/primer/view_components/linters.rb +3 -0
- data/lib/primer/view_components/linters/button_component_migration_counter.rb +16 -0
- data/lib/primer/view_components/linters/flash_component_migration_counter.rb +16 -0
- data/lib/primer/view_components/linters/helpers.rb +89 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/tasks/docs.rake +54 -32
- data/static/statuses.json +1 -1
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78f4fe987616d5ab746cbd6d6a0bc79ff62ecf33eb2365af3ade87a43461d35b
|
4
|
+
data.tar.gz: 2813cf307508ab9a413d98edbba54e1d7735dc86e853a42587487c7293d42571
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
# | `
|
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
|
@@ -23,56 +23,74 @@ module Primer
|
|
23
23
|
# description: "Description",
|
24
24
|
# ) %>
|
25
25
|
#
|
26
|
-
# @example Icon
|
27
|
-
#
|
28
|
-
# icon
|
29
|
-
#
|
30
|
-
#
|
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
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
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
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
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
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
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
|
-
#
|
55
|
-
#
|
56
|
-
#
|
66
|
+
# button_text: "Create the first page",
|
67
|
+
# button_url: "https://github.com/monalisa/mona/wiki/_new",
|
68
|
+
# ) %>
|
57
69
|
#
|
58
|
-
# @example Link
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
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
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
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.
|
@@ -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(
|
@@ -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)
|
data/app/lib/primer/classify.rb
CHANGED
@@ -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
|
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, :
|
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,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
|
data/lib/tasks/docs.rake
CHANGED
@@ -20,32 +20,12 @@ namespace :docs do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
task :build do
|
23
|
-
|
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
|
-
|
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:
|
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(
|
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
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
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
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
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": "
|
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.
|
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-
|
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
|