lookbook 1.0.0.beta.1 → 1.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +180 -40
  3. data/app/components/lookbook/{component.rb → base_component.rb} +1 -1
  4. data/app/components/lookbook/button/component.rb +1 -1
  5. data/app/components/lookbook/button_group/component.rb +1 -1
  6. data/app/components/lookbook/code/component.rb +1 -1
  7. data/app/components/lookbook/copy_button/component.html.erb +1 -1
  8. data/app/components/lookbook/copy_button/component.rb +1 -1
  9. data/app/components/lookbook/dimensions_display/component.rb +1 -1
  10. data/app/components/lookbook/embed/component.html.erb +6 -5
  11. data/app/components/lookbook/embed/component.rb +1 -1
  12. data/app/components/lookbook/filter/component.html.erb +1 -1
  13. data/app/components/lookbook/filter/component.rb +1 -1
  14. data/app/components/lookbook/header/component.html.erb +6 -11
  15. data/app/components/lookbook/header/component.rb +6 -1
  16. data/app/components/lookbook/icon/component.rb +1 -1
  17. data/app/components/lookbook/nav/component.rb +1 -1
  18. data/app/components/lookbook/nav/item/component.html.erb +2 -2
  19. data/app/components/lookbook/nav/item/component.rb +1 -1
  20. data/app/components/lookbook/page_tabs/component.rb +1 -1
  21. data/app/components/lookbook/params_editor/component.rb +1 -1
  22. data/app/components/lookbook/params_editor/field/component.rb +1 -1
  23. data/app/components/lookbook/prose/component.rb +1 -1
  24. data/app/components/lookbook/split_layout/component.rb +1 -1
  25. data/app/components/lookbook/tab_panels/component.rb +1 -1
  26. data/app/components/lookbook/tab_panels/panel/component.rb +2 -2
  27. data/app/components/lookbook/tabs/component.js +6 -6
  28. data/app/components/lookbook/tabs/component.rb +1 -1
  29. data/app/components/lookbook/tabs/dropdown_tab/component.rb +1 -1
  30. data/app/components/lookbook/tabs/tab/component.rb +1 -1
  31. data/app/components/lookbook/toolbar/component.rb +1 -1
  32. data/app/components/lookbook/viewport/component.rb +1 -1
  33. data/app/controllers/lookbook/application_controller.rb +1 -1
  34. data/app/controllers/lookbook/pages_controller.rb +1 -1
  35. data/app/controllers/lookbook/previews_controller.rb +27 -32
  36. data/app/helpers/lookbook/application_helper.rb +8 -2
  37. data/app/helpers/lookbook/component_helper.rb +4 -0
  38. data/app/helpers/lookbook/page_helper.rb +2 -2
  39. data/app/views/layouts/lookbook/application.html.erb +5 -3
  40. data/app/views/layouts/lookbook/page.html.erb +2 -2
  41. data/app/views/layouts/lookbook/shell.html.erb +2 -48
  42. data/app/views/layouts/lookbook/skeleton.html.erb +7 -1
  43. data/app/views/lookbook/404.html.erb +1 -1
  44. data/app/views/lookbook/index.html.erb +1 -1
  45. data/app/views/lookbook/pages/show.html.erb +8 -8
  46. data/app/views/lookbook/previews/panels/_notes.html.erb +1 -1
  47. data/app/views/lookbook/previews/panels/_preview.html.erb +1 -1
  48. data/app/views/lookbook/previews/show.html.erb +4 -4
  49. data/config/routes.rb +6 -6
  50. data/lib/lookbook/collection.rb +1 -1
  51. data/lib/lookbook/component.rb +31 -0
  52. data/lib/lookbook/config.rb +94 -41
  53. data/lib/lookbook/engine.rb +72 -12
  54. data/lib/lookbook/page.rb +3 -3
  55. data/lib/lookbook/parser.rb +1 -4
  56. data/lib/lookbook/preview.rb +25 -8
  57. data/lib/lookbook/preview_example.rb +2 -2
  58. data/lib/lookbook/preview_group.rb +1 -1
  59. data/lib/lookbook/source_inspector.rb +10 -0
  60. data/lib/lookbook/utils.rb +2 -2
  61. data/lib/lookbook/version.rb +1 -1
  62. data/lib/lookbook.rb +1 -12
  63. data/public/lookbook-assets/css/lookbook.css +24 -28
  64. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  65. data/public/lookbook-assets/js/lookbook.js +50 -49
  66. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  67. metadata +3 -2
