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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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