lookbook 1.0.0.beta.6 → 1.0.0.rc.1

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -30
  3. data/app/assets/lookbook/css/themes/blue.css +2 -1
  4. data/app/assets/lookbook/css/themes/indigo.css +2 -1
  5. data/app/assets/lookbook/css/themes/zinc.css +2 -1
  6. data/app/components/lookbook/base_component.rb +0 -1
  7. data/app/components/lookbook/inspector_panel/component.css +5 -0
  8. data/app/components/lookbook/inspector_panel/component.html.erb +6 -4
  9. data/app/components/lookbook/inspector_panel/component.rb +3 -3
  10. data/app/components/lookbook/nav/component.rb +1 -2
  11. data/app/components/lookbook/nav/item/component.html.erb +1 -1
  12. data/app/components/lookbook/params_editor/field/component.rb +2 -1
  13. data/app/components/lookbook/tab_panels/component.rb +1 -1
  14. data/app/components/lookbook/tab_panels/panel/component.rb +2 -2
  15. data/app/components/lookbook/tag_component.rb +3 -3
  16. data/app/controllers/lookbook/application_controller.rb +1 -1
  17. data/app/controllers/lookbook/page_controller.rb +6 -1
  18. data/app/controllers/lookbook/previews_controller.rb +8 -16
  19. data/app/helpers/lookbook/application_helper.rb +9 -0
  20. data/app/helpers/lookbook/preview_helper.rb +7 -2
  21. data/app/views/layouts/lookbook/skeleton.html.erb +15 -8
  22. data/app/views/lookbook/index.html.erb +11 -24
  23. data/app/views/lookbook/previews/panels/_notes.html.erb +1 -1
  24. data/app/views/lookbook/previews/show.html.erb +2 -2
  25. data/lib/lookbook/code_formatter.rb +1 -1
  26. data/lib/lookbook/collection.rb +8 -3
  27. data/lib/lookbook/component.rb +2 -3
  28. data/lib/lookbook/config.rb +15 -10
  29. data/lib/lookbook/data.rb +11 -0
  30. data/lib/lookbook/engine.rb +70 -77
  31. data/lib/lookbook/entity.rb +1 -1
  32. data/lib/lookbook/hooks.rb +21 -0
  33. data/lib/lookbook/markdown.rb +1 -1
  34. data/lib/lookbook/page.rb +4 -5
  35. data/lib/lookbook/page_section.rb +2 -4
  36. data/lib/lookbook/panels.rb +15 -0
  37. data/lib/lookbook/parser.rb +4 -1
  38. data/lib/lookbook/preview.rb +10 -12
  39. data/lib/lookbook/preview_example.rb +2 -2
  40. data/lib/lookbook/preview_group.rb +8 -0
  41. data/lib/lookbook/source_inspector.rb +23 -11
  42. data/lib/lookbook/store.rb +7 -3
  43. data/lib/lookbook/tag.rb +112 -0
  44. data/lib/lookbook/tags.rb +22 -0
  45. data/lib/lookbook/theme.rb +38 -9
  46. data/lib/lookbook/version.rb +1 -1
  47. data/lib/lookbook.rb +1 -0
  48. data/lib/tasks/lookbook_tasks.rake +1 -2
  49. data/public/lookbook-assets/css/lookbook.css +19 -10
  50. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  51. data/public/lookbook-assets/css/themes/blue.css +1 -0
  52. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  53. data/public/lookbook-assets/css/themes/indigo.css +1 -0
  54. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  55. data/public/lookbook-assets/css/themes/zinc.css +1 -0
  56. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  57. data/public/lookbook-assets/js/lookbook.js +48 -48
  58. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  59. metadata +8 -2
@@ -6,14 +6,14 @@ module Lookbook
6
6
  class Config
7
7
  def initialize
8
8
  @options = Store.new
