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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1f01b55ea75634f7e4cf2f7fe438ce6b56042daa5d7f178e50d0db7c267a644
4
- data.tar.gz: 81fddb93ab9aed2d51a59ecd00deced19c97a395ced5de3223db0d229f3a57dd
3
+ metadata.gz: 870ef6a17d84bca0a9fbbc421e27c2d6d682965d96c646f44d3db817e5a5e4f2
4
+ data.tar.gz: 669ce3b709792be5bdf46ac806efdca269d694349e74f759b0997cbbb456792e
5
5
  SHA512:
6
- metadata.gz: 535340241df2352ba1c0fa5983f178cdb76d5fc39f0b4c9bcc8c34e4dc782177a4110f85a47ac6632064ac52b064f6936fe9cb764d5a5f2a8b527c9a80342bff
7
- data.tar.gz: 1d580f19491db04693d6e31941c198c4b1416665836d90436e84ddf4dadad7e325612be88c959fd2fff1900c061e2e54e2b8cbf82cda5ce947addcdba7bd251d
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](https://rubydoc.info/gems/yard/file/docs/Tags.md) 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.
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
- - Hide, group and rename preview examples using comment tags
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
- ### Annotating preview files
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
- # Secondary button
93
+ # Inverted button
97
94
  # ---------------
98
- # This should be used for less important actions.
95
+ # For light-on-dark screens
96
+ #
97
+ # @display bg_color: "#000"
99
98
  def secondary
100
- render ButtonComponent.new(style: :secondary) do
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
- #### `@label <text>`
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
- #### `@hidden`
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
- #### `@!group <name> ... @!endgroup`
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
- #### Adding notes
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
- joined = render_to_string "./preview_group", locals: {examples: examples}, layout: nil
99
- preview_controller.render_in_layout_to_string(joined, @preview.lookbook_layout)
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
- preview_controller.request.params[:path] = "#{@preview.preview_name}/#{@example.name}".chomp("/")
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 "./shared/header" %>
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 "./workbench" %>
1
+ <%= render "shared/workbench" %>
@@ -10,7 +10,7 @@
10
10
 
11
11
  <% if config.auto_refresh %>
12
12
  <script>
13
- window.SOCKET_PATH = "/lookbook/cable";
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 "./sidebar" %>
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 "./nav/node", node: node do %>
1
+ <%= render "nav/node", node: node do %>
2
2
  <% node.items.each do |item| %>
3
- <%= render "./nav/#{item.type.to_s}", node: item %>
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(); if (open()) { <%= "navigate('#{path}')" if defined?(path) %>}" style="<%= nav_padding_style(node.hierarchy_depth) %>" class="hover:bg-gray-200 hover:bg-opacity-50">
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 "./nav/node", node: node, path: show_path(examples.first.path) do %>
3
+ <%= render "nav/node", node: node, path: show_path(examples.first.path) do %>
4
4
  <% examples.each do |example| %>
5
- <%= render "./nav/leaf", leaf: example, depth: example.hierarchy_depth + 1 %>
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 "./nav/leaf", leaf: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
11
- <% end %>
10
+ <%= render "nav/leaf", leaf: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
11
+ <% end %>
@@ -5,4 +5,4 @@
5
5
  </svg>
6
6
  </button>
7
7
  <%= yield %>
8
- </header>
8
+ </header>
@@ -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 "./nav/#{item.type.to_s}", node: item %>
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 "./workbench/header" %>
2
+ <%= render "workbench/header" %>
3
3
  <div class="md:grid flex-grow" :style="`grid-template-rows: 1fr 1px ${$store.inspector.height}px`">
4
- <%= render "./workbench/preview" %>
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 "./workbench/inspector", **@inspector %>
9
+ <%= render "workbench/inspector", **@inspector %>
10
10
  <% end %>
11
- </div>
12
- </div>
11
+ </div>
12
+ </div>
@@ -1,4 +1,4 @@
1
- <%= render "./shared/header" do %>
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 "./shared/clipboard" do %><%= h props[:clipboard].strip %><% end %>
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 "./workbench/inspector/#{props[:template]}", key: key, **props %>
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>
@@ -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.titleize
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(&:name) : @items
27
+ sorted ? @items.sort_by(&:label) : @items
28
28
  end
29
29
 
30
30
  def add(item)
@@ -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
@@ -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}/**/*.rb" }
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
@@ -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
@@ -1,23 +1,42 @@
1
1
  module Lookbook
2
2
  module Taggable
3
3
  def lookbook_hidden?
4
- if code_object.tag(:hidden)
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.tag(:label)&.text
10
+ code_object&.tag(:label)&.text
11
11
  end
12
12
 
13
13
  def lookbook_notes
14
- code_object.docstring.to_s.strip
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
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0.beta.1"
3
3
  end
data/lib/lookbook.rb CHANGED
@@ -12,4 +12,5 @@ module Lookbook
12
12
  autoload :PreviewExample, "lookbook/preview_example"
13
13
  autoload :PreviewGroup, "lookbook/preview_group"
14
14
  autoload :Taggable, "lookbook/taggable"
15
+ autoload :NullLogger, "lookbook/null_logger"
15
16
  end