primer_view_components 0.0.120 → 0.0.122
Sign up to get free protection for your applications and to get access to all the features.
- 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
|