9
-
9
+
10
10
  @options.set({
11
11
  project_name: "Lookbook",
12
12
  log_level: 2,
13
13
  auto_refresh: true,
14
14
 
15
15
  components_path: "app/components",
16
-
16
+
17
17
  page_controller: "Lookbook::PageController",
18
18
  page_route: "pages",
19
19
  page_paths: ["test/components/docs"],
@@ -23,6 +23,7 @@ module Lookbook
23
23
  preview_paths: [],
24
24
  preview_display_params: {},
25
25
  preview_srcdoc: nil,
26
+ preview_tags: {},
26
27
  sort_examples: false,
27
28
 
28
29
  listen: Rails.env.development?,
@@ -38,11 +39,12 @@ module Lookbook
38
39
 
39
40
  ui_theme: "indigo",
40
41
  ui_theme_overrides: {},
42
+ ui_favicon: true,
41
43
 
42
44
  hooks: {
43
45
  after_initialize: [],
44
46
  before_exit: [],
45
- after_change: [],
47
+ after_change: []
46
48
  },
47
49
 
48
50
  debug_menu: Rails.env.development?,
@@ -98,7 +100,7 @@ module Lookbook
98
100
  padded: false,
99
101
  system: true
100
102
  }
101
- },
103
+ }
102
104
  })
103
105
  end
104
106
 
@@ -145,7 +147,7 @@ module Lookbook
145
147
 
146
148
  def inspector_panels(&block)
147
149
  panels = Store.new(@options.inspector_panels.select { |key, panel| panel != false })
148
- if block_given?
150
+ if block
149
151
  yield panels
150
152
  else
151
153
  panels
@@ -156,7 +158,7 @@ module Lookbook
156
158
  pane = opts[:pane].presence || :drawer
157
159
  siblings = inspector_panels.select { |key, panel| panel.pane == pane }
158
160
  opts[:position] ||= siblings.size + 1
159
- @options.inspector_panels[name] = opts
161
+ @options.inspector_panels[name] = opts
160
162
  siblings.each do |key, panel|
161
163
  if panel.position >= opts[:position]
162
164
  panel.position += 1
@@ -190,7 +192,6 @@ module Lookbook
190
192
  copy: nil,
191
193
  panel_classes: nil,
192
194
  locals: {},
193
- padded: true,
194
195
  system: false
195
196
  }
196
197
  end
@@ -205,7 +206,7 @@ module Lookbook
205
206
  end
206
207
 
207
208
  def ui_theme_overrides(&block)
208
- if block_given?
209
+ if block
209
210
  yield @options.ui_theme_overrides
210
211
  else
211
212
  @options.ui_theme_overrides
@@ -236,7 +237,7 @@ module Lookbook
236
237
  def to_json(*a)
237
238
  to_h.to_json(*a)
238
239
  end
239
-
240
+
240
241
  protected
241
242
 
242
243
  def normalize_paths(paths)
@@ -254,5 +255,9 @@ module Lookbook
254
255
  def method_missing(name, *args)
255
256
  @options.send(name, *args)
256
257
  end
258
+
259
+ def respond_to_missing?(name, *)
260
+ to_h.key? name
261
+ end
257
262
  end
258
- end
263
+ end
@@ -0,0 +1,11 @@
1
+ module Lookbook
2
+ module Data
3
+ def data
4
+ @data ||= Store.new
5
+ end
6
+
7
+ def data=(props)
8
+ @data = Store.new(props)
9
+ end
10
+ end
11
+ end
@@ -2,12 +2,21 @@ require "rails"
2
2
  require "view_component"
3
3
  require "action_cable/engine"
4
4
  require "listen"
5
+ require "rake"
5
6
 
6
7
  module Lookbook
7
-
8
8
  autoload :Config, "lookbook/config"
9
-
9
+ autoload :Data, "lookbook/data"
10
+ autoload :Hooks, "lookbook/hooks"
11
+ autoload :Panels, "lookbook/panels"
12
+ autoload :Tags, "lookbook/tags"
13
+
10
14
  class << self
15
+ include Lookbook::Data
16
+ include Lookbook::Hooks
17
+ include Lookbook::Panels
18
+ include Lookbook::Tags
19
+
11
20
  def version
12
21
  Lookbook::VERSION
13
22
  end
@@ -48,46 +57,12 @@ module Lookbook
48
57
  Page.any?
