lookbook 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +47 -14
- data/app/components/lookbook/code/component.html.erb +1 -1
- data/app/components/lookbook/inspector_panel/component.rb +3 -5
- data/app/components/lookbook/nav/item/component.html.erb +1 -1
- data/app/components/lookbook/params/editor/component.rb +3 -10
- data/app/components/lookbook/params/field/component.html.erb +8 -8
- data/app/components/lookbook/params/field/component.rb +21 -72
- data/app/controllers/concerns/lookbook/targetable_concern.rb +156 -0
- data/app/controllers/concerns/lookbook/with_preview_controller_concern.rb +13 -0
- data/app/controllers/lookbook/application_controller.rb +13 -3
- data/app/controllers/lookbook/inspector_controller.rb +45 -0
- data/app/controllers/lookbook/page_controller.rb +11 -7
- data/app/controllers/lookbook/previews_controller.rb +4 -210
- data/app/helpers/lookbook/output_helper.rb +5 -5
- data/app/views/layouts/lookbook/skeleton.html.erb +3 -3
- data/app/views/lookbook/index.html.erb +12 -1
- data/app/views/lookbook/{previews → inspector}/inputs/_color.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_range.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_select.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_text.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_textarea.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_toggle.html.erb +3 -3
- data/app/views/lookbook/{previews → inspector}/panels/_content.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/panels/_notes.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/panels/_output.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/panels/_params.html.erb +4 -4
- data/app/views/lookbook/{previews → inspector}/panels/_preview.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/panels/_source.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/show.html.erb +4 -1
- data/config/app.yml +8 -1
- data/config/inputs.yml +12 -12
- data/config/panels.yml +5 -5
- data/config/routes.rb +5 -5
- data/config/tags.yml +4 -1
- data/lib/lookbook/engine.rb +101 -150
- data/lib/lookbook/file_watcher.rb +47 -0
- data/lib/lookbook/page.rb +15 -16
- data/lib/lookbook/param.rb +99 -0
- data/lib/lookbook/preview.rb +8 -1
- data/lib/lookbook/{preview_controller.rb → preview_actions.rb} +14 -3
- data/lib/lookbook/preview_example.rb +1 -1
- data/lib/lookbook/preview_group.rb +0 -4
- data/lib/lookbook/preview_parser.rb +53 -0
- data/lib/lookbook/process.rb +21 -0
- data/lib/lookbook/services/code/code_beautifier.rb +21 -0
- data/lib/lookbook/services/code/code_highlighter.rb +69 -0
- data/lib/lookbook/services/data/parsers/data_parser.rb +22 -0
- data/lib/lookbook/services/data/parsers/json_parser.rb +7 -0
- data/lib/lookbook/services/data/parsers/yaml_parser.rb +7 -0
- data/lib/lookbook/services/data/resolvers/data_resolver.rb +70 -0
- data/lib/lookbook/services/data/resolvers/eval_resolver.rb +10 -0
- data/lib/lookbook/services/data/resolvers/file_resolver.rb +28 -0
- data/lib/lookbook/services/data/resolvers/method_resolver.rb +10 -0
- data/lib/lookbook/services/data/resolvers/yaml_resolver.rb +18 -0
- data/lib/lookbook/services/markdown_renderer.rb +29 -0
- data/lib/lookbook/services/string_value_caster.rb +60 -0
- data/lib/lookbook/services/tags/tag_options_parser.rb +62 -0
- data/lib/lookbook/services/templates/action_view_annotations_handler.rb +21 -0
- data/lib/lookbook/services/templates/action_view_annotations_stripper.rb +15 -0
- data/lib/lookbook/services/templates/frontmatter_extractor.rb +28 -0
- data/lib/lookbook/services/templates/styles_extractor.rb +38 -0
- data/lib/lookbook/services/{search_param_builder.rb → urls/search_param_builder.rb} +1 -1
- data/lib/lookbook/services/{search_param_parser.rb → urls/search_param_parser.rb} +1 -1
- data/lib/lookbook/source_inspector.rb +26 -45
- data/lib/lookbook/stores/config_store.rb +7 -8
- data/lib/lookbook/stores/input_store.rb +7 -3
- data/lib/lookbook/stores/tag_store.rb +3 -5
- data/lib/lookbook/support/null_object.rb +10 -0
- data/lib/lookbook/support/service.rb +2 -2
- data/lib/lookbook/support/store.rb +1 -1
- data/lib/lookbook/support/utils/attribute_utils.rb +6 -1
- data/lib/lookbook/support/utils/path_utils.rb +6 -3
- data/lib/lookbook/tags/component_tag.rb +7 -0
- data/lib/lookbook/tags/custom_tag.rb +59 -0
- data/lib/lookbook/tags/display_tag.rb +15 -0
- data/lib/lookbook/tags/hidden_tag.rb +13 -0
- data/lib/lookbook/tags/id_tag.rb +7 -0
- data/lib/lookbook/tags/label_tag.rb +4 -0
- data/lib/lookbook/tags/logical_path.rb +4 -0
- data/lib/lookbook/tags/param_tag.rb +61 -0
- data/lib/lookbook/tags/position_tag.rb +16 -0
- data/lib/lookbook/tags/tag_provider.rb +18 -0
- data/lib/lookbook/tags/yard_tag.rb +62 -0
- data/lib/lookbook/utils.rb +0 -40
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook/websocket.rb +60 -0
- data/lib/lookbook.rb +2 -1
- data/public/lookbook-assets/css/lookbook.css +30 -77
- data/public/lookbook-assets/css/lookbook.css.map +1 -1
- data/public/lookbook-assets/js/lookbook.js +7 -2
- data/public/lookbook-assets/js/lookbook.js.map +1 -1
- metadata +55 -26
- data/lib/lookbook/code_formatter.rb +0 -68
- data/lib/lookbook/markdown.rb +0 -22
- data/lib/lookbook/params.rb +0 -157
- data/lib/lookbook/parser.rb +0 -42
- data/lib/lookbook/tag.rb +0 -122
- data/lib/lookbook/tag_options.rb +0 -111
- data/lib/lookbook/tags.rb +0 -17
- data/lib/lookbook/template_parser.rb +0 -72
data/lib/lookbook/engine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "view_component"
|
2
2
|
require "action_cable/engine"
|
3
3
|
require "listen"
|
4
|
+
require "yard"
|
4
5
|
|
5
6
|
module Lookbook
|
6
7
|
class Engine < Rails::Engine
|
@@ -8,18 +9,17 @@ module Lookbook
|
|
8
9
|
|
9
10
|
config.autoload_paths << File.expand_path(root.join("app/components"))
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
Lookbook.config.preview_controller ||= config.view_component.preview_controller
|
14
|
-
|
15
|
-
Lookbook.config.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present?
|
16
|
-
|
17
|
-
Lookbook.config.listen_paths += Lookbook.config.preview_paths
|
18
|
-
Lookbook.config.listen_paths << Lookbook.config.components_path
|
12
|
+
config.before_configuration do
|
13
|
+
config.lookbook = Lookbook.config
|
19
14
|
end
|
20
15
|
|
21
|
-
initializer "lookbook.
|
22
|
-
|
16
|
+
initializer "lookbook.viewcomponent.config_sync" do
|
17
|
+
opts.preview_paths += config.view_component.preview_paths
|
18
|
+
opts.preview_controller ||= config.view_component.preview_controller
|
19
|
+
|
20
|
+
if config.view_component.view_component_path.present?
|
21
|
+
opts.components_path = config.view_component.view_component_path
|
22
|
+
end
|
23
23
|
end
|
24
24
|
|
25
25
|
initializer "lookbook.assets.serve" do
|
@@ -29,178 +29,129 @@ module Lookbook
|
|
29
29
|
)
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
initializer "lookbook.file_watcher.paths" do
|
33
|
+
opts.listen_paths += opts.preview_paths
|
34
|
+
opts.listen_paths << opts.components_path
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
parser.after_parse do |registry|
|
41
|
-
Preview.load!(registry.all(:class))
|
42
|
-
reload_ui
|
43
|
-
end
|
44
|
-
|
45
|
-
if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1.3.1")
|
46
|
-
# Rails.application.server is only available for newer Rails versions
|
47
|
-
Rails.application.server do
|
48
|
-
init_listeners
|
49
|
-
end
|
50
|
-
else
|
51
|
-
# Fallback for older Rails versions - don't start listeners if running in a rake task.
|
52
|
-
unless prevent_listening?
|
53
|
-
init_listeners
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
parser.parse do
|
58
|
-
run_hooks(:after_initialize)
|
37
|
+
initializer "lookbook.file_watcher.previews" do
|
38
|
+
file_watcher.watch(opts.listen_paths, opts.listen_extensions, wait_for_delay: 0.5) do |changes|
|
39
|
+
parser.parse { run_hooks(:after_change, changes) }
|
59
40
|
end
|
60
41
|
end
|
61
42
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
43
|
+
initializer "lookbook.file_watcher.pages" do
|
44
|
+
file_watcher.watch(opts.page_paths, opts.page_extensions) do |changes|
|
45
|
+
self.class.websocket.broadcast(:reload)
|
46
|
+
run_hooks(:after_change, changes)
|
66
47
|
end
|
67
|
-
run_hooks(:before_exit)
|
68
48
|
end
|
69
49
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
listen_paths = PathUtils.normalize_all(config.listen_paths)
|
76
|
-
if listen_paths.any?
|
77
|
-
preview_listener = Listen.to(*listen_paths,
|
78
|
-
only: /\.(#{config.listen_extensions.join("|")})$/,
|
79
|
-
wait_for_delay: 0.5,
|
80
|
-
force_polling: config.listen_use_polling) do |modified, added, removed|
|
81
|
-
parser.parse do
|
82
|
-
run_hooks(:after_change, {modified: modified, added: added, removed: removed})
|
83
|
-
end
|
84
|
-
end
|
85
|
-
register_listener(preview_listener)
|
86
|
-
end
|
87
|
-
|
88
|
-
page_paths = PathUtils.normalize_all(config.page_paths)
|
89
|
-
if page_paths.any?
|
90
|
-
page_listener = Listen.to(*page_paths,
|
91
|
-
only: /\.(html.*|md.*)$/,
|
92
|
-
force_polling: config.listen_use_polling) do |modified, added, removed|
|
93
|
-
changes = {modified: modified, added: added, removed: removed}
|
94
|
-
reload_ui
|
95
|
-
run_hooks(:after_change, changes)
|
96
|
-
end
|
97
|
-
register_listener(page_listener)
|
98
|
-
end
|
50
|
+
initializer "lookbook.parser.preview_load_callback" do
|
51
|
+
parser.after_parse do |registry|
|
52
|
+
Preview.load!(registry.all(:class))
|
53
|
+
self.class.websocket.broadcast(:reload)
|
99
54
|
end
|
55
|
+
end
|
100
56
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
cable.logger = Lookbook.logger
|
112
|
-
|
113
|
-
@websocket ||= if Gem::Version.new(Rails.version) >= Gem::Version.new(6.0)
|
114
|
-
ActionCable::Server::Base.new(config: cable)
|
115
|
-
else
|
116
|
-
ws = ActionCable::Server::Base.new
|
117
|
-
ws.config = cable
|
118
|
-
ws
|
119
|
-
end
|
120
|
-
end
|
57
|
+
# The preview controller handles the rendering of individual previews.
|
58
|
+
#
|
59
|
+
# Lookbook injects some actions into whichever controller has been
|
60
|
+
# specified by the user in order to render previews within the context of
|
61
|
+
# the particular controller class instance so that any before_action/after_action
|
62
|
+
# callbacks will be correctly processed.
|
63
|
+
config.after_initialize do
|
64
|
+
@preview_controller = opts.preview_controller.constantize
|
65
|
+
@preview_controller.class_eval { include Lookbook::PreviewActions }
|
66
|
+
end
|
121
67
|
|
122
|
-
|
123
|
-
|
68
|
+
config.after_initialize do
|
69
|
+
if Rails.application.respond_to?(:server)
|
70
|
+
Rails.application.server { file_watcher.start if listen? }
|
71
|
+
elsif process.supports_listening?
|
72
|
+
file_watcher.start if listen?
|
124
73
|
end
|
74
|
+
end
|
125
75
|
|
126
|
-
|
127
|
-
|
128
|
-
|
76
|
+
config.after_initialize do
|
77
|
+
parser.parse { run_hooks(:after_initialize) }
|
78
|
+
end
|
129
79
|
|
130
|
-
|
131
|
-
|
132
|
-
|
80
|
+
def opts
|
81
|
+
Lookbook.config
|
82
|
+
end
|
133
83
|
|
134
|
-
|
135
|
-
|
136
|
-
|
84
|
+
def run_hooks(event_name, *args)
|
85
|
+
self.class.hooks.for_event(event_name).each do |hook|
|
86
|
+
hook.call(Lookbook, *args)
|
137
87
|
end
|
88
|
+
end
|
138
89
|
|
139
|
-
|
140
|
-
|
141
|
-
|
90
|
+
def parser
|
91
|
+
@parser ||= PreviewParser.new(opts.preview_paths, Engine.tags)
|
92
|
+
end
|
142
93
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
else
|
147
|
-
Rails.application.class.parent_name
|
148
|
-
end
|
149
|
-
name.underscore
|
150
|
-
end
|
94
|
+
def file_watcher
|
95
|
+
@file_watcher ||= FileWatcher.new(force_polling: opts.listen_use_polling)
|
96
|
+
end
|
151
97
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
98
|
+
def process
|
99
|
+
@process ||= Process.new(env: Rails.env)
|
100
|
+
end
|
156
101
|
|
157
|
-
|
158
|
-
|
159
|
-
|
102
|
+
def listen?
|
103
|
+
opts.listen && process.supports_listening?
|
104
|
+
end
|
160
105
|
|
161
|
-
|
162
|
-
|
163
|
-
|
106
|
+
def self.mount_path
|
107
|
+
routes.find_script_name({})
|
108
|
+
end
|
164
109
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
end
|
169
|
-
end
|
110
|
+
def self.mounted?
|
111
|
+
mount_path.present?
|
112
|
+
end
|
170
113
|
|
171
|
-
|
172
|
-
|
114
|
+
def self.app_name
|
115
|
+
name = if Rails.application.class.respond_to?(:module_parent_name)
|
116
|
+
Rails.application.class.module_parent_name
|
117
|
+
else
|
118
|
+
Rails.application.class.parent_name
|
173
119
|
end
|
120
|
+
name.underscore
|
121
|
+
end
|
174
122
|
|
175
|
-
|
176
|
-
|
123
|
+
def self.websocket
|
124
|
+
if mounted?
|
125
|
+
use_websocket = opts.auto_refresh && opts.listen && process.supports_listening?
|
126
|
+
@websocket ||= use_websocket ? Websocket.new(mount_path, logger: Lookbook.logger) : Websocket.noop
|
127
|
+
else
|
128
|
+
Websocket.noop
|
177
129
|
end
|
130
|
+
end
|
178
131
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
else
|
183
|
-
false
|
184
|
-
end
|
185
|
-
end
|
132
|
+
def self.panels
|
133
|
+
@panels ||= PanelStore.init_from_config
|
134
|
+
end
|
186
135
|
|
187
|
-
|
188
|
-
|
189
|
-
|
136
|
+
def self.inputs
|
137
|
+
@inputs ||= InputStore.init_from_config
|
138
|
+
end
|
190
139
|
|
191
|
-
|
192
|
-
|
193
|
-
|
140
|
+
def self.tags
|
141
|
+
@tags ||= TagStore.init_from_config
|
142
|
+
end
|
194
143
|
|
195
|
-
|
196
|
-
|
197
|
-
|
144
|
+
def self.hooks
|
145
|
+
@hooks ||= HookStore.init_from_config
|
146
|
+
end
|
198
147
|
|
199
|
-
|
200
|
-
|
201
|
-
|
148
|
+
def self.preview_controller
|
149
|
+
@preview_controller
|
150
|
+
end
|
202
151
|
|
203
|
-
|
152
|
+
at_exit do
|
153
|
+
file_watcher.stop
|
154
|
+
run_hooks(:before_exit)
|
204
155
|
end
|
205
156
|
end
|
206
157
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class FileWatcher
|
3
|
+
attr_reader :listeners, :force_polling
|
4
|
+
|
5
|
+
def initialize(force_polling: false)
|
6
|
+
@force_polling = force_polling
|
7
|
+
@listeners = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def watch(paths, extensions = ".*", opts = nil, &block)
|
11
|
+
paths = PathUtils.normalize_all(paths)
|
12
|
+
|
13
|
+
if paths.any?
|
14
|
+
opts = opts.to_h
|
15
|
+
opts[:only] = /\.(#{Array(extensions).join("|")})$/
|
16
|
+
|
17
|
+
listeners << init_listener(paths, opts, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
if listeners.any?
|
23
|
+
Lookbook.logger.debug "Starting listeners"
|
24
|
+
listeners.each { |l| l.start }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def stop
|
29
|
+
if listeners.any?
|
30
|
+
Lookbook.logger.debug "Stopping listeners"
|
31
|
+
listeners.each { |l| l.stop }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def init_listener(paths, opts, &block)
|
38
|
+
Listen.to(
|
39
|
+
*paths,
|
40
|
+
**opts,
|
41
|
+
force_polling: force_polling
|
42
|
+
) do |modified, added, removed|
|
43
|
+
block.call({modified: modified, added: added, removed: removed})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/lookbook/page.rb
CHANGED
@@ -13,7 +13,7 @@ module Lookbook
|
|
13
13
|
:data
|
14
14
|
]
|
15
15
|
|
16
|
-
attr_reader :errors, :rel_path
|
16
|
+
attr_reader :errors, :rel_path, :content, :frontmatter
|
17
17
|
attr_accessor :sections
|
18
18
|
|
19
19
|
def initialize(path, base_path)
|
@@ -22,9 +22,12 @@ module Lookbook
|
|
22
22
|
@options = nil
|
23
23
|
@errors = []
|
24
24
|
@sections = []
|
25
|
+
@frontmatter = {}
|
26
|
+
@content = ""
|
25
27
|
@page_name = remove_position_prefix(path_name)
|
26
28
|
@rel_path = @pathname.relative_path_from(@base_path)
|
27
29
|
page_path = @rel_path.dirname.to_s == "." ? @page_name : "#{@rel_path.dirname}/#{@page_name}"
|
30
|
+
extract_frontmatter(file_contents)
|
28
31
|
super(page_path)
|
29
32
|
end
|
30
33
|
|
@@ -60,10 +63,6 @@ module Lookbook
|
|
60
63
|
options[key]
|
61
64
|
end
|
62
65
|
|
63
|
-
def content
|
64
|
-
@content ||= strip_frontmatter(file_contents).strip
|
65
|
-
end
|
66
|
-
|
67
66
|
def matchers
|
68
67
|
normalize_matchers(label)
|
69
68
|
end
|
@@ -112,17 +111,6 @@ module Lookbook
|
|
112
111
|
|
113
112
|
def options
|
114
113
|
return @options if @options
|
115
|
-
begin
|
116
|
-
frontmatter = (get_frontmatter(file_contents) || {}).deep_symbolize_keys
|
117
|
-
rescue => exception
|
118
|
-
frontmatter = {}
|
119
|
-
line_number_match = exception.message.match(/.*line\s(\d+)/)
|
120
|
-
@errors.push(Lookbook::Error.new(exception, **{
|
121
|
-
title: "YAML frontmatter parsing error",
|
122
|
-
file_path: @pathname.to_s,
|
123
|
-
line_number: line_number_match ? line_number_match[1] : false
|
124
|
-
}))
|
125
|
-
end
|
126
114
|
@options = Lookbook.config.page_options.deep_merge(frontmatter).with_indifferent_access
|
127
115
|
@options[:id] = generate_id(@options[:id] || lookup_path)
|
128
116
|
@options[:label] ||= name.titleize
|
@@ -136,6 +124,17 @@ module Lookbook
|
|
136
124
|
@options
|
137
125
|
end
|
138
126
|
|
127
|
+
def extract_frontmatter(content)
|
128
|
+
@frontmatter, @content = FrontmatterExtractor.call(content)
|
129
|
+
rescue => exception
|
130
|
+
line_number_match = exception.message.match(/.*line\s(\d+)/)
|
131
|
+
@errors.push(Lookbook::Error.new(exception, **{
|
132
|
+
title: "YAML frontmatter parsing error",
|
133
|
+
file_path: @pathname.to_s,
|
134
|
+
line_number: line_number_match ? line_number_match[1] : false
|
135
|
+
}))
|
136
|
+
end
|
137
|
+
|
139
138
|
def path_name
|
140
139
|
@pathname.basename(@pathname.extname).to_s.gsub(/\.(html|md)$/, "")
|
141
140
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Param
|
3
|
+
attr_reader :name, :options, :value_default, :description
|
4
|
+
|
5
|
+
def initialize(name:, input: nil, description: nil, value_type: nil, value_default: nil, value: nil, options: {})
|
6
|
+
@name = name
|
7
|
+
@input = input
|
8
|
+
@description = description
|
9
|
+
@value_type = value_type
|
10
|
+
@value_default = value_default
|
11
|
+
@value = value
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def label
|
16
|
+
options.label || name.titleize
|
17
|
+
end
|
18
|
+
|
19
|
+
def hint
|
20
|
+
options.hint
|
21
|
+
end
|
22
|
+
|
23
|
+
def input
|
24
|
+
@input || guess_input
|
25
|
+
end
|
26
|
+
|
27
|
+
def value
|
28
|
+
@value || value_default
|
29
|
+
end
|
30
|
+
|
31
|
+
def value_type
|
32
|
+
@value_type || guess_value_type
|
33
|
+
end
|
34
|
+
|
35
|
+
def input_options
|
36
|
+
return @input_options if @input_options
|
37
|
+
|
38
|
+
runtime_options = options.except([*methods, :name, :value_default, :description])
|
39
|
+
@input_options ||= Store.new(input_config.options.merge(runtime_options))
|
40
|
+
end
|
41
|
+
|
42
|
+
def input_partial
|
43
|
+
input_config.partial
|
44
|
+
end
|
45
|
+
|
46
|
+
def cast_value
|
47
|
+
raise ArgumentError.new("Cannot cast param '#{name}' without a value set") if value.nil?
|
48
|
+
|
49
|
+
StringValueCaster.call(value, value_type)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.from_tag(tag, value: nil)
|
53
|
+
new(
|
54
|
+
name: tag.name,
|
55
|
+
input: tag.input || tag.options.input,
|
56
|
+
description: tag.description || tag.options.description,
|
57
|
+
value_type: tag.value_type || tag.options.value_type,
|
58
|
+
value_default: tag.value_default,
|
59
|
+
options: tag.options,
|
60
|
+
value: value
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def input_config
|
67
|
+
config = Lookbook::Engine.inputs.get_input(input)
|
68
|
+
config || raise(LookbookError.new("Unknown input type '#{input}'"))
|
69
|
+
end
|
70
|
+
|
71
|
+
def guess_input
|
72
|
+
if @value_type == "boolean" || (@value_type.blank? && boolean?(value_default))
|
73
|
+
"toggle"
|
74
|
+
else
|
75
|
+
"text"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def guess_value_type
|
80
|
+
if input == "toggle"
|
81
|
+
"boolean"
|
82
|
+
elsif input == "number"
|
83
|
+
"integer"
|
84
|
+
elsif boolean?(value_default)
|
85
|
+
"boolean"
|
86
|
+
elsif value_default.is_a?(Symbol)
|
87
|
+
"symbol"
|
88
|
+
elsif ["date", "datetime-local"].include?(input) || value_default.is_a?(DateTime)
|
89
|
+
"datetime"
|
90
|
+
else
|
91
|
+
"string"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def boolean?(value)
|
96
|
+
value == true || value == false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/lookbook/preview.rb
CHANGED
@@ -8,7 +8,14 @@ module Lookbook
|
|
8
8
|
def initialize(preview, code_object)
|
9
9
|
@preview = preview
|
10
10
|
@preview_inspector = SourceInspector.new(code_object, eval_scope: preview_class.new)
|
11
|
-
|
11
|
+
preview_path = preview_class_path(name)
|
12
|
+
|
13
|
+
if @preview_inspector.logical_path
|
14
|
+
basename = preview_path.split("/").last
|
15
|
+
preview_path = "#{@preview_inspector.logical_path}/#{basename}"
|
16
|
+
end
|
17
|
+
|
18
|
+
super(preview_path)
|
12
19
|
end
|
13
20
|
|
14
21
|
def id
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module Lookbook
|
2
|
-
module
|
2
|
+
module PreviewActions
|
3
|
+
def self.included(klass)
|
4
|
+
klass.helper Lookbook::PreviewHelper
|
5
|
+
end
|
6
|
+
|
3
7
|
def render_example_to_string(preview, example_name)
|
4
8
|
prepend_application_view_paths
|
5
9
|
prepend_preview_examples_view_path
|
@@ -12,7 +16,7 @@ module Lookbook
|
|
12
16
|
opts[:layout] = nil
|
13
17
|
opts[:locals] = locals if locals.present?
|
14
18
|
|
15
|
-
|
19
|
+
with_optional_action_view_annotations do
|
16
20
|
render html: render_to_string(template, **opts)
|
17
21
|
end
|
18
22
|
end
|
@@ -20,7 +24,7 @@ module Lookbook
|
|
20
24
|
def render_in_layout_to_string(template, locals, opts = {})
|
21
25
|
append_view_path Lookbook::Engine.root.join("app/views")
|
22
26
|
|
23
|
-
|
27
|
+
with_optional_action_view_annotations do
|
24
28
|
html = render_to_string(template, locals: locals, **determine_layout(opts[:layout]))
|
25
29
|
if opts[:append_html].present?
|
26
30
|
html += opts[:append_html]
|
@@ -28,5 +32,12 @@ module Lookbook
|
|
28
32
|
render html: html
|
29
33
|
end
|
30
34
|
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def with_optional_action_view_annotations(&block)
|
39
|
+
disable = Lookbook.config.preview_disable_action_view_annotations
|
40
|
+
ActionViewAnnotationsHandler.call(disable_annotations: disable, &block)
|
41
|
+
end
|
31
42
|
end
|
32
43
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Lookbook
|
2
2
|
class PreviewExample < Entity
|
3
3
|
attr_reader :name, :preview
|
4
|
-
delegate :
|
4
|
+
delegate :position, :group, :notes, :hidden?, :source, :tags, :tag, to: :@example_inspector
|
5
5
|
|
6
6
|
def initialize(name, preview, code_object)
|
7
7
|
@name = name
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "yard"
|
2
|
+
|
3
|
+
module Lookbook
|
4
|
+
class PreviewParser
|
5
|
+
def initialize(paths, tags = nil)
|
6
|
+
@paths = paths
|
7
|
+
@after_parse_callbacks = []
|
8
|
+
@after_parse_once_callbacks = []
|
9
|
+
@parsing = false
|
10
|
+
|
11
|
+
define_tags(tags)
|
12
|
+
YARD::Parser::SourceParser.after_parse_list { run_callbacks }
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse(&block)
|
16
|
+
unless @parsing
|
17
|
+
@parsing = true
|
18
|
+
@after_parse_once_callbacks << block if block
|
19
|
+
YARD::Registry.clear
|
20
|
+
YARD.parse(paths)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def after_parse(&block)
|
25
|
+
@after_parse_callbacks << block
|
26
|
+
end
|
27
|
+
|
28
|
+
def paths
|
29
|
+
PathUtils.normalize_all(@paths).map { |path| "#{path}/**/*preview.rb" }
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def callbacks
|
35
|
+
[
|
36
|
+
*@after_parse_callbacks,
|
37
|
+
*@after_parse_once_callbacks
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_callbacks
|
42
|
+
callbacks.each { |cb| cb.call(YARD::Registry) }
|
43
|
+
@after_parse_once_callbacks = []
|
44
|
+
@parsing = false
|
45
|
+
end
|
46
|
+
|
47
|
+
def define_tags(tags = nil)
|
48
|
+
tags.to_h.each do |name, tag|
|
49
|
+
YARD::Tags::Library.define_tag(tag[:label], name, Lookbook::TagProvider)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Process
|
3
|
+
attr_reader :env
|
4
|
+
|
5
|
+
def initialize(env: Rails.env)
|
6
|
+
@env = env
|
7
|
+
end
|
8
|
+
|
9
|
+
def supports_listening?
|
10
|
+
!rake_task? && !Rails.const_defined?(:Console)
|
11
|
+
end
|
12
|
+
|
13
|
+
def rake_task?
|
14
|
+
if defined?(Rake) && Rake.respond_to?(:application)
|
15
|
+
File.basename($0) == "rake" || Rake.application.top_level_tasks.any?
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|