lookbook 1.0.0.beta.3 → 1.0.0.beta.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +27 -254
  3. data/app/assets/lookbook/css/lookbook.css +1 -1
  4. data/app/assets/lookbook/css/themes/blue.css +57 -36
  5. data/app/assets/lookbook/css/themes/indigo.css +57 -36
  6. data/app/assets/lookbook/css/themes/zinc.css +57 -36
  7. data/app/assets/lookbook/css/tooltip.css +5 -5
  8. data/app/components/lookbook/base_component.rb +6 -4
  9. data/app/components/lookbook/button/component.html.erb +2 -2
  10. data/app/components/lookbook/copy_button/component.html.erb +3 -3
  11. data/app/components/lookbook/embed/component.html.erb +33 -33
  12. data/app/components/lookbook/embed/component.rb +8 -0
  13. data/app/components/lookbook/filter/component.html.erb +1 -1
  14. data/app/components/lookbook/header/component.html.erb +4 -4
  15. data/app/components/lookbook/header/component.rb +5 -0
  16. data/app/components/lookbook/inspector_panel/component.html.erb +4 -0
  17. data/app/components/lookbook/inspector_panel/component.rb +36 -0
  18. data/app/components/lookbook/nav/component.html.erb +4 -8
  19. data/app/components/lookbook/nav/component.rb +5 -7
  20. data/app/components/lookbook/nav/item/component.html.erb +12 -6
  21. data/app/components/lookbook/nav/item/component.rb +9 -2
  22. data/app/components/lookbook/page_tabs/component.html.erb +1 -1
  23. data/app/components/lookbook/prose/component.html.erb +1 -1
  24. data/app/components/lookbook/split_layout/component.html.erb +1 -1
  25. data/app/components/lookbook/tab_panels/panel/component.html.erb +2 -2
  26. data/app/components/lookbook/tabs/component.html.erb +2 -2
  27. data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +2 -2
  28. data/app/components/lookbook/tabs/tab/component.html.erb +2 -2
  29. data/app/components/lookbook/tag_component.rb +5 -10
  30. data/app/components/lookbook/toolbar/component.html.erb +1 -1
  31. data/app/components/lookbook/viewport/component.css +1 -1
  32. data/app/components/lookbook/viewport/component.html.erb +1 -1
  33. data/app/controllers/lookbook/application_controller.rb +1 -1
  34. data/app/controllers/lookbook/pages_controller.rb +1 -0
  35. data/app/controllers/lookbook/previews_controller.rb +15 -3
  36. data/app/helpers/lookbook/application_helper.rb +0 -6
  37. data/app/helpers/lookbook/preview_helper.rb +2 -3
  38. data/app/views/layouts/lookbook/application.html.erb +76 -58
  39. data/app/views/layouts/lookbook/page.html.erb +36 -36
  40. data/app/views/layouts/lookbook/shell.html.erb +8 -48
  41. data/app/views/layouts/lookbook/skeleton.html.erb +0 -6
  42. data/app/views/lookbook/index.html.erb +24 -11
  43. data/app/views/lookbook/pages/show.html.erb +5 -5
  44. data/app/views/lookbook/previews/panels/_content.html.erb +1 -1
  45. data/app/views/lookbook/previews/panels/_notes.html.erb +2 -2
  46. data/app/views/lookbook/previews/panels/_params.html.erb +1 -1
  47. data/app/views/lookbook/previews/show.html.erb +12 -10
  48. data/lib/lookbook/config.rb +107 -74
  49. data/lib/lookbook/engine.rb +24 -6
  50. data/lib/lookbook/markdown.rb +3 -1
  51. data/lib/lookbook/page.rb +4 -0
  52. data/lib/lookbook/params.rb +12 -0
  53. data/lib/lookbook/preview.rb +35 -5
  54. data/lib/lookbook/store.rb +8 -0
  55. data/lib/lookbook/version.rb +1 -1
  56. data/lib/tasks/lookbook_tasks.rake +1 -1
  57. data/public/lookbook-assets/css/lookbook.css +330 -182
  58. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  59. data/public/lookbook-assets/css/themes/blue.css +57 -36
  60. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  61. data/public/lookbook-assets/css/themes/indigo.css +57 -36
  62. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  63. data/public/lookbook-assets/css/themes/zinc.css +57 -36
  64. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  65. data/public/lookbook-assets/js/embed.js +193 -193
  66. data/public/lookbook-assets/js/lookbook.js +1179 -1336
  67. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  68. metadata +6 -4
