lookbook 1.5.5 → 2.0.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -31
  3. data/app/assets/lookbook/css/lookbook.css +9 -0
  4. data/app/assets/lookbook/css/themes/blue.css +7 -0
  5. data/app/assets/lookbook/css/themes/green.css +7 -0
  6. data/app/assets/lookbook/css/themes/indigo.css +7 -0
  7. data/app/assets/lookbook/css/themes/rose.css +7 -0
  8. data/app/assets/lookbook/css/themes/zinc.css +7 -0
  9. data/app/assets/lookbook/css/tooltip.css +9 -6
  10. data/app/assets/lookbook/img/lucide-sprite.svg +4960 -0
  11. data/app/assets/lookbook/js/app.js +22 -4
  12. data/app/assets/lookbook/js/helpers/dom.js +4 -7
  13. data/app/assets/lookbook/js/helpers/string.js +4 -11
  14. data/app/assets/lookbook/js/index.js +61 -0
  15. data/app/assets/lookbook/js/lib/lookbook.js +113 -0
  16. data/app/assets/lookbook/js/lib/tippy.js +1 -0
  17. data/app/assets/lookbook/js/lookbook-core.js +1 -0
  18. data/app/assets/lookbook/js/lookbook.js +2 -61
  19. data/app/components/lookbook/base_component.rb +3 -1
  20. data/app/components/lookbook/button/component.html.erb +13 -24
  21. data/app/components/lookbook/button/component.js +13 -3
  22. data/app/components/lookbook/button/component.rb +16 -25
  23. data/app/components/lookbook/code/component.rb +0 -2
  24. data/app/components/lookbook/copy_button/component.html.erb +5 -5
  25. data/app/components/lookbook/copy_button/component.rb +6 -3
  26. data/app/components/lookbook/debug_menu/component.html.erb +1 -0
  27. data/app/components/lookbook/debug_menu/component.rb +12 -1
  28. data/app/components/lookbook/display_options/editor/component.html.erb +1 -1
  29. data/app/components/lookbook/display_options/field/component.css +0 -26
  30. data/app/components/lookbook/display_options/field/component.html.erb +1 -1
  31. data/app/components/lookbook/embed/component.html.erb +6 -51
  32. data/app/components/lookbook/embed/component.rb +17 -16
  33. data/app/components/lookbook/embed/inspector/component.html.erb +102 -0
  34. data/app/components/lookbook/embed/inspector/component.js +46 -0
  35. data/app/components/lookbook/embed/inspector/component.rb +64 -0
  36. data/app/components/lookbook/embed_code_dropdown/component.css +12 -0
  37. data/app/components/lookbook/embed_code_dropdown/component.html.erb +19 -0
  38. data/app/components/lookbook/embed_code_dropdown/component.js +26 -0
  39. data/app/components/lookbook/embed_code_dropdown/component.rb +41 -0
  40. data/app/components/lookbook/header/component.html.erb +7 -6
  41. data/app/components/lookbook/header/component.rb +5 -1
  42. data/app/components/lookbook/icon/component.html.erb +1 -1
  43. data/app/components/lookbook/icon_button/component.html.erb +20 -0
  44. data/app/components/lookbook/icon_button/component.rb +46 -0
  45. data/app/components/lookbook/nav/component.html.erb +0 -1
  46. data/app/components/lookbook/nav/entity/component.rb +2 -2
  47. data/app/components/lookbook/nav/item/component.rb +1 -1
  48. data/app/components/lookbook/page_tabs/component.html.erb +2 -2
  49. data/app/components/lookbook/params/editor/component.rb +1 -0
  50. data/app/components/lookbook/prose/component.rb +1 -3
  51. data/app/components/lookbook/tabs/component.html.erb +2 -2
  52. data/app/components/lookbook/tabs/component.js +1 -1
  53. data/app/components/lookbook/tag_component.rb +2 -1
  54. data/app/components/lookbook/text_button/component.html.erb +26 -0
  55. data/app/components/lookbook/text_button/component.rb +42 -0
  56. data/app/components/lookbook/toolbar/component.html.erb +1 -1
  57. data/app/components/lookbook/viewport/component.rb +0 -4
  58. data/app/controllers/concerns/lookbook/targetable_concern.rb +26 -22
  59. data/app/controllers/concerns/lookbook/with_panels_concern.rb +30 -0
  60. data/app/controllers/concerns/lookbook/with_preview_controller_concern.rb +4 -3
  61. data/app/controllers/lookbook/application_controller.rb +9 -12
  62. data/app/controllers/lookbook/embeds_controller.rb +148 -0
  63. data/app/controllers/lookbook/inspector_controller.rb +3 -22
  64. data/app/controllers/lookbook/page_controller.rb +7 -6
  65. data/app/controllers/lookbook/pages_controller.rb +3 -4
  66. data/app/controllers/lookbook/preview_controller.rb +17 -0
  67. data/app/controllers/lookbook/previews_controller.rb +10 -30
  68. data/app/helpers/lookbook/application_helper.rb +3 -19
  69. data/app/views/layouts/lookbook/application.html.erb +85 -60
  70. data/app/views/layouts/lookbook/embed.html.erb +16 -0
  71. data/app/views/layouts/lookbook/shell.html.erb +1 -1
  72. data/app/views/layouts/lookbook/skeleton.html.erb +13 -8
  73. data/app/views/lookbook/404.html.erb +2 -2
  74. data/app/views/lookbook/embeds/show.html.erb +12 -0
  75. data/app/views/lookbook/inspector/panels/_notes.html.erb +1 -1
  76. data/app/views/lookbook/inspector/panels/_output.html.erb +3 -3
  77. data/app/views/lookbook/inspector/panels/_source.html.erb +6 -6
  78. data/app/views/lookbook/inspector/show.html.erb +130 -123
  79. data/app/views/lookbook/pages/show.html.erb +81 -34
  80. data/app/views/lookbook/partials/_iframe_content_scripts.html.erb +1 -0
  81. data/app/views/lookbook/partials/_user_styles.html.erb +5 -0
  82. data/app/views/lookbook/previews/group.html.erb +14 -0
  83. data/app/views/lookbook/previews/preview.html.erb +5 -0
  84. data/app/views/lookbook/previews/show.html.erb +1 -0
  85. data/config/app.yml +31 -16
  86. data/config/panels.yml +23 -25
  87. data/config/routes.rb +3 -1
  88. data/config/tags.yml +6 -2
  89. data/lib/lookbook/cable/cable.rb +53 -0
  90. data/lib/lookbook/engine.rb +105 -93
  91. data/lib/lookbook/entities/collections/entity_collection.rb +11 -6
  92. data/lib/lookbook/entities/collections/page_collection.rb +33 -8
  93. data/lib/lookbook/entities/collections/preview_collection.rb +42 -17
  94. data/lib/lookbook/entities/collections/render_target_collection.rb +4 -0
  95. data/lib/lookbook/entities/collections/scenario_collection.rb +4 -0
  96. data/lib/lookbook/entities/concerns/{annotatable.rb → annotatable_entity.rb} +7 -6
  97. data/lib/lookbook/entities/concerns/{inspectable.rb → inspectable_entity.rb} +2 -1
  98. data/lib/lookbook/entities/concerns/{locatable.rb → locatable_entity.rb} +8 -14
  99. data/lib/lookbook/entities/concerns/navigable_entity.rb +44 -0
  100. data/lib/lookbook/entities/entity.rb +7 -2
  101. data/lib/lookbook/entities/{page.rb → page_entity.rb} +10 -6
  102. data/lib/lookbook/entities/{page_section.rb → page_section_entity.rb} +1 -1
  103. data/lib/lookbook/entities/preview_entity.rb +99 -0
  104. data/lib/lookbook/entities/renderable_entity.rb +50 -0
  105. data/lib/lookbook/entities/rendered_scenario_entity.rb +53 -0
  106. data/lib/lookbook/entities/scenario_entity.rb +112 -0
  107. data/lib/lookbook/entities/scenario_group_entity.rb +53 -0
  108. data/lib/lookbook/error.rb +5 -5
  109. data/lib/lookbook/file_watcher.rb +19 -35
  110. data/lib/lookbook/helpers/class_names_helper.rb +28 -0
  111. data/lib/lookbook/helpers/page_helper.rb +18 -0
  112. data/{app/helpers/lookbook → lib/lookbook/helpers}/preview_helper.rb +3 -0
  113. data/lib/lookbook/helpers/ui_elements_helper.rb +115 -0
  114. data/lib/lookbook/preview.rb +79 -0
  115. data/lib/lookbook/preview_controller_actions.rb +50 -0
  116. data/lib/lookbook/preview_parser.rb +4 -2
  117. data/lib/lookbook/reloaders.rb +71 -0
  118. data/lib/lookbook/runtime_context.rb +49 -0
  119. data/lib/lookbook/services/data/resolvers/data_resolver.rb +4 -6
  120. data/lib/lookbook/services/entities/entity_tree_builder.rb +6 -6
  121. data/lib/lookbook/services/list_resolver.rb +35 -0
  122. data/lib/lookbook/services/markdown_renderer.rb +12 -2
  123. data/lib/lookbook/services/priority_prefix_parser.rb +16 -0
  124. data/lib/lookbook/services/urls/search_param_encoder.rb +16 -0
  125. data/lib/lookbook/services/urls/search_param_parser.rb +7 -6
  126. data/lib/lookbook/stores/config_store.rb +16 -16
  127. data/lib/lookbook/stores/input_store.rb +1 -3
  128. data/lib/lookbook/stores/panel_store.rb +28 -50
  129. data/lib/lookbook/support/deprecation.rb +5 -0
  130. data/lib/lookbook/support/errors/preview_template_error.rb +7 -0
  131. data/lib/lookbook/support/evented_file_update_checker.rb +69 -0
  132. data/lib/lookbook/support/null_websocket.rb +9 -0
  133. data/lib/lookbook/support/store.rb +9 -0
  134. data/lib/lookbook/support/tree_node.rb +7 -7
  135. data/lib/lookbook/support/utils/path_utils.rb +7 -1
  136. data/lib/lookbook/support/utils/utils.rb +8 -0
  137. data/lib/lookbook/tags/{position_tag.rb → priority_tag.rb} +4 -4
  138. data/lib/lookbook/tags/renders_tag.rb +4 -0
  139. data/lib/lookbook/tags/tag_provider.rb +3 -0
  140. data/lib/lookbook/tags/type_tag.rb +7 -0
  141. data/lib/lookbook/tags/yard_tag.rb +1 -2
  142. data/lib/lookbook/version.rb +1 -1
  143. data/lib/lookbook/websocket.rb +6 -53
  144. data/lib/lookbook.rb +179 -53
  145. data/public/lookbook-assets/css/lookbook.css +432 -376
  146. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  147. data/public/lookbook-assets/css/themes/blue.css +7 -0
  148. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  149. data/public/lookbook-assets/css/themes/green.css +7 -0
  150. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  151. data/public/lookbook-assets/css/themes/indigo.css +7 -0
  152. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  153. data/public/lookbook-assets/css/themes/rose.css +7 -0
  154. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  155. data/public/lookbook-assets/css/themes/zinc.css +7 -0
  156. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  157. data/public/lookbook-assets/img/lucide-sprite.svg +4960 -0
  158. data/public/lookbook-assets/js/embed.js +1363 -843
  159. data/public/lookbook-assets/js/embed.js.map +1 -1
  160. data/public/lookbook-assets/js/iframe.js +906 -0
  161. data/public/lookbook-assets/js/iframe.js.map +1 -0
  162. data/public/lookbook-assets/js/index.js +13567 -0
  163. data/public/lookbook-assets/js/index.js.map +1 -0
  164. data/public/lookbook-assets/js/lookbook-core.js +85 -0
  165. data/public/lookbook-assets/js/lookbook-core.js.map +1 -0
  166. data/public/lookbook-assets/js/lookbook.js +151 -12726
  167. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  168. data/public/lookbook-assets/lookbook-esm.js +1427 -0
  169. data/public/lookbook-assets/lookbook-esm.js.map +1 -0
  170. data/public/lookbook-assets/lookbook-global.js +1427 -0
  171. data/public/lookbook-assets/lookbook-global.js.map +1 -0
  172. data/public/lookbook-assets/lookbook.js +1427 -0
  173. data/public/lookbook-assets/lookbook.js.map +1 -0
  174. metadata +85 -77
  175. data/app/components/lookbook/embed/component.js +0 -39
  176. data/app/helpers/lookbook/component_helper.rb +0 -84
  177. data/app/helpers/lookbook/output_helper.rb +0 -19
  178. data/app/helpers/lookbook/page_helper.rb +0 -34
  179. data/app/views/layouts/lookbook/inspector.html.erb +0 -7
  180. data/app/views/layouts/lookbook/page.html.erb +0 -53
  181. data/app/views/layouts/lookbook/standalone.html.erb +0 -5
  182. data/app/views/lookbook/preview.html.erb +0 -14
  183. data/lib/lookbook/entities/collections/component_collection.rb +0 -4
  184. data/lib/lookbook/entities/collections/preview_example_collection.rb +0 -4
  185. data/lib/lookbook/entities/component.rb +0 -31
  186. data/lib/lookbook/entities/concerns/navigable.rb +0 -43
  187. data/lib/lookbook/entities/preview.rb +0 -87
  188. data/lib/lookbook/entities/preview_example.rb +0 -104
  189. data/lib/lookbook/entities/preview_group.rb +0 -52
  190. data/lib/lookbook/preview_actions.rb +0 -43
  191. data/lib/lookbook/process.rb +0 -21
  192. data/lib/lookbook/rendered_example.rb +0 -37
  193. data/lib/lookbook/services/position_prefix_parser.rb +0 -16
  194. data/lib/lookbook/services/urls/search_param_builder.rb +0 -13
  195. data/lib/lookbook/tags/component_tag.rb +0 -13
  196. /data/app/assets/lookbook/js/{embed.js → iframe.js} +0 -0
  197. /data/{app/channels/lookbook → lib/lookbook/cable}/connection.rb +0 -0
  198. /data/{app/channels/lookbook → lib/lookbook/cable}/reload_channel.rb +0 -0
