lookbook 1.0.8 → 1.1.0
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/app/assets/lookbook/css/lookbook.css +76 -2
- data/app/assets/lookbook/js/app.js +20 -2
- data/app/{components/lookbook/params_editor/field/component.js → assets/lookbook/js/components/params_input.js} +1 -14
- data/app/assets/lookbook/js/lookbook.js +2 -1
- data/app/components/lookbook/base_component.rb +2 -3
- data/app/components/lookbook/button/component.html.erb +2 -2
- data/app/components/lookbook/button/component.rb +6 -1
- data/app/components/lookbook/button_group/component.rb +3 -4
- data/app/components/lookbook/copy_button/component.html.erb +1 -1
- data/app/components/lookbook/debug_menu/component.html.erb +51 -0
- data/app/components/lookbook/debug_menu/component.rb +18 -0
- data/app/components/lookbook/embed/component.html.erb +3 -3
- data/app/components/lookbook/header/component.html.erb +19 -44
- data/app/components/lookbook/inspector_panel/component.html.erb +5 -3
- data/app/components/lookbook/inspector_panel/component.rb +6 -18
- data/app/components/lookbook/nav/component.js +4 -0
- data/app/components/lookbook/nav/component.rb +1 -1
- data/app/components/lookbook/nav/item/component.html.erb +4 -4
- data/app/components/lookbook/nav/item/component.rb +1 -1
- data/app/components/lookbook/page_tabs/component.html.erb +4 -4
- data/app/components/lookbook/page_tabs/component.rb +1 -1
- data/app/components/lookbook/params/editor/component.html.erb +21 -0
- data/app/components/lookbook/{params_editor → params/editor}/component.js +1 -1
- data/app/components/lookbook/params/editor/component.rb +40 -0
- data/app/components/lookbook/params/field/component.css +76 -0
- data/app/components/lookbook/params/field/component.html.erb +27 -0
- data/app/components/lookbook/params/field/component.js +7 -0
- data/app/components/lookbook/params/field/component.rb +101 -0
- data/app/components/lookbook/tabs/component.html.erb +2 -2
- data/app/components/lookbook/tag_component.rb +1 -0
- data/app/components/lookbook/viewport/component.css +1 -1
- data/app/components/lookbook/viewport/component.html.erb +11 -0
- data/app/controllers/lookbook/previews_controller.rb +1 -1
- data/app/helpers/lookbook/component_helper.rb +45 -26
- data/app/helpers/lookbook/page_helper.rb +1 -1
- data/app/views/layouts/lookbook/application.html.erb +18 -4
- data/app/views/layouts/lookbook/page.html.erb +4 -4
- data/app/views/layouts/lookbook/shell.html.erb +4 -4
- data/app/views/layouts/lookbook/skeleton.html.erb +0 -6
- data/app/views/lookbook/error.html.erb +1 -1
- data/app/views/lookbook/pages/show.html.erb +2 -2
- data/app/views/lookbook/previews/inputs/_color.html.erb +5 -0
- data/app/views/lookbook/previews/inputs/_range.html.erb +15 -0
- data/app/views/lookbook/previews/inputs/_select.html.erb +5 -0
- data/app/views/lookbook/previews/inputs/_text.html.erb +5 -0
- data/app/views/lookbook/previews/inputs/_textarea.html.erb +5 -0
- data/app/views/lookbook/previews/inputs/_toggle.html.erb +20 -0
- data/app/views/lookbook/previews/panels/_content.html.erb +2 -2
- data/app/views/lookbook/previews/panels/_notes.html.erb +2 -2
- data/app/views/lookbook/previews/panels/_output.html.erb +1 -1
- data/app/views/lookbook/previews/panels/_params.html.erb +3 -3
- data/app/views/lookbook/previews/panels/_preview.html.erb +1 -1
- data/app/views/lookbook/previews/panels/_source.html.erb +2 -2
- data/app/views/lookbook/previews/show.html.erb +13 -19
- data/lib/lookbook/config.rb +16 -1
- data/lib/lookbook/engine.rb +16 -6
- data/lib/lookbook/markdown.rb +1 -1
- data/lib/lookbook/panels.rb +14 -4
- data/lib/lookbook/params.rb +66 -35
- data/lib/lookbook/parser.rb +1 -0
- data/lib/lookbook/preview.rb +10 -4
- data/lib/lookbook/preview_controller.rb +7 -19
- data/lib/lookbook/preview_example.rb +1 -1
- data/lib/lookbook/source_inspector.rb +10 -4
- data/lib/lookbook/tag.rb +13 -3
- data/lib/lookbook/tag_options.rb +111 -0
- data/lib/lookbook/tags.rb +6 -2
- data/lib/lookbook/template_parser.rb +72 -0
- data/lib/lookbook/theme.rb +1 -1
- data/lib/lookbook/utils.rb +23 -0
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +2 -0
- data/public/lookbook-assets/css/lookbook.css +369 -126
- data/public/lookbook-assets/css/lookbook.css.map +1 -1
- data/public/lookbook-assets/js/embed.js +13 -13
- data/public/lookbook-assets/js/embed.js.map +1 -1
- data/public/lookbook-assets/js/lookbook.js +706 -621
- data/public/lookbook-assets/js/lookbook.js.map +1 -1
- metadata +42 -10
- data/app/components/lookbook/params_editor/component.html.erb +0 -3
- data/app/components/lookbook/params_editor/component.rb +0 -11
- data/app/components/lookbook/params_editor/field/component.html.erb +0 -49
- data/app/components/lookbook/params_editor/field/component.rb +0 -44
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
<h6 class="italic font-mono mb-4 opacity-40">
|
|
7
7
|
# <%= item.label %>
|
|
8
8
|
</h6>
|
|
9
|
-
<%=
|
|
9
|
+
<%= lookbook_render :prose, content: item.notes %>
|
|
10
10
|
</div>
|
|
11
11
|
<% end %>
|
|
12
12
|
</div>
|
|
13
13
|
<% else %>
|
|
14
14
|
<div class="px-4 py-6 bg-lookbook-prose-bg w-full h-full">
|
|
15
|
-
<%=
|
|
15
|
+
<%= lookbook_render :prose do %>
|
|
16
16
|
<%== items.any? ? items.first.notes : "<em class='opacity-50'>No notes provided.</em>" %>
|
|
17
17
|
<% end %>
|
|
18
18
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%=
|
|
1
|
+
<%= lookbook_render :code, line_numbers: true, full_height: true do -%>
|
|
2
2
|
<% if examples.many? -%>
|
|
3
3
|
<% examples.each do |example| -%><%== "<!-- #{example.label} -->\n#{beautify(example.output)}\n\n" -%><% end %>
|
|
4
4
|
<%- else -%>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<% if preview.params.none? %>
|
|
2
2
|
<div class="p-4 w-full h-full bg-lookbook-prose-bg">
|
|
3
|
-
<%=
|
|
3
|
+
<%= lookbook_render :prose do %>
|
|
4
4
|
<em class='opacity-50'>No params configured.</em>
|
|
5
5
|
<% end %>
|
|
6
6
|
</div>
|
|
7
7
|
<% else %>
|
|
8
|
-
<div class="
|
|
9
|
-
<%=
|
|
8
|
+
<div class="h-full overflow-x-hidden">
|
|
9
|
+
<%= lookbook_render "params/editor", inputs: Lookbook::Params.inputs do |editor| %>
|
|
10
10
|
<% preview.params.each do |param| %>
|
|
11
11
|
<% editor.field **param, value: params[param[:name]] %>
|
|
12
12
|
<% end %>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<div class="h-full">
|
|
2
2
|
<% if examples.many? %>
|
|
3
|
-
<%=
|
|
3
|
+
<%= lookbook_render :code, language: examples.first.source_lang[:name], line_numbers: true, full_height: true do -%>
|
|
4
4
|
<%- examples.each.with_index(1) do |example, i| -%>
|
|
5
5
|
<%== "#{sprintf example.source_lang[:comment], example.label}\n#{example.source}\n#{"\n" if i < examples.size}" %><% end %>
|
|
6
6
|
<% end %>
|
|
7
7
|
<% else %>
|
|
8
8
|
<% example = examples.first %>
|
|
9
|
-
<%=
|
|
9
|
+
<%= lookbook_render :code, language: example.source_lang[:name], line_numbers: true, full_height: true do %><%== example.source %><% end %>
|
|
10
10
|
<% end %>
|
|
11
11
|
</div>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<%=
|
|
1
|
+
<%= lookbook_render :split_layout,
|
|
2
2
|
alpine_data: "$store.layout.inspector",
|
|
3
3
|
":class": "($store.inspector.drawer.hidden || #{@drawer_panels.none?}) && '!grid-rows-[1fr] !grid-cols-[1fr]'" do |layout| %>
|
|
4
4
|
|
|
5
5
|
<%= layout.pane class: "flex flex-col h-full overflow-hidden",
|
|
6
6
|
"x-effect": "forceOrientation = (layoutWidth < $store.inspector.minVerticalSplitWidth) ? 'horizontal' : null" do %>
|
|
7
7
|
|
|
8
|
-
<%=
|
|
8
|
+
<%= lookbook_render :toolbar do |toolbar| %>
|
|
9
9
|
<% toolbar.section ":class": "layoutResizing && 'overflow-hidden'" do %>
|
|
10
|
-
<%=
|
|
10
|
+
<%= lookbook_render :tabs, alpine_data: "$store.inspector.main" do |tabs| %>
|
|
11
11
|
<%= @main_panels.each do |panel| %>
|
|
12
12
|
<% tabs.tab name: panel.name,
|
|
13
13
|
label: panel.label,
|
|
@@ -17,19 +17,13 @@
|
|
|
17
17
|
<% end %>
|
|
18
18
|
<% end %>
|
|
19
19
|
|
|
20
|
-
<% toolbar.section
|
|
21
|
-
<%=
|
|
22
|
-
target: "[data-component=viewport] iframe",
|
|
23
|
-
class: "ml-auto opacity-30 hover:opacity-100" %>
|
|
24
|
-
<% end %>
|
|
25
|
-
|
|
26
|
-
<% toolbar.section divide: :left, class: "flex-none relative z-10" do %>
|
|
27
|
-
<%= render_component :button_group do |group| %>
|
|
20
|
+
<% toolbar.section divide: :left, align: :right, class: "flex-none relative z-10" do %>
|
|
21
|
+
<%= lookbook_render :button_group do |group| %>
|
|
28
22
|
<% if @pages.any? %>
|
|
29
23
|
<% group.button icon: :code,
|
|
30
24
|
tooltip: "Copy page embed code",
|
|
31
25
|
copy: true do %>
|
|
32
|
-
<%= embed <%= @preview.
|
|
26
|
+
<%= embed <%= @preview.preview_class_name %>, :<%= @target.name %>, params: <%= request.query_parameters.deep_symbolize_keys.to_s %> %>
|
|
33
27
|
<% end %>
|
|
34
28
|
<% end %>
|
|
35
29
|
|
|
@@ -53,7 +47,7 @@
|
|
|
53
47
|
<% end %>
|
|
54
48
|
|
|
55
49
|
<div class="h-full relative overflow-auto">
|
|
56
|
-
<%=
|
|
50
|
+
<%= lookbook_render :tab_panels, alpine_data: "$store.inspector.main" do |tabs| %>
|
|
57
51
|
<% @main_panels.each do |panel| %>
|
|
58
52
|
<% tabs.panel id: panel.id, name: panel.name, class: panel.panel_classes do %>
|
|
59
53
|
<%= render panel.partial, **@inspector_data, panel: panel, **panel.locals %>
|
|
@@ -66,9 +60,9 @@
|
|
|
66
60
|
<%= layout.pane class: "flex flex-col h-full overflow-hidden bg-lookbook-drawer-bg",
|
|
67
61
|
"x-show": "!$store.inspector.drawer.hidden && #{@drawer_panels.any?}" do %>
|
|
68
62
|
|
|
69
|
-
<%=
|
|
63
|
+
<%= lookbook_render :toolbar do |toolbar| %>
|
|
70
64
|
<% toolbar.section ":class": "layoutResizing && 'overflow-hidden'" do %>
|
|
71
|
-
<%=
|
|
65
|
+
<%= lookbook_render :tabs, alpine_data: "$store.inspector.drawer" do |tabs| %>
|
|
72
66
|
<%= @drawer_panels.each do |panel| %>
|
|
73
67
|
<% tabs.tab name: panel.name,
|
|
74
68
|
label: panel.label,
|
|
@@ -79,7 +73,7 @@
|
|
|
79
73
|
<% end %>
|
|
80
74
|
|
|
81
75
|
<% toolbar.section align: :right, class: "flex-none relative z-10" do %>
|
|
82
|
-
<%=
|
|
76
|
+
<%= lookbook_render :button_group do |group| %>
|
|
83
77
|
<%= @drawer_panels.select { |p| !p.disabled && p.copy }.each do |panel| %>
|
|
84
78
|
<% group.button icon: :copy,
|
|
85
79
|
tooltip: "Copy panel contents",
|
|
@@ -93,7 +87,7 @@
|
|
|
93
87
|
<% end %>
|
|
94
88
|
|
|
95
89
|
<% toolbar.section divide: :left, class: "flex-none relative z-10" do %>
|
|
96
|
-
<%=
|
|
90
|
+
<%= lookbook_render :button_group do |group| %>
|
|
97
91
|
|
|
98
92
|
<% group.button icon: :corner_up_right,
|
|
99
93
|
tooltip: "Move drawer to right",
|
|
@@ -121,10 +115,10 @@
|
|
|
121
115
|
<% end %>
|
|
122
116
|
|
|
123
117
|
<div class="h-full overflow-auto">
|
|
124
|
-
<%=
|
|
118
|
+
<%= lookbook_render :tab_panels, alpine_data: "$store.inspector.drawer" do |tabs| %>
|
|
125
119
|
<% @drawer_panels.each do |panel| %>
|
|
126
120
|
<% tabs.panel id: panel.id, name: panel.name, class: panel.panel_classes do %>
|
|
127
|
-
<%=
|
|
121
|
+
<%= lookbook_render :inspector_panel, **panel.slice(:id, :name, :system) do %>
|
|
128
122
|
<%= render panel.partial, **@inspector_data, panel: panel, **panel.locals %>
|
|
129
123
|
<% end %>
|
|
130
124
|
<% end %>
|
data/lib/lookbook/config.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Lookbook
|
|
|
10
10
|
@options.set({
|
|
11
11
|
project_name: "Lookbook",
|
|
12
12
|
log_level: 2,
|
|
13
|
+
log_use_rails_logger: true,
|
|
13
14
|
auto_refresh: true,
|
|
14
15
|
|
|
15
16
|
components_path: "app/components",
|
|
@@ -25,6 +26,21 @@ module Lookbook
|
|
|
25
26
|
preview_srcdoc: nil,
|
|
26
27
|
preview_tags: {},
|
|
27
28
|
preview_disable_action_view_annotations: true,
|
|
29
|
+
preview_param_inputs: {
|
|
30
|
+
select: "lookbook/previews/inputs/select",
|
|
31
|
+
textarea: "lookbook/previews/inputs/textarea",
|
|
32
|
+
toggle: "lookbook/previews/inputs/toggle",
|
|
33
|
+
color: "lookbook/previews/inputs/color",
|
|
34
|
+
range: "lookbook/previews/inputs/range",
|
|
35
|
+
text: "lookbook/previews/inputs/text",
|
|
36
|
+
email: "lookbook/previews/inputs/text",
|
|
37
|
+
number: "lookbook/previews/inputs/text",
|
|
38
|
+
tel: "lookbook/previews/inputs/text",
|
|
39
|
+
url: "lookbook/previews/inputs/text",
|
|
40
|
+
date: "lookbook/previews/inputs/text",
|
|
41
|
+
datetime_local: "lookbook/previews/inputs/text"
|
|
42
|
+
},
|
|
43
|
+
preview_params_options_eval: false,
|
|
28
44
|
sort_examples: false,
|
|
29
45
|
|
|
30
46
|
listen: Rails.env.development?,
|
|
@@ -33,7 +49,6 @@ module Lookbook
|
|
|
33
49
|
listen_use_polling: false,
|
|
34
50
|
|
|
35
51
|
cable_mount_path: "/cable",
|
|
36
|
-
cable_logger: Lookbook.logger,
|
|
37
52
|
|
|
38
53
|
parser_registry_path: "tmp/storage/.yardoc",
|
|
39
54
|
|
data/lib/lookbook/engine.rb
CHANGED
|
@@ -28,7 +28,13 @@ module Lookbook
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def logger
|
|
31
|
-
@logger ||= Rails.
|
|
31
|
+
@logger ||= if Rails.logger.present? && config.log_use_rails_logger
|
|
32
|
+
Rails.logger
|
|
33
|
+
else
|
|
34
|
+
logger = Logger.new($stdout)
|
|
35
|
+
logger.level = config.log_level
|
|
36
|
+
logger
|
|
37
|
+
end
|
|
32
38
|
end
|
|
33
39
|
|
|
34
40
|
def debug_data
|
|
@@ -54,6 +60,13 @@ module Lookbook
|
|
|
54
60
|
def theme
|
|
55
61
|
@theme ||= Lookbook::Theme.new(config.ui_theme, config.ui_theme_overrides)
|
|
56
62
|
end
|
|
63
|
+
|
|
64
|
+
def define_param_input(input, partial, input_options = nil)
|
|
65
|
+
config.preview_param_inputs[input.to_sym] = {
|
|
66
|
+
partial: partial,
|
|
67
|
+
input_options: input_options || {}
|
|
68
|
+
}
|
|
69
|
+
end
|
|
57
70
|
end
|
|
58
71
|
|
|
59
72
|
class Engine < Rails::Engine
|
|
@@ -72,10 +85,6 @@ module Lookbook
|
|
|
72
85
|
config.lookbook.listen_paths << config.lookbook.components_path
|
|
73
86
|
end
|
|
74
87
|
|
|
75
|
-
initializer "lookbook.logging.development" do
|
|
76
|
-
Lookbook.logger.level = Lookbook.config.log_level if Rails.env.development?
|
|
77
|
-
end
|
|
78
|
-
|
|
79
88
|
initializer "lookbook.parser.tags" do
|
|
80
89
|
Lookbook::Parser.define_tags(Lookbook.config.preview_tags)
|
|
81
90
|
end
|
|
@@ -131,6 +140,7 @@ module Lookbook
|
|
|
131
140
|
if listen_paths.any?
|
|
132
141
|
preview_listener = Listen.to(*listen_paths,
|
|
133
142
|
only: /\.(#{config.listen_extensions.join("|")})$/,
|
|
143
|
+
wait_for_delay: 0.5,
|
|
134
144
|
force_polling: config.listen_use_polling) do |modified, added, removed|
|
|
135
145
|
parser.parse do
|
|
136
146
|
run_hooks(:after_change, {modified: modified, added: added, removed: removed})
|
|
@@ -162,7 +172,7 @@ module Lookbook
|
|
|
162
172
|
cable.cable = {adapter: "async"}.with_indifferent_access
|
|
163
173
|
cable.mount_path = nil
|
|
164
174
|
cable.connection_class = -> { Lookbook::Connection }
|
|
165
|
-
cable.logger =
|
|
175
|
+
cable.logger = Lookbook.logger
|
|
166
176
|
|
|
167
177
|
@websocket ||= if Gem::Version.new(Rails.version) >= Gem::Version.new(6.0)
|
|
168
178
|
ActionCable::Server::Base.new(config: cable)
|
data/lib/lookbook/markdown.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Lookbook
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
def self.render(text)
|
|
16
|
-
|
|
16
|
+
Utils.strip_action_view_annotations!(text)
|
|
17
17
|
markdown = Redcarpet::Markdown.new(Renderer, Lookbook.config.markdown_options)
|
|
18
18
|
markdown.render(text).html_safe
|
|
19
19
|
end
|
data/lib/lookbook/panels.rb
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
module Lookbook
|
|
2
2
|
module Panels
|
|
3
|
-
def define_panel(name,
|
|
4
|
-
Lookbook.config.define_inspector_panel(name,
|
|
3
|
+
def define_panel(name, *args)
|
|
4
|
+
Lookbook.config.define_inspector_panel(name, extract_opts(args))
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
def amend_panel(name,
|
|
8
|
-
Lookbook.amend_inspector_panel(name,
|
|
7
|
+
def amend_panel(name, *args)
|
|
8
|
+
Lookbook.amend_inspector_panel(name, extract_opts(args))
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def remove_panel(name)
|
|
12
12
|
Lookbook.remove_inspector_panel(name)
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
def extract_opts(args)
|
|
16
|
+
if args.many?
|
|
17
|
+
opts = args[1]
|
|
18
|
+
opts[:partial] = args[0]
|
|
19
|
+
opts
|
|
20
|
+
elsif args.any?
|
|
21
|
+
args[0].is_a?(String) ? {partial: args[0]} : args[0]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
14
24
|
end
|
|
15
25
|
end
|
data/lib/lookbook/params.rb
CHANGED
|
@@ -2,32 +2,68 @@ require "active_model"
|
|
|
2
2
|
|
|
3
3
|
module Lookbook
|
|
4
4
|
module Params
|
|
5
|
+
VALUE_TYPE_MATCH_REGEXP = /^(\[\s?([A-Z]{1}\w+)\s?\])/
|
|
6
|
+
DESCRIPTION_MATCH_REGEXP = /"(.*[^\\])"$/
|
|
7
|
+
|
|
8
|
+
PARAM_OPTION_KEYS = %i[name input label hint description value_type value_default].freeze
|
|
9
|
+
|
|
5
10
|
class << self
|
|
6
|
-
def build_param(param, default: nil,
|
|
7
|
-
input, options_str = param.text
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
YAML.safe_load(options_str || "~")
|
|
11
|
+
def build_param(param, default: nil, eval_scope: nil)
|
|
12
|
+
input, value_type, options_str, description = parse_param_tag_text(param.text)
|
|
13
|
+
|
|
14
|
+
tag_options = Lookbook::TagOptions.new(options_str,
|
|
15
|
+
base_dir: (File.dirname(param.object.files.first[0]) if param.object.files.any?),
|
|
16
|
+
eval_scope: eval_scope).options
|
|
17
|
+
|
|
18
|
+
if tag_options.is_a? Array
|
|
19
|
+
# handle special case legacy situation for selects where
|
|
20
|
+
# options are an array of choices rather than a Hash
|
|
21
|
+
tag_options = {choices: tag_options}
|
|
18
22
|
end
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
|
|
24
|
+
param_options = tag_options.select { |key| PARAM_OPTION_KEYS.include? key }
|
|
25
|
+
input_options = tag_options.except(*PARAM_OPTION_KEYS)
|
|
26
|
+
|
|
27
|
+
value_type ||= param_options[:value_type]
|
|
28
|
+
input ||= param_options[:input] || guess_input(value_type, default)
|
|
29
|
+
name = param.name.to_s
|
|
30
|
+
|
|
21
31
|
{
|
|
22
|
-
name:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
name: name,
|
|
33
|
+
label: param_options[:label] || name.titleize,
|
|
34
|
+
hint: param_options[:hint],
|
|
35
|
+
description: description || param_options[:description],
|
|
36
|
+
input: input.to_s.tr("_", "-"),
|
|
37
|
+
input_options: input_options,
|
|
38
|
+
value: nil,
|
|
39
|
+
value_type: value_type || guess_value_type(input, default),
|
|
40
|
+
value_default: default
|
|
28
41
|
}
|
|
29
42
|
end
|
|
30
43
|
|
|
44
|
+
# Parses param tag strings with the format: `[<value_type>] <input> <description?> <opts?>`
|
|
45
|
+
def parse_param_tag_text(text)
|
|
46
|
+
text = (text.presence || "").strip
|
|
47
|
+
|
|
48
|
+
value_type = nil
|
|
49
|
+
text.match(VALUE_TYPE_MATCH_REGEXP) do |m|
|
|
50
|
+
value_type = m[2]
|
|
51
|
+
text.gsub!(VALUE_TYPE_MATCH_REGEXP, "").strip!
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
text, options_str = Lookbook::TagOptions.extract_options(text)
|
|
55
|
+
|
|
56
|
+
description = nil
|
|
57
|
+
text.match(DESCRIPTION_MATCH_REGEXP) do |m|
|
|
58
|
+
description = m[1]
|
|
59
|
+
text.gsub!(DESCRIPTION_MATCH_REGEXP, "").strip!
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
input, rest = text.split(" ", 2)
|
|
63
|
+
|
|
64
|
+
[input, value_type, options_str, description, rest]
|
|
65
|
+
end
|
|
66
|
+
|
|
31
67
|
def parse_method_param_str(param_str)
|
|
32
68
|
return nil if param_str[0].nil? || param_str[1].nil?
|
|
33
69
|
name = param_str[0].chomp(":")
|
|
@@ -81,17 +117,24 @@ module Lookbook
|
|
|
81
117
|
end
|
|
82
118
|
end
|
|
83
119
|
|
|
120
|
+
def inputs
|
|
121
|
+
@inputs ||= Lookbook.config.preview_param_inputs.map do |name, config|
|
|
122
|
+
config = {partial: config} if config.is_a?(String)
|
|
123
|
+
[name, {input_options: {}}.merge(config)]
|
|
124
|
+
end.to_h
|
|
125
|
+
end
|
|
126
|
+
|
|
84
127
|
private
|
|
85
128
|
|
|
86
|
-
def guess_input(
|
|
87
|
-
if
|
|
129
|
+
def guess_input(value_type, default)
|
|
130
|
+
if value_type&.downcase == "boolean" || (value_type.blank? && boolean?(default))
|
|
88
131
|
"toggle"
|
|
89
132
|
else
|
|
90
133
|
"text"
|
|
91
134
|
end
|
|
92
135
|
end
|
|
93
136
|
|
|
94
|
-
def
|
|
137
|
+
def guess_value_type(input, default)
|
|
95
138
|
if input&.downcase == "toggle"
|
|
96
139
|
"Boolean"
|
|
97
140
|
elsif input&.downcase == "number"
|
|
@@ -107,18 +150,6 @@ module Lookbook
|
|
|
107
150
|
end
|
|
108
151
|
end
|
|
109
152
|
|
|
110
|
-
def input_text?(input)
|
|
111
|
-
[
|
|
112
|
-
"date",
|
|
113
|
-
"datetime-local",
|
|
114
|
-
"email",
|
|
115
|
-
"number",
|
|
116
|
-
"tel",
|
|
117
|
-
"text",
|
|
118
|
-
"url"
|
|
119
|
-
].include? input.to_s
|
|
120
|
-
end
|
|
121
|
-
|
|
122
153
|
def safe_parse_yaml(value, fallback)
|
|
123
154
|
value.present? ? YAML.safe_load(value) : fallback
|
|
124
155
|
rescue Psych::SyntaxError
|
data/lib/lookbook/parser.rb
CHANGED
|
@@ -39,6 +39,7 @@ module Lookbook
|
|
|
39
39
|
YARD::Tags::Library.define_tag("Position", :position)
|
|
40
40
|
YARD::Tags::Library.define_tag("ID", :id)
|
|
41
41
|
YARD::Tags::Library.define_tag("Component", :component)
|
|
42
|
+
YARD::Tags::Library.define_tag("Param", :param, :with_name)
|
|
42
43
|
custom.each do |name, opts|
|
|
43
44
|
YARD::Tags::Library.define_tag(name.to_s.titleize, name)
|
|
44
45
|
end
|
data/lib/lookbook/preview.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Lookbook
|
|
|
7
7
|
|
|
8
8
|
def initialize(preview, code_object)
|
|
9
9
|
@preview = preview
|
|
10
|
-
@preview_inspector = SourceInspector.new(code_object)
|
|
10
|
+
@preview_inspector = SourceInspector.new(code_object, eval_scope: preview_class.new)
|
|
11
11
|
super(preview_class_path(@preview.name))
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -15,10 +15,14 @@ module Lookbook
|
|
|
15
15
|
@preview_inspector&.id || generate_id(lookup_path)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def preview_class_name
|
|
19
19
|
@preview.name
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
def preview_class
|
|
23
|
+
@preview
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
def label
|
|
23
27
|
@preview_inspector&.label&.presence || lookup_path.split("/").last.titleize
|
|
24
28
|
end
|
|
@@ -143,10 +147,12 @@ module Lookbook
|
|
|
143
147
|
|
|
144
148
|
sorted_previews = previews.compact.sort_by { |preview| [preview.position, preview.label] }
|
|
145
149
|
@previews = PreviewCollection.new(sorted_previews)
|
|
146
|
-
|
|
150
|
+
@previews
|
|
151
|
+
elsif !@preview_objects.present?
|
|
147
152
|
PreviewCollection.new([])
|
|
153
|
+
else
|
|
154
|
+
@previews
|
|
148
155
|
end
|
|
149
|
-
@previews
|
|
150
156
|
end
|
|
151
157
|
|
|
152
158
|
def errors
|
|
@@ -12,32 +12,20 @@ module Lookbook
|
|
|
12
12
|
opts[:layout] = nil
|
|
13
13
|
opts[:locals] = locals if locals.present?
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Utils.with_optional_action_view_annotations do
|
|
16
16
|
render html: render_to_string(template, **opts)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def render_in_layout_to_string(template, locals, opts = {})
|
|
21
21
|
append_view_path Lookbook::Engine.root.join("app/views")
|
|
22
|
-
html = render_to_string(template, locals: locals, **determine_layout(opts[:layout]))
|
|
23
|
-
if opts[:append_html].present?
|
|
24
|
-
html += opts[:append_html]
|
|
25
|
-
end
|
|
26
|
-
render html: html
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def with_optional_annotations
|
|
30
|
-
if ActionView::Base.respond_to?(:annotate_rendered_view_with_filenames) && Lookbook.config.preview_disable_action_view_annotations
|
|
31
|
-
original_value = ActionView::Base.annotate_rendered_view_with_filenames
|
|
32
|
-
ActionView::Base.annotate_rendered_view_with_filenames = false
|
|
33
|
-
|
|
34
|
-
res = yield
|
|
35
|
-
|
|
36
|
-
ActionView::Base.annotate_rendered_view_with_filenames = original_value
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
23
|
+
Utils.with_optional_action_view_annotations do
|
|
24
|
+
html = render_to_string(template, locals: locals, **determine_layout(opts[:layout]))
|
|
25
|
+
if opts[:append_html].present?
|
|
26
|
+
html += opts[:append_html]
|
|
27
|
+
end
|
|
28
|
+
render html: html
|
|
41
29
|
end
|
|
42
30
|
end
|
|
43
31
|
end
|
|
@@ -6,7 +6,7 @@ module Lookbook
|
|
|
6
6
|
def initialize(name, preview, code_object)
|
|
7
7
|
@name = name
|
|
8
8
|
@preview = preview
|
|
9
|
-
@example_inspector = SourceInspector.new(code_object)
|
|
9
|
+
@example_inspector = SourceInspector.new(code_object, eval_scope: @preview.preview_class.new)
|
|
10
10
|
super("#{@preview.path}/#{name}")
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -5,8 +5,9 @@ module Lookbook
|
|
|
5
5
|
attr_reader :code_object
|
|
6
6
|
delegate :groups, :source, to: :@code_object, allow_nil: true
|
|
7
7
|
|
|
8
|
-
def initialize(code_object)
|
|
8
|
+
def initialize(code_object, eval_scope: nil)
|
|
9
9
|
@code_object = code_object
|
|
10
|
+
@eval_scope = eval_scope
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def hidden?
|
|
@@ -74,8 +75,11 @@ module Lookbook
|
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
def params
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
@params ||= {}
|
|
79
|
+
@params[:param] ||= code_object&.tags("param")&.map do |param|
|
|
80
|
+
Lookbook::Params.build_param(param,
|
|
81
|
+
default: parameter_defaults[param.name],
|
|
82
|
+
eval_scope: @eval_scope)
|
|
79
83
|
end
|
|
80
84
|
end
|
|
81
85
|
|
|
@@ -85,7 +89,9 @@ module Lookbook
|
|
|
85
89
|
|
|
86
90
|
def tags(name = nil)
|
|
87
91
|
tag_objects = code_object&.tags(name).presence || []
|
|
88
|
-
Lookbook::Tags.process_tags(tag_objects
|
|
92
|
+
Lookbook::Tags.process_tags(tag_objects,
|
|
93
|
+
eval_scope: @eval_scope,
|
|
94
|
+
file: (code_object.files.first[0] if code_object.files.any?))
|
|
89
95
|
end
|
|
90
96
|
|
|
91
97
|
def tag(name = nil)
|
data/lib/lookbook/tag.rb
CHANGED
|
@@ -5,13 +5,15 @@ module Lookbook
|
|
|
5
5
|
attr_reader :data, :arg_names
|
|
6
6
|
attr_accessor :args, :opts
|
|
7
7
|
|
|
8
|
-
def initialize(tag_object, arg_names = nil, parser: nil, **options)
|
|
8
|
+
def initialize(tag_object, arg_names = nil, parser: nil, eval_scope: nil, file: nil, **options)
|
|
9
9
|
@tag_object = tag_object
|
|
10
10
|
@arg_names = arg_names
|
|
11
11
|
@args = {}
|
|
12
12
|
@opts = {}
|
|
13
13
|
@options = options
|
|
14
14
|
@parser = parser
|
|
15
|
+
@eval_scope = eval_scope
|
|
16
|
+
@file = file
|
|
15
17
|
@data = Store.new
|
|
16
18
|
run_parser
|
|
17
19
|
end
|
|
@@ -43,8 +45,16 @@ module Lookbook
|
|
|
43
45
|
|
|
44
46
|
def parse_opts
|
|
45
47
|
return @opts if @options[:parse_options] == false
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
tag_opts = Lookbook::TagOptions.new(opts_str,
|
|
49
|
+
eval_scope: @eval_scope,
|
|
50
|
+
base_dir: File.dirname(@file))
|
|
51
|
+
options = tag_opts.resolve || {}
|
|
52
|
+
@opts = if options.is_a?(Hash)
|
|
53
|
+
options.with_indifferent_access
|
|
54
|
+
else
|
|
55
|
+
Lookbook.logger.warn "'@#{tag_name}' tag options should resolve to a Hash"
|
|
56
|
+
options
|
|
57
|
+
end
|
|
48
58
|
end
|
|
49
59
|
|
|
50
60
|
def run_parser
|