@@ -6,11 +6,13 @@ 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,
13
13
  auto_refresh: true,
14
+
15
+ components_path: "app/components",
14
16
 
15
17
  page_controller: "Lookbook::PageController",
16
18
  page_route: "pages",
@@ -37,13 +39,24 @@ module Lookbook
37
39
  ui_theme: "indigo",
38
40
  ui_theme_overrides: {},
39
41
 
42
+ hooks: {
43
+ after_initialize: [],
44
+ before_exit: [],
45
+ after_change: [],
46
+ },
47
+
48
+ debug_menu: Rails.env.development?,
49
+
50
+ experimental_features: false,
51
+
40
52
  inspector_panels: {
41
53
  preview: {
42
54
  pane: :main,
43
55
  position: 1,
44
56
  partial: "lookbook/previews/panels/preview",
45
57
  hotkey: "v",
46
- panel_classes: "overflow-hidden"
58
+ panel_classes: "overflow-hidden",
59
+ padded: false
47
60
  },
48
61
  output: {
49
62
  pane: :main,
@@ -51,6 +64,7 @@ module Lookbook
51
64
  partial: "lookbook/previews/panels/output",
52
65
  label: "HTML",
53
66
  hotkey: "h",
67
+ padded: false
54
68
  },
55
69
  source: {
56
70
  pane: :drawer,
@@ -58,7 +72,8 @@ module Lookbook
58
72
  partial: "lookbook/previews/panels/source",
59
73
  label: "Source",
60
74
  hotkey: "s",
61
- copy: ->(data) { data.examples.map { |e| e[:source] }.join("\n") }
75
+ copy: ->(data) { data.examples.map { |e| e.source }.join("\n") },
76
+ padded: false
62
77
  },
63
78
  notes: {
64
79
  pane: :drawer,
@@ -66,7 +81,8 @@ module Lookbook
66
81
  partial: "lookbook/previews/panels/notes",
67
82
  label: "Notes",
68
83
  hotkey: "n",
69
- disabled: ->(data) { data.examples.filter { |e| e.notes.present? }.none? }
84
+ disabled: ->(data) { data.examples.select { |e| e.notes.present? }.none? },
85
+ padded: false
70
86
  },
71
87
  params: {
72
88
  pane: :drawer,
@@ -74,7 +90,8 @@ module Lookbook
74
90
  partial: "lookbook/previews/panels/params",
75
91
  label: "Params",
76
92
  hotkey: "p",
77
- disabled: ->(data) { data.preview.params.none? }
93
+ disabled: ->(data) { data.preview.params.none? },
94
+ padded: false
78
95
  }
79
96
  },
80
97
 
@@ -90,25 +107,76 @@ module Lookbook
90
107
  show: true,
91
108
  copy: nil,
92
109
  panel_classes: nil,
93
- locals: {}
110
+ locals: {},
111
+ padded: true
94
112
  },
95
-
96
- experimental_features: false,
97
113
  })
98
114
  end
99
115
 
116
+ def project_name
117
+ @options.project_name == false ? nil : @options.project_name
118
+ end
119
+
120
+ def components_path
121
+ absolute_path(@options.components_path)
122
+ end
123
+
124
+ def page_paths
125
+ normalize_paths(@options.page_paths)
126
+ end
127
+
128
+ def preview_paths
129
+ normalize_paths(@options.preview_paths)
130
+ end
131
+
132
+ def listen_paths
133
+ normalize_paths(@options.listen_paths)
134
+ end
135
+
136
+ def parser_registry_path
137
+ absolute_path(@options.parser_registry_path)
138
+ end
139
+
100
140
  def inspector_panels(&block)