@@ -14,7 +14,7 @@ module Lookbook
14
14
 
15
15
  def add(to_add = nil)
16
16
  Array(to_add).each do |entity|
17
- unless find_by_path(entity.path)
17
+ unless find_by_path(entity.lookup_path)
18
18
  @entities.push(entity)
19
19
  end
20
20
  end
@@ -23,20 +23,20 @@ module Lookbook
23
23
 
24
24
  def find_by_id(id)
25
25
  id = Utils.id(id)
26
- entities.find { |entity| entity.id == id }
26
+ @entities.find { |entity| entity.id == id }
27
27
  end
28
28
 
29
29
  def find_by_path(path)
30
- entities.find { |entity| entity.path.to_s == path.to_s }
30
+ @entities.find { |entity| entity.lookup_path.to_s == path.to_s }
31
31
  end
32
32
 
33
33
  def next(entity)
34
- index = entities.find_index { |i| i.path == entity.path }
34
+ index = entities.find_index { |i| i.lookup_path == entity.lookup_path }
35
35
  entities[index + 1] unless index.nil?
36
36
  end
37
37
 
38
38
  def previous(entity)
39
- index = entities.find_index { |i| i.path == entity.path }
39
+ index = entities.find_index { |i| i.lookup_path == entity.lookup_path }
40
40
  entities[index - 1] if !index.nil? && index > 0
