lookbook 0.3.1 → 0.4.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +103 -15
- data/app/assets/lookbook/js/nav/node.js +18 -0
- data/app/controllers/lookbook/app_controller.rb +19 -4
- data/app/views/lookbook/app/index.html.erb +2 -2
- data/app/views/lookbook/app/show.html.erb +1 -1
- data/app/views/lookbook/layouts/app.html.erb +3 -3
- data/app/views/lookbook/nav/_collection.html.erb +4 -4
- data/app/views/lookbook/nav/_leaf.html.erb +1 -1
- data/app/views/lookbook/nav/_node.html.erb +2 -2
- data/app/views/lookbook/nav/_preview.html.erb +4 -4
- data/app/views/lookbook/shared/_header.html.erb +1 -1
- data/app/views/lookbook/{_sidebar.html.erb → shared/_sidebar.html.erb} +3 -3
- data/app/views/lookbook/{_workbench.html.erb → shared/_workbench.html.erb} +5 -5
- data/app/views/lookbook/workbench/_header.html.erb +2 -2
- data/app/views/lookbook/workbench/_inspector.html.erb +3 -3
- data/lib/lookbook/collection.rb +3 -3
- data/lib/lookbook/engine.rb +15 -4
- data/lib/lookbook/null_logger.rb +47 -0
- data/lib/lookbook/parser.rb +2 -1
- data/lib/lookbook/preview.rb +1 -3
- data/lib/lookbook/taggable.rb +22 -3
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +1 -0
- data/lib/tasks/lookbook_tasks.rake +1 -1
- data/public/lookbook-assets/app.css +102 -87
- data/public/lookbook-assets/app.js +345 -212
- metadata +7 -7
- data/lib/lookbook/navigation.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 870ef6a17d84bca0a9fbbc421e27c2d6d682965d96c646f44d3db817e5a5e4f2
|
4
|
+
data.tar.gz: 669ce3b709792be5bdf46ac806efdca269d694349e74f759b0997cbbb456792e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0293806f0d57b130c07ae84b5d30fad2625df0cbf2477303d924dddfd42ece6e49b10f15fc0b395fa65adfca3de3ab1096e72565a175bdab14df2af1ba57050
|
7
|
+
data.tar.gz: 2e5ad4ca7957d2684dc367b3a7d89d9922024cfc01cdbcd2567d30b830fe891b815924d64f5b7048783efd42736f41924354255f847850498fd596ba1c25e977
|
data/README.md
CHANGED
@@ -16,19 +16,17 @@
|
|
16
16
|
|
17
17
|
It uses (and extends) the native [ViewComponent preview functionality](https://viewcomponent.org/guide/previews.html), so you don't need to learn a new DSL or create any extra files to get up and running.
|
18
18
|
|
19
|
-
Lookbook uses [RDoc/Yard-style comment tags](
|
19
|
+
Lookbook uses [RDoc/Yard-style comment tags](#annotating-preview-files) to extend the capabilities of ViewComponent's previews whilst maintaining compatability with the standard preview class format, so you can add or remove Lookbook at any time without having to rework your code.
|
20
20
|
|
21
21
|
![Lookbook UI](.github/assets/lookbook_screenshot.png)
|
22
22
|
|
23
23
|
### Features
|
24
24
|
|
25
|
-
- Tree-style navigation menu
|
26
|
-
- Live nav search/filter
|
25
|
+
- Tree-style navigation menu with live search/filter
|
27
26
|
- Resizable preview window for responsive testing
|
28
27
|
- Highlighted preview source code and HTML output
|
29
|
-
- Add notes via comments in the preview file (markdown supported)
|
30
28
|
- Auto-updating UI when component or preview files are updated _(Rails v6.0+ only)_
|
31
|
-
-
|
29
|
+
- Use comment tag annotations for granular customisation of the preview experience
|
32
30
|
- Fully compatible with standard the ViewComponent preview system
|
33
31
|
|
34
32
|
## Lookbook demo
|
@@ -39,8 +37,6 @@ The [demo app repo](https://github.com/allmarkedup/lookbook-demo) contains instr
|
|
39
37
|
|
40
38
|
## Installing
|
41
39
|
|
42
|
-
> ⚠️ **Please note:** Lookbook is still in the early stages of development and has not yet been well tested across a wide range of Rails/ViewComponent versions and setups. If you run into any problems please [open an issue](issues) with as much detail as possible. Thanks! ⚠️
|
43
|
-
|
44
40
|
### 1. Add as a dependency
|
45
41
|
|
46
42
|
Add Lookbook to your `Gemfile` somewhere **after** the ViewComponent gem. For example:
|
@@ -74,12 +70,13 @@ You don't need to do anything special to see your ViewComponent previews and exa
|
|
74
70
|
|
75
71
|
> If you are new to ViewComponent development, checkout the ViewComponent [documentation](https://viewcomponent.org/guide/) on how to get started developing your components and [creating previews](https://viewcomponent.org/guide/previews.html).
|
76
72
|
|
77
|
-
|
73
|
+
## Annotating preview files
|
78
74
|
|
79
75
|
Lookbook parses [Yard-style comment tags](https://rubydoc.info/gems/yard/file/docs/Tags.md) in your preview classes to customise and extend the standard ViewComponent preview experience:
|
80
76
|
|
81
77
|
```ruby
|
82
78
|
# @label Basic Button
|
79
|
+
# @display bg_color: "#fff"
|
83
80
|
class ButtonComponentPreview < ViewComponent::Preview
|
84
81
|
|
85
82
|
# Primary button
|
@@ -93,11 +90,13 @@ class ButtonComponentPreview < ViewComponent::Preview
|
|
93
90
|
end
|
94
91
|
end
|
95
92
|
|
96
|
-
#
|
93
|
+
# Inverted button
|
97
94
|
# ---------------
|
98
|
-
#
|
95
|
+
# For light-on-dark screens
|
96
|
+
#
|
97
|
+
# @display bg_color: "#000"
|
99
98
|
def secondary
|
100
|
-
render ButtonComponent.new(style: :
|
99
|
+
render ButtonComponent.new(style: :inverted) do
|
101
100
|
"Click me"
|
102
101
|
end
|
103
102
|
end
|
@@ -142,7 +141,12 @@ end
|
|
142
141
|
|
143
142
|
The following Lookbook-specific tags are available for use:
|
144
143
|
|
145
|
-
|
144
|
+
* `@label <label>` -[Customise navigation labels](#-label-text)
|
145
|
+
* `@hidden` - [Prevent items displaying in the navigation](#-hidden)
|
146
|
+
* `@display <key>:<value>` - [Specify params to pass into the preview template](#-display-key-value)
|
147
|
+
* `@!group <name> ... @!endgroup` - [Render examples in a group on the same page](#-group-name--endgroup)
|
148
|
+
|
149
|
+
### 🔖 `@label <text>`
|
146
150
|
|
147
151
|
Used to replace the auto-generated navigation label for the item with `<text>`.
|
148
152
|
|
@@ -158,7 +162,7 @@ class FooComponentPreview < ViewComponent::Preview
|
|
158
162
|
end
|
159
163
|
```
|
160
164
|
|
161
|
-
|
165
|
+
### 🔖 `@hidden`
|
162
166
|
|
163
167
|
Used to temporarily exclude an item from the Lookbook navigation. The item will still be accessible via it's URL.
|
164
168
|
|
@@ -176,7 +180,91 @@ class FooComponentPreview < ViewComponent::Preview
|
|
176
180
|
end
|
177
181
|
```
|
178
182
|
|
179
|
-
|
183
|
+
### 🔖 `@display <key>: <value>`
|
184
|
+
|
185
|
+
The `@display` tag lets you pass custom parameters to your preview layout so that the component preview can be customised on a per-example basis.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
# @display bg_color: "#eee"
|
189
|
+
class FooComponentPreview < ViewComponent::Preview
|
190
|
+
|
191
|
+
# @display max_width: "500px"
|
192
|
+
# @display wrapper: true
|
193
|
+
def default
|
194
|
+
end
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
198
|
+
The `@display` tag can be applied at the preview (class) or at the example (method) level, and takes the following format:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
# @display <key>: <value>
|
202
|
+
```
|
203
|
+
|
204
|
+
- `<key>` must be a valid Ruby hash key name, without quotes or spaces
|
205
|
+
- `<value>` must be a valid JSON-parsable value. It can be a string (surrounded by **double** quotes), a boolean or an integer.
|
206
|
+
|
207
|
+
> [See below for some examples](#some-display-value-examples) of valid and invalid `@display` values.
|
208
|
+
|
209
|
+
These display parameters can then be accessed via the `params` hash in your preview layout using `params[:lookbook][:display][<key>]`:
|
210
|
+
|
211
|
+
```html
|
212
|
+
<!DOCTYPE html>
|
213
|
+
<html style="background-color: <%= params[:lookbook][:display][:bg_color] %>">
|
214
|
+
<head>
|
215
|
+
<title>Preview Layout</title>
|
216
|
+
</head>
|
217
|
+
<body>
|
218
|
+
<div style="max-width: <%= params[:lookbook][:display][:max_width] || '100%' %>">
|
219
|
+
<% if params[:lookbook][:display][:wrapper] == true %>
|
220
|
+
<div class="wrapper"><%= yield %></div>
|
221
|
+
<% else %>
|
222
|
+
<%= yield %>
|
223
|
+
<% end %>
|
224
|
+
</div>
|
225
|
+
</body>
|
226
|
+
</html>
|
227
|
+
```
|
228
|
+
|
229
|
+
> By default ViewComponent will use your default application layout for displaying the rendered example. However it's often better to create a seperate layout that you can customise and use specifically for previewing your components. See the ViewComponent [preview docs](https://viewcomponent.org/guide/previews.html) for instructions on how to set that up.
|
230
|
+
|
231
|
+
Any `@display` params set at the preview (class) level with be merged with those set on individual example methods.
|
232
|
+
|
233
|
+
#### Global display params
|
234
|
+
|
235
|
+
Global (fallback) display params can be defined via a configuration option:
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
# config/application.rb
|
239
|
+
config.lookbook.preview_display_params = {
|
240
|
+
bg_color: "#fff",
|
241
|
+
max_width: "100%"
|
242
|
+
}
|
243
|
+
```
|
244
|
+
|
245
|
+
Globally defined display params will be available to all previews. Any preview or example-level `@display` values with the same name will take precedence and override a globally-set one.
|
246
|
+
|
247
|
+
#### Some `@display` value examples:
|
248
|
+
|
249
|
+
Valid:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
# @display body_classes: "bg-red border border-4 border-green"
|
253
|
+
# @display wrap_in_container: true
|
254
|
+
# @display emojis_to_show: 4
|
255
|
+
# @display page_title: "Special example title"
|
256
|
+
```
|
257
|
+
|
258
|
+
Invalid:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
# @display body_classes: 'bg-red border border-4 border-green' [❌ single quotes]
|
262
|
+
# @display wrap_in_container: should_wrap [❌ unquoted string, perhaps trying to call a method]
|
263
|
+
# @display page title: "Special example title" [❌ space in key]
|
264
|
+
# @display bg_color: #fff [❌ colors need quotes around them, it's not CSS!]
|
265
|
+
```
|
266
|
+
|
267
|
+
### 🔖 `@!group <name> ... @!endgroup`
|
180
268
|
|
181
269
|
For smaller components, it can often make sense to render a set of preview examples in a single window, rather than representing them as individual items in the navigation which can start to look a bit cluttered.
|
182
270
|
|
@@ -222,7 +310,7 @@ The example above would display the `Sizes` examples grouped together on a singl
|
|
222
310
|
|
223
311
|
You can have as many groups as you like within a single preview class, but each example can only belong to one group.
|
224
312
|
|
225
|
-
|
313
|
+
### Adding notes
|
226
314
|
|
227
315
|
All comment text other than tags will be treated as markdown and rendered in the **Notes** panel for that example in the Lookbook UI.
|
228
316
|
|
@@ -14,6 +14,17 @@ export default function navNode() {
|
|
14
14
|
? Array.from(this.$refs.items.querySelectorAll(":scope > li"))
|
15
15
|
: [];
|
16
16
|
},
|
17
|
+
navigateToFirstChild() {
|
18
|
+
if (this.open()) {
|
19
|
+
const child = this.firstVisibleChild();
|
20
|
+
if (child) {
|
21
|
+
const link = child.querySelector(":scope > a.nav-link");
|
22
|
+
if (link) {
|
23
|
+
this.navigate(link.getAttribute("href"));
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
},
|
17
28
|
filter() {
|
18
29
|
this.hidden = true;
|
19
30
|
this.getChildren().forEach((child) => {
|
@@ -27,5 +38,12 @@ export default function navNode() {
|
|
27
38
|
toggle() {
|
28
39
|
this.$store.nav.open[this.id] = !this.$store.nav.open[this.id];
|
29
40
|
},
|
41
|
+
firstVisibleChild() {
|
42
|
+
return this.getChildren().find((child) => {
|
43
|
+
return child._x_dataStack
|
44
|
+
? child._x_dataStack[0].hidden === false
|
45
|
+
: false;
|
46
|
+
});
|
47
|
+
},
|
30
48
|
};
|
31
49
|
}
|
@@ -95,14 +95,29 @@ module Lookbook
|
|
95
95
|
html: preview_controller.render_example_to_string(@preview, example.name)
|
96
96
|
}
|
97
97
|
end
|
98
|
-
|
99
|
-
|
98
|
+
set_params
|
99
|
+
joined = render_to_string "lookbook/preview_group", locals: {examples: examples}, layout: nil
|
100
|
+
preview_controller.render_in_layout_to_string(joined, @preview.lookbook_layout || current_layout)
|
100
101
|
else
|
101
|
-
|
102
|
+
set_params(@example)
|
103
|
+
preview_controller.params[:path] = "#{@preview.preview_name}/#{@example.name}".chomp("/")
|
102
104
|
preview_controller.process(:previews)
|
103
105
|
end
|
104
106
|
end
|
105
107
|
|
108
|
+
def set_params(example = nil)
|
109
|
+
example_params = @preview.lookbook_display_params.deep_merge(example ? example.lookbook_display_params : {})
|
110
|
+
preview_controller.params.merge!({
|
111
|
+
lookbook: {
|
112
|
+
display: Lookbook.config.preview_display_params.deep_merge(example_params)
|
113
|
+
}
|
114
|
+
})
|
115
|
+
end
|
116
|
+
|
117
|
+
def current_layout
|
118
|
+
preview_controller.send :_layout, preview_controller.lookup_context, [:html]
|
119
|
+
end
|
120
|
+
|
106
121
|
def assign_inspector
|
107
122
|
@inspector = {
|
108
123
|
panes: {
|
@@ -152,7 +167,7 @@ module Lookbook
|
|
152
167
|
end
|
153
168
|
|
154
169
|
def previews
|
155
|
-
Lookbook::Preview.all
|
170
|
+
Lookbook::Preview.all.sort_by(&:label)
|
156
171
|
end
|
157
172
|
|
158
173
|
def preview_controller
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="flex flex-col h-full min-h-fill w-full">
|
2
|
-
<%= render "
|
2
|
+
<%= render "shared/header" %>
|
3
3
|
<div class="flex flex-col items-center justify-center h-full min-h-fill">
|
4
4
|
<div class="p-4 text-center">
|
5
5
|
<svg class="feather w-10 h-10 text-gray-300 mx-auto">
|
@@ -8,4 +8,4 @@
|
|
8
8
|
<h5 class="mt-4 text-gray-400 text-base">Select a preview to get started</h5>
|
9
9
|
</div>
|
10
10
|
</div>
|
11
|
-
</div>
|
11
|
+
</div>
|
@@ -1 +1 @@
|
|
1
|
-
<%= render "
|
1
|
+
<%= render "shared/workbench" %>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
|
11
11
|
<% if config.auto_refresh %>
|
12
12
|
<script>
|
13
|
-
window.SOCKET_PATH = "
|
13
|
+
window.SOCKET_PATH = "<%= Lookbook::Engine.websocket_mount_path %>";
|
14
14
|
</script>
|
15
15
|
<% end %>
|
16
16
|
<script src="/lookbook-assets/app.js" defer></script>
|
@@ -21,14 +21,14 @@
|
|
21
21
|
<div
|
22
22
|
x-data="page"
|
23
23
|
x-effect="updateTitle"
|
24
|
-
@refresh.document="fetchHTML().then(doc => $dispatch('document:updated', {doc}))"
|
24
|
+
@refresh.document="fetchHTML().then(doc => $dispatch('document:updated', {doc}))"
|
25
25
|
@popstate.window="fetchHTML().then(doc => { $dispatch('document:loaded', {doc}); sidebarOpenMobile = false})"
|
26
26
|
@sidebar:toggle.window="sidebarOpenMobile = !sidebarOpenMobile"
|
27
27
|
:style="`grid-template-columns: ${$store.nav.width}px 1px 1fr;`"
|
28
28
|
class="md:grid w-screen h-screen"
|
29
29
|
>
|
30
30
|
<div class="h-full bg-gray-100 overflow-hidden" x-show="$screen('md') || sidebarOpenMobile" x-cloak>
|
31
|
-
<%= render "
|
31
|
+
<%= render "shared/sidebar" %>
|
32
32
|
</div>
|
33
33
|
<div x-data="split(splitProps)" class="h-full gutter border-r border-gray-300 relative" x-show="$screen('md')" x-cloak>
|
34
34
|
<div class="w-[9px] h-full bg-transparent hover:bg-indigo-100 hover:bg-opacity-20 transition absolute top-0 bottom-0 transform -translate-x-1/2 cursor-[col-resize] z-10"></div>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<%= render "
|
1
|
+
<%= render "nav/node", node: node do %>
|
2
2
|
<% node.items.each do |item| %>
|
3
|
-
<%= render "
|
4
|
-
<% end %>
|
5
|
-
<% end %>
|
3
|
+
<%= render "nav/#{item.type.to_s}", node: item %>
|
4
|
+
<% end %>
|
5
|
+
<% end %>
|
@@ -5,7 +5,7 @@ label ||= leaf.label
|
|
5
5
|
%>
|
6
6
|
<li x-data="navLeaf" :class="{hidden}" x-init="matchers = <%= leaf.matchers.to_json %>; path = '<%= path %>'; setActive()" @popstate.window="setActive">
|
7
7
|
<a href="<%= path %>"
|
8
|
-
class="pr-3 py-[5px] flex items-center w-full group transition hover:bg-gray-200 hover:bg-opacity-50"
|
8
|
+
class="nav-link pr-3 py-[5px] flex items-center w-full group transition hover:bg-gray-200 hover:bg-opacity-50"
|
9
9
|
style="<%= nav_padding_style(depth) %>"
|
10
10
|
:class="{'!bg-indigo-100':active}"
|
11
11
|
@click.stop.prevent="navigate"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<li id="<%= node.id %>" x-data="navNode" <% if node.hierarchy_depth == 1 %> class="py-1 border-b border-gray-300 cursor-pointer"<% end %> :class="{hidden}" x-cloak>
|
2
|
-
<div @click="toggle
|
2
|
+
<div @click="toggle" style="<%= nav_padding_style(node.hierarchy_depth) %>" class="hover:bg-gray-200 hover:bg-opacity-50">
|
3
3
|
<div class="flex items-center cursor-pointer pr-3 py-[5px]">
|
4
4
|
<svg class="feather w-3 h-3 mr-1 text-gray-500 flex-none">
|
5
5
|
<use xlink:href="/lookbook-assets/feather-sprite.svg#chevron-down" x-show="open" x-cloak />
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<svg class="feather h-3.5 w-3.5 mr-1.5 flex-none text-indigo-500">
|
9
9
|
<use xlink:href="/lookbook-assets/feather-sprite.svg#<%= node.type == :preview ? 'layers' : 'folder' %>" />
|
10
10
|
</svg>
|
11
|
-
<div class="truncate whitespace-nowrap text-left <%= "font-bold" if node.type == :preview %>">
|
11
|
+
<div class="truncate w-full whitespace-nowrap text-left <%= "font-bold" if node.type == :preview %>" @click.stop="toggle(); navigateToFirstChild();">
|
12
12
|
<%= node.label %>
|
13
13
|
</div>
|
14
14
|
</div>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<% examples = node.get_examples %>
|
2
2
|
<% if examples.many? %>
|
3
|
-
<%= render "
|
3
|
+
<%= render "nav/node", node: node, path: show_path(examples.first.path) do %>
|
4
4
|
<% examples.each do |example| %>
|
5
|
-
<%= render "
|
5
|
+
<%= render "nav/leaf", leaf: example, depth: example.hierarchy_depth + 1 %>
|
6
6
|
<% end %>
|
7
7
|
<% end %>
|
8
8
|
<% else %>
|
9
9
|
<% example = examples.first %>
|
10
|
-
<%= render "
|
11
|
-
<% end %>
|
10
|
+
<%= render "nav/leaf", leaf: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
|
11
|
+
<% end %>
|
@@ -27,7 +27,7 @@
|
|
27
27
|
<% if @nav.items.any? %>
|
28
28
|
<ul x-ref="items">
|
29
29
|
<% @nav.items.each do |item| %>
|
30
|
-
<%= render "
|
30
|
+
<%= render "nav/#{item.type.to_s}", node: item %>
|
31
31
|
<% end %>
|
32
32
|
</ul>
|
33
33
|
<div class="p-4 text-center" x-show="hidden" x-cloak>
|
@@ -41,5 +41,5 @@
|
|
41
41
|
<% end %>
|
42
42
|
</nav>
|
43
43
|
</div>
|
44
|
-
</div>
|
45
|
-
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<div id="workbench" class="bg-gray-50 h-screen flex flex-col" x-data="workbench">
|
2
|
-
<%= render "
|
2
|
+
<%= render "workbench/header" %>
|
3
3
|
<div class="md:grid flex-grow" :style="`grid-template-rows: 1fr 1px ${$store.inspector.height}px`">
|
4
|
-
<%= render "
|
4
|
+
<%= render "workbench/preview" %>
|
5
5
|
<div class="w-full gutter border-t border-gray-300 relative" x-data="split(splitProps)" x-show="$screen('md')">
|
6
6
|
<div class="h-[11px] w-full bg-transparent hover:bg-indigo-100 hover:bg-opacity-20 transition absolute left-0 right-0 transform -translate-y-1/2 cursor-[row-resize]"></div>
|
7
7
|
</div>
|
8
8
|
<% if @inspector %>
|
9
|
-
<%= render "
|
9
|
+
<%= render "workbench/inspector", **@inspector %>
|
10
10
|
<% end %>
|
11
|
-
</div>
|
12
|
-
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= render "
|
1
|
+
<%= render "shared/header" do %>
|
2
2
|
<div class="flex items-center">
|
3
3
|
<div class="flex items-center space-x-1">
|
4
4
|
<strong class="whitespace-nowrap truncate"><%= @preview.label %></strong>
|
@@ -36,4 +36,4 @@
|
|
36
36
|
</svg>
|
37
37
|
</a>
|
38
38
|
</div>
|
39
|
-
<% end %>
|
39
|
+
<% end %>
|
@@ -21,12 +21,12 @@
|
|
21
21
|
<% panes.each do |key, props| %>
|
22
22
|
<div class="flex flex-col h-full relative" x-show="active('<%= key %>')" x-cloak>
|
23
23
|
<% if props[:clipboard].present? %>
|
24
|
-
<%= render "
|
24
|
+
<%= render "shared/clipboard" do %><%= h props[:clipboard].strip %><% end %>
|
25
25
|
<% end %>
|
26
26
|
<div class="flex flex-col h-full overflow-auto">
|
27
|
-
<%= render "
|
27
|
+
<%= render "workbench/inspector/#{props[:template]}", key: key, **props %>
|
28
28
|
</div>
|
29
29
|
</div>
|
30
30
|
<% end %>
|
31
31
|
</div>
|
32
|
-
</div>
|
32
|
+
</div>
|
data/lib/lookbook/collection.rb
CHANGED
@@ -12,11 +12,11 @@ module Lookbook
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def name
|
15
|
-
@path ? @path.split("/").last : "root"
|
15
|
+
@path.present? ? @path.split("/").last : "root"
|
16
16
|
end
|
17
17
|
|
18
18
|
def label
|
19
|
-
name
|
19
|
+
name&.titleize
|
20
20
|
end
|
21
21
|
|
22
22
|
def hierarchy_depth
|
@@ -24,7 +24,7 @@ module Lookbook
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def items(sorted = true)
|
27
|
-
sorted ? @items.sort_by(&:
|
27
|
+
sorted ? @items.sort_by(&:label) : @items
|
28
28
|
end
|
29
29
|
|
30
30
|
def add(item)
|
data/lib/lookbook/engine.rb
CHANGED
@@ -23,12 +23,14 @@ module Lookbook
|
|
23
23
|
|
24
24
|
options.auto_refresh = true if options.auto_refresh.nil?
|
25
25
|
options.sort_examples = false if options.sort_examples.nil?
|
26
|
+
options.debug = false unless options.debug == true
|
26
27
|
|
27
28
|
options.preview_paths = options.preview_paths.map(&:to_s)
|
28
29
|
options.preview_paths += vc_options.preview_paths
|
29
30
|
|
30
31
|
options.preview_controller = vc_options.preview_controller if options.preview_controller.nil?
|
31
32
|
options.preview_srcdoc = true if options.preview_srcdoc.nil?
|
33
|
+
options.preview_display_params ||= {}
|
32
34
|
|
33
35
|
options.listen_paths = options.listen_paths.map(&:to_s)
|
34
36
|
options.listen_paths += options.preview_paths
|
@@ -43,10 +45,6 @@ module Lookbook
|
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
46
|
-
initializer "lookbook.cable.logger" do
|
47
|
-
Lookbook::Engine.cable.logger ||= Rails.logger
|
48
|
-
end
|
49
|
-
|
50
48
|
initializer "lookbook.parser.tags" do
|
51
49
|
Lookbook::Parser.define_tags
|
52
50
|
end
|
@@ -58,6 +56,15 @@ module Lookbook
|
|
58
56
|
)
|
59
57
|
end
|
60
58
|
|
59
|
+
initializer "lookbook.logging" do
|
60
|
+
if config.lookbook.debug == true
|
61
|
+
Lookbook::Engine.cable.logger ||= Rails.logger
|
62
|
+
else
|
63
|
+
Lookbook::Engine.cable.logger = Lookbook::NullLogger.new
|
64
|
+
config.action_view.logger = Lookbook::NullLogger.new
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
61
68
|
initializer "lookbook.preview.extend" do
|
62
69
|
ActiveSupport.on_load(:view_component) do
|
63
70
|
ViewComponent::Preview.extend Lookbook::Preview
|
@@ -93,6 +100,10 @@ module Lookbook
|
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
103
|
+
def websocket_mount_path
|
104
|
+
"#{Lookbook::Engine.routes.find_script_name({})}#{cable.mount_path}"
|
105
|
+
end
|
106
|
+
|
96
107
|
def cable
|
97
108
|
@cable ||= ActionCable::Server::Configuration.new
|
98
109
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class NullLogger
|
3
|
+
def unknown(*)
|
4
|
+
nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def fatal(*)
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def fatal?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def error(*)
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def error?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def warn(*)
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def warn?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def info(*)
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def info?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def debug(*)
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def debug?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/lookbook/parser.rb
CHANGED
@@ -5,7 +5,7 @@ module Lookbook
|
|
5
5
|
YARDOC_FILE_PATH = Rails.root.join("tmp/storage/.yardoc").to_s
|
6
6
|
|
7
7
|
def initialize(paths)
|
8
|
-
@paths = paths.map { |p| "#{p}
|
8
|
+
@paths = paths.map { |p| "#{p}/**/*_preview.rb" }
|
9
9
|
YARD::Registry.yardoc_file = YARDOC_FILE_PATH
|
10
10
|
end
|
11
11
|
|
@@ -27,6 +27,7 @@ module Lookbook
|
|
27
27
|
def define_tags
|
28
28
|
YARD::Tags::Library.define_tag("Hidden status", :hidden)
|
29
29
|
YARD::Tags::Library.define_tag("Label", :label)
|
30
|
+
YARD::Tags::Library.define_tag("Display", :display)
|
30
31
|
end
|
31
32
|
end
|
32
33
|
end
|
data/lib/lookbook/preview.rb
CHANGED
@@ -80,7 +80,7 @@ module Lookbook
|
|
80
80
|
|
81
81
|
class << self
|
82
82
|
def all
|
83
|
-
ViewComponent::Preview.all
|
83
|
+
ViewComponent::Preview.all.sort_by(&:label)
|
84
84
|
end
|
85
85
|
|
86
86
|
def find(path)
|
@@ -90,8 +90,6 @@ module Lookbook
|
|
90
90
|
def exists?(path)
|
91
91
|
!!find(path)
|
92
92
|
end
|
93
|
-
|
94
|
-
|
95
93
|
end
|
96
94
|
|
97
95
|
private
|
data/lib/lookbook/taggable.rb
CHANGED
@@ -1,23 +1,42 @@
|
|
1
1
|
module Lookbook
|
2
2
|
module Taggable
|
3
3
|
def lookbook_hidden?
|
4
|
-
if code_object
|
4
|
+
if code_object&.tag(:hidden)
|
5
5
|
code_object.tag(:hidden).text.strip != "false"
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
def lookbook_label
|
10
|
-
code_object
|
10
|
+
code_object&.tag(:label)&.text
|
11
11
|
end
|
12
12
|
|
13
13
|
def lookbook_notes
|
14
|
-
code_object
|
14
|
+
if code_object&.docstring
|
15
|
+
code_object.docstring.to_s.strip
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
17
19
|
def lookbook_group
|
18
20
|
code_object&.group
|
19
21
|
end
|
20
22
|
|
23
|
+
def lookbook_display_params
|
24
|
+
display_params = {}
|
25
|
+
if code_object&.tags(:display).present?
|
26
|
+
code_object.tags(:display).each do |tag|
|
27
|
+
parts = tag.text.match(/^\s?([^:]*)\s?:\s?(.*)\s?$/)
|
28
|
+
if parts.present?
|
29
|
+
begin
|
30
|
+
display_params[parts[1]] = JSON.parse parts[2]
|
31
|
+
rescue JSON::ParserError => err
|
32
|
+
Rails.logger.error("\n👀 [Lookbook] Invalid JSON in @display tag.\n👀 [Lookbook] (#{err.to_s})\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
display_params
|
38
|
+
end
|
39
|
+
|
21
40
|
# private
|
22
41
|
|
23
42
|
def code_object
|
data/lib/lookbook/version.rb
CHANGED