49
58
  end
50
59
 
51
- def data
52
- @data ||= Store.new
53
- end
54
-
55
- def data=(props)
56
- @data = Store.new(props)
57
- end
58
-
59
- def after_initialize(&block)
60
- add_hook(:after_initialize, block)
61
- end
62
-
63
- def before_exit(&block)
64
- add_hook(:before_exit, block)
65
- end
66
-
67
- def after_change(&block)
68
- add_hook(:after_change, block)
69
- end
70
-
71
- def define_panel(name, opts = {})
72
- config.define_inspector_panel(name, opts)
73
- end
74
-
75
- def amend_panel(name, opts = {})
76
- config.amend_inspector_panel(name, opts)
77
- end
78
-
79
- def remove_panel(name)
80
- config.remove_inspector_panel(name)
81
- end
82
-
83
60
  def broadcast(event_name, data = {})
84
61
  Engine.websocket&.broadcast(event_name.to_s, data)
85
62
  end
86
63
 
87
- protected
88
-
89
- def add_hook(event_name, block)
90
- config.hooks[event_name] << block
64
+ def theme
65
+ @theme ||= Lookbook::Theme.new(config.ui_theme, config.ui_theme_overrides)
91
66
  end
92
67
  end
93
68
 
@@ -97,14 +72,14 @@ module Lookbook
97
72
  config.lookbook = Lookbook.config
98
73
  config.autoload_paths << File.expand_path(Lookbook::Engine.root.join("app/components"))
99
74
 
100
- initializer "lookbook.viewcomponent.config" do
75
+ initializer "lookbook.viewcomponent.config" do
101
76
  config.lookbook.preview_paths += config.view_component.preview_paths
102
77
  config.lookbook.preview_controller ||= config.view_component.preview_controller
103
78
 
104
79
  config.lookbook.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present?
105
80
 
106
81
  config.lookbook.listen_paths += config.lookbook.preview_paths
107
- config.lookbook.listen_paths << config.lookbook.components_path
82
+ config.lookbook.listen_paths << config.lookbook.components_path
108
83
  end
109
84
 
110
85
  initializer "lookbook.logging.development" do
@@ -112,7 +87,7 @@ module Lookbook
112
87
  end
113
88
 
114
89
  initializer "lookbook.parser.tags" do
115
- Lookbook::Parser.define_tags
90
+ Lookbook::Parser.define_tags(Lookbook.config.preview_tags)
116
91
  end
117
92
 
118
93
  initializer "lookbook.assets.serve" do
@@ -126,39 +101,20 @@ module Lookbook
126
101
  @preview_controller = Lookbook.config.preview_controller.constantize
127
102
  @preview_controller.include(Lookbook::PreviewController)
128
103
 
