lookbook 2.0.0.beta.1 → 2.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/lookbook/css/fonts.css +33 -0
  3. data/app/assets/lookbook/css/lookbook.css +1 -0
  4. data/app/assets/lookbook/fonts/Inter-italic.var.woff2 +0 -0
  5. data/app/assets/lookbook/fonts/Inter-roman.var.woff2 +0 -0
  6. data/app/assets/lookbook/fonts/SourceCodeVariable-Italic.ttf.woff2 +0 -0
  7. data/app/assets/lookbook/fonts/SourceCodeVariable-Roman.ttf.woff2 +0 -0
  8. data/app/assets/lookbook/js/lib/lookbook.js +12 -2
  9. data/app/components/lookbook/embed_code_dropdown/component.html.erb +4 -1
  10. data/app/components/lookbook/embed_code_dropdown/component.rb +3 -2
  11. data/app/components/lookbook/nav/entity/component.html.erb +1 -1
  12. data/app/components/lookbook/page_tabs/component.html.erb +2 -2
  13. data/app/controllers/concerns/lookbook/targetable_concern.rb +3 -2
  14. data/app/controllers/lookbook/previews_controller.rb +6 -1
  15. data/app/views/layouts/lookbook/application.html.erb +1 -1
  16. data/app/views/lookbook/inspector/show.html.erb +10 -7
  17. data/app/views/lookbook/pages/show.html.erb +3 -3
  18. data/config/app.yml +2 -1
  19. data/config/routes.rb +4 -2
  20. data/lib/lookbook/engine.rb +24 -5
  21. data/lib/lookbook/entities/scenario_group_entity.rb +1 -1
  22. data/lib/lookbook/error.rb +1 -1
  23. data/lib/lookbook/helpers/preview_helper.rb +4 -0
  24. data/lib/lookbook/services/markdown_renderer.rb +2 -4
  25. data/lib/lookbook/version.rb +1 -1
  26. data/public/lookbook-assets/Inter-italic.var.69eb0fe1.woff2 +0 -0
  27. data/public/lookbook-assets/Inter-italic.var.736a7044.woff2 +0 -0
  28. data/public/lookbook-assets/Inter-roman.var.b695afbe.woff2 +0 -0
  29. data/public/lookbook-assets/Inter-roman.var.fbdd51d0.woff2 +0 -0
  30. data/public/lookbook-assets/SourceCodeVariable-Italic.cad97b83.otf +0 -0
  31. data/public/lookbook-assets/SourceCodeVariable-Italic.ttf.09b4354a.woff2 +0 -0
  32. data/public/lookbook-assets/SourceCodeVariable-Italic.ttf.fcd7e9f4.woff2 +0 -0
  33. data/public/lookbook-assets/SourceCodeVariable-Roman.185ddb17.otf +0 -0
  34. data/public/lookbook-assets/SourceCodeVariable-Roman.ttf.118e9f22.woff2 +0 -0
  35. data/public/lookbook-assets/SourceCodeVariable-Roman.ttf.91043609.woff2 +0 -0
  36. data/public/lookbook-assets/css/lookbook.css +426 -386
  37. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  38. data/public/lookbook-assets/js/lookbook-core.js +4 -2
  39. data/public/lookbook-assets/js/lookbook.js +4 -2
  40. metadata +18 -21
  41. data/lib/tasks/lookbook_tasks.rake +0 -10
  42. data/public/lookbook-assets/css/app.css +0 -2341
  43. data/public/lookbook-assets/css/app.css.map +0 -11
  44. data/public/lookbook-assets/css/themes/zinc.css.map.91837.5 +0 -1
  45. data/public/lookbook-assets/feather-sprite.svg +0 -1
  46. data/public/lookbook-assets/js/app.js +0 -10862
  47. data/public/lookbook-assets/js/app.js.map +0 -2571
  48. data/public/lookbook-assets/js/embed.js +0 -1427
  49. data/public/lookbook-assets/js/embed.js.91837.6 +0 -0
  50. data/public/lookbook-assets/js/embed.js.map +0 -1
  51. data/public/lookbook-assets/js/lookbook-core.js.map +0 -1
  52. data/public/lookbook-assets/js/lookbook.js.map +0 -1
  53. data/public/lookbook-assets/lookbook-esm.js +0 -1427
  54. data/public/lookbook-assets/lookbook-esm.js.map +0 -1
  55. data/public/lookbook-assets/lookbook-global.js +0 -1427
  56. data/public/lookbook-assets/lookbook-global.js.map +0 -1
  57. data/public/lookbook-assets/lookbook.js +0 -1427
  58. data/public/lookbook-assets/lookbook.js.map +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03b89a2cdb1b56200c40166eb670887c79a01cf98152653ece5c512fff450492
