primer_view_components 0.0.120 → 0.0.122
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 +58 -0
- 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.css.json +123 -1
- data/app/components/primer/alpha/auto_complete.css.json +23 -1
- data/app/components/primer/alpha/banner.css.json +24 -1
- data/app/components/primer/alpha/button_marketing.css.json +33 -1
- data/app/components/primer/alpha/check_box.rb +74 -0
- data/app/components/primer/alpha/check_box_group.rb +36 -0
- data/app/components/primer/alpha/dialog.css.json +82 -1
- data/app/components/primer/alpha/dialog.rb +1 -1
- data/app/components/primer/alpha/dropdown.css.json +40 -1
- data/app/components/primer/alpha/form_button.rb +32 -0
- data/app/components/primer/alpha/form_control.html.erb +26 -0
- data/app/components/primer/alpha/form_control.rb +105 -0
- data/app/components/primer/alpha/layout.css.json +80 -1
- data/app/components/primer/alpha/menu.css.json +28 -1
- data/app/components/primer/alpha/multi_input.rb +81 -0
- data/app/components/primer/alpha/radio_button.rb +25 -0
- data/app/components/primer/alpha/radio_button_group.rb +36 -0
- data/app/components/primer/alpha/segmented_control/item.rb +1 -0
- data/app/components/primer/alpha/segmented_control.css +1 -1
- data/app/components/primer/alpha/segmented_control.css.json +31 -1
- data/app/components/primer/alpha/segmented_control.css.map +1 -1
- data/app/components/primer/alpha/segmented_control.pcss +43 -12
- data/app/components/primer/alpha/segmented_control.rb +30 -0
- data/app/components/primer/alpha/select.rb +37 -0
- data/app/components/primer/alpha/submit_button.rb +32 -0
- data/app/components/primer/alpha/tab_nav.css.json +24 -1
- data/app/components/primer/alpha/tab_panels.rb +7 -0
- data/app/components/primer/alpha/text_area.rb +24 -0
- data/app/components/primer/alpha/text_field.css +2 -2
- data/app/components/primer/alpha/text_field.css.json +134 -1
- data/app/components/primer/alpha/text_field.css.map +1 -1
- data/app/components/primer/alpha/text_field.pcss +27 -0
- data/app/components/primer/alpha/text_field.rb +16 -20
- data/app/components/primer/alpha/toggle_switch.css +1 -1
- data/app/components/primer/alpha/toggle_switch.css.json +40 -1
- data/app/components/primer/alpha/toggle_switch.css.map +1 -1
- data/app/components/primer/alpha/toggle_switch.pcss +31 -61
- data/app/components/primer/alpha/underline_nav.css.json +28 -1
- data/app/components/primer/base_component.rb +3 -3
- data/app/components/primer/beta/avatar.css.json +17 -1
- data/app/components/primer/beta/avatar_stack.css.json +28 -1
- data/app/components/primer/beta/blankslate.css.json +22 -1
- data/app/components/primer/beta/border_box.css.json +54 -1
- data/app/components/primer/beta/breadcrumbs.css.json +11 -1
- data/app/components/primer/beta/button.css.json +71 -1
- data/app/components/primer/beta/close_button.rb +1 -1
- data/app/components/primer/beta/counter.css.json +10 -1
- data/app/components/primer/beta/flash.css.json +27 -1
- data/app/components/primer/beta/label.css.json +25 -1
- data/app/components/primer/beta/link.css.json +19 -1
- data/app/components/primer/beta/popover.css.json +39 -1
- data/app/components/primer/beta/progress_bar.css.json +10 -1
- data/app/components/primer/{local_time.d.ts → beta/relative_time.d.ts} +0 -0
- data/app/components/primer/{local_time.js → beta/relative_time.js} +0 -0
- data/app/components/primer/{local_time.ts → beta/relative_time.ts} +0 -0
- data/app/components/primer/beta/state.css.json +13 -1
- data/app/components/primer/beta/subhead.css.json +12 -1
- data/app/components/primer/beta/timeline_item.css.json +16 -1
- data/app/components/primer/beta/truncate.css.json +12 -1
- data/app/components/primer/component.rb +12 -3
- data/app/components/primer/primer.d.ts +1 -2
- data/app/components/primer/primer.js +1 -2
- data/app/components/primer/primer.ts +1 -2
- data/app/components/primer/truncate.css.json +13 -1
- data/app/forms/example_toggle_switch_form.rb +1 -1
- data/app/forms/{select_list_form.rb → select_form.rb} +1 -1
- data/app/lib/primer/css/layout.css.json +316 -1
- data/app/lib/primer/css/utilities.css.json +1659 -1
- data/app/lib/primer/view_helper.rb +0 -1
- data/lib/primer/deprecations.yml +0 -78
- data/lib/primer/form_components.rb +26 -6
- data/lib/primer/forms/acts_as_component.rb +12 -1
- data/lib/primer/forms/builder.rb +1 -17
- data/lib/primer/forms/button.rb +4 -1
- data/lib/primer/forms/check_box_group.html.erb +14 -9
- data/lib/primer/forms/check_box_group.rb +5 -0
- data/lib/primer/forms/dsl/check_box_group_input.rb +3 -4
- data/lib/primer/forms/dsl/input.rb +33 -2
- data/lib/primer/forms/dsl/input_methods.rb +49 -1
- data/lib/primer/forms/dsl/radio_button_group_input.rb +2 -3
- data/lib/primer/forms/dsl/{select_list_input.rb → select_input.rb} +2 -2
- data/lib/primer/forms/dsl/text_field_input.rb +7 -5
- data/lib/primer/forms/form_control.rb +0 -1
- data/lib/primer/forms/group.html.erb +1 -1
- data/lib/primer/forms/multi.html.erb +8 -6
- data/lib/primer/forms/multi.rb +2 -0
- data/lib/primer/forms/radio_button_group.html.erb +14 -9
- data/lib/primer/forms/radio_button_group.rb +5 -0
- data/lib/primer/forms/{select_list.html.erb → select.html.erb} +0 -0
- data/lib/primer/forms/{select_list.rb → select.rb} +2 -2
- data/lib/primer/forms/spacing_wrapper.html.erb +1 -1
- data/lib/primer/forms/text_area.rb +1 -1
- data/lib/primer/forms/text_field.rb +5 -1
- data/lib/primer/forms/toggle_switch_form.rb +10 -3
- data/lib/primer/forms/utils.rb +20 -0
- data/lib/primer/view_components/engine.rb +1 -1
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/primer/yard/backend.rb +1 -15
- data/lib/primer/yard/component_manifest.rb +44 -27
- data/lib/primer/yard/component_ref.rb +40 -0
- data/lib/primer/yard/docs_helper.rb +16 -2
- data/lib/primer/yard/legacy_gatsby_backend.rb +9 -15
- data/lib/primer/yard/lookbook_docs_helper.rb +32 -0
- data/lib/primer/yard/lookbook_pages_backend.rb +194 -0
- data/lib/primer/yard/registry.rb +6 -21
- data/lib/primer/yard/renders_many_handler.rb +1 -1
- data/lib/primer/yard/renders_one_handler.rb +1 -1
- data/lib/primer/yard.rb +14 -0
- data/lib/tasks/docs.rake +26 -13
- data/lib/tasks/static.rake +22 -0
- data/previews/pages/forms/01_introduction.md.erb +44 -0
- data/previews/pages/forms/02_getting_started.md.erb +125 -0
- data/previews/pages/forms/03_caption_templates.md.erb +30 -0
- data/previews/pages/forms/04_after_content.md.erb +39 -0
- data/previews/pages/forms/05_groups_layouts.md.erb +22 -0
- data/previews/pages/forms/06_miscellaneous_inputs.md.erb +43 -0
- data/previews/pages/forms/07_toggle_switch_forms.md.erb +58 -0
- data/previews/pages/forms/08_validations.md.erb +28 -0
- data/previews/pages/forms/09_compound_forms.md.erb +97 -0
- data/previews/primer/alpha/auto_complete_preview.rb +6 -6
- data/previews/primer/alpha/check_box_group_preview.rb +89 -0
- data/previews/primer/alpha/check_box_preview.rb +62 -0
- data/previews/primer/alpha/form_control_preview/playground.html.erb +9 -0
- data/previews/primer/alpha/form_control_preview.rb +106 -0
- data/previews/primer/alpha/multi_input_preview/playground.html.erb +41 -0
- data/previews/primer/alpha/multi_input_preview.rb +80 -0
- data/previews/primer/alpha/radio_button_group_preview.rb +83 -0
- data/previews/primer/alpha/radio_button_preview.rb +62 -0
- data/previews/primer/alpha/segmented_control_preview/with_label_and_caption.html.erb +9 -0
- data/previews/primer/alpha/segmented_control_preview/with_subhead_actions.html.erb +11 -0
- data/previews/primer/alpha/segmented_control_preview.rb +7 -1
- data/previews/primer/alpha/select_preview.rb +130 -0
- data/previews/primer/alpha/text_area_preview.rb +87 -0
- data/previews/primer/alpha/text_field_preview.rb +24 -1
- data/previews/primer/alpha/toggle_switch_preview.rb +9 -9
- data/previews/primer/beta/auto_complete_preview.rb +17 -17
- data/previews/primer/forms/forms_preview/example_toggle_switch_form.html.erb +2 -2
- data/previews/primer/forms/forms_preview/{select_list_form.html.erb → select_form.html.erb} +1 -1
- data/previews/primer/forms/forms_preview.rb +3 -1
- data/previews/primer/url_helpers.rb +1 -1
- data/static/arguments.json +1348 -1412
- data/static/audited_at.json +12 -21
- data/static/constants.json +20 -51
- data/static/previews.json +1812 -0
- data/static/statuses.json +10 -19
- metadata +47 -32
- data/app/components/primer/dropdown/menu.rb +0 -14
- data/app/components/primer/dropdown.rb +0 -7
- data/app/components/primer/hellip_button.rb +0 -7
- data/app/components/primer/label_component.rb +0 -7
- data/app/components/primer/link_component.rb +0 -7
- data/app/components/primer/local_time.rb +0 -63
- data/app/components/primer/markdown.rb +0 -7
- data/app/components/primer/menu_component.rb +0 -7
- data/app/components/primer/octicon_component.rb +0 -7
- data/app/components/primer/octicon_symbols_component.rb +0 -7
- data/app/components/primer/popover_component.rb +0 -8
- data/app/components/primer/spinner_component.rb +0 -7
- data/app/components/primer/state_component.rb +0 -7
- data/app/components/primer/subhead_component.rb +0 -7
- data/app/components/primer/tab_container_component.rb +0 -7
- data/app/components/primer/time_ago_component.d.ts +0 -1
- data/app/components/primer/time_ago_component.js +0 -1
- data/app/components/primer/time_ago_component.rb +0 -51
- data/app/components/primer/time_ago_component.ts +0 -1
- data/app/components/primer/timeline_item_component.rb +0 -13
- data/previews/primer/local_time_component_preview.rb +0 -57
- data/previews/primer/time_ago_component_preview.rb +0 -27
@@ -9,10 +9,14 @@ module Primer
|
|
9
9
|
def initialize(input:)
|
10
10
|
@input = input
|
11
11
|
|
12
|
+
@input.add_input_classes(
|
13
|
+
"FormControl-input",
|
14
|
+
Primer::Forms::Dsl::Input::SIZE_MAPPINGS[@input.size]
|
15
|
+
)
|
16
|
+
|
12
17
|
@field_wrap_arguments = {
|
13
18
|
class: class_names(
|
14
19
|
"FormControl-input-wrap",
|
15
|
-
Primer::Forms::Dsl::Input::SIZE_MAPPINGS[@input.size],
|
16
20
|
"FormControl-input-wrap--trailingAction": @input.show_clear_button?,
|
17
21
|
"FormControl-input-wrap--leadingVisual": @input.leading_visual?
|
18
22
|
),
|
@@ -32,8 +32,10 @@ module Primer
|
|
32
32
|
#
|
33
33
|
class ToggleSwitchForm < Primer::Forms::Base
|
34
34
|
# Define the form on subclasses so render(Subclass.new) works as expected.
|
35
|
-
|
36
|
-
|
35
|
+
# (this is called directly on this class, but also on classes
|
36
|
+
# that inherit from this class)
|
37
|
+
def self.define_form_on(klass)
|
38
|
+
klass.form do |toggle_switch_form|
|
37
39
|
input = Dsl::ToggleSwitchInput.new(
|
38
40
|
builder: toggle_switch_form.builder, form: self, **@system_arguments
|
39
41
|
)
|
@@ -42,8 +44,13 @@ module Primer
|
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
47
|
+
def self.inherited(base)
|
48
|
+
super
|
49
|
+
define_form_on(base)
|
50
|
+
end
|
51
|
+
|
45
52
|
# Define the form on self so render(ToggleSwitchForm.new) works as expected.
|
46
|
-
|
53
|
+
define_form_on(self)
|
47
54
|
|
48
55
|
# Override to avoid accepting a builder argument. We create our own builder
|
49
56
|
# on render. See the implementation of render_in below.
|
data/lib/primer/forms/utils.rb
CHANGED
@@ -5,6 +5,10 @@ module Primer
|
|
5
5
|
module Forms
|
6
6
|
# :nodoc:
|
7
7
|
module Utils
|
8
|
+
include Primer::ClassNameHelper
|
9
|
+
|
10
|
+
PRIMER_UTILITY_KEYS = Primer::Classify::Utilities::UTILITIES.keys.freeze
|
11
|
+
|
8
12
|
# Unfortunately this bug (https://github.com/ruby/ruby/pull/5646) prevents us from using
|
9
13
|
# Ruby's native Module.const_source_location. Instead we have to fudge it by searching
|
10
14
|
# for the file in the configured autoload paths. Doing so relies on Rails' autoloading
|
@@ -21,6 +25,22 @@ module Primer
|
|
21
25
|
|
22
26
|
nil
|
23
27
|
end
|
28
|
+
|
29
|
+
# This method does the following:
|
30
|
+
#
|
31
|
+
# 1. Runs Primer's classify routine to convert entries like mb: 1 to mb-1.
|
32
|
+
# 2. Runs classify on both options[:class] and options[:classes]. The first
|
33
|
+
# is expected by Rails/HTML while the second is specific to Primer.
|
34
|
+
# 3. Combines options[:class] and options[:classes] into options[:class]
|
35
|
+
# so the options hash can be easily passed to Rails form builder methods.
|
36
|
+
#
|
37
|
+
def classify(options)
|
38
|
+
options[:classes] = class_names(options.delete(:class), options[:classes])
|
39
|
+
options.merge!(Primer::Classify.call(options))
|
40
|
+
options.except!(*PRIMER_UTILITY_KEYS)
|
41
|
+
options[:class] = class_names(options[:class], options.delete(:classes))
|
42
|
+
options
|
43
|
+
end
|
24
44
|
end
|
25
45
|
|
26
46
|
Utils.extend(Utils)
|
data/lib/primer/yard/backend.rb
CHANGED
@@ -2,27 +2,13 @@
|
|
2
2
|
|
3
3
|
# :nocov:
|
4
4
|
module Primer
|
5
|
-
module
|
5
|
+
module Yard
|
6
6
|
# Shared functionality for generating documentation from YARD comments.
|
7
7
|
class Backend
|
8
8
|
include DocsHelper
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
-
def pretty_default_value(tag, component)
|
13
|
-
params = tag.object.parameters.find { |param| [tag.name.to_s, "#{tag.name}:"].include?(param[0]) }
|
14
|
-
default = tag.defaults&.first || params&.second
|
15
|
-
|
16
|
-
return "N/A" unless default
|
17
|
-
|
18
|
-
constant_name = "#{component.name}::#{default}"
|
19
|
-
constant_value = default.safe_constantize || constant_name.safe_constantize
|
20
|
-
|
21
|
-
return pretty_value(default) if constant_value.nil?
|
22
|
-
|
23
|
-
pretty_value(constant_value)
|
24
|
-
end
|
25
|
-
|
26
12
|
def view_context
|
27
13
|
@view_context ||= begin
|
28
14
|
# Rails controller for rendering arbitrary ERB
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# :nocov:
|
4
4
|
module Primer
|
5
|
-
module
|
5
|
+
module Yard
|
6
6
|
# The set of documented components (and associated metadata).
|
7
7
|
class ComponentManifest
|
8
8
|
COMPONENTS = {
|
@@ -13,7 +13,6 @@ module Primer
|
|
13
13
|
Primer::Alpha::Layout => {},
|
14
14
|
Primer::Alpha::HellipButton => {},
|
15
15
|
Primer::Alpha::Image => {},
|
16
|
-
Primer::LocalTime => { js: true },
|
17
16
|
Primer::Alpha::OcticonSymbols => {},
|
18
17
|
Primer::Alpha::ImageCrop => { js: true },
|
19
18
|
Primer::IconButton => { js: true },
|
@@ -54,7 +53,6 @@ module Primer
|
|
54
53
|
Primer::Beta::Subhead => {},
|
55
54
|
Primer::Alpha::TabContainer => { js: true },
|
56
55
|
Primer::Beta::Text => {},
|
57
|
-
Primer::TimeAgoComponent => { js: true },
|
58
56
|
Primer::Beta::TimelineItem => {},
|
59
57
|
Primer::Tooltip => {},
|
60
58
|
Primer::Truncate => {},
|
@@ -79,42 +77,61 @@ module Primer
|
|
79
77
|
Primer::Alpha::ActionList::Item => { examples: false },
|
80
78
|
|
81
79
|
# Forms
|
82
|
-
Primer::Alpha::TextField => { form_component: true }
|
80
|
+
Primer::Alpha::TextField => { form_component: true },
|
81
|
+
Primer::Alpha::TextArea => { form_component: true, published: false },
|
82
|
+
Primer::Alpha::Select => { form_component: true, published: false },
|
83
|
+
Primer::Alpha::MultiInput => { form_component: true, js: true, published: false },
|
84
|
+
Primer::Alpha::RadioButton => { form_component: true, published: false },
|
85
|
+
Primer::Alpha::RadioButtonGroup => { form_component: true, published: false },
|
86
|
+
Primer::Alpha::CheckBox => { form_component: true, published: false },
|
87
|
+
Primer::Alpha::CheckBoxGroup => { form_component: true, published: false },
|
88
|
+
Primer::Alpha::SubmitButton => { form_component: true, published: false },
|
89
|
+
Primer::Alpha::FormButton => { form_component: true, published: false }
|
83
90
|
}.freeze
|
84
91
|
|
85
|
-
|
86
|
-
def each(&block)
|
87
|
-
COMPONENTS.keys.each(&block)
|
88
|
-
end
|
92
|
+
include Enumerable
|
89
93
|
|
90
|
-
|
91
|
-
|
92
|
-
|
94
|
+
def initialize(components)
|
95
|
+
@components = components
|
96
|
+
end
|
97
|
+
|
98
|
+
def each
|
99
|
+
return to_enum(__method__) unless block_given?
|
93
100
|
|
94
|
-
|
95
|
-
|
101
|
+
@components.each do |klass|
|
102
|
+
yield self.class.ref_for(klass)
|
96
103
|
end
|
104
|
+
end
|
97
105
|
|
98
|
-
|
99
|
-
|
106
|
+
def where(**attrs)
|
107
|
+
self.class.where(@components, **attrs)
|
108
|
+
end
|
109
|
+
|
110
|
+
class << self
|
111
|
+
def where(components = COMPONENTS, **desired_attrs)
|
112
|
+
new(
|
113
|
+
components.each_with_object([]) do |(klass, component_attrs), memo|
|
114
|
+
matches = desired_attrs.all? do |name, desired_value|
|
115
|
+
component_attrs.fetch(name, ComponentRef::ATTR_DEFAULTS[name]) == desired_value
|
116
|
+
end
|
117
|
+
|
118
|
+
memo << klass if matches
|
119
|
+
end
|
120
|
+
)
|
100
121
|
end
|
101
122
|
|
102
|
-
def
|
103
|
-
|
104
|
-
COMPONENTS[c].fetch(:examples, true)
|
105
|
-
end
|
123
|
+
def all
|
124
|
+
new(COMPONENTS.keys)
|
106
125
|
end
|
107
126
|
|
108
|
-
def
|
109
|
-
|
110
|
-
COMPONENTS[c].fetch(:js, false)
|
111
|
-
end
|
127
|
+
def ref_for(klass)
|
128
|
+
ref_cache[klass] ||= ComponentRef.new(klass, COMPONENTS[klass])
|
112
129
|
end
|
113
130
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
131
|
+
private
|
132
|
+
|
133
|
+
def ref_cache
|
134
|
+
@ref_cache ||= {}
|
118
135
|
end
|
119
136
|
end
|
120
137
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nocov:
|
4
|
+
module Primer
|
5
|
+
module Yard
|
6
|
+
# :nodoc:
|
7
|
+
class ComponentRef
|
8
|
+
ATTR_DEFAULTS = {
|
9
|
+
js: false,
|
10
|
+
examples: true,
|
11
|
+
published: true,
|
12
|
+
form_component: false
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
attr_reader :klass, :attrs
|
16
|
+
|
17
|
+
def initialize(klass, attrs)
|
18
|
+
@klass = klass
|
19
|
+
@attrs = attrs
|
20
|
+
end
|
21
|
+
|
22
|
+
def requires_js?
|
23
|
+
@attrs.fetch(:js, ATTR_DEFAULTS[:js])
|
24
|
+
end
|
25
|
+
|
26
|
+
def should_have_examples?
|
27
|
+
@attrs.fetch(:examples, ATTR_DEFAULTS[:examples])
|
28
|
+
end
|
29
|
+
|
30
|
+
def published?
|
31
|
+
@attrs.fetch(:published, ATTR_DEFAULTS[:published])
|
32
|
+
end
|
33
|
+
|
34
|
+
def form_component?
|
35
|
+
@attrs.fetch(:form_component, ATTR_DEFAULTS[:form_component])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# :nocov:
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# :nocov:
|
4
|
-
|
5
4
|
module Primer
|
6
|
-
module
|
5
|
+
module Yard
|
7
6
|
# Helper methods to use for yard documentation
|
8
7
|
module DocsHelper
|
9
8
|
def one_of(enumerable, lower: false, sort: true)
|
@@ -66,6 +65,20 @@ module Primer
|
|
66
65
|
[m[:status]&.downcase, m[:name].gsub("::", ""), m[:name]]
|
67
66
|
end
|
68
67
|
|
68
|
+
def pretty_default_value(tag, component)
|
69
|
+
params = tag.object.parameters.find { |param| [tag.name.to_s, "#{tag.name}:"].include?(param[0]) }
|
70
|
+
default = tag.defaults&.first || params&.second
|
71
|
+
|
72
|
+
return "N/A" unless default
|
73
|
+
|
74
|
+
constant_name = "#{component.name}::#{default}"
|
75
|
+
constant_value = default.safe_constantize || constant_name.safe_constantize
|
76
|
+
|
77
|
+
return pretty_value(default) if constant_value.nil?
|
78
|
+
|
79
|
+
pretty_value(constant_value)
|
80
|
+
end
|
81
|
+
|
69
82
|
def pretty_value(val)
|
70
83
|
case val
|
71
84
|
when nil
|
@@ -79,3 +92,4 @@ module Primer
|
|
79
92
|
end
|
80
93
|
end
|
81
94
|
end
|
95
|
+
# :nocov:
|
@@ -3,12 +3,8 @@
|
|
3
3
|
# rubocop:disable Naming/MethodParameterName
|
4
4
|
|
5
5
|
# :nocov:
|
6
|
-
|
7
|
-
require "primer/yard/component_manifest"
|
8
|
-
require "primer/yard/backend"
|
9
|
-
|
10
6
|
module Primer
|
11
|
-
module
|
7
|
+
module Yard
|
12
8
|
# Backend that generates documentation for the legacy, Gatsby-powered PVC docsite.
|
13
9
|
class LegacyGatsbyBackend < Backend
|
14
10
|
class << self
|
@@ -29,17 +25,19 @@ module Primer
|
|
29
25
|
end
|
30
26
|
end
|
31
27
|
|
32
|
-
attr_reader :registry
|
28
|
+
attr_reader :registry, :manifest
|
33
29
|
|
34
|
-
def initialize(registry)
|
30
|
+
def initialize(registry, manifest)
|
35
31
|
@registry = registry
|
32
|
+
@manifest = manifest
|
36
33
|
end
|
37
34
|
|
38
35
|
def generate
|
39
36
|
args_for_components = []
|
40
37
|
errors = []
|
41
38
|
|
42
|
-
each_component do |
|
39
|
+
each_component do |component_ref|
|
40
|
+
component = component_ref.klass
|
43
41
|
docs = registry.find(component)
|
44
42
|
status_path = docs.status_module.nil? ? "" : "#{docs.status_module}/"
|
45
43
|
|
@@ -66,7 +64,7 @@ module Primer
|
|
66
64
|
f.puts
|
67
65
|
f.puts("import Example from '#{metadata[:example_path]}'")
|
68
66
|
|
69
|
-
if
|
67
|
+
if component_ref.requires_js?
|
70
68
|
f.puts("import RequiresJSFlash from '#{metadata[:require_js_path]}'")
|
71
69
|
f.puts
|
72
70
|
f.puts("<RequiresJSFlash />")
|
@@ -170,7 +168,7 @@ module Primer
|
|
170
168
|
f.puts(code.to_s)
|
171
169
|
f.puts("```")
|
172
170
|
end
|
173
|
-
elsif
|
171
|
+
elsif component_ref.should_have_examples?
|
174
172
|
errors << { component.name => { example: "No examples found" } }
|
175
173
|
end
|
176
174
|
end
|
@@ -219,11 +217,7 @@ module Primer
|
|
219
217
|
end
|
220
218
|
|
221
219
|
def each_component(&block)
|
222
|
-
manifest.
|
223
|
-
end
|
224
|
-
|
225
|
-
def manifest
|
226
|
-
Primer::YARD::ComponentManifest
|
220
|
+
manifest.each(&block)
|
227
221
|
end
|
228
222
|
|
229
223
|
def source_url(component)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nocov:
|
4
|
+
module Primer
|
5
|
+
module Yard
|
6
|
+
# Helper methods for documentation generated in Lookbook pages.
|
7
|
+
module LookbookDocsHelper
|
8
|
+
# Adheres to the same signature as Primer::Yard::DocsHelper#link_to_component so link_to_component
|
9
|
+
# may be used in a Gatsby or Lookbook context and produce the correct link for each platform.
|
10
|
+
#
|
11
|
+
# @param component [Class] The component class to link to.
|
12
|
+
# @return [String] The link, either in HTML or markdown format.
|
13
|
+
def link_to_component(component)
|
14
|
+
backend = Primer::Yard::LookbookPagesBackend.new(Primer::Yard::Registry.make, nil)
|
15
|
+
component_ref = Primer::Yard::ComponentManifest.ref_for(component)
|
16
|
+
page = backend.page_for(component_ref)
|
17
|
+
|
18
|
+
# If the page_path method is available, we're being rendered into HTML by Lookbook
|
19
|
+
# and should emit an HTML <a> tag. No page_path means we're being rendered into
|
20
|
+
# markdown by LookbookPagesBackend and should emit a markdown + ERB link that
|
21
|
+
# Lookbook will eventually render on page load.
|
22
|
+
if respond_to?(:page_path)
|
23
|
+
link_to(page.docs.short_name, page_path(page.page_id.to_sym.inspect))
|
24
|
+
else
|
25
|
+
# rubocop:disable Rails/OutputSafety
|
26
|
+
"[#{page.docs.short_name}](<%= page_path(#{page.page_id.to_sym.inspect}) %>)".html_safe
|
27
|
+
# rubocop:enable Rails/OutputSafety
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nocov:
|
4
|
+
module Primer
|
5
|
+
module Yard
|
6
|
+
# A single Lookbook page.
|
7
|
+
class LookbookPage
|
8
|
+
include DocsHelper
|
9
|
+
|
10
|
+
PREVIEW_MAP = {
|
11
|
+
Primer::Alpha::TextField => [:single_text_field_form, :multi_text_field_form],
|
12
|
+
Primer::Alpha::TextArea => [],
|
13
|
+
Primer::Alpha::Select => [:select_list_form],
|
14
|
+
Primer::Alpha::MultiInput => [:multi_input_form],
|
15
|
+
Primer::Alpha::RadioButton => [:radio_button_with_nested_form],
|
16
|
+
Primer::Alpha::RadioButtonGroup => [:radio_button_group_form],
|
17
|
+
Primer::Alpha::CheckBox => [:check_box_with_nested_form],
|
18
|
+
Primer::Alpha::CheckBoxGroup => [:check_box_group_form],
|
19
|
+
Primer::Alpha::SubmitButton => [:submit_button_form],
|
20
|
+
Primer::Alpha::FormButton => [:submit_button_form]
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
attr_reader :component_ref, :backend, :docs
|
24
|
+
|
25
|
+
def initialize(component_ref, backend, docs)
|
26
|
+
@component_ref = component_ref
|
27
|
+
@backend = backend
|
28
|
+
@docs = docs
|
29
|
+
end
|
30
|
+
|
31
|
+
def page_id
|
32
|
+
@page_id ||= docs.short_name.dasherize.underscore.tap do |page_id|
|
33
|
+
page_id << "_input" unless page_id.end_with?("_input")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def generate
|
38
|
+
path = File.expand_path(
|
39
|
+
File.join(
|
40
|
+
*%w[.. .. .. previews pages forms inputs],
|
41
|
+
"#{docs.short_name.dasherize.underscore}.md.erb"
|
42
|
+
), __dir__
|
43
|
+
)
|
44
|
+
|
45
|
+
# rubocop:disable Lint/UselessAssignment
|
46
|
+
documented_methods = docs.non_slot_methods.select do |mtd|
|
47
|
+
[component.name, "Primer::Forms::Dsl::InputMethods"].include?(mtd.parent.title)
|
48
|
+
end
|
49
|
+
|
50
|
+
preview_methods = PREVIEW_MAP[component]
|
51
|
+
preview_erbs = preview_methods.map do |preview_method|
|
52
|
+
"<%= embed Primer::Forms::FormsPreview, #{preview_method.inspect} %>"
|
53
|
+
end
|
54
|
+
# rubocop:enable Lint/UselessAssignment
|
55
|
+
|
56
|
+
# rubocop:disable Security/Eval
|
57
|
+
File.open(path, "w") do |f|
|
58
|
+
f.write(eval(Erubi::Engine.new(<<~ERB, trim: true).src))
|
59
|
+
---
|
60
|
+
title: <%= docs.title.underscore.titleize %>
|
61
|
+
id: <%= page_id %>
|
62
|
+
---
|
63
|
+
|
64
|
+
<%= docs.base_docstring %>
|
65
|
+
|
66
|
+
## Usage
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
<%= docs.tags(:form_usage).first.text %>
|
70
|
+
```
|
71
|
+
|
72
|
+
<% specific_args = specific_args_from(docs.params) %>
|
73
|
+
<% unless specific_args.empty? %>
|
74
|
+
## Arguments
|
75
|
+
|
76
|
+
<%= generate_args_table(specific_args) %>
|
77
|
+
<% end %>
|
78
|
+
|
79
|
+
## Common arguments
|
80
|
+
|
81
|
+
<%= generate_args_table(common_args_from(docs.params)) %>
|
82
|
+
|
83
|
+
<% unless documented_methods.empty? %>
|
84
|
+
## Methods
|
85
|
+
|
86
|
+
<% documented_methods.each do |method_docs| %>
|
87
|
+
### `#<%= method_docs.signature.sub(/def /, "") %>`
|
88
|
+
|
89
|
+
<%= method_docs.base_docstring %>
|
90
|
+
|
91
|
+
<% param_tags = method_docs.tags(:param) %>
|
92
|
+
|
93
|
+
<% if param_tags.any? %>
|
94
|
+
|
95
|
+
<%= generate_args_table(param_tags) %>
|
96
|
+
<% end %>
|
97
|
+
<% end %>
|
98
|
+
<% end %>
|
99
|
+
|
100
|
+
<% unless preview_methods.empty? %>
|
101
|
+
## Examples
|
102
|
+
|
103
|
+
<%= preview_erbs.join("\n") %>
|
104
|
+
<% end %>
|
105
|
+
ERB
|
106
|
+
end
|
107
|
+
# rubocop:enable Security/Eval
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def registry
|
113
|
+
backend.registry
|
114
|
+
end
|
115
|
+
|
116
|
+
def generate_args_table(params)
|
117
|
+
rows = params.map do |tag|
|
118
|
+
description = backend.view_context.render(inline: tag.text.squish)
|
119
|
+
parts = [
|
120
|
+
"`#{tag.name}`",
|
121
|
+
tag.types.join(", "),
|
122
|
+
description
|
123
|
+
]
|
124
|
+
|
125
|
+
"| #{parts.join(' | ')} |"
|
126
|
+
end
|
127
|
+
|
128
|
+
<<~MARKDOWN
|
129
|
+
| Name | Type | Description |
|
130
|
+
| :- | :- | :- |
|
131
|
+
#{rows.join("\n")}
|
132
|
+
MARKDOWN
|
133
|
+
end
|
134
|
+
|
135
|
+
def common_args_from(params)
|
136
|
+
params.select { |param| common_form_input_argument_names.include?(param.name) }
|
137
|
+
end
|
138
|
+
|
139
|
+
def specific_args_from(params)
|
140
|
+
params.reject { |param| common_form_input_argument_names.include?(param.name) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def common_form_input_argument_names
|
144
|
+
@common_form_input_argument_names ||= begin
|
145
|
+
macro = registry.yard_registry[".macro.form_input_arguments"]
|
146
|
+
parser = ::YARD::Docstring.parser
|
147
|
+
parser.parse(macro.macro_data)
|
148
|
+
parser
|
149
|
+
.tags
|
150
|
+
.select { |tag| tag.tag_name == "param" }
|
151
|
+
.map(&:name)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def component
|
156
|
+
component_ref.klass
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Backend that generates Lookbook pages.
|
161
|
+
class LookbookPagesBackend < Backend
|
162
|
+
attr_reader :registry, :manifest
|
163
|
+
|
164
|
+
def initialize(registry, manifest)
|
165
|
+
@registry = registry
|
166
|
+
@manifest = manifest
|
167
|
+
end
|
168
|
+
|
169
|
+
def generate
|
170
|
+
each_component do |component_ref|
|
171
|
+
page_for(component_ref).generate
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def page_for(component_ref)
|
176
|
+
docs = registry.find(component_ref.klass)
|
177
|
+
LookbookPage.new(component_ref, self, docs)
|
178
|
+
end
|
179
|
+
|
180
|
+
def view_context
|
181
|
+
@view_context ||= super.tap do |vc|
|
182
|
+
vc.singleton_class.include(LookbookDocsHelper)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def each_component(&block)
|
189
|
+
manifest.each(&block)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
# :nocov:
|
data/lib/primer/yard/registry.rb
CHANGED
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
# :nocov:
|
4
4
|
|
5
|
-
require "primer/view_components"
|
6
|
-
require "primer/yard/docs_helper"
|
7
5
|
require "view_component/test_helpers"
|
8
6
|
|
9
7
|
module Primer
|
10
|
-
module
|
8
|
+
module Yard
|
11
9
|
# A wrapper around a YARD class reference that provides convenience methods
|
12
10
|
# for extracting component parameters, accessibility status, etc.
|
13
11
|
class RegistryEntry
|
@@ -62,8 +60,9 @@ module Primer
|
|
62
60
|
def public_methods
|
63
61
|
# Returns: only public methods that belong to this class (i.e. no inherited methods)
|
64
62
|
# excluding the constructor
|
65
|
-
@public_methods ||=
|
66
|
-
|
63
|
+
@public_methods ||= docs.meths.reject do |mtd|
|
64
|
+
mtd.tag(:private) || mtd.name == :initialize
|
65
|
+
end
|
67
66
|
end
|
68
67
|
|
69
68
|
def title
|
@@ -89,20 +88,6 @@ module Primer
|
|
89
88
|
def a11y_reviewed?
|
90
89
|
metadata[:a11y_reviewed]
|
91
90
|
end
|
92
|
-
|
93
|
-
def requires_js?
|
94
|
-
manifest.components_requiring_js.include?(component)
|
95
|
-
end
|
96
|
-
|
97
|
-
def includes_examples?
|
98
|
-
manifest.components_with_examples.include?(component)
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
def manifest
|
104
|
-
Primer::YARD::ComponentManifest
|
105
|
-
end
|
106
91
|
end
|
107
92
|
|
108
93
|
# Wrapper around an instance of YARD::Registry that provides easy access to component
|
@@ -111,11 +96,11 @@ module Primer
|
|
111
96
|
class << self
|
112
97
|
include ViewComponent::TestHelpers
|
113
98
|
include Primer::ViewHelper
|
114
|
-
include Primer::
|
99
|
+
include Primer::Yard::DocsHelper
|
115
100
|
|
116
101
|
def make
|
117
102
|
registry = ::YARD::RegistryStore.new
|
118
|
-
registry.load!(".yardoc")
|
103
|
+
registry.load!(File.expand_path(File.join("..", "..", "..", ".yardoc"), __dir__))
|
119
104
|
|
120
105
|
new(registry)
|
121
106
|
end
|