41
41
  end
42
42
 
@@ -49,7 +49,12 @@ module Lookbook
49
49
  end
50
50
 
51
51
  def flat_map(...)
52
- entities.map(...).map(&:to_a).flatten
52
+ entities.map(...).map { |e| e.respond_to?(:to_a) ? e.to_a : e }.flatten
53
+ end
54
+
55
+ def clear_all
56
+ @entities = []
57
+ clear_cache
53
58
  end
54
59
 
55
60
  protected
@@ -2,14 +2,33 @@ module Lookbook
2
2
  class PageCollection < EntityCollection
3
3
  include HierarchicalCollection
4
4
 
5
- def load(page_paths)
6
- @entities = []
7
- clear_cache
5
+ def load(page_paths, changes = nil)
6
+ file_paths = PageCollection.file_paths(page_paths)
7
+ reload_all(file_paths) # TODO: Fix incremental reloading
8
+ # changes.present? ? reload_changed(file_paths, changes) : reload_all(file_paths)
9
+ end
8
10
 
9
- file_paths = page_paths.flat_map do |dir|
10
- PathUtils.normalize_paths(Dir["#{dir}/**/*.html.*", "#{dir}/**/*.md.*"].sort)
11
- end
11
+ def reload_all(file_paths)
12
+ clear_all
13
+ add(pages_from_paths(file_paths))
14
+ end
15
+
16
+ def reload_changed(file_paths, changes)
17
+ modified = Array(changes[:modified])
18
+ removed = Array(changes[:removed]) + modified
19
+ added = Array(changes[:added]) + modified
20
+
21
+ remove_by_file_path(removed)
22
+ add(pages_from_paths(added))
23
+ end
12
24
 