141
+ panels = Store.new(@options.inspector_panels.select { |key, panel| panel != false })
101
142
  if block_given?
102
- yield get(:inspector_panels)
143
+ yield panels
144
+ else
145
+ panels
146
+ end
147
+ end
148
+
149
+ def define_inspector_panel(name, opts = {})
150
+ @options.inspector_panels[name] = opts
151
+ if opts[:position].present?
152
+ pane = inspector_panels[name].pane.presence || :drawer
153
+ siblings = inspector_panels.select do |key, panel|
154
+ panel.pane == pane && key != name.to_sym
155
+ end
156
+ siblings.each do |key, panel|
157
+ if panel.position >= opts[:position]
158
+ panel.position += 1
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ def amend_inspector_panel(name, opts = {})
165
+ if opts == false
166
+ @options.inspector_panels[name] = false
103
167
  else
104
- get(:inspector_panels)
168
+ @options.inspector_panels[name].merge!(opts)
105
169
  end
106
170
  end
107
171
 
172
+ def remove_inspector_panel(name)
173
+ amend_inspector_panel(name, false)
174
+ end
175
+
108
176
  def ui_theme=(name)
109
177
  name = name.to_s
110
178
  if Theme.valid_theme?(name)
111
- @options[:ui_theme] = name
179
+ @options.ui_theme = name
112
180
  else
113
181
  Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Theme setting not changed."
114
182
  end
@@ -116,18 +184,27 @@ module Lookbook
116
184
 
117
185
  def ui_theme_overrides(&block)
118
186
  if block_given?
119
- yield get(:ui_theme_overrides)
187
+ yield @options.ui_theme_overrides
120
188
  else
121
- get(:ui_theme_overrides)
189
+ @options.ui_theme_overrides
122
190
  end
123
191
  end
124
192
 
125
193
  def [](key)
126
- get(key.to_sym)
194
+ if respond_to? key.to_sym
195
+ public_send(key.to_sym)
196
+ else
197
+ @options[key.to_sym]
198
+ end
127
199
  end
128
200
 
129
201
  def []=(key, value)
130
- @options[key.to_sym] = value
202
+ setter_key = "#{key}=".to_sym
203
+ if respond_to? setter_key
204
+ public_send(setter_key, value)
205
+ else
206
+ @options[key.to_sym] = value
207
+ end
131
208
  end
132
209
 
133
210
  def to_h
@@ -140,41 +217,17 @@ module Lookbook
140
217
 
141
218
  protected
142
219
 
143
- def get_inspector_panels(panels)
144
- panels.filter! { |key, panel| panel }
145
- panels
146
- end
147
-
148
- def get_project_name(name)
149
- name == false ? nil : name
150
- end
151
-
152
220
  def normalize_paths(paths)
153
221
  paths.map! { |path| absolute_path(path) }
154
- paths.filter! { |path| Dir.exist?(path) }
155
- paths
222
+ paths.select { |path| Dir.exist?(path) }
156
223
  end
157
224
 
158
225
  def absolute_path(path)
159
226
  File.absolute_path(path.to_s, Rails.root)
160
227
  end
161
228
 
162
- alias_method :get_page_paths, :normalize_paths
163
- alias_method :get_preview_paths, :normalize_paths
164
- alias_method :get_listen_paths, :normalize_paths
165
- alias_method :get_parser_registry_path, :absolute_path
166
-
167
- def get(name)
168
- getter_name = "get_#{name}".to_sym
169
- respond_to?(getter_name, true) ? send(getter_name, @options[name]) : @options[name]
170
- end
171
-
172
- def set(name, *args)
173
- @options.send(name, *args)
174
- end
175
-
176
229
  def method_missing(name, *args)
177
- args.any? ? set(name, *args) : get(name)
230
+ @options.send(name, *args)
178
231
  end
179
232
  end
180
233
  end
@@ -8,16 +8,20 @@ module Lookbook
8
8
  autoload :Config, "lookbook/config"
9
9
 
10
10
  class << self
11
+ def version
12
+ Lookbook::VERSION
13
+ end
14
+
11
15
  def config
