lookbook 1.0.7 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +17 -1
- data/lib/lookbook/engine.rb +17 -7
- 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 +11 -5
- data/lib/lookbook/preview_example.rb +2 -2
- 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 +772 -687
- 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",
|
@@ -24,6 +25,22 @@ module Lookbook
|
|
24
25
|
preview_display_params: {},
|
25
26
|
preview_srcdoc: nil,
|
26
27
|
preview_tags: {},
|
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,
|
27
44
|
sort_examples: false,
|
28
45
|
|
29
46
|
listen: Rails.env.development?,
|
@@ -32,7 +49,6 @@ module Lookbook
|
|
32
49
|
listen_use_polling: false,
|
33
50
|
|
34
51
|
cable_mount_path: "/cable",
|
35
|
-
cable_logger: Lookbook.logger,
|
36
52
|
|
37
53
|
parser_registry_path: "tmp/storage/.yardoc",
|
38
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)
|
@@ -174,7 +184,7 @@ module Lookbook
|
|
174
184
|
end
|
175
185
|
|
176
186
|
def websocket_mount_path
|
177
|
-
"#{mounted_path}#{config.lookbook.cable_mount_path}" if websocket?
|
187
|
+
"#{mounted_path}#{config.lookbook.cable_mount_path}".gsub("//", "/") if websocket?
|
178
188
|
end
|
179
189
|
|
180
190
|
def websocket?
|
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
|
@@ -11,16 +11,22 @@ module Lookbook
|
|
11
11
|
opts = {}
|
12
12
|
opts[:layout] = nil
|
13
13
|
opts[:locals] = locals if locals.present?
|
14
|
-
|
14
|
+
|
15
|
+
Utils.with_optional_action_view_annotations do
|
16
|
+
render html: render_to_string(template, **opts)
|
17
|
+
end
|
15
18
|
end
|
16
19
|
|
17
20
|
def render_in_layout_to_string(template, locals, opts = {})
|
18
21
|
append_view_path Lookbook::Engine.root.join("app/views")
|
19
|
-
|
20
|
-
|
21
|
-
html
|
22
|
+
|
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
|
22
29
|
end
|
23
|
-
render html: html
|
24
30
|
end
|
25
31
|
end
|
26
32
|
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
|
|
@@ -27,7 +27,7 @@ module Lookbook
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def method_source
|
30
|
-
@example_inspector.source.split("\n")[
|
30
|
+
@example_inspector.source.sub(/^def \w+\s?(\([^)]+\))?/m, "").split("\n")[0..-2].join("\n").strip_heredoc.strip
|
31
31
|
end
|
32
32
|
|
33
33
|
def lang
|
@@ -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
|