25
+ def remove_by_file_path(paths)
26
+ paths = Array(paths).map(&:to_s)
27
+ @entities.reject! { |page| page.file_path.to_s.in?(paths) }
28
+ clear_cache
29
+ end
30
+
31
+ def pages_from_paths(file_paths)
13
32
  entities = file_paths.map { |path| PageCollection.entity(path) }
14
33
  pages, sections = entities.partition { |page| page.type == :page }
15
34
 
@@ -20,11 +39,17 @@ module Lookbook
20
39
  parent.add_section(section)
21
40
  end
22
41
 
23
- add(pages)
42
+ pages
43
+ end
44
+
45
+ def self.file_paths(directories)
46
+ directories.flat_map do |dir|
47
+ PathUtils.normalize_paths(Dir["#{dir}/**/*.html.*", "#{dir}/**/*.md.*"].sort)
48
+ end
24
49
  end
25
50
 
26
51
  def self.entity(file_path)
27
- File.basename(file_path).match?(%r{\[(.*?\w+)\]}) ? PageSection.new(file_path) : Page.new(file_path)
52
+ File.basename(file_path).match?(%r{\[(.*?\w+)\]}) ? PageSectionEntity.new(file_path) : PageEntity.new(file_path)
28
53
  end
29
54
  end
30
55
  end