129
- if config.lookbook.listen
130
- Listen.logger = Lookbook.logger
131
-
132
- preview_listener = Listen.to(
133
- *config.lookbook.listen_paths,
134
- only: /\.(#{config.lookbook.listen_extensions.join("|")})$/,
135
- force_polling: config.lookbook.listen_use_polling
136
- ) do |modified, added, removed|
137
- changes = { modified: modified, added: added, removed: removed }
138
- begin
139
- parser.parse
140
- rescue
141
- end
142
- Lookbook::Preview.clear_cache
143
- Lookbook::Engine.reload_ui(changes)
144
- Lookbook::Engine.run_hooks(:after_change, changes)
104
+ if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1.3.1")
105
+ # Rails.application.server is only available for newer Rails versions
106
+ Rails.application.server do
107
+ init_listeners
145
108
  end
146
- Lookbook::Engine.register_listener(preview_listener)
147
-
148
- page_listener = Listen.to(
149
- *config.lookbook.page_paths,
150
- only: /\.(html.*|md.*)$/,
151
- force_polling: config.lookbook.listen_use_polling
152
- ) do |modified, added, removed|
153
- changes = { modified: modified, added: added, removed: removed }
154
- Lookbook::Engine.reload_ui(changes)
155
- Lookbook::Engine.run_hooks(:after_change, changes)
109
+ else
110
+ # Fallback for older Rails versions - don't start listeners if running in a rake task.
111
+ unless File.basename($0) == "rake" || Rake.application.top_level_tasks.any?
112
+ init_listeners
156
113
  end
157
- Lookbook::Engine.register_listener(page_listener)
158
114
  end
159
115
 
160
116
  if config.lookbook.runtime_parsing
161
- parser.parse
117
+ Lookbook::Engine.parser.parse
162
118
  else
163
119
  unless File.exist?(config.lookbook.parser_registry_path)
164
120
  Lookbook.logger.warn "
@@ -172,16 +128,48 @@ module Lookbook
172
128
  Lookbook::Engine.run_hooks(:after_initialize)
173
129
  end
174
130
 
131
+ def init_listeners
132
+ return unless config.lookbook.listen == true
133
+ Listen.logger = Lookbook.logger
134
+ Lookbook.logger.info "Initializing listeners"
135
+
136
+ preview_listener = Listen.to(
137
+ *config.lookbook.listen_paths,
138
+ only: /\.(#{config.lookbook.listen_extensions.join("|")})$/,
139
+ force_polling: config.lookbook.listen_use_polling
140
+ ) do |modified, added, removed|
141
+ changes = {modified: modified, added: added, removed: removed}
142
+ begin
143
+ Lookbook::Engine.parser.parse
144
+ rescue
145
+ end
146
+ Lookbook::Preview.clear_cache
147
+ Lookbook::Engine.reload_ui(changes)
148
+ Lookbook::Engine.run_hooks(:after_change, changes)
149
+ end
150
+ Lookbook::Engine.register_listener(preview_listener)
151
+
152
+ page_listener = Listen.to(
153
+ *config.lookbook.page_paths,
154
+ only: /\.(html.*|md.*)$/,
155
+ force_polling: config.lookbook.listen_use_polling
156
+ ) do |modified, added, removed|
157
+ changes = {modified: modified, added: added, removed: removed}
158
+ Lookbook::Engine.reload_ui(changes)
159
+ Lookbook::Engine.run_hooks(:after_change, changes)
160
+ end
161
+ Lookbook::Engine.register_listener(page_listener)
162
+ end
163
+
175
164
  at_exit do
176
- if config.lookbook.listen
165
+ if Lookbook::Engine.listeners.any?
177
166
  Lookbook.logger.debug "Stopping listeners"
178
- Lookbook::Engine.listeners.each { |listener| listener.stop }
167
+ Lookbook::Engine.listeners.each { |listener| listener.stop }
179
168
  end
180
169
  Lookbook::Engine.run_hooks(:before_exit)
181
170
  end
182
171
 
183
172
  class << self
184
-
185
173
  def websocket
186
174
  return @websocket unless @websocket.nil?
187
175
  if config.lookbook.auto_refresh
@@ -194,9 +182,9 @@ module Lookbook
194
182
  @websocket ||= if Rails.version.to_f >= 6.0
195
183
  ActionCable::Server::Base.new(config: cable)
196
184
  else
197
- @websocket ||= ActionCable::Server::Base.new
198
- @websocket.config = cable
199
- @websocket
185
+ ws = ActionCable::Server::Base.new
186
+ ws.config = cable
187
+ ws
200
188
  end
201
189
  end
202
190
  end
@@ -218,7 +206,12 @@ module Lookbook
218
206
  end
219
207
 
220
208
  def app_name
221
- Rails.application.class.module_parent_name.underscore
209
+ name = if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1")
210
+ Rails.application.class.module_parent_name
211
+ else
212
+ Rails.application.class.parent_name
213
+ end
214
+ name.underscore
222
215
  end
223
216
 
224
217
  def register_listener(listener)
@@ -231,7 +224,7 @@ module Lookbook
231
224
  end
232
225
 
233
226
  def run_hooks(event_name, *args)
234
- Lookbook.config.hooks[event_name].each do |hook|
227
+ config.lookbook.hooks[event_name].each do |hook|
235
228
  hook.call(Lookbook, *args)
236
229
  end
237
230
  end
@@ -44,4 +44,4 @@ module Lookbook
44
44
 
45
45
  alias_method :url_path, :lookup_path
46
46
  end
47
- end
47
+ end
@@ -0,0 +1,21 @@
1
+ module Lookbook
2
+ module Hooks
3
+ def after_initialize(&block)
4
+ add_hook(:after_initialize, block)
5
+ end
6
+
7
+ def before_exit(&block)
8
+ add_hook(:before_exit, block)
9
+ end
10
+
11
+ def after_change(&block)
12
+ add_hook(:after_change, block)
13
+ end
14
+
15
+ protected
16
+
17
+ def add_hook(event_name, block)
18
+ Lookbook.config.hooks[event_name] << block
19
+ end
20
+ end
21
+ end
@@ -13,7 +13,7 @@ module Lookbook
13
13
  }
14
14
 
15
15
  def self.render(text)
16
- text&.gsub!(/\<\!\-\- (BEGIN|END) (.*) \-\-\>/, "")
16
+ text&.gsub!(/<!-- (BEGIN|END) (.*) -->/, "")
17
17
  markdown = Redcarpet::Markdown.new(Renderer, Lookbook.config.markdown_options)
18
18
  markdown.render(text).html_safe
19
19
  end
data/lib/lookbook/page.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module Lookbook
2
2
  class Page < Entity
3
-
4
3
  FRONTMATTER_FIELDS = [
5
4
  :id,
6
5
  :label,
@@ -76,7 +75,7 @@ module Lookbook
76
75
  def type
77
76
  :page
78
77
  end
79
-
78
+
80
79
  def id
81
80
  options[:id]
82
81
  end
@@ -125,7 +124,7 @@ module Lookbook
125
124
  }))
