lookbook 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -11
- data/app/assets/lookbook/css/themes/blue.css +1 -1
- data/app/assets/lookbook/css/themes/green.css +66 -0
- data/app/assets/lookbook/css/themes/indigo.css +1 -1
- data/app/assets/lookbook/css/themes/rose.css +66 -0
- data/app/assets/lookbook/css/themes/zinc.css +1 -1
- data/app/components/lookbook/base_component.rb +2 -2
- data/app/components/lookbook/code/component.rb +2 -2
- data/app/components/lookbook/header/component.html.erb +1 -1
- data/app/components/lookbook/inspector_panel/component.rb +1 -1
- data/app/components/lookbook/nav/component.rb +8 -15
- data/app/components/lookbook/nav/directory/component.html.erb +26 -0
- data/app/components/lookbook/nav/directory/component.rb +4 -0
- data/app/components/lookbook/nav/{item → entity}/component.html.erb +5 -7
- data/app/components/lookbook/nav/entity/component.rb +49 -0
- data/app/components/lookbook/nav/item/component.css +15 -0
- data/app/components/lookbook/nav/item/component.js +4 -0
- data/app/components/lookbook/nav/item/component.rb +13 -56
- data/app/components/lookbook/tag_component.rb +1 -1
- data/app/components/lookbook/viewport/component.rb +1 -1
- data/app/controllers/concerns/lookbook/targetable_concern.rb +13 -38
- data/app/controllers/lookbook/application_controller.rb +9 -7
- data/app/controllers/lookbook/page_controller.rb +2 -2
- data/app/controllers/lookbook/pages_controller.rb +9 -15
- data/app/helpers/lookbook/application_helper.rb +2 -2
- data/app/helpers/lookbook/page_helper.rb +7 -4
- data/app/views/layouts/lookbook/application.html.erb +3 -4
- data/app/views/layouts/lookbook/page.html.erb +2 -2
- data/app/views/layouts/lookbook/shell.html.erb +2 -2
- data/app/views/layouts/lookbook/skeleton.html.erb +7 -7
- data/app/views/lookbook/index.html.erb +3 -3
- data/app/views/lookbook/inspector/panels/_params.html.erb +2 -2
- data/config/languages.yml +41 -0
- data/config/panels.yml +1 -1
- data/config/tags.yml +4 -0
- data/lib/lookbook/engine.rb +65 -43
- data/lib/lookbook/entities/collections/component_collection.rb +4 -0
- data/lib/lookbook/entities/collections/concerns/hierarchical_collection.rb +27 -0
- data/lib/lookbook/entities/collections/entity_collection.rb +66 -0
- data/lib/lookbook/entities/collections/page_collection.rb +30 -0
- data/lib/lookbook/entities/collections/preview_collection.rb +35 -0
- data/lib/lookbook/entities/collections/preview_example_collection.rb +9 -0
- data/lib/lookbook/entities/component.rb +31 -0
- data/lib/lookbook/entities/concerns/annotatable.rb +58 -0
- data/lib/lookbook/entities/concerns/inspectable.rb +44 -0
- data/lib/lookbook/entities/concerns/locatable.rb +73 -0
- data/lib/lookbook/entities/concerns/navigable.rb +27 -0
- data/lib/lookbook/entities/entity.rb +48 -0
- data/lib/lookbook/entities/page.rb +80 -0
- data/lib/lookbook/entities/page_section.rb +43 -0
- data/lib/lookbook/entities/preview.rb +87 -0
- data/lib/lookbook/entities/preview_example.rb +91 -0
- data/lib/lookbook/entities/preview_group.rb +48 -0
- data/lib/lookbook/file_watcher.rb +1 -1
- data/lib/lookbook/lang.rb +12 -35
- data/lib/lookbook/param.rb +2 -2
- data/lib/lookbook/preview_parser.rb +1 -1
- data/lib/lookbook/rendered_example.rb +37 -0
- data/lib/lookbook/services/code/code_beautifier.rb +1 -1
- data/lib/lookbook/services/code/code_highlighter.rb +1 -1
- data/lib/lookbook/services/code/code_indenter.rb +14 -0
- data/lib/lookbook/services/data/resolvers/data_resolver.rb +2 -2
- data/lib/lookbook/services/data/resolvers/method_resolver.rb +1 -1
- data/lib/lookbook/services/entities/entity_tree_builder.rb +45 -0
- data/lib/lookbook/services/position_prefix_parser.rb +16 -0
- data/lib/lookbook/stores/config_store.rb +1 -1
- data/lib/lookbook/stores/panel_store.rb +2 -2
- data/lib/lookbook/support/store.rb +1 -34
- data/lib/lookbook/support/tree_node.rb +83 -0
- data/lib/lookbook/support/utils/path_utils.rb +26 -2
- data/lib/lookbook/support/utils/utils.rb +24 -0
- data/lib/lookbook/tags/component_tag.rb +6 -0
- data/lib/lookbook/tags/custom_tag.rb +2 -0
- data/lib/lookbook/tags/id_tag.rb +1 -1
- data/lib/lookbook/tags/logical_path_tag.rb +3 -0
- data/lib/lookbook/tags/param_tag.rb +2 -0
- data/lib/lookbook/tags/position_tag.rb +1 -1
- data/lib/lookbook/tags/source_tag.rb +7 -0
- data/lib/lookbook/tags/yard_tag.rb +35 -7
- data/lib/lookbook/theme.rb +8 -0
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +11 -7
- data/public/lookbook-assets/css/lookbook.css +55 -125
- data/public/lookbook-assets/css/lookbook.css.map +1 -1
- data/public/lookbook-assets/css/themes/blue.css.map +1 -1
- data/public/lookbook-assets/css/themes/green.css +68 -0
- data/public/lookbook-assets/css/themes/green.css.map +1 -0
- data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
- data/public/lookbook-assets/css/themes/rose.css +68 -0
- data/public/lookbook-assets/css/themes/rose.css.map +1 -0
- data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
- data/public/lookbook-assets/js/embed.js +9 -0
- data/public/lookbook-assets/js/embed.js.map +1 -1
- data/public/lookbook-assets/js/lookbook.js +288 -565
- data/public/lookbook-assets/js/lookbook.js.map +1 -1
- metadata +41 -18
- data/lib/lookbook/collection.rb +0 -161
- data/lib/lookbook/component.rb +0 -34
- data/lib/lookbook/entity.rb +0 -47
- data/lib/lookbook/page.rb +0 -194
- data/lib/lookbook/page_collection.rb +0 -19
- data/lib/lookbook/page_section.rb +0 -29
- data/lib/lookbook/preview.rb +0 -181
- data/lib/lookbook/preview_collection.rb +0 -23
- data/lib/lookbook/preview_example.rb +0 -93
- data/lib/lookbook/preview_group.rb +0 -58
- data/lib/lookbook/source_inspector.rb +0 -76
- data/lib/lookbook/support/utils/attribute_utils.rb +0 -14
- data/lib/lookbook/utils.rb +0 -65
@@ -9,16 +9,16 @@ module Lookbook
|
|
9
9
|
helper Lookbook::ComponentHelper
|
10
10
|
|
11
11
|
before_action :generate_theme_overrides
|
12
|
-
before_action :
|
12
|
+
before_action :assign_instance_vars
|
13
13
|
|
14
14
|
def self.controller_path
|
15
15
|
"lookbook"
|
16
16
|
end
|
17
17
|
|
18
18
|
def index
|
19
|
-
landing = Lookbook.pages.find(&:landing) || Lookbook.pages.first
|
19
|
+
landing = Lookbook.pages.find(&:landing?) || Lookbook.pages.first
|
20
20
|
if landing.present?
|
21
|
-
redirect_to lookbook_page_path(landing.
|
21
|
+
redirect_to lookbook_page_path(landing.path)
|
22
22
|
else
|
23
23
|
render "lookbook/index"
|
24
24
|
end
|
@@ -30,9 +30,11 @@ module Lookbook
|
|
30
30
|
@theme_overrides ||= Lookbook.theme.to_css
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
@previews =
|
35
|
-
@pages =
|
33
|
+
def assign_instance_vars
|
34
|
+
@previews = Lookbook.previews
|
35
|
+
@pages = Lookbook.pages
|
36
|
+
@config = Lookbook.config
|
37
|
+
@engine = Lookbook.engine
|
36
38
|
end
|
37
39
|
|
38
40
|
def feature_enabled?(feature)
|
@@ -48,7 +50,7 @@ module Lookbook
|
|
48
50
|
error_params = {}
|
49
51
|
if exception.is_a?(ViewComponent::PreviewTemplateError)
|
50
52
|
error_params = {
|
51
|
-
file_path: @preview&.
|
53
|
+
file_path: @preview&.file_path,
|
52
54
|
line_number: 0,
|
53
55
|
source_code: @target&.source
|
54
56
|
}
|
@@ -11,8 +11,8 @@ module Lookbook
|
|
11
11
|
def render_page(page, locals = {})
|
12
12
|
@page = page
|
13
13
|
@pages = Lookbook.pages
|
14
|
-
@next_page = @pages.
|
15
|
-
@previous_page = @pages.
|
14
|
+
@next_page = @pages.next(@page)
|
15
|
+
@previous_page = @pages.previous(@page)
|
16
16
|
|
17
17
|
content = ActionViewAnnotationsHandler.call(disable_annotations: true) do
|
18
18
|
render_to_string inline: @page.content, locals: {
|
@@ -9,9 +9,9 @@ module Lookbook
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def index
|
12
|
-
landing = Lookbook.pages.find(&:landing) || Lookbook.pages.first
|
12
|
+
landing = Lookbook.pages.find(&:landing?) || Lookbook.pages.first
|
13
13
|
if landing.present?
|
14
|
-
redirect_to lookbook_page_path
|
14
|
+
redirect_to lookbook_page_path(landing.path)
|
15
15
|
else
|
16
16
|
show_404
|
17
17
|
end
|
@@ -20,21 +20,15 @@ module Lookbook
|
|
20
20
|
def show
|
21
21
|
@page = @pages.find_by_path(params[:path])
|
22
22
|
if @page
|
23
|
-
@next_page = @pages.
|
24
|
-
@previous_page = @pages.
|
25
|
-
|
23
|
+
@next_page = @pages.next(@page)
|
24
|
+
@previous_page = @pages.previous(@page)
|
25
|
+
begin
|
26
|
+
@page_content = page_controller.render_page(@page)
|
27
|
+
@title = @page.title
|
28
|
+
rescue => exception
|
26
29
|
render_in_layout "lookbook/error",
|
27
30
|
layout: "lookbook/page",
|
28
|
-
error: @page.
|
29
|
-
else
|
30
|
-
begin
|
31
|
-
@page_content = page_controller.render_page(@page)
|
32
|
-
@title = @page.title
|
33
|
-
rescue => exception
|
34
|
-
render_in_layout "lookbook/error",
|
35
|
-
layout: "lookbook/page",
|
36
|
-
error: Lookbook::Error.new(exception, file_path: @page.full_path, source_code: @page.content)
|
37
|
-
end
|
31
|
+
error: Lookbook::Error.new(exception, file_path: @page.file_path, source_code: @page.content)
|
38
32
|
end
|
39
33
|
else
|
40
34
|
show_404
|
@@ -18,7 +18,7 @@ module Lookbook
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def landing_path
|
21
|
-
landing = Lookbook.pages.find(&:landing) || Lookbook.pages.first
|
21
|
+
landing = Lookbook.pages.find(&:landing?) || Lookbook.pages.first
|
22
22
|
if landing.present?
|
23
23
|
lookbook_page_path landing.lookup_path
|
24
24
|
else
|
@@ -27,7 +27,7 @@ module Lookbook
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def generate_id(*args)
|
30
|
-
args.map { |args| args.delete_prefix("/").tr("&?=/_
|
30
|
+
args.map { |args| args.delete_prefix("/").tr("&?=/_-", "-") }.join("-")
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -3,7 +3,7 @@ module Lookbook
|
|
3
3
|
include Utils
|
4
4
|
|
5
5
|
def page_path(id)
|
6
|
-
page = id.is_a?(Page) ? id : Lookbook.pages.
|
6
|
+
page = id.is_a?(Page) ? id : Lookbook.pages.find_by_id(id)
|
7
7
|
if page.present?
|
8
8
|
lookbook_page_path page.lookup_path
|
9
9
|
else
|
@@ -16,10 +16,13 @@ module Lookbook
|
|
16
16
|
|
17
17
|
@embed_counter ||= 0
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
preview = if args.first.is_a?(Symbol)
|
20
|
+
Lookbook.previews.find_by_path(args.first)
|
21
|
+
else
|
22
|
+
Lookbook.previews.find_by_preview_class(args.first)
|
23
|
+
end
|
22
24
|
|
25
|
+
example = args[1] ? preview&.example(args[1]) : preview&.default_example
|
23
26
|
embed_id = "#{url_for}/embed/#{example.lookup_path}".delete_prefix("/").tr("/", "-")
|
24
27
|
|
25
28
|
lookbook_render :embed,
|
@@ -21,9 +21,8 @@
|
|
21
21
|
<% layout.pane class: "overflow-hidden" do %>
|
22
22
|
<%= lookbook_render :nav,
|
23
23
|
id: "previews-nav",
|
24
|
-
|
25
|
-
alpine_data: "$store.nav.previews"
|
26
|
-
collapse_singles: true do |nav| %>
|
24
|
+
tree: @previews.to_tree,
|
25
|
+
alpine_data: "$store.nav.previews" do |nav| %>
|
27
26
|
<%= nav.toolbar do |toolbar| %>
|
28
27
|
<% toolbar.section padded: true do %>
|
29
28
|
<h4 class="pt-1">Previews</h4>
|
@@ -45,7 +44,7 @@
|
|
45
44
|
<% layout.pane class: "overflow-hidden" do %>
|
46
45
|
<%= lookbook_render :nav,
|
47
46
|
id: "pages-nav",
|
48
|
-
|
47
|
+
tree: @pages.to_tree,
|
49
48
|
alpine_data: "$store.nav.pages" do |nav| %>
|
50
49
|
<%= nav.toolbar do |toolbar| %>
|
51
50
|
<% toolbar.section padded: true do %>
|
@@ -16,7 +16,7 @@
|
|
16
16
|
size: :lg,
|
17
17
|
icon: :chevron_left,
|
18
18
|
tooltip: "Previous page",
|
19
|
-
href: lookbook_page_path(@previous_page.
|
19
|
+
href: lookbook_page_path(@previous_page.path),
|
20
20
|
class: "pr-0.5 bg-transparent" %>
|
21
21
|
<% else %>
|
22
22
|
<%= lookbook_render :button,
|
@@ -31,7 +31,7 @@
|
|
31
31
|
size: :lg,
|
32
32
|
icon: :chevron_right,
|
33
33
|
tooltip: "Next page",
|
34
|
-
href: lookbook_page_path(@next_page.
|
34
|
+
href: lookbook_page_path(@next_page.path),
|
35
35
|
class: "pl-0.5 bg-transparent" %>
|
36
36
|
<% else %>
|
37
37
|
<%= lookbook_render :button,
|
@@ -13,8 +13,8 @@
|
|
13
13
|
</style>
|
14
14
|
<% end %>
|
15
15
|
|
16
|
-
<%= lookbook_render :header, id: "app-header", debug_menu: config.debug_menu do |header| %>
|
17
|
-
<% header.branding { config.project_name } %>
|
16
|
+
<%= lookbook_render :header, id: "app-header", debug_menu: @config.debug_menu do |header| %>
|
17
|
+
<% header.branding { @config.project_name } %>
|
18
18
|
<% end %>
|
19
19
|
|
20
20
|
<%= content_for?(:shell) ? yield(:shell) : yield %>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
7
7
|
|
8
8
|
<link href="<%= asset_path("/css/lookbook.css") %>" rel="stylesheet">
|
9
|
-
<link href="<%= asset_path("/css/themes/#{config.ui_theme}.css") %>" rel="stylesheet">
|
9
|
+
<link href="<%= asset_path("/css/themes/#{@config.ui_theme}.css") %>" rel="stylesheet">
|
10
10
|
|
11
11
|
<%- if @theme_overrides.present? %>
|
12
12
|
<style media="all">
|
@@ -14,7 +14,7 @@
|
|
14
14
|
</style>
|
15
15
|
<% end %>
|
16
16
|
|
17
|
-
<% if config.ui_favicon == true %>
|
17
|
+
<% if @config.ui_favicon == true %>
|
18
18
|
<link
|
19
19
|
rel="icon"
|
20
20
|
href="data:image/svg+xml,%3Csvg width='96' height='84' viewBox='0 0 96 84' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3CclipPath id='a'%3E%3Cpath d='M96 0v84H0V0h96Z'/%3E%3C/clipPath%3E%3CclipPath id='b'%3E%3Cpath d='M71.897 0a1.5 1.5 0 0 1 1.31.769l22.605 40.5a1.5 1.5 0 0 1 0 1.462l-22.605 40.5a1.5 1.5 0 0 1-1.31.769H49.481a1 1 0 0 1-.873-1.487L70.812 42.73a1.5 1.5 0 0 0 0-1.462L48.608 1.487A1 1 0 0 1 49.481 0ZM24.655.564l22.72 40.705a1.5 1.5 0 0 1 0 1.462l-22.72 40.705a1 1 0 0 1-1.746 0L.19 42.73a1.5 1.5 0 0 1 0-1.462L22.91.564a1 1 0 0 1 1.746 0Z'/%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23a)'%3E%3Cg clip-path='url(%23b)'%3E%3Cpath fill='<%= url_encode theme.favicon_dark_mode %>' d='M0 0h96v84H0V0z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"
|
@@ -26,10 +26,10 @@
|
|
26
26
|
<% end %>
|
27
27
|
|
28
28
|
<script>
|
29
|
-
window.LOG_LEVEL = <%= config.log_level %>;
|
30
|
-
window.APP_NAME = "<%=
|
31
|
-
<% if
|
32
|
-
window.SOCKET_PATH = "<%=
|
29
|
+
window.LOG_LEVEL = <%= @config.log_level %>;
|
30
|
+
window.APP_NAME = "<%= @engine.app_name %>";
|
31
|
+
<% if @engine.websocket.mounted? %>
|
32
|
+
window.SOCKET_PATH = "<%= @engine.websocket.full_mount_path %>";
|
33
33
|
<% end %>
|
34
34
|
</script>
|
35
35
|
|
@@ -38,7 +38,7 @@
|
|
38
38
|
<script src="<%= asset_path("/js/embed.js") %>" defer></script>
|
39
39
|
<% end %>
|
40
40
|
|
41
|
-
<title><%= [@title, config.project_name || "Lookbook"].compact.join(" :: ") %></title>
|
41
|
+
<title><%= [@title, @config.project_name || "Lookbook"].compact.join(" :: ") %></title>
|
42
42
|
</head>
|
43
43
|
<body>
|
44
44
|
<%= yield :body %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div id="landing" class="flex flex-col items-center justify-center h-full w-full">
|
2
2
|
<div class="text-center" id="landing-<%= @previews.any? ? "with" : "no" %>-content">
|
3
|
-
<% if config.project_name.downcase == "lookbook" %>
|
3
|
+
<% if @config.project_name.downcase == "lookbook" %>
|
4
4
|
<div class="flex justify-center pb-4">
|
5
5
|
<svg class="flex-none mx-auto w-[140px]" viewBox="0 0 275 36">
|
6
6
|
<g fill-rule="nonzero" fill="none">
|
@@ -9,9 +9,9 @@
|
|
9
9
|
</g>
|
10
10
|
</svg>
|
11
11
|
</div>
|
12
|
-
<% elsif config.project_name != false %>
|
12
|
+
<% elsif @config.project_name != false %>
|
13
13
|
<h5 class="text-base text-lookbook-blank-slate-title truncate uppercase font-black tracking-wide mb-2">
|
14
|
-
<%= config.project_name %>
|
14
|
+
<%= @config.project_name %>
|
15
15
|
</h5>
|
16
16
|
<% end %>
|
17
17
|
<div class="opacity-60">
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<% if @params.none? %>
|
2
|
-
<div class="p-4 w-full h-full bg-lookbook-prose-bg">
|
2
|
+
<div class="p-4 w-full h-full bg-lookbook-prose-bg" id="params-editor-blank-slate">
|
3
3
|
<%= lookbook_render :prose do %>
|
4
4
|
<em class='opacity-50'>No params configured.</em>
|
5
5
|
<% end %>
|
6
6
|
</div>
|
7
7
|
<% else %>
|
8
|
-
<div class="p-4 w-full h-full overflow-x-hidden">
|
8
|
+
<div class="p-4 w-full h-full overflow-x-hidden" id="params-editor-<%= @target.id %>">
|
9
9
|
<%= lookbook_render "params/editor" do |editor| %>
|
10
10
|
<% @params.each do |param| %>
|
11
11
|
<% editor.field param: param %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
shared:
|
2
|
+
definitions:
|
3
|
+
- name: ruby
|
4
|
+
ext: .rb
|
5
|
+
label: Ruby
|
6
|
+
comment: "# %s"
|
7
|
+
|
8
|
+
- name: html
|
9
|
+
ext: .html
|
10
|
+
label: HTML
|
11
|
+
comment: "<!-- %s -->"
|
12
|
+
|
13
|
+
- name: erb
|
14
|
+
ext: .erb
|
15
|
+
label: ERB
|
16
|
+
comment: "<%%# %s %%>"
|
17
|
+
|
18
|
+
- name: haml
|
19
|
+
ext: .haml
|
20
|
+
label: Haml
|
21
|
+
comment: "<!-- %s -->"
|
22
|
+
|
23
|
+
- name: slim
|
24
|
+
ext: .slim
|
25
|
+
label: Slim
|
26
|
+
comment: "<!-- %s -->"
|
27
|
+
|
28
|
+
- name: tsx
|
29
|
+
ext: .tsx
|
30
|
+
label: TypeScript
|
31
|
+
comment: "// %s"
|
32
|
+
|
33
|
+
- name: js
|
34
|
+
ext: .js
|
35
|
+
label: JavasScript
|
36
|
+
comment: "// %s"
|
37
|
+
|
38
|
+
- name: css
|
39
|
+
ext: .css
|
40
|
+
label: CSS
|
41
|
+
comment: "/* %s */"
|
data/config/panels.yml
CHANGED
data/config/tags.yml
CHANGED
data/lib/lookbook/engine.rb
CHANGED
@@ -42,15 +42,16 @@ module Lookbook
|
|
42
42
|
|
43
43
|
initializer "lookbook.file_watcher.pages" do
|
44
44
|
file_watcher.watch(opts.page_paths, opts.page_extensions) do |changes|
|
45
|
-
|
45
|
+
Engine.pages.load(Engine.page_paths)
|
46
|
+
Engine.websocket.broadcast(:reload)
|
46
47
|
run_hooks(:after_change, changes)
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
initializer "lookbook.parser.
|
51
|
-
parser.after_parse do |
|
52
|
-
|
53
|
-
|
51
|
+
initializer "lookbook.parser.previews_load_callback" do
|
52
|
+
parser.after_parse do |code_objects|
|
53
|
+
Engine.previews.load(code_objects.all(:class))
|
54
|
+
Engine.websocket.broadcast(:reload)
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
@@ -74,6 +75,7 @@ module Lookbook
|
|
74
75
|
end
|
75
76
|
|
76
77
|
config.after_initialize do
|
78
|
+
Engine.pages.load(Engine.page_paths)
|
77
79
|
parser.parse { run_hooks(:after_initialize) }
|
78
80
|
end
|
79
81
|
|
@@ -82,71 +84,91 @@ module Lookbook
|
|
82
84
|
end
|
83
85
|
|
84
86
|
def run_hooks(event_name, *args)
|
85
|
-
|
87
|
+
Engine.hooks.for_event(event_name).each do |hook|
|
86
88
|
hook.call(Lookbook, *args)
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
90
92
|
def parser
|
91
|
-
@
|
93
|
+
@_parser ||= PreviewParser.new(opts.preview_paths, Engine.tags)
|
92
94
|
end
|
93
95
|
|
94
96
|
def file_watcher
|
95
|
-
@
|
97
|
+
@_file_watcher ||= FileWatcher.new(force_polling: opts.listen_use_polling)
|
96
98
|
end
|
97
99
|
|
98
100
|
def process
|
99
|
-
@
|
101
|
+
@_process ||= Process.new(env: Rails.env)
|
100
102
|
end
|
101
103
|
|
102
104
|
def listen?
|
103
105
|
opts.listen && process.supports_listening?
|
104
106
|
end
|
105
107
|
|
106
|
-
|
107
|
-
|
108
|
-
|
108
|
+
class << self
|
109
|
+
def mount_path
|
110
|
+
routes.find_script_name({})
|
111
|
+
end
|
109
112
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
+
def mounted?
|
114
|
+
mount_path.present?
|
115
|
+
end
|
113
116
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
117
|
+
def app_name
|
118
|
+
name = if Rails.application.class.respond_to?(:module_parent_name)
|
119
|
+
Rails.application.class.module_parent_name
|
120
|
+
else
|
121
|
+
Rails.application.class.parent_name
|
122
|
+
end
|
123
|
+
name.underscore
|
119
124
|
end
|
120
|
-
name.underscore
|
121
|
-
end
|
122
125
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
def websocket
|
127
|
+
if mounted?
|
128
|
+
use_websocket = opts.auto_refresh && opts.listen && process.supports_listening?
|
129
|
+
@websocket ||= use_websocket ? Websocket.new(mount_path, logger: Lookbook.logger) : Websocket.noop
|
130
|
+
else
|
131
|
+
Websocket.noop
|
132
|
+
end
|
129
133
|
end
|
130
|
-
end
|
131
134
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
+
def panels
|
136
|
+
@_panels ||= PanelStore.init_from_config
|
137
|
+
end
|
135
138
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
+
def inputs
|
140
|
+
@_inputs ||= InputStore.init_from_config
|
141
|
+
end
|
139
142
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
+
def tags
|
144
|
+
@_tags ||= TagStore.init_from_config
|
145
|
+
end
|
143
146
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
+
def hooks
|
148
|
+
@_hooks ||= HookStore.init_from_config
|
149
|
+
end
|
150
|
+
|
151
|
+
def component_paths
|
152
|
+
@_component_paths ||= Array(PathUtils.to_absolute(opts.components_path))
|
153
|
+
end
|
154
|
+
|
155
|
+
def page_paths
|
156
|
+
@_page_paths ||= PathUtils.normalize_paths(opts.page_paths)
|
157
|
+
end
|
158
|
+
|
159
|
+
def preview_paths
|
160
|
+
@_preview_paths ||= PathUtils.normalize_paths(opts.preview_paths)
|
161
|
+
end
|
162
|
+
|
163
|
+
def pages
|
164
|
+
@_pages ||= PageCollection.new
|
165
|
+
end
|
166
|
+
|
167
|
+
def previews
|
168
|
+
@_previews ||= PreviewCollection.new
|
169
|
+
end
|
147
170
|
|
148
|
-
|
149
|
-
@preview_controller
|
171
|
+
attr_reader :preview_controller
|
150
172
|
end
|
151
173
|
|
152
174
|
at_exit do
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Lookbook
|
2
|
+
module HierarchicalCollection
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def entities
|
7
|
+
@_cache[:entities] ||= collect_ordered_entities(to_tree(include_hidden: true))
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_tree(include_hidden: false)
|
11
|
+
@_cache[include_hidden ? :tree_with_hidden : :tree] ||= EntityTreeBuilder.call(@entities, include_hidden: include_hidden)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def collect_ordered_entities(start_node)
|
17
|
+
start_node.inject([]) do |entities, node|
|
18
|
+
entities.append(node.content? ? node.content : collect_ordered_entities(node))
|
19
|
+
end.flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
def sort_entities
|
23
|
+
@entities.sort_by! { |entity| [entity.depth, entity.position, entity.label] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class EntityCollection
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
delegate_missing_to :entities
|
6
|
+
|
7
|
+
attr_reader :entities
|
8
|
+
|
9
|
+
def initialize(entities = nil)
|
10
|
+
@_cache = {}
|
11
|
+
@entities = []
|
12
|
+
add(entities)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(entities = nil)
|
16
|
+
Array(entities).each do |entity|
|
17
|
+
unless find_by_path(entity.path)
|
18
|
+
clear_cache
|
19
|
+
@entities.push(entity)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
sort_entities
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_by_id(id)
|
26
|
+
id = Utils.id(id)
|
27
|
+
find { |entity| entity.id == id }
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_by_path(path)
|
31
|
+
find { |entity| entity.path.to_s == path.to_s }
|
32
|
+
end
|
33
|
+
|
34
|
+
def next(entity)
|
35
|
+
index = find_index { |i| i.path == entity.path }
|
36
|
+
entities[index + 1] unless index.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def previous(entity)
|
40
|
+
index = find_index { |i| i.path == entity.path }
|
41
|
+
entities[index - 1] if !index.nil? && index > 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def each(&block)
|
45
|
+
if block
|
46
|
+
entities.each { |entity| yield entity }
|
47
|
+
else
|
48
|
+
to_enum(:each)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def flat_map(...)
|
53
|
+
map(...).map(&:to_a).flatten
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def sort_entities
|
59
|
+
@entities.sort_by! { |entity| [entity.label] }
|
60
|
+
end
|
61
|
+
|
62
|
+
def clear_cache
|
63
|
+
@_cache = {}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class PageCollection < EntityCollection
|
3
|
+
include HierarchicalCollection
|
4
|
+
|
5
|
+
def load(page_paths)
|
6
|
+
@entities = []
|
7
|
+
clear_cache
|
8
|
+
|
9
|
+
file_paths = page_paths.flat_map do |dir|
|
10
|
+
PathUtils.normalize_paths(Dir["#{dir}/**/*.html.*", "#{dir}/**/*.md.*"].sort)
|
11
|
+
end
|
12
|
+
|
13
|
+
entities = file_paths.map { |path| PageCollection.entity(path) }
|
14
|
+
pages, sections = entities.partition { |page| page.type == :page }
|
15
|
+
|
16
|
+
page_dict = pages.index_by(&:lookup_path)
|
17
|
+
sections.each do |section|
|
18
|
+
parent = page_dict[section.lookup_path]
|
19
|
+
section.parent = parent
|
20
|
+
parent.add_section(section)
|
21
|
+
end
|
22
|
+
|
23
|
+
add(pages)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.entity(file_path)
|
27
|
+
File.basename(file_path).match?(%r{\[(.*?\w+)\]}) ? PageSection.new(file_path) : Page.new(file_path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class PreviewCollection < EntityCollection
|
3
|
+
include HierarchicalCollection
|
4
|
+
|
5
|
+
def find_example_by_path(lookup_path)
|
6
|
+
examples.find_by_path(lookup_path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_by_preview_class(klass)
|
10
|
+
find { |preview| preview.preview_class.name == klass.to_s }
|
11
|
+
end
|
12
|
+
|
13
|
+
def load(code_objects)
|
14
|
+
@entities = []
|
15
|
+
clear_cache
|
16
|
+
|
17
|
+
previews = Array(code_objects).map { |obj| PreviewCollection.preview_from_code_object(obj) }.compact
|
18
|
+
add(previews)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.preview_from_code_object(code_object)
|
22
|
+
klass = code_object.path.constantize
|
23
|
+
Preview.new(code_object) if klass.ancestors.include?(ViewComponent::Preview)
|
24
|
+
rescue => exception
|
25
|
+
Lookbook.logger.error LookbookError.new(exception)
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def examples
|
32
|
+
@_cache[:examples] ||= PreviewExampleCollection.new(flat_map(&:examples))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|