@@ -2,40 +2,65 @@ module Lookbook
2
2
  class PreviewCollection < EntityCollection
3
3
  include HierarchicalCollection
4
4
 
5
- def find_example_by_path(lookup_path)
6
- examples.find_by_path(lookup_path)
5
+ def find_scenario_by_path(lookup_path)
6
+ scenarios.find_by_path(lookup_path)
7
7
  end
8
8
 
9
9
  def find_by_preview_class(klass)
10
10
  find { |preview| preview.preview_class.name == klass.to_s }
11
11
  end
12
12
 
13
- def load(code_objects)
14
- @entities = []
15
- clear_cache
13
+ def load(code_objects, changes = nil)
14
+ changes.present? ? reload_changed(code_objects, changes) : reload_all(code_objects)
15
+ end
16
16
 
17
- previews = Array(code_objects).map { |obj| PreviewCollection.preview_from_code_object(obj) }.compact
17
+ def reload_all(code_objects)
18
+ clear_all
19
+ previews = code_objects.map { |obj| PreviewCollection.preview_from_code_object(obj) }.compact
18
20
  add(previews)
19
21
  end
20
22
 
21
- def self.preview_from_code_object(code_object)
22
- klass = code_object.path.constantize
23
- Preview.new(code_object) if preview_class?(klass)
24
- rescue => exception
25
- Lookbook.logger.error exception.to_s
26
- nil
23
+ def reload_changed(code_objects, changes)
24
+ modified = Array(changes[:modified])
25
+ removed = Array(changes[:removed]) + modified
26
+ added = Array(changes[:added]) + modified
27
+
28
+ remove_by_file_path(removed)
29
+
30
+ previews = added.map do |path|
31
+ code_object = code_objects.find { |obj| obj if obj&.file.to_s == path.to_s }
32
+ PreviewCollection.preview_from_code_object(code_object) if code_object
33
+ end.compact
34
+
35
+ add(previews)
27
36
  end
28
37
 
29
- def self.preview_class?(klass)
30
- if klass.ancestors.include?(ViewComponent::Preview)
31
- !klass.respond_to?(:abstract_class) || klass.abstract_class != true
38
+ def remove_by_file_path(paths)
39
+ paths = Array(paths).map(&:to_s)
40
+ @entities.reject! { |preview| preview.file_path.to_s.in?(paths) }
41
+ clear_cache
42
+ end
43
+
44
+ class << self
45
+ def preview_from_code_object(code_object)
46
+ klass = code_object.path.constantize
47
+ PreviewEntity.new(code_object) if preview_class?(klass)
48
+ rescue => exception
49
+ Lookbook.logger.error exception.to_s
50
+ nil
51
+ end
52
+
53
+ def preview_class?(klass)
54
+ if (defined?(ViewComponent) && klass.ancestors.include?(ViewComponent::Preview)) || klass.ancestors.include?(Lookbook::Preview)
55
+ !klass.respond_to?(:abstract_class) || klass.abstract_class != true
56
+ end
32
57
  end
33
58
  end
34
59
 
35
60
  protected
36
61
 