12
16
  @config ||= Config.new
13
17
  end
14
18
 
15
- def logger
16
- @logger ||= Rails.env.development? ? Logger.new($stdout) : Rails.logger
19
+ def configure
20
+ yield(config)
17
21
  end
18
22
 
19
- def version
20
- Lookbook::VERSION
23
+ def logger
24
+ @logger ||= Rails.env.development? ? Logger.new($stdout) : Rails.logger
21
25
  end
22
26
 
23
27
  def debug_data
@@ -28,8 +32,46 @@ module Lookbook
28
32
  }
29
33
  end
30
34
 
31
- def configure
32
- yield(config)
35
+ def previews
36
+ Preview.all
37
+ end
38
+
39
+ def pages
40
+ Page.all
41
+ end
42
+
43
+ def after_initialize(&block)
44
+ add_hook(:after_initialize, block)
45
+ end
46
+
47
+ def before_exit(&block)
48
+ add_hook(:before_exit, block)
49
+ end
50
+
51
+ def after_change(&block)
52
+ add_hook(:after_change, block)
53
+ end
54
+
55
+ def define_panel(name, opts = {})
56
+ config.define_inspector_panel(name, opts)
57
+ end
58
+
59
+ def amend_panel(name, opts = {})
60
+ config.amend_inspector_panel(name, opts)
61
+ end
62
+
63
+ def remove_panel(name)
64
+ config.remove_inspector_panel(name)
65
+ end
66
+
67
+ def broadcast(event_name, data = {})
68
+ Engine.websocket&.broadcast(event_name.to_s, data)
69
+ end
70
+
71
+ protected
72
+
73
+ def add_hook(event_name, block)
74
+ config.hooks[event_name] << block
33
75
  end
34
76
  end
35
77
 
@@ -43,8 +85,10 @@ module Lookbook
43
85
  config.lookbook.preview_paths += config.view_component.preview_paths
44
86
  config.lookbook.preview_controller ||= config.view_component.preview_controller
45
87
 
88
+ config.lookbook.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present?
89
+
46
90
  config.lookbook.listen_paths += config.lookbook.preview_paths
47
- config.lookbook.listen_paths << (config.view_component.view_component_path.presence || "app/components")
91
+ config.lookbook.listen_paths << config.lookbook.components_path
48
92
  end
49
93
 
50
94
  initializer "lookbook.logging.development" do
@@ -73,12 +117,14 @@ module Lookbook
73
117
  only: /\.(rb|html.*)$/,
74
118
  force_polling: Lookbook.config.listen_use_polling
75
119
  ) do |modified, added, removed|
120
+ changes = { modified: modified, added: added, removed: removed }
76
121
  begin
77
122
  parser.parse
78
123
  rescue
79
124
  end
80
125
  Lookbook::Preview.clear_cache
81
- Lookbook::Engine.websocket&.broadcast("reload", {})
126
+ Lookbook::Engine.reload_ui(changes)
127
+ Lookbook::Engine.run_hooks(:after_change, changes)
82
128
  end
83
129
  Lookbook::Engine.register_listener(preview_listener)
84
130
 
@@ -87,7 +133,9 @@ module Lookbook
87
133
  only: /\.(html.*|md.*)$/,
88
134
  force_polling: Lookbook.config.listen_use_polling
89
135
  ) do |modified, added, removed|
90
- Lookbook::Engine.websocket&.broadcast("reload", {})
136
+ changes = { modified: modified, added: added, removed: removed }
137
+ Lookbook::Engine.reload_ui(changes)
138
+ Lookbook::Engine.run_hooks(:after_change, changes)
91
139
  end
92
140
  Lookbook::Engine.register_listener(page_listener)
93
141
  end
@@ -103,18 +151,20 @@ module Lookbook
103
151
  "
104
152
  end
105
153
  end
154
+
155
+ Lookbook::Engine.run_hooks(:after_initialize)
106
156
  end
107
157
 
108
158
  at_exit do
109
159
  if config.lookbook.listen
