lookbook 2.0.0.beta.0 → 2.0.0.beta.2

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: 01c53cc76e29d3d9862a67b29bbabd927c623003bc55355415775c778ec0c99a
4
- data.tar.gz: e8bf4e7538bf3224e70a00458cddea148c594cf4a61287dce978c15793873dfe
3
+ metadata.gz: a6a6aedff44436d4f892bc5b0fc28f596d0cd14f4578af150ea004997f1aa01c
4
+ data.tar.gz: 548938fd0815d99535f3c70831ad9b5a554c23dd8dd6f6d9896538150b1a79ad
5
5
  SHA512:
6
- metadata.gz: 7d2049f0d6b79e2994596a3cbe76e14e247ae75f15f137b0ccd8ed6863dc71637145765beb7c2b826d84f2b350af2e88d72e746667b809f82626e7a70aa4d03f
7
- data.tar.gz: afc5b06b19975253e8f9125723fc1e11d3857ae53af9f5831b9b4c59f1c79fa5d620ffdeed3177a30175c9ad98e92b19b5ba4a37508c0940520ac63ac13fa7bf
6
+ metadata.gz: a3ff63b130c8a92fc6a0f84296d3d56529941a21957eb1ec056d31121ef3eddef308a5397c032d77bf630b9d465085a3dd5f9dd81381abc2fdf88905bfb24ab2
7
+ data.tar.gz: 8fd98d1823d8a9f5b00d690c73416f98993d8dacf6d8af92935e85891a1c9c06452f82cef88e57c48148bc4329104d2f7583a683ae4e7a5dfb58735d337c1fab
data/README.md CHANGED
@@ -27,7 +27,7 @@ For the current stable release see the [main branch](https://github.com/ViewComp
27
27
 
28
28
  ## Development
29
29
 
30
- Lookbook is implemented as an isolated [Rails Engine](https://guides.rubyonrails.org/engines.html) and uses [ViewComponent](https://viewcomponent.org), [Tailwind](https://tailwindcss.com/) and [Alpine](https://alpinejs.dev/) for it's UI.
30
+ Lookbook is implemented as an isolated [Rails Engine](https://guides.rubyonrails.org/engines.html) and uses [ViewComponent](https://viewcomponent.org), [Tailwind](https://tailwindcss.com/) and [Alpine](https://alpinejs.dev/) for its UI.
31
31
 
32
32
  This repository contains:
33
33
 
@@ -57,7 +57,7 @@
57
57
  x-ref="viewportWrapper">
58
58
  <%= lookbook_render :viewport,
59
59
  iframe_id: "#{id}-viewport",
60
- src: helpers.lookbook_preview_path(target.path, params.merge(lookbook_embed: true)),
60
+ src: helpers.lookbook_preview_path(target.path, request.query_parameters.merge(lookbook_timestamp: Time.now, lookbook_embed: true)),
61
61
  alpine_data: "store",
62
62
  resize_height: false,
63
63
  class: "mb-[-2px] transition-[height] duration-150",
@@ -1,7 +1,10 @@
1
1
  <%= render_component_tag class:"p-3 w-[320px]" do %>
2
2
  <h4 class="text-[11px] uppercase tracking-wider mb-2 font-bold">Preview embed code</h4>
3
3
 
4
- <p class="text-xs text-gray-600 mb-3">This code can be used to embed this preview in Lookbook pages or on external sites.</p>
4
+ <p class="text-xs text-gray-600 mb-3">
5
+ This code can be used to embed this preview in
6
+ Lookbook pages<% unless policy == "SAMEORIGIN" %> or on external sites<% end %>.
7
+ </p>
5
8
 
6
9
  <div class="border-t border-lookbook-dropdown-divider pt-3 pb-3">
7
10
  <%= code :html do %><%= embed_code %><% end %>
@@ -1,11 +1,12 @@
1
1
  module Lookbook
2
2
  class EmbedCodeDropdown::Component < Lookbook::BaseComponent
3
- attr_reader :preview, :pages, :params, :target
3
+ attr_reader :preview, :pages, :params, :target, :policy
4
4
 
5
- def initialize(preview:, target:, pages:, params:, **html_attrs)
5
+ def initialize(preview:, target:, pages:, params:, policy:, **html_attrs)
6
6
  @preview = preview
7
7
  @target = target
8
8
  @pages = pages
9
+ @policy = policy
9
10
  @params = params.deep_symbolize_keys
10
11
  super(**html_attrs)
11
12
  end
@@ -1,6 +1,6 @@
1
1
  <%= render_component_tag :header do %>
2
2
  <%= lookbook_render :toolbar, class: "!bg-lookbook-header-bg !text-lookbook-header-text !border-lookbook-header-border" do |toolbar| %>
3
- <% toolbar.with_section class: "mt-[-2px]", padded: true do %>
3
+ <% toolbar.with_section padded: true do %>
4
4
  <% if branding.present? %>
5
5
  <a
6
6
  <% if landing_path %>href="<%= landing_path %>"<% end %>
@@ -42,14 +42,15 @@ module Lookbook
42
42
  display_params = SearchParamParser.call(params[:_display])
43
43
  display_params.each do |name, value|
44
44
  if @dynamic_display_options.key?(name)
45
- cookies["lookbook-display-#{name}"] = value
45
+ cookies["lookbook-display-#{name}"] = value.is_a?(Array) ? value[1] : value
46
46
  end
47
47
  end
48
48
  end
49
49
 
50
50
  @dynamic_display_options.each do |name, opts|
51
51
  choices = opts.is_a?(Hash) ? opts[:choices].to_a : opts
52
- @static_display_options[name] ||= cookies.fetch("lookbook-display-#{name}", choices.first)
52
+ value = choices.first.is_a?(Array) ? choices.first[1] : choices.first
53
+ @static_display_options[name] ||= cookies.fetch("lookbook-display-#{name}", value)
53
54
  end
54
55
 
55
56
  unless params[:_display]
@@ -5,6 +5,8 @@ module Lookbook
5
5
 
6
6
  layout false
7
7
 
8
+ before_action :permit_framing, only: [:show]
9
+
8
10
  def self.controller_path
9
11
  "lookbook/previews"
10
12
  end
@@ -17,10 +19,15 @@ module Lookbook
17
19
  {
18
20
  name: preview.name,
19
21
  scenarios: preview.scenarios.map { |scenario|
20
- {
21
- inspect_path: scenario.url_path,
22
- name: scenario.name
23
- }
22
+ case scenario
23
+ when Lookbook::ScenarioEntity
24
+ scenario_json(scenario)
25
+ when Lookbook::ScenarioGroupEntity
26
+ {
27
+ name: scenario.name,
28
+ examples: scenario.scenarios.map { |s| scenario_json(s) }
29
+ }
30
+ end
24
31
  }
25
32
  }
26
33
  end
@@ -33,7 +40,7 @@ module Lookbook
33
40
  if @target
34
41
  begin
35
42
  opts = {layout: @preview.layout}
36
- if params[:lookbook_embed] == "true"
43
+ if embedded?
37
44
  opts[:append_html] = render_to_string("lookbook/partials/_iframe_content_scripts", layout: nil)
38
45
  end
39
46
  @preview_html = preview_controller.process(:render_in_layout_to_string, "lookbook/previews/group", inspector_data, **opts)
@@ -46,5 +53,24 @@ module Lookbook
46
53
  show_404
47
54
  end
48
55
  end
56
+
57
+ private
58
+
59
+ def embedded?
60
+ params[:lookbook_embed] == "true"
61
+ end
62
+
63
+ def scenario_json(scenario)
64
+ {
65
+ name: scenario.name,
66
+ inspect_path: scenario.url_path,
67
+ preview_path: scenario.preview_path
68
+ }
69
+ end
70
+
71
+ def permit_framing
72
+ headers["X-Frame-Options"] = Lookbook.config.preview_embeds.policy if embedded?
73
+ headers["X-Frame-Options"] = "SAMEORIGIN" if headers["X-Frame-Options"] == "DENY"
74
+ end
49
75
  end
50
76
  end
@@ -11,7 +11,7 @@
11
11
  <%= render "lookbook/partials/user_styles" %>
12
12
 
13
13
  <%= lookbook_render :header, id: "app-header", debug_menu: @config.debug_menu do |header| %>
14
- <% header.branding { @config.project_name } %>
14
+ <% header.with_branding { @config.project_name } %>
15
15
  <% end %>
16
16
 
17
17
  <% if @previews.any? || @pages.any? %>
@@ -29,7 +29,7 @@
29
29
  "@click.outside": "closeMobileSidebar",
30
30
  cloak: true do %>
31
31
 
32
- <% cache do %>
32
+ <% cache @engine.last_changed do %>
33
33
 
34
34
  <%= lookbook_render :split_layout,
35
35
  alpine_data: "$store.layout.#{@pages.any? && @previews.any? ? "sidebar" : "singleSectionSidebar"}",
@@ -53,7 +53,7 @@
53
53
  <% end %>
54
54
  <% end %>
55
55
  <% end %>
56
- <% nav.filter store: "$store.nav.previews.filter", placeholder: "Filter previews by name&hellip;" %>
56
+ <% nav.with_filter store: "$store.nav.previews.filter", placeholder: "Filter previews by name&hellip;" %>
57
57
  <% end %>
58
58
  <% end %>
59
59
  <% end %>
@@ -33,13 +33,16 @@
33
33
 
34
34
  <% toolbar.with_section divide: :left, class: "flex-none relative z-10" do %>
35
35
  <%= lookbook_render :button_group do |group| %>
36
- <%= group.with_button id: "embed-generator-dropdown-button", icon: :code_2, tooltip: "Get embed code" do |button| %>
37
- <% button.with_dropdown.with_content(lookbook_render :embed_code_dropdown,
38
- pages: @pages,
39
- preview: @preview,
40
- target: @target,
41
- params: request.query_parameters
42
- ) %>
36
+ <% if @engine.preview_embeds_allowed? %>
37
+ <%= group.with_button id: "embed-generator-dropdown-button", icon: :code_2, tooltip: "Get embed code" do |button| %>
38
+ <% button.with_dropdown.with_content(lookbook_render :embed_code_dropdown,
39
+ pages: @pages,
40
+ preview: @preview,
41
+ target: @target,
42
+ params: request.query_parameters,
43
+ policy: @config.preview_embeds.policy
44
+ ) %>
45
+ <% end %>
43
46
  <% end %>
44
47
  <% group.with_button id: "copy-preview-url-button",
45
48
  icon: :link,
@@ -2,7 +2,7 @@
2
2
  <%# Render a group of scenarios %>
3
3
  <% scenarios.each do |scenario| %>
4
4
  <div style="margin-bottom: 30px !important; display: block !important;">
5
- <h6 style="all: unset; display: block; color: #999; font-family: sans-serif; font-size: 14px; margin-top: 0; margin-bottom: 10px;">
5
+ <h6 style="all: unset; display: block; color: #555; font-family: sans-serif; font-size: 14px; margin-top: 0; margin-bottom: 10px;">
6
6
  <%= scenario.label %>
7
7
  </h6>
8
8
  <%= scenario.output %>
data/config/app.yml CHANGED
@@ -9,7 +9,8 @@ shared:
9
9
  main_panels: [preview, output]
10
10
  drawer_panels: [source, notes, params, "*"]
11
11
  preview_embeds:
12
- policy: "SAMEORIGIN"
12
+ enabled: true
13
+ policy: SAMEORIGIN
13
14
  panels: false
14
15
  actions: []
15
16
  scenarios: []
data/config/routes.rb CHANGED
@@ -13,6 +13,8 @@ Lookbook::Engine.routes.draw do
13
13
 
14
14
  get "/inspect/*path", to: "inspector#show", as: :lookbook_inspect
15
15
 
16
- get "/embed", to: "embeds#lookup", as: :lookbook_embed_lookup
17
- get "/embed/*path", to: "embeds#show", as: :lookbook_embed
16
+ if Lookbook::Engine.preview_embeds_allowed?
17
+ get "/embed", to: "embeds#lookup", as: :lookbook_embed_lookup
18
+ get "/embed/*path", to: "embeds#show", as: :lookbook_embed
19
+ end
18
20
  end
@@ -82,6 +82,10 @@ module Lookbook
82
82
  reloading? && runtime_context.web? && FileWatcher.evented?
83
83
  end
84
84
 
85
+ def preview_embeds_allowed?
86
+ opts.preview_embeds.enabled == true && opts.preview_embeds.policy != "DENY"
87
+ end
88
+
85
89
  def websocket
86
90
  @_websocket ||= auto_refresh? ? Websocket.new(mount_path, logger: Lookbook.logger) : NullWebsocket.new
87
91
  end
@@ -150,7 +154,7 @@ module Lookbook
150
154
  def preview_watch_paths
151
155
  return @_preview_watch_paths if @_preview_watch_paths
152
156
 
153
- paths = [*opts.preview_paths, opts.components_path, *opts.listen_paths, *view_paths].uniq
157
+ paths = [*opts.preview_paths, *opts.component_paths, *opts.listen_paths, *view_paths].uniq
154
158
  @_preview_watch_paths ||= PathUtils.normalize_paths(paths)
155
159
  end
156
160
 
@@ -173,11 +177,13 @@ module Lookbook
173
177
  changed_files = [*changes[:added], *changes[:modified]] if changes
174
178
  parser.parse(changed_files) do |code_objects|
175
179
  previews.load(code_objects.all(:class), changes)
180
+ mark_changed
176
181
  end
177
182
  end
178
183
 
179
184
  def load_pages(changes = nil)
180
185
  pages.load(Engine.page_paths, changes)
186
+ mark_changed
181
187
  end
182
188
 
183
189
  def notify_clients(changes = nil)
@@ -192,6 +198,15 @@ module Lookbook
192
198
  reloaders.register_changes(changes)
193
199
  notify_clients(changes)
194
200
  end
201
+
202
+ def mark_changed
203
+ @_last_changed = (Time.now.to_f * 1000).to_i
204
+ end
205
+
206
+ def last_changed
207
+ mark_changed unless @_last_changed
208
+ @_last_changed
209
+ end
195
210
  end
196
211
 
197
212
  at_exit do
@@ -61,6 +61,10 @@ module Lookbook
61
61
  lookbook_inspect_path(lookup_path)
62
62
  end
63
63
 
64
+ def preview_path
65
+ lookbook_preview_path(lookup_path)
66
+ end
67
+
64
68
  def type
65
69
  :scenario
66
70
  end
@@ -24,7 +24,7 @@ module Lookbook
24
24
  end
25
25
 
26
26
  def render_targets
27
- @_render_targets ||= RenderTargetCollection.new(scenarios.flat_map(&:render_targets).uniq(&:path))
27
+ @_render_targets ||= RenderTargetCollection.new(scenarios.flat_map(&:render_targets).uniq(&:lookup_path))
28
28
  end
29
29
 
30
30
  def search_terms
@@ -43,6 +43,10 @@ module Lookbook
43
43
  lookbook_inspect_path(lookup_path)
44
44
  end
45
45
 
46
+ def preview_path
47
+ lookbook_preview_path(lookup_path)
48
+ end
49
+
46
50
  def type
47
51
  :group
48
52
  end
@@ -10,5 +10,9 @@ module Lookbook
10
10
  def lookbook_data(key, fallback = nil)
11
11
  Lookbook.data.fetch(key.to_sym, fallback)
12
12
  end
13
+
14
+ def url_for(*args)
15
+ main_app.url_for(*args)
16
+ end
13
17
  end
14
18
  end
@@ -5,7 +5,6 @@ module Lookbook
5
5
  included do
6
6
  helper PreviewHelper
7
7
  prepend_view_path Engine.root.join("app/views")
8
- before_action :permit_embeds
9
8
 
10
9
  def render_scenario_to_string(preview, scenario_name)
11
10
  prepend_application_view_paths
@@ -41,10 +40,6 @@ module Lookbook
41
40
  disable = Lookbook.config.preview_disable_action_view_annotations
42
41
  ActionViewAnnotationsHandler.call(disable_annotations: disable, &block)
43
42
  end
44
-
45
- def permit_embeds
46
- headers["X-Frame-Options"] = Lookbook.config.preview_embeds.policy
47
- end
48
43
  end
49
44
  end
50
45
  end
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "2.0.0.beta.0"
2
+ VERSION = "2.0.0.beta.2"
3
3
  end