37
- def examples
38
- @_cache[:examples] ||= PreviewExampleCollection.new(flat_map(&:examples))
62
+ def scenarios
63
+ @_cache[:scenarios] ||= ScenarioCollection.new(flat_map(&:scenarios))
39
64
  end
40
65
  end
41
66
  end
@@ -0,0 +1,4 @@
1
+ module Lookbook
2
+ class RenderTargetCollection < EntityCollection
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Lookbook
2
+ class ScenarioCollection < EntityCollection
3
+ end
4
+ end
@@ -1,5 +1,6 @@
1
1
  module Lookbook
2
- module Annotatable
2
+ # @api private
3
+ module AnnotatableEntity
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
@@ -23,8 +24,8 @@ module Lookbook
23
24
 
24
25
  def fetch_config(key, fallback = nil, &block)
25
26
  value = case key.to_sym
26
- when :components
27
- components_config
27
+ when :renders
28
+ renders_config
28
29
  when :display_options
29
30
  display_options_config
30
31
  else
@@ -36,10 +37,10 @@ module Lookbook
36
37
 
37
38
  private
38
39
 
39
- def components_config
40
- return unless has_tag?(:component)
40
+ def renders_config
41
+ return unless has_tag?(:component) || has_tag?(:renders)
41
42
 
42
- Array(tags(:component)).map(&:value).compact
43
+ [*tags(:component), *tags(:renders)].map(&:value).compact
43
44
  end
44
45
 
45
46
  def display_options_config
@@ -1,5 +1,6 @@
1
1
  module Lookbook
2
- module Inspectable
2
+ # @api private
3
+ module InspectableEntity
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
@@ -1,5 +1,6 @@
1
1
  module Lookbook
2
- module Locatable
2
+ # @api private
3
+ module LocatableEntity
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
@@ -41,20 +42,13 @@ module Lookbook
41
42
  @_logical_path ||= PathUtils.to_path(directory, file_name_base)
42
43
  end
43
44
 
44
- def full_path
45
- Lookbook.logger.warn "The `full_path` method has been deprecated - use `file_path` instead. `full_path` will be removed in v2.0"
46
- file_path
47
- end
48
-
49
- def rel_path
50
- Lookbook.logger.warn "The `rel_path` method has been deprecated - use `relative_file_path` instead. `rel_path` will be removed in v2.0"
51
- relative_file_path
52
- end
45
+ alias_method :full_path, :file_path
46
+ alias_method :rel_path, :relative_file_path
47
+ alias_method :dir_path, :directory_path
53
48
 
54
- def dir_path
55
- Lookbook.logger.warn "The `dir_path` method has been deprecated - use `directory_path` instead. `dir_path` will be removed in v2.0"
56
- directory_path
57
- end
49
+ deprecate full_path: :file_path, deprecator: Deprecation
50
+ deprecate rel_path: :relative_file_path, deprecator: Deprecation
51
+ deprecate dir_path: :directory_path, deprecator: Deprecation
58
52
 
59
53
  protected
60
54
 
@@ -0,0 +1,44 @@
1
+ module Lookbook
2
+ # @api private
3
+ module NavigableEntity
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def hidden?
8
+ fetch_config(:hidden, false)
9
+ end
10
+
11
+ def visible?
12
+ !hidden?
13
+ end
14
+
15
+ def priority
16
+ return @_priority if @_priority
17
+
18
+ pos = if @priority_prefixes && respond_to?(:file_name)
19
+ PriorityPrefixParser.call(file_name).first || fetch_config(:priority, default_priority)
20
+ else
21
+ fetch_config(:priority, default_priority)
22
+ end
23
+
24
+ @_priority ||= pos.to_i
25
+ end
26
+
27
+ def depth
28
+ lookup_path.split("/").size
29
+ end
30
+
31
+ def default_priority
32
+ @default_priority || 10000
33
+ end
34
+
35
+ def <=>(other)
36
+ if respond_to?(:sort_handler, true)
37
+ sort_handler(other)
38
+ else
39
+ [priority, label] <=> [other.priority, other.label]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,7 +1,10 @@
1
1
  module Lookbook
2
+ # Base entity class
3
+ #
4
+ # @api private
2
5
  class Entity
3
6
  include Comparable
4
- include Lookbook::Engine.routes.url_helpers
7
+ send(:include, Lookbook::Engine.routes.url_helpers) # YARD parsing workaround: https://github.com/lsegal/yard/issues/546
5
8
 