@@ -6,7 +6,7 @@ module Lookbook
6
6
  class Config
7
7
  def initialize
8
8
  @options = Store.new
9
- foobar = "bax"
9
+
10
10
  @options.set({
11
11
  project_name: "Lookbook",
12
12
  log_level: 2,
@@ -22,12 +22,12 @@ module Lookbook
22
22
 
23
23
  preview_paths: [],
24
24
  preview_display_params: {},
25
- preview_options: {},
26
- preview_srcdoc: false,
27
- sort_examples: true,
25
+ preview_srcdoc: nil,
26
+ sort_examples: false,
28
27
 
29
28
  listen: Rails.env.development?,
30
29
  listen_paths: [],
30
+ listen_extensions: ["rb", "html.*"],
31
31
  listen_use_polling: false,
32
32
 
33
33
  cable_mount_path: "/lookbook-cable",
@@ -45,6 +45,8 @@ module Lookbook
45
45
  after_change: [],
46
46
  },
47
47
 
48
+ debug_menu: Rails.env.development?,
49
+
48
50
  experimental_features: false,
49
51
 
50
52
  inspector_panels: {
@@ -54,7 +56,8 @@ module Lookbook
54
56
  partial: "lookbook/previews/panels/preview",
55
57
  hotkey: "v",
56
58
  panel_classes: "overflow-hidden",
57
- padded: false
59
+ padded: false,
60
+ system: true
58
61
  },
59
62
  output: {
60
63
  pane: :main,
@@ -62,7 +65,8 @@ module Lookbook
62
65
  partial: "lookbook/previews/panels/output",
63
66
  label: "HTML",
64
67
  hotkey: "h",
65
- padded: false
68
+ padded: false,
69
+ system: true
66
70
  },
67
71
  source: {
68
72
  pane: :drawer,
@@ -71,7 +75,8 @@ module Lookbook
71
75
  label: "Source",
72
76
  hotkey: "s",
73
77
  copy: ->(data) { data.examples.map { |e| e.source }.join("\n") },
74
- padded: false
78
+ padded: false,
79
+ system: true
75
80
  },
76
81
  notes: {
77
82
  pane: :drawer,
@@ -80,7 +85,8 @@ module Lookbook
80
85
  label: "Notes",
81
86
  hotkey: "n",
82
87
  disabled: ->(data) { data.examples.select { |e| e.notes.present? }.none? },
83
- padded: false
88
+ padded: false,
89
+ system: true
84
90
  },
85
91
  params: {
86
92
  pane: :drawer,
@@ -89,56 +95,80 @@ module Lookbook
89
95
  label: "Params",
90
96
  hotkey: "p",
91
97
  disabled: ->(data) { data.preview.params.none? },
92
- padded: false
98
+ padded: false,
99
+ system: true
93
100
  }
94
101
  },
95
-
96
- inspector_panel_defaults: {
97
- id: ->(data) { "inspector-panel-#{data.name}" },
98
- partial: "lookbook/previews/panels/content",
99
- content: nil,
100
- label: ->(data) { data.name.titleize },
101
- pane: :drawer,
102
- position: ->(data) { data.index_position },
103
- hotkey: nil,
104
- disabled: false,
105
- show: true,
106
- copy: nil,
107
- panel_classes: nil,
108
- locals: {},
109
- padded: true
110
- },
111
102
  })
112
103
  end
113
104
 
105
+ def project_name
106
+ @options.project_name == false ? nil : @options.project_name
107
+ end
108
+
109
+ def components_path
110
+ absolute_path(@options.components_path)
111
+ end
112
+
113
+ def page_paths=(paths = [])
114
+ @options.page_paths += paths if paths.is_a? Array
115
+ end
116
+
117
+ def page_paths
118
+ normalize_paths(@options.page_paths)
119
+ end
120
+
121
+ def preview_paths=(paths = [])
122
+ @options.preview_paths += paths if paths.is_a? Array
123
+ end
124
+
125
+ def preview_paths
126
+ normalize_paths(@options.preview_paths)
127
+ end
128
+
129
+ def preview_srcdoc=(enable)
130
+ Lookbook.logger.warn "The `preview_srcdoc` config option is deprecated and will be removed in v2.0"
131
+ end
132
+
133
+ def listen_paths
134
+ normalize_paths(@options.listen_paths)
135
+ end
136
+
137
+ def listen_extensions=(extensions = [])
138
+ @options.listen_extensions += extensions if extensions.is_a? Array
139
+ @options.listen_extensions.uniq!
140
+ end
141
+
142
+ def parser_registry_path
143
+ absolute_path(@options.parser_registry_path)
144
+ end
145
+
114
146
  def inspector_panels(&block)