110
160
  Lookbook.logger.debug "Stopping listeners"
111
- Lookbook::Engine.listeners.each do |listener|
112
- listener.stop
113
- end
161
+ Lookbook::Engine.listeners.each { |listener| listener.stop }
114
162
  end
163
+ Lookbook::Engine.run_hooks(:before_exit)
115
164
  end
116
165
 
117
166
  class << self
167
+
118
168
  def websocket
119
169
  if config.lookbook.auto_refresh
120
170
  cable = ActionCable::Server::Configuration.new
@@ -162,6 +212,16 @@ module Lookbook
162
212
  @listeners ||= []
163
213
  end
164
214
 
215
+ def run_hooks(event_name, *args)
216
+ Lookbook.config.hooks[event_name].each do |hook|
217
+ hook.call(Lookbook, *args)
218
+ end
219
+ end
220
+
221
+ def reload_ui(changed = {})
222
+ websocket&.broadcast("reload", changed)
223
+ end
224
+
165
225
  attr_reader :preview_controller
166
226
  end
167
227
  end
data/lib/lookbook/page.rb CHANGED
@@ -19,7 +19,7 @@ module Lookbook
19
19
 
20
20
  def initialize(path, base_path)
21
21
  @pathname = Pathname.new path
22
- @base_path = base_path
22
+ @base_path = Pathname.new base_path
23
23
  @options = nil
24
24
  @errors = []
25
25
  @sections = []
@@ -30,7 +30,7 @@ module Lookbook
30
30
  end
31
31
 
32
32
  def url_path
33
- page_path lookup_path
33
+ lookbook_page_path lookup_path
34
34
  end
35
35
 
36
36
  def full_path
@@ -177,7 +177,7 @@ module Lookbook
177
177
  end
178
178
 
179
179
  def page_paths
180
- Lookbook.config.page_paths.filter { |dir| Dir.exist? dir }
180
+ Lookbook.config.page_paths.select { |dir| Dir.exist? dir }
181
181
  end
182
182
 
183
183
  def section_path?(path)
@@ -23,10 +23,6 @@ module Lookbook
23
23
  registry.get(path)
24
24
  end
25
25
 
26
- # def yardoc_file_path
27
- # Rails&.root ? Rails.root.join(YARDOC_FILE_PATH) : YARDOC_FILE_PATH
28
- # end
29
-
30
26
  class << self
31
27
  def define_tags
32
28
  YARD::Tags::Library.define_tag("Hidden status", :hidden)
@@ -34,6 +30,7 @@ module Lookbook
34
30
  YARD::Tags::Library.define_tag("Display", :display)
35
31
  YARD::Tags::Library.define_tag("Position", :position)
36
32
  YARD::Tags::Library.define_tag("ID", :id)
33
+ YARD::Tags::Library.define_tag("Component", :component)
37
34
  end
38
35
  end
39
36
  end
@@ -8,7 +8,7 @@ module Lookbook
8
8
  def initialize(preview)
9
9
  @preview = preview
10
10
  @preview_inspector = SourceInspector.new(@preview.name)
11
- super(preview_class_name(preview_class_basename(@preview.name)))
11
+ super(preview_class_path(@preview.name))
12
12
  end
13
13
 
14
14
  def id
@@ -34,7 +34,7 @@ module Lookbook
34
34
  def examples
35
35
  return @examples if @examples.present?
36
36
  public_methods = @preview.public_instance_methods(false)
37
- public_method_objects = @preview_inspector&.methods&.filter { |m| public_methods.include?(m.name) }
37
+ public_method_objects = @preview_inspector&.methods&.select { |m| public_methods.include?(m.name) }
38
38
  examples = (public_method_objects || []).map { |m| PreviewExample.new(m.name.to_s, self) }
39
39
  sorted = Lookbook.config.sort_examples ? examples.sort_by(&:label) : examples
40
40
  @examples = []
@@ -62,18 +62,14 @@ module Lookbook
62
62
  end
63
63
 
64
64
  def full_path