6
9
  def initialize(lookup_path = nil)
7
10
  @lookup_path = lookup_path
@@ -34,7 +37,7 @@ module Lookbook
34
37
  end
35
38
 
36
39
  def type
37
- @_type ||= self.class.name.demodulize.underscore.downcase.to_sym
40
+ @_type ||= self.class.name.gsub("Entity", "").demodulize.underscore.downcase.to_sym
38
41
  end
39
42
 
40
43
  def <=>(other)
@@ -44,6 +47,8 @@ module Lookbook
44
47
  alias_method :path, :lookup_path
45
48
  alias_method :logical_path, :lookup_path
46
49
 
50
+ deprecate path: :lookup_path, deprecator: Deprecation
51
+
47
52
  protected
48
53
 
49
54
  def fetch_config(key, fallback = nil, &block)
@@ -1,7 +1,11 @@
1
1
  module Lookbook
2
- class Page < Entity
3
- include Locatable
4
- include Navigable
2
+ # Represents a documentation page
3
+ #
4
+ # @ignore methods
5
+ # @api public
6
+ class PageEntity < Entity
7
+ include LocatableEntity
8
+ include NavigableEntity
5
9
 
6
10
  attr_reader :content, :sections
7
11
 
@@ -10,7 +14,7 @@ module Lookbook
10
14
  @base_directories = Engine.page_paths
11
15
  @lookup_path = PathUtils.to_lookup_path(relative_file_path)
12
16
  @frontmatter, @content = FrontmatterExtractor.call(file_contents)
13
- @position_prefixes = true
17
+ @priority_prefixes = true
14
18
  @sections = []
15
19
  end
16
20
 
@@ -46,12 +50,12 @@ module Lookbook
46
50
  end
47
51
 
48
52
  def url_path
49
- lookbook_page_path(path)
53
+ lookbook_page_path(lookup_path)
50
54
  end
51
55
 
52
56
  def add_section(section)
53
57
  @sections << section
54
- @sections.sort_by! { |section| [section.position, section.label] }
58
+ @sections.sort_by! { |section| [section.priority, section.label] }
55
59
  end
56
60
 
57
61
  def method_missing(method_name, *args, &block)
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class PageSection < Page
2
+ class PageSectionEntity < PageEntity
3
3
  attr_accessor :parent
4
4
 
5
5
  def initialize(file_path)
