lookbook 0.8.0 → 1.0.0.beta.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 +43 -830
- data/app/assets/lookbook/css/lookbook.css +55 -0
- data/app/assets/lookbook/css/themes/blue.css +42 -0
- data/app/assets/lookbook/css/themes/indigo.css +42 -0
- data/app/assets/lookbook/css/themes/zinc.css +42 -0
- data/app/assets/lookbook/css/{tooltip_theme.css → tooltip.css} +14 -8
- data/app/assets/lookbook/js/app.js +64 -61
- data/app/assets/lookbook/js/components/clipboard.js +47 -0
- data/app/assets/lookbook/js/components/tooltip.js +30 -0
- data/app/assets/lookbook/js/config.js +7 -4
- data/app/assets/lookbook/js/helpers/build.js +22 -0
- data/app/assets/lookbook/js/helpers/dom.js +45 -0
- data/app/assets/lookbook/js/helpers/layout.js +21 -0
- data/app/assets/lookbook/js/helpers/request.js +16 -0
- data/app/assets/lookbook/js/helpers/string.js +11 -0
- data/app/assets/lookbook/js/lib/socket.js +4 -3
- data/app/assets/lookbook/js/lib/tippy.js +8 -0
- data/app/assets/lookbook/js/lookbook.js +61 -0
- data/app/assets/lookbook/js/plugins/logger.js +39 -0
- data/app/assets/lookbook/js/stores/filter.js +2 -2
- data/app/assets/lookbook/js/stores/inspector.js +22 -16
- data/app/assets/lookbook/js/stores/layout.js +101 -5
- data/app/assets/lookbook/js/stores/nav.js +17 -16
- data/app/assets/lookbook/js/stores/pages.js +4 -2
- data/app/assets/lookbook/js/stores/settings.js +7 -0
- data/app/assets/lookbook/js/stores/workbench.js +29 -0
- data/app/components/lookbook/button/component.html.erb +28 -0
- data/app/components/lookbook/button/component.js +55 -0
- data/app/components/lookbook/button/component.rb +39 -0
- data/app/components/lookbook/button_group/component.html.erb +3 -0
- data/app/components/lookbook/button_group/component.rb +18 -0
- data/app/components/lookbook/code/component.css +57 -0
- data/app/components/lookbook/code/component.html.erb +10 -0
- data/app/components/lookbook/code/component.js +3 -0
- data/app/components/lookbook/code/component.rb +56 -0
- data/app/components/lookbook/code/highlight_github_light.css +217 -0
- data/app/components/lookbook/component.rb +41 -0
- data/app/components/lookbook/copy_button/component.html.erb +11 -0
- data/app/components/lookbook/copy_button/component.js +16 -0
- data/app/components/lookbook/copy_button/component.rb +23 -0
- data/app/components/lookbook/dimensions_display/component.html.erb +10 -0
- data/app/components/lookbook/dimensions_display/component.js +30 -0
- data/app/components/lookbook/dimensions_display/component.rb +18 -0
- data/app/components/lookbook/embed/component.html.erb +50 -0
- data/app/components/lookbook/embed/component.js +39 -0
- data/app/components/lookbook/embed/component.rb +22 -0
- data/app/components/lookbook/filter/component.html.erb +17 -0
- data/app/components/lookbook/filter/component.js +21 -0
- data/app/components/lookbook/filter/component.rb +15 -0
- data/app/components/lookbook/header/component.html.erb +79 -0
- data/app/components/lookbook/header/component.rb +9 -0
- data/app/components/lookbook/icon/component.css +11 -0
- data/app/components/lookbook/icon/component.html.erb +5 -0
- data/app/components/lookbook/icon/component.js +5 -0
- data/app/components/lookbook/icon/component.rb +23 -0
- data/app/components/lookbook/nav/component.html.erb +33 -0
- data/app/components/lookbook/nav/component.js +52 -0
- data/app/components/lookbook/nav/component.rb +37 -0
- data/app/components/lookbook/nav/item/component.html.erb +23 -0
- data/app/components/lookbook/nav/item/component.js +66 -0
- data/app/components/lookbook/nav/item/component.rb +84 -0
- data/app/components/lookbook/params_editor/component.html.erb +3 -0
- data/app/components/lookbook/params_editor/component.js +12 -0
- data/app/components/lookbook/params_editor/component.rb +11 -0
- data/app/components/lookbook/params_editor/field/component.html.erb +50 -0
- data/app/components/lookbook/params_editor/field/component.js +36 -0
- data/app/components/lookbook/params_editor/field/component.rb +41 -0
- data/app/components/lookbook/prose/component.css +12 -0
- data/app/components/lookbook/prose/component.html.erb +3 -0
- data/app/components/lookbook/prose/component.rb +26 -0
- data/app/components/lookbook/split_layout/component.html.erb +13 -0
- data/app/components/lookbook/split_layout/component.js +151 -0
- data/app/components/lookbook/split_layout/component.rb +11 -0
- data/app/components/lookbook/tabbed_content/component.html.erb +5 -0
- data/app/components/lookbook/tabbed_content/component.js +21 -0
- data/app/components/lookbook/tabbed_content/component.rb +20 -0
- data/app/components/lookbook/tabbed_content/section/component.html.erb +8 -0
- data/app/components/lookbook/tabbed_content/section/component.rb +9 -0
- data/app/components/lookbook/tabs/component.css +8 -0
- data/app/components/lookbook/tabs/component.html.erb +14 -0
- data/app/components/lookbook/tabs/component.js +107 -0
- data/app/components/lookbook/tabs/component.rb +30 -0
- data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +14 -0
- data/app/components/lookbook/tabs/dropdown_tab/component.rb +16 -0
- data/app/components/lookbook/tabs/tab/component.html.erb +18 -0
- data/app/components/lookbook/tabs/tab/component.rb +16 -0
- data/app/components/lookbook/tag_component.rb +29 -0
- data/app/components/lookbook/toolbar/component.css +16 -0
- data/app/components/lookbook/toolbar/component.html.erb +5 -0
- data/app/components/lookbook/toolbar/component.rb +26 -0
- data/app/components/lookbook/viewport/component.css +11 -0
- data/app/components/lookbook/viewport/component.html.erb +57 -0
- data/app/{assets/lookbook/js/components/preview-window.js → components/lookbook/viewport/component.js} +57 -14
- data/app/components/lookbook/viewport/component.rb +21 -0
- data/app/controllers/lookbook/application_controller.rb +16 -5
- data/app/controllers/lookbook/pages_controller.rb +18 -8
- data/app/controllers/lookbook/previews_controller.rb +60 -23
- data/app/helpers/lookbook/application_helper.rb +5 -1
- data/app/helpers/lookbook/component_helper.rb +22 -10
- data/app/helpers/lookbook/output_helper.rb +8 -4
- data/app/helpers/lookbook/page_helper.rb +13 -21
- data/app/views/layouts/lookbook/application.html.erb +76 -28
- data/app/views/layouts/lookbook/inspector.html.erb +7 -0
- data/app/views/layouts/lookbook/page.html.erb +53 -0
- data/app/views/layouts/lookbook/shell.html.erb +64 -0
- data/app/views/layouts/lookbook/skeleton.html.erb +27 -10
- data/app/views/layouts/lookbook/standalone.html.erb +5 -0
- data/app/views/lookbook/404.html.erb +15 -0
- data/app/views/lookbook/error.html.erb +34 -34
- data/app/views/lookbook/index.html.erb +11 -6
- data/app/views/lookbook/pages/show.html.erb +29 -67
- data/app/views/{layouts/lookbook → lookbook}/preview.html.erb +3 -5
- data/app/views/lookbook/previews/panels/_notes.html.erb +19 -25
- data/app/views/lookbook/previews/panels/_output.html.erb +7 -18
- data/app/views/lookbook/previews/panels/_params.html.erb +13 -15
- data/app/views/lookbook/previews/panels/_preview.html.erb +6 -52
- data/app/views/lookbook/previews/panels/_source.html.erb +7 -16
- data/app/views/lookbook/previews/show.html.erb +130 -24
- data/config/routes.rb +5 -5
- data/lib/lookbook/code_formatter.rb +37 -13
- data/lib/lookbook/collection.rb +19 -16
- data/lib/lookbook/config.rb +125 -0
- data/lib/lookbook/engine.rb +79 -74
- data/lib/lookbook/entity.rb +47 -0
- data/lib/lookbook/error.rb +1 -2
- data/lib/lookbook/features.rb +1 -1
- data/lib/lookbook/markdown.rb +3 -4
- data/lib/lookbook/page.rb +21 -12
- data/lib/lookbook/page_collection.rb +8 -0
- data/lib/lookbook/params.rb +15 -4
- data/lib/lookbook/preview.rb +15 -6
- data/lib/lookbook/preview_collection.rb +8 -0
- data/lib/lookbook/preview_controller.rb +6 -2
- data/lib/lookbook/preview_example.rb +5 -6
- data/lib/lookbook/preview_group.rb +4 -9
- data/lib/lookbook/{code_inspector.rb → source_inspector.rb} +2 -2
- data/lib/lookbook/theme.rb +22 -0
- data/lib/lookbook/utils.rb +10 -2
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +4 -1
- data/lib/tasks/lookbook_tasks.rake +12 -0
- data/public/lookbook-assets/css/app.css +2340 -1
- data/public/lookbook-assets/css/app.css.map +11 -1
- data/public/lookbook-assets/css/lookbook.css +3040 -0
- data/public/lookbook-assets/css/lookbook.css.map +1 -0
- data/public/lookbook-assets/css/themes/blue.css +44 -0
- data/public/lookbook-assets/css/themes/blue.css.map +1 -0
- data/public/lookbook-assets/css/themes/indigo.css +44 -0
- data/public/lookbook-assets/css/themes/indigo.css.map +1 -0
- data/public/lookbook-assets/css/themes/zinc.css +44 -0
- data/public/lookbook-assets/css/themes/zinc.css.map +1 -0
- data/public/lookbook-assets/js/app.js +10861 -1
- data/public/lookbook-assets/js/app.js.map +2571 -1
- data/public/lookbook-assets/js/embed.js +895 -1
- data/public/lookbook-assets/js/embed.js.map +1 -1
- data/public/lookbook-assets/js/lookbook.js +13529 -0
- data/public/lookbook-assets/js/lookbook.js.map +1 -0
- metadata +127 -114
- data/app/assets/lookbook/css/app.css +0 -161
- data/app/assets/lookbook/css/code_theme.css +0 -214
- data/app/assets/lookbook/js/components/app.js +0 -55
- data/app/assets/lookbook/js/components/code.js +0 -5
- data/app/assets/lookbook/js/components/copy.js +0 -20
- data/app/assets/lookbook/js/components/embed.js +0 -89
- data/app/assets/lookbook/js/components/filter.js +0 -35
- data/app/assets/lookbook/js/components/inspector.js +0 -66
- data/app/assets/lookbook/js/components/nav-group.js +0 -47
- data/app/assets/lookbook/js/components/nav-item.js +0 -29
- data/app/assets/lookbook/js/components/nav.js +0 -28
- data/app/assets/lookbook/js/components/page.js +0 -25
- data/app/assets/lookbook/js/components/param.js +0 -34
- data/app/assets/lookbook/js/components/sidebar.js +0 -18
- data/app/assets/lookbook/js/components/sizes.js +0 -16
- data/app/assets/lookbook/js/components/splitter.js +0 -25
- data/app/assets/lookbook/js/components/tabs.js +0 -52
- data/app/assets/lookbook/js/lib/split.js +0 -15
- data/app/assets/lookbook/js/stores/sidebar.js +0 -26
- data/app/views/layouts/lookbook/basic.html.erb +0 -7
- data/app/views/lookbook/components/_branding.html.erb +0 -8
- data/app/views/lookbook/components/_code.html.erb +0 -17
- data/app/views/lookbook/components/_copy_button.html.erb +0 -11
- data/app/views/lookbook/components/_drawer.html.erb +0 -112
- data/app/views/lookbook/components/_embed.html.erb +0 -39
- data/app/views/lookbook/components/_errors.html.erb +0 -13
- data/app/views/lookbook/components/_filter.html.erb +0 -18
- data/app/views/lookbook/components/_header.html.erb +0 -6
- data/app/views/lookbook/components/_icon.html.erb +0 -5
- data/app/views/lookbook/components/_nav.html.erb +0 -16
- data/app/views/lookbook/components/_nav_collection.html.erb +0 -5
- data/app/views/lookbook/components/_nav_group.html.erb +0 -14
- data/app/views/lookbook/components/_nav_item.html.erb +0 -24
- data/app/views/lookbook/components/_nav_page.html.erb +0 -22
- data/app/views/lookbook/components/_nav_preview.html.erb +0 -13
- data/app/views/lookbook/components/_not_found.html.erb +0 -11
- data/app/views/lookbook/components/_param.html.erb +0 -21
- data/app/views/lookbook/components/_preview.html.erb +0 -77
- data/app/views/lookbook/components/_sidebar.html.erb +0 -69
- data/app/views/lookbook/pages/not_found.html.erb +0 -15
- data/app/views/lookbook/previews/error.html.erb +0 -1
- data/app/views/lookbook/previews/inputs/_select.html.erb +0 -7
- data/app/views/lookbook/previews/inputs/_text.html.erb +0 -8
- data/app/views/lookbook/previews/inputs/_textarea.html.erb +0 -8
- data/app/views/lookbook/previews/inputs/_toggle.html.erb +0 -13
- data/app/views/lookbook/previews/not_found.html.erb +0 -23
@@ -1,24 +1,130 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
1
|
+
<%= render_component :split_layout,
|
2
|
+
alpine_data: "$store.layout.inspector",
|
3
|
+
":class": "$store.inspector.drawer.hidden && '!grid-rows-[1fr] !grid-cols-[1fr]'" do |layout| %>
|
4
|
+
|
5
|
+
<%= layout.pane class: "flex flex-col h-full overflow-hidden",
|
6
|
+
x_effect: "forceOrientation = (layoutWidth < $store.inspector.minVerticalSplitWidth) ? 'horizontal' : null" do %>
|
7
|
+
|
8
|
+
<%= render_component :toolbar do |toolbar| %>
|
9
|
+
<% toolbar.section ":class": "layoutResizing && 'overflow-hidden'" do %>
|
10
|
+
<%= render_component :tabs, alpine_data: "$store.inspector.preview" do |tabs| %>
|
11
|
+
<%= @preview_panels.each do |key, panel| %>
|
12
|
+
<% tabs.tab ref: key, **panel.extract!(:label, :hotkey, :disabled) %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% toolbar.section align: :right, padded: true, class: "flex-none min-w-[140px]", ":class": "{invisible: $store.inspector.preview.activeTab !== 'preview'}" do %>
|
18
|
+
<%= render_component :dimensions_display,
|
19
|
+
target: "[data-component=viewport] iframe",
|
20
|
+
class: "ml-auto opacity-30 hover:opacity-100" %>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<% toolbar.section divide: :left, class: "flex-none relative z-10" do %>
|
24
|
+
<%= render_component :button_group do |group| %>
|
25
|
+
<% if Lookbook.pages.any? %>
|
26
|
+
<% group.button icon: :code,
|
27
|
+
tooltip: "Copy page embed code",
|
28
|
+
copy: true do %>
|
29
|
+
<%= embed <%= @preview.preview_class %>, :<%= @example.name %>, params: <%= request.query_parameters.deep_symbolize_keys.to_s %> %>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
<% group.button icon: :refresh_cw,
|
34
|
+
tooltip: "Refresh preview",
|
35
|
+
"@click.stop": "startSpin(); $dispatch('viewport:reload'); stopSpin(500);" %>
|
36
|
+
|
37
|
+
<% group.button icon: :external_link,
|
38
|
+
href: lookbook.preview_path(@example.lookup_path),
|
39
|
+
tooltip: "Open preview in new window",
|
40
|
+
target: "_blank" %>
|
41
|
+
|
42
|
+
<% group.button icon: "vertical ? 'sidebar' : 'credit-card'",
|
43
|
+
tooltip: "Show drawer",
|
44
|
+
"@click": "$store.inspector.drawer.hidden = false",
|
45
|
+
class: "rotate-180",
|
46
|
+
x_show: "$store.inspector.drawer.hidden",
|
47
|
+
cloak: true %>
|
48
|
+
<% end %>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
<div class="h-full relative overflow-auto">
|
53
|
+
<%= render_component :tabbed_content, alpine_data: "$store.inspector.preview" do |content| %>
|
54
|
+
<%= @preview_panels.each do |key, panel| %>
|
55
|
+
<% content.section ref: key, class: "overflow-hidden" do %>
|
56
|
+
<%= render panel[:template],
|
57
|
+
preview: @preview,
|
58
|
+
example: @example,
|
59
|
+
rendered_examples: @rendered_examples,
|
60
|
+
**panel %>
|
61
|
+
<% end %>
|
62
|
+
<% end %>
|
63
|
+
<% end %>
|
64
|
+
</div>
|
65
|
+
<% end %>
|
66
|
+
|
67
|
+
<%= layout.pane class: "flex flex-col h-full overflow-hidden bg-lookbook-drawer", x_show: "!$store.inspector.drawer.hidden" do %>
|
68
|
+
|
69
|
+
<%= render_component :toolbar do |toolbar| %>
|
70
|
+
<% toolbar.section ":class": "layoutResizing && 'overflow-hidden'" do %>
|
71
|
+
<%= render_component :tabs, alpine_data: "$store.inspector.drawer" do |tabs| %>
|
72
|
+
<%= @drawer_panels.each do |key, panel| %>
|
73
|
+
<% tabs.tab ref: key, **panel.extract!(:label, :hotkey, :disabled) %>
|
74
|
+
<% end %>
|
75
|
+
<% end %>
|
76
|
+
<% end %>
|
77
|
+
|
78
|
+
<% toolbar.section align: :right, divide: :left, class: "flex-none relative z-10" do %>
|
79
|
+
<%= render_component :button_group do |group| %>
|
80
|
+
|
81
|
+
<%= @drawer_panels.each do |key, panel| %>
|
82
|
+
<% group.button icon: :clipboard,
|
83
|
+
tooltip: "Copy to clipboard",
|
84
|
+
copy: !!panel[:copy],
|
85
|
+
disabled: panel[:disabled] || !panel[:copy],
|
86
|
+
x_show: "$store.inspector.drawer.activeTab === '#{key}'",
|
87
|
+
cloak: true do %>
|
88
|
+
<%== panel[:copy] ? panel[:copy] : "" %>
|
89
|
+
<% end %>
|
90
|
+
<% end %>
|
91
|
+
|
92
|
+
<% group.button icon: :corner_up_right,
|
93
|
+
tooltip: "Move drawer to right",
|
94
|
+
"@click": "switchOrientation",
|
95
|
+
x_show: "horizontal && layoutWidth > $store.inspector.minVerticalSplitWidth",
|
96
|
+
cloak: true %>
|
97
|
+
<% group.button icon: :corner_up_right,
|
98
|
+
x_show: "horizontal && layoutWidth <= $store.inspector.minVerticalSplitWidth",
|
99
|
+
disabled: true,
|
100
|
+
cloak: true %>
|
101
|
+
|
102
|
+
<% group.button icon: :corner_left_down,
|
103
|
+
tooltip: "Move drawer to bottom",
|
104
|
+
"@click": "switchOrientation",
|
105
|
+
x_show: "vertical",
|
106
|
+
cloak: true %>
|
107
|
+
|
108
|
+
<% group.button icon: :x_circle,
|
109
|
+
tooltip: "Hide drawer",
|
110
|
+
"@click": "$store.inspector.drawer.hidden = true",
|
111
|
+
cloak: true %>
|
112
|
+
<% end %>
|
113
|
+
<% end %>
|
114
|
+
<% end %>
|
115
|
+
|
116
|
+
<div class="h-full overflow-auto">
|
117
|
+
<%= render_component :tabbed_content, alpine_data: "$store.inspector.drawer" do |content| %>
|
118
|
+
<% @drawer_panels.each do |key, panel| %>
|
119
|
+
<% content.section ref: key do %>
|
120
|
+
<%= render panel[:template],
|
121
|
+
preview: @preview,
|
122
|
+
example: @example,
|
123
|
+
rendered_examples: @rendered_examples,
|
124
|
+
**panel %>
|
125
|
+
<% end %>
|
126
|
+
<% end %>
|
127
|
+
<% end %>
|
128
|
+
</div>
|
129
|
+
<% end %>
|
130
|
+
<% end %>
|
data/config/routes.rb
CHANGED
@@ -5,11 +5,11 @@ Lookbook::Engine.routes.draw do
|
|
5
5
|
|
6
6
|
root to: "application#index", as: :home
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
get "/#{Lookbook.config.page_route}/*path", to: "pages#show", as: :page
|
11
|
-
end
|
8
|
+
get "/#{Lookbook.config.page_route}", to: "pages#index", as: :page_index
|
9
|
+
get "/#{Lookbook.config.page_route}/*path", to: "pages#show", as: :page
|
12
10
|
|
13
11
|
get "/preview/*path", to: "previews#preview", as: :preview
|
14
|
-
get "/*path", to: "previews#show", as: :
|
12
|
+
get "/inspect/*path", to: "previews#show", as: :inspect
|
13
|
+
|
14
|
+
get "/*path", to: "previews#show_legacy", as: :inspect_legacy
|
15
15
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
require "rouge"
|
2
2
|
require "htmlbeautifier"
|
3
|
+
require 'htmlentities'
|
3
4
|
|
4
5
|
module Lookbook
|
5
6
|
module CodeFormatter
|
6
7
|
class << self
|
7
|
-
def highlight(source,
|
8
|
-
|
9
|
-
source
|
10
|
-
language
|
11
|
-
formatter = Formatter.new(opts)
|
8
|
+
def highlight(source, **opts)
|
9
|
+
coder = HTMLEntities.new
|
10
|
+
source = coder.decode source
|
11
|
+
language = opts[:language] || "ruby"
|
12
|
+
formatter = Formatter.new(**opts)
|
12
13
|
lexer = Rouge::Lexer.find(language.to_s) || Rouge::Lexer.find("plaintext")
|
13
14
|
formatter.format(lexer.lex(source)).html_safe
|
14
15
|
end
|
15
16
|
|
16
|
-
def beautify(source,
|
17
|
+
def beautify(source, **opts)
|
18
|
+
language = opts[:language] || "html"
|
17
19
|
source = source.strip
|
18
20
|
result = language.downcase == "html" ? HtmlBeautifier.beautify(source) : source
|
19
21
|
result.strip.html_safe
|
@@ -22,23 +24,45 @@ module Lookbook
|
|
22
24
|
end
|
23
25
|
|
24
26
|
class Formatter < Rouge::Formatters::HTML
|
25
|
-
def initialize(opts
|
27
|
+
def initialize(**opts)
|
26
28
|
@opts = opts
|
27
29
|
@highlight_lines = opts[:highlight_lines].to_a || []
|
28
|
-
@start_line = opts[:start_line] ||
|
30
|
+
@start_line = opts[:start_line] || 1
|
31
|
+
@language = opts[:language]
|
29
32
|
end
|
30
33
|
|
31
34
|
def stream(tokens, &block)
|
32
|
-
token_lines(tokens)
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
lines = token_lines(tokens)
|
36
|
+
|
37
|
+
yield "<div class='wrapper'>"
|
38
|
+
|
39
|
+
if @opts[:line_numbers]
|
40
|
+
yield "<div class='line-numbers'>"
|
41
|
+
lines.each.with_index do |line, i|
|
42
|
+
yield "<div class='line #{"highlighted" if highlighted?(i)}'><span class='line-number'>#{line_number(i)}</span></div>"
|
43
|
+
end
|
44
|
+
yield "</div>"
|
45
|
+
end
|
46
|
+
|
47
|
+
yield "<pre class='code highlight' data-lang='#{@language}'><code>"
|
48
|
+
lines.each.with_index do |line_tokens, i|
|
49
|
+
yield "<div class='line#{" highlighted" if highlighted?(i)}'>"
|
36
50
|
line_tokens.each do |token, value|
|
37
51
|
yield span(token, value)
|
38
52
|
end
|
39
|
-
yield "</span>"
|
40
53
|
yield "</div>"
|
41
54
|
end
|
55
|
+
yield "</code></pre>"
|
56
|
+
|
57
|
+
yield "</div>"
|
58
|
+
end
|
59
|
+
|
60
|
+
def highlighted?(i)
|
61
|
+
@highlight_lines.include?(i + 1)
|
62
|
+
end
|
63
|
+
|
64
|
+
def line_number(i)
|
65
|
+
@start_line + i
|
42
66
|
end
|
43
67
|
end
|
44
68
|
end
|
data/lib/lookbook/collection.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
module Lookbook
|
2
|
-
class Collection
|
3
|
-
include Utils
|
2
|
+
class Collection < Entity
|
4
3
|
include Enumerable
|
5
4
|
|
6
|
-
attr_reader :path
|
7
5
|
delegate :size, :each, to: :items
|
8
6
|
|
9
7
|
def initialize(path = "", items = [])
|
8
|
+
@items = []
|
10
9
|
if path.is_a?(Array)
|
11
|
-
|
10
|
+
items = path
|
12
11
|
path = ""
|
13
|
-
else
|
14
|
-
@items = items
|
15
12
|
end
|
13
|
+
|
16
14
|
@path = path.delete_prefix("/").delete_suffix("/")
|
15
|
+
super(@path)
|
16
|
+
|
17
|
+
items.each { |item| add(item) }
|
17
18
|
end
|
18
19
|
|
19
20
|
def id
|
20
|
-
|
21
|
+
lookup_path.present? ? super : "root"
|
21
22
|
end
|
22
23
|
|
23
24
|
def name
|
@@ -28,26 +29,24 @@ module Lookbook
|
|
28
29
|
name&.titleize
|
29
30
|
end
|
30
31
|
|
31
|
-
def lookup_path
|
32
|
-
@lookup_path ||= to_lookup_path(@path)
|
33
|
-
end
|
34
|
-
|
35
32
|
def position
|
36
33
|
@position ||= parse_position_prefix(basename).first
|
37
34
|
end
|
38
35
|
|
39
|
-
def hierarchy_depth
|
40
|
-
@path ? @path.split("/").size : 0
|
41
|
-
end
|
42
|
-
|
43
36
|
def items
|
44
|
-
@items.sort_by { |item| [item.hierarchy_depth, item
|
37
|
+
@items.sort_by { |item| [item.hierarchy_depth, item&.position, item.label] }
|
45
38
|
end
|
46
39
|
|
47
40
|
def visible_items
|
48
41
|
reject { |i| i.hidden? }
|
49
42
|
end
|
50
43
|
|
44
|
+
def non_empty_items
|
45
|
+
items.filter do |item|
|
46
|
+
!item.is_a?(Lookbook::Collection) || item.items.any?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
51
50
|
def add(item)
|
52
51
|
@ordered_entities = nil
|
53
52
|
@tree = nil
|
@@ -134,6 +133,10 @@ module Lookbook
|
|
134
133
|
@tree
|
135
134
|
end
|
136
135
|
|
136
|
+
def collapsible?
|
137
|
+
false
|
138
|
+
end
|
139
|
+
|
137
140
|
def type
|
138
141
|
:collection
|
139
142
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require "lookbook/markdown"
|
2
|
+
|
3
|
+
module Lookbook
|
4
|
+
class ConfigOptions < ActiveSupport::OrderedOptions
|
5
|
+
def initialize(**data)
|
6
|
+
super()
|
7
|
+
data.keys.each { |key| self[key.to_sym] = data[key] }
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
super(key.to_sym)
|
12
|
+
end
|
13
|
+
|
14
|
+
def []=(key, value)
|
15
|
+
super(key.to_sym, value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Config
|
20
|
+
def initialize
|
21
|
+
@store = ConfigOptions.new(**{
|
22
|
+
project_name: "Lookbook",
|
23
|
+
log_level: 2,
|
24
|
+
auto_refresh: true,
|
25
|
+
|
26
|
+
page_controller: "Lookbook::PageController",
|
27
|
+
page_route: "pages",
|
28
|
+
page_paths: ["test/components/docs"],
|
29
|
+
page_options: ConfigOptions.new,
|
30
|
+
markdown_options: ConfigOptions.new(**Markdown::DEFAULT_OPTIONS),
|
31
|
+
|
32
|
+
preview_paths: [],
|
33
|
+
preview_display_params: ConfigOptions.new,
|
34
|
+
preview_options: ConfigOptions.new,
|
35
|
+
preview_srcdoc: false,
|
36
|
+
sort_examples: true,
|
37
|
+
|
38
|
+
listen: Rails.env.development?,
|
39
|
+
listen_paths: [],
|
40
|
+
listen_use_polling: false,
|
41
|
+
|
42
|
+
cable_mount_path: "/lookbook-cable",
|
43
|
+
cable_logger: Lookbook.logger,
|
44
|
+
|
45
|
+
runtime_parsing: !Rails.env.production?,
|
46
|
+
parser_registry_path: "tmp/storage/.yardoc",
|
47
|
+
|
48
|
+
ui_theme: "indigo",
|
49
|
+
ui_theme_overrides: ConfigOptions.new,
|
50
|
+
experimental_features: false,
|
51
|
+
})
|
52
|
+
end
|
53
|
+
|
54
|
+
def ui_theme=(name)
|
55
|
+
name = name.to_s
|
56
|
+
if ["indigo", "zinc", "blue"].include?(name)
|
57
|
+
@store[:ui_theme] = name
|
58
|
+
else
|
59
|
+
Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Falling back to default."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def ui_theme_overrides=(theme)
|
64
|
+
@store[:ui_theme_overrides] = ConfigOptions.new(theme)
|
65
|
+
end
|
66
|
+
|
67
|
+
def ui_theme_overrides(&block)
|
68
|
+
if block_given?
|
69
|
+
yield get(:ui_theme_overrides)
|
70
|
+
else
|
71
|
+
get(:ui_theme_overrides)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](key)
|
76
|
+
get(key.to_sym)
|
77
|
+
end
|
78
|
+
|
79
|
+
def []=(key, value)
|
80
|
+
@store[key.to_sym] = value
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_h
|
84
|
+
@store.to_h
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_json(*a)
|
88
|
+
to_h.to_json(*a)
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def get_project_name(name)
|
94
|
+
name == false ? nil : name
|
95
|
+
end
|
96
|
+
|
97
|
+
def normalize_paths(paths)
|
98
|
+
paths.map! { |path| absolute_path(path) }
|
99
|
+
paths.filter! { |path| Dir.exist?(path) }
|
100
|
+
paths
|
101
|
+
end
|
102
|
+
|
103
|
+
def absolute_path(path)
|
104
|
+
File.absolute_path(path.to_s, Rails.root)
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method :get_page_paths, :normalize_paths
|
108
|
+
alias_method :get_preview_paths, :normalize_paths
|
109
|
+
alias_method :get_listen_paths, :normalize_paths
|
110
|
+
alias_method :get_parser_registry_path, :absolute_path
|
111
|
+
|
112
|
+
def get(name)
|
113
|
+
getter_name = "get_#{name}".to_sym
|
114
|
+
respond_to?(getter_name, true) ? send(getter_name, @store[name]) : @store[name]
|
115
|
+
end
|
116
|
+
|
117
|
+
def set(name, *args)
|
118
|
+
@store.send(name, *args)
|
119
|
+
end
|
120
|
+
|
121
|
+
def method_missing(name, *args)
|
122
|
+
args.any? ? set(name, *args) : get(name)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/lookbook/engine.rb
CHANGED
@@ -4,64 +4,51 @@ require "action_cable/engine"
|
|
4
4
|
require "listen"
|
5
5
|
|
6
6
|
module Lookbook
|
7
|
+
|
8
|
+
autoload :Config, "lookbook/config"
|
9
|
+
|
7
10
|
class << self
|
8
11
|
def config
|
9
|
-
@config ||=
|
12
|
+
@config ||= Config.new
|
10
13
|
end
|
11
14
|
|
12
15
|
def logger
|
13
|
-
@logger ||= Rails.logger
|
16
|
+
@logger ||= Rails.env.development? ? Logger.new($stdout) : Rails.logger
|
14
17
|
end
|
15
18
|
|
16
19
|
def version
|
17
20
|
Lookbook::VERSION
|
18
21
|
end
|
22
|
+
|
23
|
+
def debug_data
|
24
|
+
{
|
25
|
+
version: version,
|
26
|
+
env: Rails.env.to_s,
|
27
|
+
config: config
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure
|
32
|
+
yield(config)
|
33
|
+
end
|
19
34
|
end
|
20
35
|
|
21
36
|
class Engine < Rails::Engine
|
22
37
|
isolate_namespace Lookbook
|
23
38
|
|
24
|
-
config.lookbook =
|
25
|
-
config.
|
26
|
-
config.lookbook.preview_paths ||= []
|
27
|
-
config.lookbook.page_paths ||= ["test/components/docs"]
|
28
|
-
|
29
|
-
initializer "view_component.set_configs" do
|
30
|
-
options = config.lookbook
|
31
|
-
vc_options = config.view_component
|
32
|
-
|
33
|
-
options.project_name ||= options.project_name == false ? nil : options.project_name || "Lookbook"
|
34
|
-
options.auto_refresh = true if options.auto_refresh.nil?
|
35
|
-
options.sort_examples = false if options.sort_examples.nil?
|
36
|
-
options.debug = false unless options.debug == true
|
39
|
+
config.lookbook = Lookbook.config
|
40
|
+
config.autoload_paths << File.expand_path(Lookbook::Engine.root.join("app/components"))
|
37
41
|
|
38
|
-
|
39
|
-
|
42
|
+
initializer "lookbook.viewcomponent.config" do
|
43
|
+
config.lookbook.preview_paths += config.view_component.preview_paths
|
44
|
+
config.lookbook.preview_controller ||= config.view_component.preview_controller
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
options.page_options ||= {}.with_indifferent_access
|
45
|
-
|
46
|
-
options.markdown_options = Markdown::DEFAULT_OPTIONS.merge(options.markdown_options || {})
|
47
|
-
|
48
|
-
options.preview_controller = vc_options.preview_controller if options.preview_controller.nil?
|
49
|
-
options.preview_srcdoc = false if options.preview_srcdoc.nil?
|
50
|
-
options.preview_display_params ||= {}.with_indifferent_access
|
51
|
-
|
52
|
-
options.listen = Rails.env.development? if options.listen.nil?
|
53
|
-
options.listen_paths = options.listen_paths.map(&:to_s)
|
54
|
-
options.listen_paths += options.preview_paths
|
55
|
-
options.listen_paths << (vc_options.view_component_path || Rails.root.join("app/components"))
|
56
|
-
options.listen_paths.filter! { |path| Dir.exist? path }
|
57
|
-
|
58
|
-
options.cable_mount_path ||= "/lookbook-cable"
|
59
|
-
options.cable_logger ||= Rails.logger
|
60
|
-
|
61
|
-
options.runtime_parsing = !Rails.env.production? if options.runtime_parsing.nil?
|
62
|
-
options.parser_registry_path ||= Rails.root.join("tmp/storage/.yardoc")
|
46
|
+
config.lookbook.listen_paths += config.lookbook.preview_paths
|
47
|
+
config.lookbook.listen_paths << (config.view_component.view_component_path.presence || "app/components")
|
48
|
+
end
|
63
49
|
|
64
|
-
|
50
|
+
initializer "lookbook.logging.development" do
|
51
|
+
Lookbook.logger.level = Lookbook.config.log_level if Rails.env.development?
|
65
52
|
end
|
66
53
|
|
67
54
|
initializer "lookbook.parser.tags" do
|
@@ -76,49 +63,55 @@ module Lookbook
|
|
76
63
|
end
|
77
64
|
|
78
65
|
config.after_initialize do
|
66
|
+
@preview_controller = Lookbook.config.preview_controller.constantize
|
67
|
+
@preview_controller.include(Lookbook::PreviewController)
|
68
|
+
|
79
69
|
if config.lookbook.listen
|
80
|
-
|
70
|
+
Listen.logger = Lookbook.logger
|
71
|
+
preview_listener = Listen.to(
|
72
|
+
*config.lookbook.listen_paths,
|
73
|
+
only: /\.(rb|html.*)$/,
|
74
|
+
force_polling: Lookbook.config.listen_use_polling
|
75
|
+
) do |modified, added, removed|
|
81
76
|
begin
|
82
77
|
parser.parse
|
83
78
|
rescue
|
84
79
|
end
|
85
80
|
Lookbook::Preview.clear_cache
|
86
|
-
Lookbook::Engine.websocket&.broadcast("reload", {
|
87
|
-
modified: modified,
|
88
|
-
removed: removed,
|
89
|
-
added: added
|
90
|
-
})
|
81
|
+
Lookbook::Engine.websocket&.broadcast("reload", {})
|
91
82
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
})
|
101
|
-
end
|
102
|
-
@page_listener.start
|
83
|
+
Lookbook::Engine.register_listener(preview_listener)
|
84
|
+
|
85
|
+
page_listener = Listen.to(
|
86
|
+
*config.lookbook.page_paths,
|
87
|
+
only: /\.(html.*|md.*)$/,
|
88
|
+
force_polling: Lookbook.config.listen_use_polling
|
89
|
+
) do |modified, added, removed|
|
90
|
+
Lookbook::Engine.websocket&.broadcast("reload", {})
|
103
91
|
end
|
92
|
+
Lookbook::Engine.register_listener(page_listener)
|
93
|
+
end
|
104
94
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
end
|
95
|
+
if config.lookbook.runtime_parsing
|
96
|
+
parser.parse
|
97
|
+
else
|
98
|
+
unless File.exist?(config.lookbook.parser_registry_path)
|
99
|
+
Lookbook.logger.warn "
|
100
|
+
Runtime parsing is disabled but no registry file has been found.
|
101
|
+
Did you run `rake lookbook:preparse` before starting the app?
|
102
|
+
Expected to find registry file at #{config.lookbook.parser_registry_path}
|
103
|
+
"
|
115
104
|
end
|
116
105
|
end
|
117
106
|
end
|
118
107
|
|
119
108
|
at_exit do
|
120
|
-
|
121
|
-
|
109
|
+
if config.lookbook.listen
|
110
|
+
Lookbook.logger.debug "Stopping listeners"
|
111
|
+
Lookbook::Engine.listeners.each do |listener|
|
112
|
+
listener.stop
|
113
|
+
end
|
114
|
+
end
|
122
115
|
end
|
123
116
|
|
124
117
|
class << self
|
@@ -152,12 +145,24 @@ module Lookbook
|
|
152
145
|
@parser ||= Lookbook::Parser.new(config.lookbook.preview_paths, config.lookbook.parser_registry_path)
|
153
146
|
end
|
154
147
|
|
155
|
-
def
|
156
|
-
|
157
|
-
controller = Lookbook.config.preview_controller.constantize
|
158
|
-
controller.class_eval { include Lookbook::PreviewController }
|
159
|
-
@preview_controller || controller
|
148
|
+
def log_level
|
149
|
+
Lookbook.logger.level
|
160
150
|
end
|
151
|
+
|
152
|
+
def app_name
|
153
|
+
Rails.application.class.module_parent_name.underscore
|
154
|
+
end
|
155
|
+
|
156
|
+
def register_listener(listener)
|
157
|
+
listener.start
|
158
|
+
listeners << listener
|
159
|
+
end
|
160
|
+
|
161
|
+
def listeners
|
162
|
+
@listeners ||= []
|
163
|
+
end
|
164
|
+
|
165
|
+
attr_reader :preview_controller
|
161
166
|
end
|
162
167
|
end
|
163
168
|
end
|