65
- base_path = Array(preview_paths).detect do |preview_path|
65
+ base_path = Array(Lookbook.config.preview_paths).detect do |preview_path|
66
66
  Dir["#{preview_path}/#{name.underscore}.rb"].first
67
67
  end
68
68
  Pathname.new(Dir["#{base_path}/#{name.underscore}.rb"].first)
69
69
  end
70
70
 
71
71
  def url_path
72
- inspect_path lookup_path
73
- end
74
-
75
- def preview_paths
76
- ViewComponent::Base.preview_paths
72
+ lookbook_inspect_path lookup_path
77
73
  end
78
74
 
79
75
  def parent_collections_names
@@ -96,6 +92,27 @@ module Lookbook
96
92
  true
97
93
  end
98
94
 
95
+ def component
96
+ components.first
97
+ end
98
+
99
+ def components
100
+ component_classes = @preview_inspector&.components.any? ? @preview_inspector&.components : [guess_component]
101
+ component_classes.map do |class_name|
102
+ Component.new(class_name.to_s)
103
+ end
104
+ end
105
+
106
+ protected
107
+
108
+ def guess_component
109
+ begin
110
+ name.chomp("Preview").constantize
111
+ rescue
112
+ nil
113
+ end
114
+ end
115
+
99
116
  class << self
100
117
  def find(path)
101
118
  all.find { |p| p.lookup_path == path }
@@ -15,7 +15,7 @@ module Lookbook
15
15
  end
16
16
 
17
17
  def url_path
18
- inspect_path lookup_path
18
+ lookbook_inspect_path lookup_path
19
19
  end
20
20
 
21
21
  def label
@@ -30,7 +30,7 @@ module Lookbook
30
30
  @example_inspector.source.split("\n")[1..-2].join("\n").strip_heredoc
31
31
  end
32
32
 
33
- def source_lang
33
+ def lang
34
34
  Lookbook::Lang.find(:ruby)
35
35
  end
36
36
 
@@ -10,7 +10,7 @@ module Lookbook
10
10
  end
11
11
 
12
12
  def url_path
13
- inspect_path lookup_path
13
+ lookbook_inspect_path lookup_path
14
14
  end
15
15
 
16
16
  def label
@@ -39,6 +39,16 @@ module Lookbook
39
39
  code_object&.tag(:position)&.text&.to_i || 10000
40
40
  end
41
41
 
42
+ def components
43
+ if code_object&.tags(:component).present?
44
+ code_object.tags(:component).map do |component|
45
+ component.text.constantize
46
+ end
47
+ else
48
+ []
49
+ end
50
+ end
51
+
42
52
  def display_params
43
53
  display_params = {}.with_indifferent_access
44
54
  if code_object&.tags(:display).present?
@@ -16,7 +16,7 @@ module Lookbook
16
16
  class_name(klass).to_s.chomp("ComponentPreview").chomp("Component::Preview").chomp("::Preview").chomp("Component").chomp("Preview").chomp("::")
17
17
  end
18
18
 
19
- def preview_class_name(klass)
19
+ def preview_class_path(klass)
20
20
  preview_class_basename(klass).underscore
21
21
  end
22
22
 
@@ -49,7 +49,7 @@ module Lookbook
49
49
  end
50
50
 
51
51
  def to_preview_path(*args)
52
- args.flatten.map { |arg| preview_class_name(arg) }.join("/")
52
+ args.flatten.map { |arg| preview_class_path(arg) }.join("/")
53
53
  end
54
54
 
55
55
  protected
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "1.0.0.beta.1"
2
+ VERSION = "1.0.0.beta.4"
3
3
  end
data/lib/lookbook.rb CHANGED
@@ -27,16 +27,5 @@ module Lookbook
27
27
  autoload :Markdown, "lookbook/markdown"
28
28
  autoload :Theme, "lookbook/theme"
29
29
  autoload :Store, "lookbook/store"
30
-
31
- class << self
32
- include Utils
33
-
34
- def previews
35
- Preview.all
36
- end
37
-
38
- def pages
39
- Page.all
40
- end
41
- end
30
+ autoload :Component, "lookbook/component"
42
31
  end