126
125
  end
127
126
  @options = Lookbook.config.page_options.deep_merge(frontmatter).with_indifferent_access
128
- @options[:id] = @options[:id] ? generate_id(@options[:id]) : generate_id(lookup_path)
127
+ @options[:id] = generate_id(@options[:id] || lookup_path)
129
128
  @options[:label] ||= name.titleize
130
129
  @options[:title] ||= @options[:label]
131
130
  @options[:hidden] ||= false
@@ -159,7 +158,7 @@ module Lookbook
159
158
  end
160
159
 
161
160
  def all
162
- pages, sections =
161
+ pages, sections =
163
162
  Array(page_paths).flat_map do |dir|
164
163
  Dir["#{dir}/**/*.html.*", "#{dir}/**/*.md.*"].sort.map do |path|
165
164
  create(path, dir)
@@ -172,7 +171,7 @@ module Lookbook
172
171
 
173
172
  page_dict = sorted_pages.index_by(&:path)
174
173
  sorted_sections = sections.sort_by { |section| [section.position, section.label] }
175
-
174
+
176
175
  sorted_sections.each do |section|
177
176
  page_dict[section.path].sections << section
178
177
  end
@@ -1,6 +1,5 @@
1
1
  module Lookbook
2
2
  class PageSection < Page
3
-
4
3
  def name
5
4
  return @name if @name.present?
6
5
  matches = full_path.to_s.match(%r{\[(?<name>\w+)\]})
@@ -24,8 +23,7 @@ module Lookbook
24
23
  end
25
24
 
26
25
  def lookup_path
27
- "#{super}/#{name}"
26
+ "#{super}/#{name}"
28
27
  end
29
-
30
28
  end
31
- end
29
+ end
@@ -0,0 +1,15 @@
1
+ module Lookbook
2
+ module Panels
3
+ def define_panel(name, opts = {})
4
+ Lookbook.config.define_inspector_panel(name, opts)
5
+ end
6
+
7
+ def amend_panel(name, opts = {})
8
+ Lookbook.amend_inspector_panel(name, opts)
9
+ end
10
+
11
+ def remove_panel(name)
12
+ Lookbook.remove_inspector_panel(name)
13
+ end
14
+ end
15
+ end
@@ -24,13 +24,16 @@ module Lookbook
24
24
  end
25
25
 
26
26
  class << self