@@ -0,0 +1,99 @@
1
+ module Lookbook
2
+ # Represents a preview class
3
+ #
4
+ # @ignore methods
5
+ # @api public
6
+ class PreviewEntity < Entity
7
+ include AnnotatableEntity
8
+ include LocatableEntity
9
+ include NavigableEntity
10
+
11
+ delegate :render_args, to: :preview_class
12
+
13
+ attr_reader :preview_class
14
+
15
+ def initialize(code_object)
16
+ @code_object = code_object
17
+ @preview_class = code_object.path.constantize
18
+ @file_path = Pathname(code_object.file)
19
+ @base_directories = Engine.preview_paths
20
+
21
+ cleaned_path = relative_file_path.to_s
22
+ .gsub(/\/(component_preview|preview)(\..*)$/, "")
23
+ .gsub(/(_component_preview|_preview)(\..*)$/, "")
24
+
25
+ @lookup_path = PathUtils.to_lookup_path(cleaned_path)
26
+ end
27
+
28
+ def scenarios
29
+ @_scenarios ||= ScenarioCollection.new(load_scenarios)
30
+ end
31
+
32
+ def scenario(scenario_name)
33
+ scenarios.find { |m| m.name == scenario_name.to_s }
34
+ end
35
+
36
+ def visible_scenarios
37
+ @_visible_scenarios ||= ScenarioCollection.new(scenarios.select(&:visible?))
38
+ end
39
+
40
+ def default_scenario
41
+ visible_scenarios.first
42
+ end
43
+
44
+ def render_targets
45
+ @_render_targets ||= RenderTargetCollection.new(scenarios.flat_map(&:render_targets).uniq(&:lookup_path))
46
+ end
47
+
48
+ def render_target
49
+ render_targets.first
50
+ end
51
+
52
+ def display_options
53
+ global_options = Lookbook.config.preview_display_options
54
+ global_options.deep_merge(fetch_config(:display_options, {}))
55
+ end
56
+
57
+ def layout
58
+ preview_class.instance_variable_get(:@layout)
59
+ end
60
+
61
+ def url_path
62
+ lookbook_inspect_path(lookup_path)
63
+ end
64
+
65
+ def preview_class_name
66
+ preview_class.name
67
+ end
68
+
69
+ def guess_render_targets
70
+ [preview_class.name.chomp("Preview").constantize&.name]
71
+ rescue
72
+ []
73
+ end
74
+
75
+ alias_method :components, :render_targets
76
+ alias_method :component, :render_target
77
+ alias_method :examples, :scenarios
78
+ alias_method :example, :scenario
79
+
80
+ deprecate examples: :scenarios, deprecator: Deprecation
81
+ deprecate example: :scenario, deprecator: Deprecation
82
+
83
+ protected
84
+
85
+ def load_scenarios
86
+ return scenario_entities unless code_object.groups.any?
87
+
88
+ scenario_entities.group_by(&:group).flat_map do |group_name, grouped_scenarios|
89
+ group_name.nil? ? grouped_scenarios : ScenarioGroupEntity.new(group_name.presence || label.pluralize, grouped_scenarios, self)
90
+ end
91
+ end
92
+
93
+ def scenario_entities
94
+ public_methods = preview_class.public_instance_methods(false)
95
+ method_objects = code_object.meths.select { |m| public_methods.include?(m.name) }
96
+ method_objects.map.with_index { |code_object, i| ScenarioEntity.new(code_object, self, priority: i) }
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,50 @@
1
+ module Lookbook
2
+ # Represents the component or view template partial
3
+ # that is being rendered in a preview.
4
+ #
5
+ # @ignore methods
6
+ # @api public
7
+ class RenderableEntity < Entity
8
+ include LocatableEntity
9
+
10
+ def initialize(identifier)
11
+ @identifier = identifier
12
+ @base_directories = Engine.component_paths
13
+ @file_path = PathUtils.determine_full_path(component? ? "#{name}.rb" : identifier, @base_directories)
14
+ unless @file_path && File.exist?(@file_path)
15
+ raise LookbookError, "The render target #{@identifier} was not found."
16
+ end
17
+ @lookup_path = PathUtils.to_lookup_path(relative_file_path)
18
+ end
19
+
20
+ def component_class
21
+ @identifier.constantize if component?
22
+ end
23
+
24
+ def name
25
+ component? ? component_class.name.underscore : @identifier
26
+ end
27
+
28
+ def template_file_path
29
+ component? ? Dir.glob("#{directory_path}/#{file_name(true)}.*.erb").first : file_path
30
+ end
31
+
32
+ def inline?
33
+ component? ? template_file_path.present? : false
34
+ end
35
+
36
+ def component?
37
+ @identifier.first.upcase == @identifier.first &&
38
+ !@identifier.include?(".") &&
39
+ !@identifier.include?("/")
40
+ end
41
+
42
+ def template?
43
+ !component?
44
+ end
45
+
46
+ def type
47
+ component? ? :component : :template
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,53 @@
1
+ module Lookbook
2
+ # Represents a **rendered** preview scenario
3
+ #
4
+ # @ignore methods
5
+ # @api public
6
+ class RenderedScenarioEntity
7
+ delegate_missing_to :scenario
8
+
9
+ attr_reader :scenario
10
+
11
+ def initialize(scenario, output, params)
12
+ @scenario = scenario
13
+ @params = params
14
+ @output = output
15
+ end
16
+
17
+ def source
18
+ has_custom_template? ? template_source(template) : scenario.source
19
+ end
20
+
21
+ def source_lang
22
+ has_custom_template? ? template_lang(template) : scenario.source_lang
23
+ end
24
+
25
+ def output
26
+ @_output ||= CodeBeautifier.call(@output)
27
+ end
28
+
29
+ protected
30
+
31
+ attr_reader :params
32
+
33
+ def render_args
34
+ @_render_args ||= preview.render_args(scenario.name, params: params)
35
+ end
36
+
37
+ def template
38
+ render_args[:template]
39
+ end
40
+
41
+ def view?
42
+ render_args[:type] == :view
43
+ end
44
+
45
+ def has_custom_template?
46
+ !template.in?(system_templates) && !custom_source? && !view?
47
+ end
48
+
49
+ def system_templates
50
+ ["view_components/preview", Lookbook.config.preview_template]
51
+ end
52
+ end
53
+ end