147
+ panels = Store.new(@options.inspector_panels.select { |key, panel| panel != false })
115
148
  if block_given?
116
- yield get(:inspector_panels)
149
+ yield panels
117
150
  else
118
- get(:inspector_panels)
151
+ panels
119
152
  end
120
153
  end
121
154
 
122
155
  def define_inspector_panel(name, opts = {})
123
- inspector_panels[name] = opts
124
- if opts[:position].present?
125
- pane = inspector_panels[name].pane.presence || :drawer
126
- siblings = inspector_panels.select do |key, panel|
127
- panel.pane == pane && key != name.to_sym
128
- end
129
- siblings.each do |key, panel|
130
- if panel.position >= opts[:position]
131
- panel.position += 1
132
- end
156
+ pane = opts[:pane].presence || :drawer
157
+ siblings = inspector_panels.select { |key, panel| panel.pane == pane }
158
+ opts[:position] ||= siblings.size + 1
159
+ @options.inspector_panels[name] = opts
160
+ siblings.each do |key, panel|
161
+ if panel.position >= opts[:position]
162
+ panel.position += 1
133
163
  end
134
164
  end
135
165
  end
136
166
 
137
167
  def amend_inspector_panel(name, opts = {})
138
168
  if opts == false
139
- inspector_panels[name] = false
169
+ @options.inspector_panels[name] = false
140
170
  else
141
- inspector_panels[name].merge!(opts)
171
+ @options.inspector_panels[name].merge!(opts)
142
172
  end
143
173
  end
144
174
 
@@ -146,10 +176,29 @@ module Lookbook
146
176
  amend_inspector_panel(name, false)
147
177
  end
148
178
 
179
+ def inspector_panel_defaults
180
+ {
181
+ id: ->(data) { "inspector-panel-#{data.name}" },
182
+ partial: "lookbook/previews/panels/content",
183
+ content: nil,
184
+ label: ->(data) { data.name.titleize },
185
+ pane: :drawer,
186
+ position: ->(data) { data.index_position },
187
+ hotkey: nil,
188
+ disabled: false,
189
+ show: true,
190
+ copy: nil,
191
+ panel_classes: nil,
192
+ locals: {},
193
+ padded: true,
194
+ system: false
195
+ }
196
+ end
197
+
149
198
  def ui_theme=(name)
150
199
  name = name.to_s
151
200
  if Theme.valid_theme?(name)
152
- @options[:ui_theme] = name
201
+ @options.ui_theme = name
153
202
  else
154
203
  Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Theme setting not changed."
155
204
  end
@@ -157,18 +206,27 @@ module Lookbook
157
206
 
158
207
  def ui_theme_overrides(&block)
159
208
  if block_given?
160
- yield get(:ui_theme_overrides)
209
+ yield @options.ui_theme_overrides
161
210
  else
162
- get(:ui_theme_overrides)
211
+ @options.ui_theme_overrides
163
212
  end
164
213
  end
165
214
 
166
215
  def [](key)
167
- get(key.to_sym)
216
+ if respond_to? key.to_sym
217
+ public_send(key.to_sym)
218
+ else
219
+ @options[key.to_sym]
220
+ end
168
221
  end
169
222
 
170
223
  def []=(key, value)
171
- @options[key.to_sym] = value
224
+ setter_key = "#{key}=".to_sym
225
+ if respond_to? setter_key
226
+ public_send(setter_key, value)
227
+ else
228
+ @options[key.to_sym] = value
229
+ end
172
230
  end
173
231
 
174
232
  def to_h
@@ -181,22 +239,11 @@ module Lookbook
181
239
 
182
240
  protected
183
241
 
184
- def get_inspector_panels(panels)
185
- panels.select! { |key, panel| panel }
186
- panels
187
- end
188
-
189
- def get_project_name(name)
190
- name == false ? nil : name
191
- end
192
-
193
- def get_components_path(path)
194
- absolute_path(path)
195
- end
196
-
197
242
  def normalize_paths(paths)
198
- paths.map! { |path| absolute_path(path) }
199
- paths.select! { |path| Dir.exist?(path) }
243
+ paths.map! do |path|
244
+ full_path = absolute_path(path)
245
+ full_path if Dir.exist?(full_path)
246
+ end.compact!
200
247
  paths
201
248
  end
202
249
 
@@ -204,22 +251,8 @@ module Lookbook
204
251
  File.absolute_path(path.to_s, Rails.root)