27
- def define_tags
27
+ def define_tags(custom = {})
28
28
  YARD::Tags::Library.define_tag("Hidden status", :hidden)
29
29
  YARD::Tags::Library.define_tag("Label", :label)
30
30
  YARD::Tags::Library.define_tag("Display", :display)
31
31
  YARD::Tags::Library.define_tag("Position", :position)
32
32
  YARD::Tags::Library.define_tag("ID", :id)
33
33
  YARD::Tags::Library.define_tag("Component", :component)
34
+ custom.each do |name, opts|
35
+ YARD::Tags::Library.define_tag(name.to_s.titleize, name)
36
+ end
34
37
  end
35
38
  end
36
39
  end
@@ -3,7 +3,7 @@ module Lookbook
3
3
  include Utils
4
4
 
5
5
  delegate :name, :render_args, to: :@preview
6
- delegate :position, :group, :notes, :hidden?, to: :@preview_inspector
6
+ delegate :position, :group, :notes, :hidden?, :tags, :tag, to: :@preview_inspector
7
7
 
8
8
  def initialize(preview)
9
9
  @preview = preview
@@ -97,7 +97,7 @@ module Lookbook
97
97
  end
98
98
 
99
99
  def components
100
- component_classes = @preview_inspector&.components.any? ? @preview_inspector&.components : [guess_component]
100
+ component_classes = @preview_inspector&.components&.any? ? @preview_inspector&.components : [guess_component]
101
101
  component_classes.map do |class_name|
102
102
  Component.new(class_name.to_s)
103
103
  end
@@ -106,11 +106,9 @@ module Lookbook
106
106
  protected
107
107
 
108
108
  def guess_component
109
- begin
110
- name.chomp("Preview").constantize
111
- rescue
112
- nil
113
- end
109
+ name.chomp("Preview").constantize
110
+ rescue
111
+ nil
114
112
  end
115
113
 
116
114
  class << self
@@ -156,7 +154,7 @@ module Lookbook
156
154
 
157
155
  def clear_cache
158
156
  cache_dir = File.dirname(cache_marker_path)
159
- FileUtils.mkdir_p(cache_dir) unless File.exists?(cache_dir)
157
+ FileUtils.mkdir_p(cache_dir) unless File.exist?(cache_dir)
160
158
  File.write(cache_marker_path, Time.now.to_i)
161
159
  end
162
160
 
@@ -167,7 +165,7 @@ module Lookbook
167
165
  end
168
166
 
169
167
  def cache_stale?
170
- return false if !File.exists?(cache_marker_path)
168
+ return false if !File.exist?(cache_marker_path)
171
169
  cache_timestamp = File.read(cache_marker_path).to_i
172
170
  if @last_cache_timestamp.nil? || cache_timestamp > @last_cache_timestamp
173
171
  @last_cache_timestamp = cache_timestamp
@@ -179,7 +177,7 @@ module Lookbook
179
177
 
180
178
  def mark_as_cached
181
179
  cache_dir = File.dirname(cache_marker_path)
182
- FileUtils.mkdir_p(cache_dir) unless File.exists?(cache_dir)
180
+ FileUtils.mkdir_p(cache_dir) unless File.exist?(cache_dir)
183
181
  File.write(cache_marker_path, Time.now)
184
182
  end
185
183
 
@@ -196,14 +194,14 @@ module Lookbook
196
194
  )
197
195
  end
198
196
  end
199
-
197
+
200
198
  def preview_files
201
199
  files = Array(Lookbook.config.preview_paths).map do |preview_path|
202
200
  Dir["#{preview_path}/**/*preview.rb"].map do |path|
203
201
  {
204
202
  path: path,
205
203
  base_path: preview_path,
206
- rel_path: Pathname(path).relative_path_from(preview_path).to_s
204
+ rel_path: Pathname(path).relative_path_from(Pathname.new(preview_path)).to_s
207
205
  }
208
206
  end
209
207
  end
@@ -1,7 +1,7 @@
1
1
  module Lookbook
2
2
  class PreviewExample < Entity
3
3
  attr_reader :name, :preview
