lookbook 1.0.3 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/lookbook/js/app.js +1 -0
  3. data/app/assets/lookbook/js/lib/socket.js +9 -5
  4. data/app/components/lookbook/base_component.rb +10 -2
  5. data/app/components/lookbook/copy_button/component.rb +1 -1
  6. data/app/components/lookbook/dimensions_display/component.rb +1 -4
  7. data/app/components/lookbook/embed/component.rb +1 -1
  8. data/app/components/lookbook/icon/component.rb +1 -5
  9. data/app/components/lookbook/nav/component.html.erb +1 -1
  10. data/app/components/lookbook/nav/item/component.rb +2 -2
  11. data/app/components/lookbook/params_editor/field/component.rb +1 -1
  12. data/app/components/lookbook/tabs/component.js +2 -2
  13. data/app/controllers/lookbook/application_controller.rb +10 -1
  14. data/app/controllers/lookbook/pages_controller.rb +0 -1
  15. data/app/controllers/lookbook/previews_controller.rb +9 -6
  16. data/app/helpers/lookbook/component_helper.rb +2 -1
  17. data/app/views/layouts/lookbook/application.html.erb +6 -36
  18. data/app/views/lookbook/index.html.erb +2 -2
  19. data/app/views/lookbook/previews/show.html.erb +1 -1
  20. data/config/routes.rb +1 -1
  21. data/lib/lookbook/config.rb +7 -3
  22. data/lib/lookbook/data.rb +2 -2
  23. data/lib/lookbook/engine.rb +34 -50
  24. data/lib/lookbook/parser.rb +19 -11
  25. data/lib/lookbook/preview.rb +22 -76
  26. data/lib/lookbook/preview_controller.rb +19 -1
  27. data/lib/lookbook/preview_example.rb +12 -5
  28. data/lib/lookbook/source_inspector.rb +2 -2
  29. data/lib/lookbook/store.rb +2 -2
  30. data/lib/lookbook/version.rb +1 -1
  31. data/lib/tasks/lookbook_tasks.rake +1 -2
  32. data/public/lookbook-assets/css/lookbook.css +8 -34
  33. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  34. data/public/lookbook-assets/js/lookbook.js +174 -120
  35. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  36. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 741dcc6296e79ba365a64945fb70b7ba7e8b8df2eee9e83e72ef4e32c619b2fc
4
- data.tar.gz: aa5d6647abc755e54b37837847f5929803eba7545272e6c33b887f2f7c5ef54e
3
+ metadata.gz: 95694c758af19ee6a561b2aedfee93d932c663f7027471204da2dce393052a5a
4
+ data.tar.gz: 1b4f3e4af714af47b6719cbbef7a861ad0ca2341089e2689ef8ed80b9a745867
5
5
  SHA512:
6
- metadata.gz: d19a7567121be4be2c010f61d9c7d62ecff33d53d034a138124516883cbb190102aa0f8c9e9457a0aaf1d33c6d9d5250d3a60ad507af9973348f3c08c03c26bb
7
- data.tar.gz: 8cc77046623125e88550cfd7ff4dd626a2deda064fee6cf3171d5a5cd59bed8ec2277e8091d48d995763db7b3fe66c730e99bde1380a4e5703986e7cc0808ff4
6
+ metadata.gz: 0a148ae5b71546463c003244040e54de07106db6f927e61b77ff35c92d524f37ed59e53646833675a8d1c399968904ffe41891817e85628aa8da879af8aa3bd8
7
+ data.tar.gz: ee91d909da4634558dbf542802ee770c921f0dfdec0bdc37592977b082a97705957bf7e19cf5168b599e78dca1f5d4222147417262c4b41f90b305a43c2c4f72
@@ -11,6 +11,7 @@ export default function app() {
11
11
 
12
12
  init() {
13
13
  if (window.SOCKET_PATH) {
14
+ console.log("SOCKET CREATED");
14
15
  const socket = createSocket(window.SOCKET_PATH);
15
16
  socket.addListener("Lookbook::ReloadChannel", () => this.updateDOM());
16
17
  }
@@ -1,5 +1,5 @@
1
1
  import { createConsumer } from "@rails/actioncable";
2
- import debounce from "debounce";
2
+ import { debounce } from "throttle-debounce";
3
3
  import { log } from "../plugins/logger";
4
4
 
5
5
  export default function socket(endpoint) {
@@ -8,10 +8,14 @@ export default function socket(endpoint) {
8
8
  return {
9
9
  addListener(channel, callback) {
10
10
  consumer.subscriptions.create(channel, {
11
- received: debounce((data) => {
12
- log.debug("Lookbook files changed");
13
- callback(data);
14
- }, 200),
11
+ received: debounce(
12
+ 200,
13
+ (data) => {
14
+ log.debug("Lookbook files changed");
15
+ callback(data);
16
+ },
17
+ { atBegin: true }
18
+ ),
15
19
  connected() {
16
20
  log.info("Lookbook websocket connected");
17
21
  },
@@ -31,11 +31,19 @@ module Lookbook
31
31
  nil
32
32
  end
33
33
 
34
+ def alpine_encode(data)
35
+ if data.is_a? String
36
+ "\'#{json_escape data}\'"
37
+ else
38
+ json_escape data.to_json.tr("\"", "\'")
39
+ end
40
+ end
41
+
34
42
  def prepare_alpine_data(x_data = nil)
35
43
  alpine_component_name = x_data || @html_attrs&.dig(:"x-data") || alpine_component
36
44
  if alpine_component_name.present?
37
- args = Array.wrap(alpine_data)
38
- args.any? ? "#{alpine_component_name}(#{safe_join(args)})" : alpine_component_name
45
+ args = Array.wrap(alpine_data).compact
46
+ args.any? ? "#{alpine_component_name}(#{args.join(",")})" : alpine_component_name
39
47
  end
40
48
  end
41
49
  end
@@ -13,7 +13,7 @@ module Lookbook
13
13
  protected
14
14
 
15
15
  def alpine_data
16
- content ? nil : @target.to_json
16
+ content ? nil : alpine_encode(@target)
17
17
  end
18
18
 
19
19
  def alpine_component
@@ -2,15 +2,12 @@ module Lookbook
2
2
  class DimensionsDisplay::Component < Lookbook::BaseComponent
3
3
  def initialize(target:, **html_attrs)
4
4
  @target = target
5
+ @alpine_data = alpine_encode(@target)
5
6
  super(**html_attrs)
6
7
  end
7
8
 
8
9
  protected
9
10
 
10
- def alpine_data
11
- @target.to_json
12
- end
13
-
14
11
  def alpine_component
15
12
  "dimensionsDisplayComponent"
16
13
  end
@@ -20,7 +20,7 @@ module Lookbook
20
20
  end
21
21
 
22
22
  def alpine_data
23
- [@id.to_json, "$store.pages.embeds"].join(",")
23
+ [alpine_encode(@id), "$store.pages.embeds"].join(",")
24
24
  end
25
25
 
26
26
  def alpine_component
@@ -1,7 +1,7 @@
1
1
  module Lookbook
2
2
  class Icon::Component < Lookbook::BaseComponent
3
3
  def initialize(name:, size: 4, **html_attrs)
4
- @icon_name = name.is_a?(Symbol) ? name.to_s.tr("_", "-").to_json : name
4
+ @alpine_data = name.is_a?(Symbol) ? alpine_encode(name.to_s.tr("_", "-")) : name
5
5
  @size = size || 4
6
6
  super(**html_attrs)
7
7
  end
@@ -12,10 +12,6 @@ module Lookbook
12
12
 
13
13
  protected
14
14
 
15
- def alpine_data
16
- @icon_name
17
- end
18
-
19
15
  def alpine_component
20
16
  "iconComponent"
21
17
  end
@@ -11,7 +11,7 @@
11
11
  </div>
12
12
  <% end %>
13
13
 
14
- <div class="overflow-auto">
14
+ <div class="overflow-auto h-full">
15
15
  <% if items.any? %>
16
16
  <ul class="py-2" x-ref="items" x-show="!empty" x-cloak>
17
17
  <%= safe_join(items) %>
@@ -78,10 +78,10 @@ module Lookbook
78
78
  protected
79
79
 
80
80
  def alpine_data
81
- {
81
+ alpine_encode({
82
82
  id: @item.id,
83
83
  matchers: item.is_a?(Lookbook::Collection) ? nil : item.matchers
84
- }.to_json
84
+ })
85
85
  end
86
86
 
87
87
  def alpine_component
@@ -33,7 +33,7 @@ module Lookbook
33
33
  protected
34
34
 
35
35
  def alpine_data
36
- escaped_value = helpers.raw json_escape(value.to_json)
36
+ escaped_value = json_escape(value.to_json)
37
37
  "{name: '#{name}', value: #{escaped_value}}"
38
38
  end
39
39
 
@@ -1,4 +1,4 @@
1
- import debounce from "debounce";
1
+ import { debounce } from "throttle-debounce";
2
2
  import tippy from "~/app/assets/lookbook/js/lib/tippy";
3
3
  import { observeSize } from "@helpers/layout";
4
4
  import { getElementSize } from "@helpers/dom";
@@ -49,7 +49,7 @@ export default function tabsComponent(store) {
49
49
 
50
50
  this.parentObserver = observeSize(
51
51
  this.$root.parentElement,
52
- debounce(this.handleResize.bind(this), 10)
52
+ debounce(10, this.handleResize.bind(this))
53
53
  );
54
54
 
55
55
  this.$watch("visibleTabsCount", (value) => {
@@ -1,6 +1,9 @@
1
1
  module Lookbook
2
2
  class ApplicationController < ActionController::Base
3
- content_security_policy false, if: -> { Rails.env.development? }
3
+ if respond_to?(:content_security_policy)
4
+ content_security_policy false, if: -> { Rails.env.development? }
5
+ end
6
+
4
7
  protect_from_forgery with: :exception
5
8
 
6
9
  helper Lookbook::ApplicationHelper
@@ -8,6 +11,7 @@ module Lookbook
8
11
  helper Lookbook::ComponentHelper
9
12
 
10
13
  before_action :generate_theme_overrides
14
+ before_action :assign_collections
11
15
 
12
16
  def self.controller_path
13
17
  "lookbook"
@@ -28,6 +32,11 @@ module Lookbook
28
32
  @theme_overrides ||= Lookbook.theme.to_css
29
33
  end
30
34
 
35
+ def assign_collections
36
+ @previews = Preview.all
37
+ @pages = Page.all
38
+ end
39
+
31
40
  def feature_enabled?(feature)
32
41
  Lookbook::Features.enabled?(feature)
33
42
  end
@@ -18,7 +18,6 @@ module Lookbook
18
18
  end
19
19
 
20
20
  def show
21
- @pages = Lookbook.pages
22
21
  @page = @pages.find_by_path(params[:path])
23
22
  if @page
24
23
  @next_page = @pages.find_next(@page)
@@ -158,22 +158,25 @@ module Lookbook
158
158
 
159
159
  def panels
160
160
  return @panels if @panels.present?
161
- @panels = []
162
- Lookbook.config.inspector_panels.each do |name, config|
161
+ inspector_data_hash = inspector_data.to_h
162
+ panel_counts = {}
163
+
164
+ @panels = Lookbook.config.inspector_panels.map do |name, config|
163
165
  config_with_defaults = Lookbook.config.inspector_panel_defaults.merge(config)
166
+ panel_counts[config_with_defaults[:pane].to_sym] ||= 0
167
+ panel_counts[config_with_defaults[:pane].to_sym] += 1
164
168
 
165
169
  callable_data = {
166
170
  name: name.to_s,
167
- index_position: (@panels.count { |p| p.pane == config.pane } + 1),
168
- **inspector_data
171
+ index_position: panel_counts[config_with_defaults[:pane].to_sym],
172
+ **inspector_data_hash
169
173
  }
170
174
 
171
175
  resolved_config = config_with_defaults.transform_values do |value|
172
176
  value.instance_of?(Proc) ? value.call(Lookbook::Store.new(callable_data)) : value
173
177
  end
174
178
  resolved_config[:name] = name.to_s
175
-
176
- @panels << Lookbook::Store.new(resolved_config, deep: false)
179
+ Store.new(resolved_config)
177
180
  end
178
181
 
179
182
  @panels = @panels.select(&:show).sort_by { |p| [p.position, p.label] }
@@ -6,7 +6,8 @@ module Lookbook
6
6
  render Lookbook::Icon::Component.new(name: name, **attrs)
7
7
  end
8
8
 
9
- def code(**attrs, &block)
9
+ def code(language = :html, **attrs, &block)
10
+ attrs[:language] ||= language
10
11
  render Lookbook::Code::Component.new(**attrs), &block
11
12
  end
12
13
 
@@ -1,5 +1,5 @@
1
1
  <% content_for :shell do %>
2
- <% if Lookbook.previews? || Lookbook.pages? %>
2
+ <% if @previews.any? || @pages.any? %>
3
3
  <%= render_component :split_layout,
4
4
  alpine_data: "$store.layout.main",
5
5
  ":class": "$store.layout.mobile && '!block'" do |layout| %>
@@ -14,14 +14,14 @@
14
14
  cloak: true do %>
15
15
 
16
16
  <%= render_component :split_layout,
17
- alpine_data: "$store.layout.#{Lookbook.pages? && Lookbook.previews? ? "sidebar" : "singleSectionSidebar"}",
17
+ alpine_data: "$store.layout.#{@pages.any? && @previews.any? ? "sidebar" : "singleSectionSidebar"}",
18
18
  style: "height: calc(100vh - 2.5rem);" do |layout| %>
19
19
 
20
- <% if Lookbook.previews? %>
20
+ <% if @previews.any? %>
21
21
  <% layout.pane class: "overflow-hidden" do %>
22
22
  <%= render_component :nav,
23
23
  id: "previews-nav",
24
- collection: Lookbook.previews,
24
+ collection: @previews,
25
25
  alpine_data: "$store.nav.previews",
26
26
  collapse_singles: true do |nav| %>
27
27
  <%= nav.toolbar do |toolbar| %>
@@ -34,11 +34,11 @@
34
34
  <% end %>
35
35
  <% end %>
36
36
 
37
- <% if Lookbook.pages? %>
37
+ <% if @pages.any? %>
38
38
  <% layout.pane class: "overflow-hidden" do %>
39
39
  <%= render_component :nav,
40
40
  id: "pages-nav",
41
- collection: Lookbook.pages,
41
+ collection: @pages,
42
42
  alpine_data: "$store.nav.pages" do |nav| %>
43
43
  <%= nav.toolbar do |toolbar| %>
44
44
  <% toolbar.section padded: true do %>
@@ -49,36 +49,6 @@
49
49
  <% end %>
50
50
  <% end %>
51
51
  <% end %>
52
-
53
- <% if Lookbook::Preview.errors.any? %>
54
- <div x-data="{hidden: false}" class="flex-none border-t border-lookbook-divider absolute bottom-0 left-0 right-0" x-show="!hidden">
55
- <%= render_component :toolbar do |toolbar| %>
56
- <% toolbar.section padded: true, class: "flex items-center" do %>
57
- <%= icon :alert_triangle, size: 4, class: "text-red-700" %>
58
- <span class="ml-2">Preview load errors</span>
59
- <% end %>
60
- <% toolbar.section align: :right do %>
61
- <% render_component :button, icon: :x, "@click": "hidden = !hidden" %>
62
- <% end %>
63
- <% end %>
64
-
65
- <div class="h-full max-h-[300px] overflow-hidden">
66
- <div class="bg-red-50 w-full overflow-auto h-full">
67
- <ul class="text-sm divide-y divide-red-200">
68
- <% Lookbook::Preview.errors.each do |error| %>
69
- <% error = error.is_a?(Lookbook::Error) ? error : Lookbook::Error.new(error) %>
70
- <li class="px-4 py-3">
71
- <h4 class="break-all leading-tight text-xs ">
72
- <%= error.file_name %><%= ":#{error.line_number}" if error.line_number %>
73
- </h4>
74
- <pre class="text-red-800 text-xs mt-2 whitespace-pre-wrap opacity-80 font-mono"><%= error.message %></pre>
75
- </li>
76
- <% end %>
77
- </ul>
78
- </div>
79
- </div>
80
- </div>
81
- <% end %>
82
52
  <% end %>
83
53
 
84
54
  <% layout.pane id: "app-main", class: "overflow-hidden h-full", ":class": "$store.layout.mobile && 'w-screen'" do %>
@@ -1,10 +1,10 @@
1
1
  <div id="landing" class="flex flex-col items-center justify-center h-full w-full">
2
- <div class="text-center" id="landing-<%= Lookbook.previews? ? "with" : "no" %>-content">
2
+ <div class="text-center" id="landing-<%= @previews.any? ? "with" : "no" %>-content">
3
3
  <h5 class="text-base text-lookbook-blank-slate-title truncate uppercase font-black tracking-wider mb-2">
4
4
  <%= config.project_name %>
5
5
  </h5>
6
6
  <div class="opacity-60">
7
- <% if Lookbook.previews? %>
7
+ <% if @previews.any? %>
8
8
  <p>Select a preview from the nav to get started.</p>
9
9
  <% else %>
10
10
  <p><a class="underline" href="https://lookbook.build/guide/previews" target="_blank">Create a preview</a> to get started.</p>
@@ -25,7 +25,7 @@
25
25
 
26
26
  <% toolbar.section divide: :left, class: "flex-none relative z-10" do %>
27
27
  <%= render_component :button_group do |group| %>
28
- <% if Lookbook.pages.any? %>
28
+ <% if @pages.any? %>
29
29
  <% group.button icon: :code,
30
30
  tooltip: "Copy page embed code",
31
31
  copy: true do %>
data/config/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  Lookbook::Engine.routes.draw do
2
2
  if Lookbook::Engine.websocket?
3
- mount Lookbook::Engine.websocket => Lookbook.config.cable_mount_path
3
+ mount Lookbook::Engine.websocket => Lookbook.config.cable_mount_path, :as => :cable
4
4
  end
5
5
 
6
6
  root to: "application#index", as: :lookbook_home
@@ -5,7 +5,7 @@ require "lookbook/store"
5
5
  module Lookbook
6
6
  class Config
7
7
  def initialize
8
- @options = Store.new
8
+ @options = Store.new({}, true)
9
9
 
10
10
  @options.set({
11
11
  project_name: "Lookbook",
@@ -24,6 +24,7 @@ module Lookbook
24
24
  preview_display_params: {},
25
25
  preview_srcdoc: nil,
26
26
  preview_tags: {},
27
+ preview_disable_action_view_annotations: true,
27
28
  sort_examples: false,
28
29
 
29
30
  listen: Rails.env.development?,
@@ -31,10 +32,9 @@ module Lookbook
31
32
  listen_extensions: ["rb", "html.*"],
32
33
  listen_use_polling: false,
33
34
 
34
- cable_mount_path: "/lookbook-cable",
35
+ cable_mount_path: "/cable",
35
36
  cable_logger: Lookbook.logger,
36
37
 
37
- runtime_parsing: !Rails.env.production?,
38
38
  parser_registry_path: "tmp/storage/.yardoc",
39
39
 
40
40
  ui_theme: "indigo",
@@ -104,6 +104,10 @@ module Lookbook
104
104
  })
105
105
  end
106
106
 
107
+ def runtime_parsing=(value)
108
+ Lookbook.logger.warn "The `runtime_parsing` config option has been deprecated and will be removed in v2.0"
109
+ end
110
+
107
111
  def project_name
108
112
  @options.project_name == false ? nil : @options.project_name
109
113
  end
data/lib/lookbook/data.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  module Lookbook
2
2
  module Data
3
3
  def data
4
- @data ||= Store.new
4
+ @data ||= Store.new({}, true)
5
5
  end
6
6
 
7
7
  def data=(props)
8
- @data = Store.new(props)
8
+ @data = Store.new(props, true)
9
9
  end
10
10
  end
11
11
  end
@@ -35,7 +35,7 @@ module Lookbook
35
35
  {
36
36
  version: version,
37
37
  env: Rails.env.to_s,
38
- config: config
38
+ config: config.to_h
39
39
  }
40
40
  end
41
41
 
@@ -43,18 +43,10 @@ module Lookbook
43
43
  Preview.all
44
44
  end
45
45
 
46
- def previews?
47
- Preview.any?
48
- end
49
-
50
46
  def pages
51
47
  Page.all
52
48
  end
53
49
 
54
- def pages?
55
- Page.any?
56
- end
57
-
58
50
  def broadcast(event_name, data = {})
59
51
  Engine.websocket&.broadcast(event_name.to_s, data)
60
52
  end
@@ -99,6 +91,11 @@ module Lookbook
99
91
  @preview_controller = Lookbook.config.preview_controller.constantize
100
92
  @preview_controller.include(Lookbook::PreviewController)
101
93
 
94
+ parser.after_parse do |registry|
95
+ Preview.load!(registry.all(:class))
96
+ reload_ui
97
+ end
98
+
102
99
  if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1.3.1")
103
100
  # Rails.application.server is only available for newer Rails versions
104
101
  Rails.application.server do
@@ -111,19 +108,9 @@ module Lookbook
111
108
  end
112
109
  end
113
110
 
114
- if config.lookbook.runtime_parsing
115
- Lookbook::Engine.parser.parse
116
- else
117
- unless File.exist?(config.lookbook.parser_registry_path)
118
- Lookbook.logger.warn "
119
- Runtime parsing is disabled but no registry file has been found.
120
- Did you run `rake lookbook:preparse` before starting the app?
121
- Expected to find registry file at #{config.lookbook.parser_registry_path}
122
- "
123
- end
111
+ parser.parse do
112
+ Lookbook::Engine.run_hooks(:after_initialize)
124
113
  end
125
-
126
- Lookbook::Engine.run_hooks(:after_initialize)
127
114
  end
128
115
 
129
116
  at_exit do
@@ -140,43 +127,40 @@ module Lookbook
140
127
  return unless config.listen == true
141
128
  Listen.logger = Lookbook.logger
142
129
 
143
- preview_listener = Listen.to(
144
- *config.listen_paths,
145
- only: /\.(#{config.listen_extensions.join("|")})$/,
146
- force_polling: config.listen_use_polling
147
- ) do |modified, added, removed|
148
- changes = {modified: modified, added: added, removed: removed}
149
- begin
150
- parser.parse
151
- rescue
130
+ listen_paths = config.listen_paths.uniq
131
+ if listen_paths.any?
132
+ preview_listener = Listen.to(*listen_paths,
133
+ only: /\.(#{config.listen_extensions.join("|")})$/,
134
+ force_polling: config.listen_use_polling) do |modified, added, removed|
135
+ parser.parse do
136
+ run_hooks(:after_change, {modified: modified, added: added, removed: removed})
137
+ end
152
138
  end
153
- Lookbook::Preview.clear_cache
154
- reload_ui(changes)
155
- run_hooks(:after_change, changes)
139
+ register_listener(preview_listener)
156
140
  end
157
- register_listener(preview_listener)
158
-
159
- page_listener = Listen.to(
160
- *config.page_paths,
161
- only: /\.(html.*|md.*)$/,
162
- force_polling: config.listen_use_polling
163
- ) do |modified, added, removed|
164
- changes = {modified: modified, added: added, removed: removed}
165
- reload_ui(changes)
166
- run_hooks(:after_change, changes)
141
+
142
+ page_paths = config.page_paths.uniq
143
+ if page_paths.any?
144
+ page_listener = Listen.to(*page_paths,
145
+ only: /\.(html.*|md.*)$/,
146
+ force_polling: config.listen_use_polling) do |modified, added, removed|
147
+ changes = {modified: modified, added: added, removed: removed}
148
+ reload_ui
149
+ run_hooks(:after_change, changes)
150
+ end
151
+ register_listener(page_listener)
167
152
  end
168
- register_listener(page_listener)
169
153
  end
170
154
 
171
155
  def websocket
172
156
  config = Lookbook.config
173
157
  return @websocket unless @websocket.nil?
174
- return unless config.auto_refresh == true
158
+ return unless config.auto_refresh == true && config.listen == true && !Rails.env.test?
175
159
  Lookbook.logger.info "Initializing websocket"
176
160
 
177
161
  cable = ActionCable::Server::Configuration.new
178
162
  cable.cable = {adapter: "async"}.with_indifferent_access
179
- cable.mount_path = config.cable_mount_path
163
+ cable.mount_path = nil
180
164
  cable.connection_class = -> { Lookbook::Connection }
181
165
  cable.logger = config.cable_logger
182
166
 
@@ -190,7 +174,7 @@ module Lookbook
190
174
  end
191
175
 
192
176
  def websocket_mount_path
193
- "#{mounted_path}#{config.lookbook.cable_mount_path}" if websocket?
177
+ "#{mounted_path}#{config.lookbook.cable_mount_path}".gsub("//", "/") if websocket?
194
178
  end
195
179
 
196
180
  def websocket?
@@ -202,7 +186,7 @@ module Lookbook
202
186
  end
203
187
 
204
188
  def parser
205
- @parser ||= Lookbook::Parser.new(config.lookbook.preview_paths, config.lookbook.parser_registry_path)
189
+ @parser ||= Lookbook::Parser.new(config.lookbook.preview_paths)
206
190
  end
207
191
 
208
192
  def log_level
@@ -237,8 +221,8 @@ module Lookbook
237
221
  end
238
222
  end
239
223
 
240
- def reload_ui(changed = {})
241
- websocket&.broadcast("reload", changed)
224
+ def reload_ui
225
+ websocket&.broadcast("reload", {})
242
226
  end
243
227
 
244
228
  def prevent_listening?
@@ -3,24 +3,32 @@ require "yard"
3
3
  module Lookbook
4
4
  class Parser
5
5
  attr_reader :registry_path
6
- def initialize(paths, registry_path)
6
+ def initialize(paths)
7
7
  @paths = paths.map { |p| "#{p}/**/*preview.rb" }
8
- @registry_path = registry_path.to_s
9
- YARD::Registry.yardoc_file = registry_path
8
+ @after_parse_callbacks = []
9
+ @after_parse_once_callbacks = []
10
+ @parsing = false
11
+
12
+ YARD::Parser::SourceParser.after_parse_list do
13
+ [*@after_parse_callbacks, *@after_parse_once_callbacks].each do |callback|
14
+ callback.call(YARD::Registry)
15
+ end
16
+ @after_parse_once_callbacks = []
17
+ @parsing = false
18
+ end
10
19
  end
11
20
 
12
- def parse
13
- YARD::Registry.clear
14
- YARD::Registry.lock_for_writing do
21
+ def parse(&block)
22
+ unless @parsing
23
+ @parsing = true
24
+ @after_parse_once_callbacks << block if block
25
+ YARD::Registry.clear
15
26
  YARD.parse(@paths)
16
- YARD::Registry.save(false, registry_path)
17
27
  end
18
28
  end
19
29
 
20
- def get_code_object(path)
21
- registry = YARD::RegistryStore.new
22
- registry.load!(registry_path)
23
- registry.get(path)
30
+ def after_parse(&block)
31
+ @after_parse_callbacks << block
24
32
  end
25
33
 
26
34
  class << self