4
- data.tar.gz: ff7da5b63b5023bb3e9f0149af2a49eab5392450cc8851dd258eb7b2973d3267
3
+ metadata.gz: fcdd4b9e317b56fb9844a1f7017604b77de9992c2d837dc927c9114d5da085cd
4
+ data.tar.gz: 4cde43bf1aa5df6d781fdf5406faff47cee683bd778654b78d7c96b1439e61ab
5
5
  SHA512:
6
- metadata.gz: bac766446880b1f66ac4e68746b638934d1c451e32231a1f24b48b931823ffd11a83147eadeb5106a39c9302759a7f234daba0a2ffbbf7ec46cc9d38090a6757
7
- data.tar.gz: 25acb93d4fb260485627def8d01fa7975034662fdc9ca6db621445cf83708c66423e5318655130189bdd1b5edd8f6132e8126658bddc48ad3442bedc1430799f
6
+ metadata.gz: 99f938fc0e5827535823a9631dd8f7de7fe341da07ebdd1591a70fdb25b1124613c8a5d07d621985447a1e00eb6ee2314f933059652b21b9fd33997452010acd
7
+ data.tar.gz: 4f0378245e9e3239affe31022d69a61c276bfa1389450a410db183acd9faa137a32c1908859b88f6e5808bdbf2a6fced966751834627ae6a96025d85df7c6967
@@ -0,0 +1,33 @@
1
+ @font-face {
2
+ font-family: "Inter var";
3
+ font-weight: 100 900;
4
+ font-display: swap;
5
+ font-style: normal;
6
+ font-named-instance: "Regular";
7
+ src: url("../fonts/Inter-roman.var.woff2?v=3.19") format("woff2");
8
+ }
9
+
10
+ @font-face {
11
+ font-family: "Inter var";
12
+ font-weight: 100 900;
13
+ font-display: swap;
14
+ font-style: italic;
15
+ font-named-instance: "Italic";
16
+ src: url("../fonts/Inter-italic.var.woff2?v=3.19") format("woff2");
17
+ }
18
+
19
+ @font-face {
20
+ font-family: "Source Code Variable";
21
+ font-weight: 200 900;
22
+ font-style: normal;
23
+ font-stretch: normal;
24
+ src: url("../fonts/SourceCodeVariable-Roman.ttf.woff2") format("woff2");
25
+ }
26
+
27
+ @font-face {
28
+ font-family: "Source Code Variable";
29
+ font-weight: 200 900;
30
+ font-style: italic;
31
+ font-stretch: normal;
32
+ src: url("../fonts/SourceCodeVariable-Italic.ttf.woff2") format("woff2");
33
+ }
@@ -1,3 +1,4 @@
1
+ @import "./fonts.css";
1
2
  @import "tailwindcss/base";
2
3
  @import "tailwindcss/components";
3
4
  @import "tailwindcss/utilities";
@@ -10,7 +10,7 @@ const whiteListedAttributes = [
10
10
  "param-*",
11
11
  ];
12
12
 