4
- delegate :params, :position, :group, :notes, :hidden?, :source, to: :@example_inspector
4
+ delegate :params, :position, :group, :notes, :hidden?, :source, :tags, :tag, to: :@example_inspector
5
5
 
6
6
  def initialize(name, preview)
7
7
  @name = name
@@ -11,7 +11,7 @@ module Lookbook
11
11
  end
12
12
 
13
13
  def id
14
- generate_id(@preview.id, name)
14
+ @example_inspector&.id || generate_id(@preview.id, name)
15
15
  end
16
16
 
17
17
  def url_path
@@ -49,6 +49,14 @@ module Lookbook
49
49
  @preview.hierarchy_depth + 1
50
50
  end
51
51
 
52
+ def tags(name = nil)
53
+ examples.map { |example| example.tags(name) }.flatten
54
+ end
55
+
56
+ def tag(name = nil)
57
+ tags(name).first
58
+ end
59
+
52
60
  alias_method :lookup_path, :path
53
61
  end
54
62
  end
@@ -10,37 +10,39 @@ module Lookbook
10
10
  end
11
11
 
12
12
  def hidden?
13
- if code_object&.tag(:hidden)
13
+ @hidden ||= if code_object&.tag(:hidden)
14
14
  code_object.tag(:hidden).text.strip != "false"
15
+ else
16
+ false
15
17
  end
16
18
  end
17
19
 
18
20
  def id
19
- if code_object&.tag(:id)&.text&.present?
21
+ @id ||= if code_object&.tag(:id)&.text&.present?
20
22
  generate_id(code_object&.tag(:id)&.text)
21
23
  end
22
24
  end
23
25
 
24
26
  def label
25
- code_object&.tag(:label)&.text
27
+ @label ||= code_object&.tag(:label)&.text
26
28
  end
27
29
 
28
30
  def notes
29
- if code_object&.docstring
31
+ @notes ||= if code_object&.docstring
30
32
  code_object.docstring.to_s.strip
31
33
  end
32
34
  end
33
35
 
34
36
  def group
35
- code_object&.group
37
+ @group ||= code_object&.group
36
38
  end
37
39
 
38
40
  def position
39
- code_object&.tag(:position)&.text&.to_i || 10000
41
+ @position ||= code_object&.tag(:position)&.text&.to_i || 10000
40
42
  end
41
43
 
42
44
  def components
43
- if code_object&.tags(:component).present?
45
+ @components ||= if code_object&.tags(:component).present?
44
46
  code_object.tags(:component).map do |component|
45
47
  component.text.constantize
46
48
  end
@@ -50,7 +52,8 @@ module Lookbook
50
52
  end
51
53
 
52
54
  def display_params
53
- display_params = {}.with_indifferent_access
55
+ return @display_params unless @display_params.nil?
56
+ @display_params = {}.with_indifferent_access
54
57
  if code_object&.tags(:display).present?
55
58
  code_object.tags(:display).each do |tag|
56
59
  parts = tag.text.strip.match(/^([^\s]*)\s?(.*)$/)
@@ -63,11 +66,11 @@ module Lookbook
63
66
  end
64
67
  end
65
68
  end
66
- display_params
69
+ @display_params
67
70
  end
68
71
 
69
72
  def parameter_defaults
70
- code_object&.parameters&.map { |str| Params.parse_method_param_str(str) }&.compact&.to_h
73
+ @param_defaults ||= code_object&.parameters&.map { |str| Params.parse_method_param_str(str) }&.compact&.to_h
71
74
  end
72
75
 
73
76
  def params
@@ -77,7 +80,16 @@ module Lookbook
77
80
  end
78
81
 
79
82
  def methods
80
- code_object&.meths
83
+ @methods ||= code_object&.meths
84
+ end
85
+
86
+ def tags(name = nil)
87
+ tag_objects = code_object&.tags(name).presence || []
88
+ Lookbook::Tags.process_tags(tag_objects)
89
+ end
90
+
91
+ def tag(name = nil)
92
+ tags(name).first
81
93
  end
82
94
  end
83
95
  end