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

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