205
252
  end
206
253
 
207
- alias_method :get_page_paths, :normalize_paths
208
- alias_method :get_preview_paths, :normalize_paths
209
- alias_method :get_listen_paths, :normalize_paths
210
- alias_method :get_parser_registry_path, :absolute_path
211
-
212
- def get(name)
213
- getter_name = "get_#{name}".to_sym
214
- respond_to?(getter_name, true) ? send(getter_name, @options[name]) : @options[name]
215
- end
216
-
217
- def set(name, *args)
218
- @options.send(name, *args)
219
- end
220
-
221
254
  def method_missing(name, *args)
222
- args.any? ? set(name, *args) : get(name)
255
+ @options.send(name, *args)
223
256
  end
224
257
  end
225
258
  end
@@ -36,10 +36,26 @@ module Lookbook
36
36
  Preview.all
37
37
  end
38
38
 
39
+ def previews?
40
+ Preview.any?
41
+ end
42
+
39
43
  def pages
40
44
  Page.all
41
45
  end
42
46
 
47
+ def pages?
48
+ Page.any?
49
+ end
50
+
51
+ def data
52
+ @data ||= Store.new
53
+ end
54
+
55
+ def data=(props)
56
+ @data = Store.new(props)
57
+ end
58
+
43
59
  def after_initialize(&block)
44
60
  add_hook(:after_initialize, block)
45
61
  end
@@ -112,10 +128,11 @@ module Lookbook
112
128
 
113
129
  if config.lookbook.listen
114
130
  Listen.logger = Lookbook.logger
131
+
115
132
  preview_listener = Listen.to(
116
133
  *config.lookbook.listen_paths,
117
- only: /\.(rb|html.*)$/,
118
- force_polling: Lookbook.config.listen_use_polling
134
+ only: /\.(#{config.lookbook.listen_extensions.join("|")})$/,
135
+ force_polling: config.lookbook.listen_use_polling
119
136
  ) do |modified, added, removed|
120
137
  changes = { modified: modified, added: added, removed: removed }
121
138
  begin
@@ -131,7 +148,7 @@ module Lookbook
131
148
  page_listener = Listen.to(
132
149
  *config.lookbook.page_paths,
133
150
  only: /\.(html.*|md.*)$/,
134
- force_polling: Lookbook.config.listen_use_polling
151
+ force_polling: config.lookbook.listen_use_polling
135
152
  ) do |modified, added, removed|
136
153
  changes = { modified: modified, added: added, removed: removed }
137
154
  Lookbook::Engine.reload_ui(changes)
@@ -166,6 +183,7 @@ module Lookbook
166
183
  class << self
167
184
 
168
185
  def websocket
186
+ return @websocket unless @websocket.nil?
169
187
  if config.lookbook.auto_refresh
170
188
  cable = ActionCable::Server::Configuration.new
171
189
  cable.cable = {adapter: "async"}.with_indifferent_access
@@ -176,9 +194,9 @@ module Lookbook
176
194
  @websocket ||= if Rails.version.to_f >= 6.0
177
195
  ActionCable::Server::Base.new(config: cable)
178
196
  else
179
- websocket ||= ActionCable::Server::Base.new
180
- websocket.config = cable
181
- websocket
197
+ @websocket ||= ActionCable::Server::Base.new
198
+ @websocket.config = cable
199
+ @websocket
182
200
  end
183
201
  end
184
202
  end
@@ -8,10 +8,12 @@ module Lookbook
8
8
  disable_indented_code_blocks: true,
9
9
  strikethrough: true,
10
10
  highlight: true,
11
- with_toc_data: true
11
+ with_toc_data: true,
12
+ lax_spacing: true
12
13
  }
13
14
 
14
15
  def self.render(text)
16
+ text&.gsub!(/\<\!\-\- (BEGIN|END) (.*) \-\-\>/, "")
15
17
  markdown = Redcarpet::Markdown.new(Renderer, Lookbook.config.markdown_options)
16
18
  markdown.render(text).html_safe
17
19
  end
data/lib/lookbook/page.rb CHANGED
@@ -154,6 +154,10 @@ module Lookbook
154
154
  !!find(path)
155
155
  end
156
156
 
157
+ def any?
158
+ all.any?
159
+ end
160
+
157
161
  def all
158
162
  pages, sections =
159
163
  Array(page_paths).flat_map do |dir|
@@ -63,6 +63,14 @@ module Lookbook
63
63
  result = []
64
64
  end
65
65
  result