13
- function initEmbeds() {
13
+ function initEmbeds(root = document) {
14
14
  if (typeof window.iFrameResize !== "function") {
15
15
  console.error(
16
16
  "Lookbook embeds require the 'iframe-resizer' library to be available. Skipping embed instantiation."
@@ -18,7 +18,17 @@ function initEmbeds() {
18
18
  return;
19
19
  }
20
20
 
21
- const embeds = Array.from(document.querySelectorAll("lookbook-embed"));
21
+ if (typeof root === "string") {
22
+ root = document.querySelector(root);
23
+ }
24
+
25
+ if (!root) {
26
+ return console.error(
27
+ "Could not initialize Lookbook embeds. Root node not found."
28
+ );
29
+ }
30
+
31
+ const embeds = Array.from(root.querySelectorAll("lookbook-embed"));
22
32
 
23
33
  embeds.forEach((embed) => {
24
34
  const attrs = Array.from(embed.attributes);
@@ -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
@@ -17,7 +17,7 @@
17
17
  class: "nav-toggle-icon",
18
18
  "x-effect": "iconName = open ? 'chevron-down' : 'chevron-right'" if children? %>
19
19
  <%= icon nav_icon, size: 3.5, class: "mr-1.5 text-lookbook-nav-icon-stroke" %>
20
- <span class="truncate <% if node.type == :preview %>font-bold<% end %>"><%= label %></span>
20
+ <span class="truncate <% if node.type == :preview %>font-semibold<% end %>"><%= label %></span>
21
21
  </div>
22
22
  <% end %>
23
23
 
@@ -2,13 +2,13 @@
2
2
  <div class="flex w-full border-b border-lookbook-divider mb-6">
3
3
  <%= lookbook_render :tabs, theme: :page do |t| %>
4
4
  <% @tabs.each do |props| %>
5
- <%= t.tab **props %>
5
+ <%= t.with_tab **props %>
6
6
  <% end %>
7
7
  <% end %>
8
8
  </div>
9
9
  <%= lookbook_render :tab_panels do |t| %>
10
10
  <% @tabs.each do |props| %>
11
- <% t.panel name: props[:name] do %>
11
+ <% t.with_panel name: props[:name] do %>
12
12
  <%= lookbook_render :prose, markdown: props[:markdown], class: "max-w-none flex-none" do %>
13
13
  <%== props[:tab_content] %>
14
14
  <% 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]
@@ -40,7 +40,7 @@ module Lookbook
40
40
  if @target
41
41
  begin
42
42
  opts = {layout: @preview.layout}
43
- if params[:lookbook_embed] == "true"
43
+ if embedded?
44
44
  opts[:append_html] = render_to_string("lookbook/partials/_iframe_content_scripts", layout: nil)
45
45
  end
46
46
  @preview_html = preview_controller.process(:render_in_layout_to_string, "lookbook/previews/group", inspector_data, **opts)
@@ -56,6 +56,10 @@ module Lookbook
56
56
 
57
57
  private
58
58
 
59
+ def embedded?
60
+ params[:lookbook_embed] == "true"
61
+ end
62
+
59
63
  def scenario_json(scenario)
60
64
  {
61
65
  name: scenario.name,
@@ -65,6 +69,7 @@ module Lookbook
65
69
  end
66
70
 
67
71
  def permit_framing
72
+ headers["X-Frame-Options"] = Lookbook.config.preview_embeds.policy if embedded?
68
73
  headers["X-Frame-Options"] = "SAMEORIGIN" if headers["X-Frame-Options"] == "DENY"
69
74
  end
70
75
  end
@@ -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"}",
@@ -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,
@@ -5,11 +5,11 @@
5
5
  @dom:update-complete.window="Lookbook.initEmbeds();">
6
6
  <div class="h-full bg-lookbook-page-bg relative">
7
7
  <% unless @error %>
8
-
8
+
9
9
  <div class="absolute top-0 right-0 pt-1 pr-0 pl-1 pb-1 rounded-bl-md">
10
10
  <div class="bg-lookbook-page-bg opacity-90 absolute inset-0 w-full h-full z-0"></div>
11
11
  <div class="relative z-10 flex items-center">
12
-
12
+
13
13
  <% if @previous_page %>
14
14
  <%= lookbook_render :icon_button,
15
15
  size: :lg,
@@ -58,7 +58,7 @@
58
58
  <% if @page.sections.any? %>
59
59
  <%= lookbook_render :page_tabs, id: "page-tabbed-sections", markdown: false, class: "mt-6" do |page_tabs| %>
60
60
  <% @page.sections.each do |section| %>
61
- <% page_tabs.tab name: "page-section-#{section.name}", label: section.label do %>
61
+ <% page_tabs.with_tab name: "page-section-#{section.name}", label: section.label do %>
62
62
  <%= page_controller.render_page(section) %>
63
63
  <% end %>
64
64
  <% end %>
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
@@ -26,7 +26,7 @@ module Lookbook
26
26
  end
27
27
 
28
28
  config.after_initialize do
29
- if opts.using_view_component || Rails.env.test?
29
+ if opts.using_view_component
30
30
  vc_config = Engine.host_config.view_component
31
31
 
32
32
  opts.preview_paths += vc_config.preview_paths
@@ -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
@@ -125,14 +129,18 @@ module Lookbook
125
129
  end
126
130
 
127
131
  def view_paths
128
- ActionView::ViewPaths.all_view_paths.flat_map do |view_path|
129
- view_path.paths.map { |path| Pathname(path.to_s) }
132
+ # handle view path registry changes in Rails 7.1
133
+ paths = if defined?(ActionView::ViewPaths::Registry)
134
+ ActionView::ViewPaths::Registry.all_file_system_resolvers.map(&:path)
135
+ else
136
+ ActionView::ViewPaths.all_view_paths.flat_map(&paths)
130
137
  end
138
+ paths.map { |path| Pathname(path.to_s) }
131
139
  end
132
140
 
133
141
  def component_paths
134
142
  @_component_paths ||= begin
135
- paths = [*opts.component_paths, *Engine.view_paths, host_app_path]
143
+ paths = [*opts.component_paths, *view_paths, host_app_path]
136
144
  PathUtils.normalize_paths(paths)
137
145
  end
138
146
  end
@@ -150,7 +158,7 @@ module Lookbook
150
158
  def preview_watch_paths
151
159
  return @_preview_watch_paths if @_preview_watch_paths
152
160
 
153
- paths = [*opts.preview_paths, opts.components_path, *opts.listen_paths, *view_paths].uniq
161
+ paths = [*opts.preview_paths, *opts.component_paths, *opts.listen_paths, *view_paths].uniq
154
162
  @_preview_watch_paths ||= PathUtils.normalize_paths(paths)
155
163
  end
156
164
 
@@ -173,11 +181,13 @@ module Lookbook
173
181
  changed_files = [*changes[:added], *changes[:modified]] if changes
174
182
  parser.parse(changed_files) do |code_objects|
175
183
  previews.load(code_objects.all(:class), changes)
184
+ mark_changed
176
185
  end
177
186
  end
178
187
 
179
188
  def load_pages(changes = nil)
180
189
  pages.load(Engine.page_paths, changes)
190
+ mark_changed
181
191
  end
182
192
 
183
193
  def notify_clients(changes = nil)
@@ -192,6 +202,15 @@ module Lookbook
192
202
  reloaders.register_changes(changes)
193
203
  notify_clients(changes)
194
204
  end
205
+
206
+ def mark_changed
207
+ @_last_changed = (Time.now.to_f * 1000).to_i
208
+ end
209
+
210
+ def last_changed
211
+ mark_changed unless @_last_changed
212
+ @_last_changed
213
+ end
195
214
  end
196
215
 
197
216
  at_exit do
@@ -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
@@ -80,7 +80,7 @@ module Lookbook
80
80
  else
81
81
  @file_path.presence || nil
82
82
  end
83
- path.nil? ? nil : path.to_s.delete_prefix("#{Rails.root}/")
83
+ path&.to_s&.delete_prefix("#{Rails.root}/")
84
84
  end
85
85
 
86
86
  def line_number
@@ -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
@@ -18,11 +18,9 @@ module Lookbook
18
18
  class LookbookMarkdownRenderer < Redcarpet::Render::HTML
19
19
  def block_code(code, language = "ruby")
20
20
  line_numbers = language.to_s.end_with? "-numbered"
21
- ApplicationController.render(Lookbook::Code::Component.new(**{
22
- source: code,
21
+ ApplicationController.render(Lookbook::Code::Component.new(source: code,
23
22
  language: language.to_s.chomp("-numbered"),
24
- line_numbers: line_numbers
25
- }), layout: nil)
23
+ line_numbers: line_numbers), layout: nil)
26
24
  end
27
25
 
28
26
  def postprocess(full_document)
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "2.0.0.beta.1"
2
+ VERSION = "2.0.0.beta.3"
3
3
  end