66
+ when "datetime"
67
+ begin
68
+ result = DateTime.parse(value)
69
+ rescue Date::Error
70
+ Lookbook.logger.debug "Failed to parse '#{value}' into a DateTime"
71
+ result = DateTime.now
72
+ end
73
+ result
66
74
  else
67
75
  begin
68
76
  type_class = "ActiveModel::Type::#{type}".constantize
@@ -92,6 +100,8 @@ module Lookbook
92
100
  "Boolean"
93
101
  elsif default.is_a? Symbol
94
102
  "Symbol"
103
+ elsif ["date", "datetime-local"].include?(input&.downcase) || default.is_a?(DateTime)
104
+ "DateTime"
95
105
  else
96
106
  "String"
97
107
  end
@@ -99,6 +109,8 @@ module Lookbook
99
109
 
100
110
  def input_text?(input)
101
111
  [
112
+ "date",
113
+ "datetime-local",
102
114
  "email",
103
115
  "number",
104
116
  "tel",
@@ -122,14 +122,15 @@ module Lookbook
122
122
  !!find(path)
123
123
  end
124
124
 
125
- def clear_cache
126
- @previews = nil
125
+ def any?
126
+ all.any?
127
127
  end
128
128
 
129
129
  def all
130
130
  load_previews if preview_files.size > ViewComponent::Preview.descendants.size
131
131
 
132
- return @previews if @previews.present?
132
+ @previews = nil if cache_stale?
133
+ return @previews unless @previews.nil?
133
134
 
134
135
  previews = ViewComponent::Preview.descendants.map do |p|
135
136
  new(p)
@@ -144,15 +145,44 @@ module Lookbook
144
145
  end
145
146
 
146
147
  sorted_previews = previews.compact.sort_by { |preview| [preview.position, preview.label] }
147
- @previews ||= PreviewCollection.new(sorted_previews)
148
+ @previews = PreviewCollection.new(sorted_previews)
149
+ mark_as_cached if Lookbook.config.listen == true
150
+ @previews
148
151
  end
149
152
 
150
153
  def errors
151
154
  @errors ||= []
152
155
  end
153
156
 
157
+ def clear_cache
158
+ cache_dir = File.dirname(cache_marker_path)
159
+ FileUtils.mkdir_p(cache_dir) unless File.exists?(cache_dir)
160
+ File.write(cache_marker_path, Time.now.to_i)
161
+ end
162
+
154
163
  protected
155
164
 
165
+ def cache_marker_path
166
+ Rails.root.join("tmp/cache/lookbook-previews")
167
+ end
168
+
169
+ def cache_stale?
170
+ return false if !File.exists?(cache_marker_path)
171
+ cache_timestamp = File.read(cache_marker_path).to_i
172
+ if @last_cache_timestamp.nil? || cache_timestamp > @last_cache_timestamp
173
+ @last_cache_timestamp = cache_timestamp
174
+ true
175
+ else
176
+ false
177
+ end
178
+ end
179
+
180
+ def mark_as_cached
181
+ cache_dir = File.dirname(cache_marker_path)
182
+ FileUtils.mkdir_p(cache_dir) unless File.exists?(cache_dir)
183
+ File.write(cache_marker_path, Time.now)
184
+ end
185
+
156
186
  def load_previews
157
187
  @errors = []
158
188
  preview_files.each do |file|
@@ -166,7 +196,7 @@ module Lookbook
166
196
  )
167
197
  end
168
198
  end
169
-
199
+
170
200
  def preview_files
171
201
  files = Array(Lookbook.config.preview_paths).map do |preview_path|
172
202
  Dir["#{preview_path}/**/*preview.rb"].map do |path|
@@ -21,6 +21,14 @@ module Lookbook
21
21
  self
22
22
  end
23
23
 
24
+ def get(key, fallback = nil)
25
+ if self.key?(normalize_key(key))
26
+ self[normalize_key(key)]
27
+ else
28
+ fallback
29
+ end
30
+ end
31
+
24
32
  def method_missing(name, *args)
25
33
  super(normalize_key(name), *args.map { |arg| normalize_value(arg) })
26
34
  end
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "1.0.0.beta.3"
2
+ VERSION = "1.0.0.beta.6"
3
3
  end
@@ -16,7 +16,7 @@ namespace :lookbook do
16
16
 
17
17
  namespace :previews do
18
18
  desc "Preparse the previews"
19
- task :preparse do
19
+ task :preparse => :environment do
20
20
  Lookbook::Engine.parser.parse
21
21
  puts "Lookbook preview parsing complete"
22
22
  end