lookbook 1.1.1 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/lookbook/js/helpers/string.js +23 -1
  3. data/app/assets/lookbook/js/lookbook.js +0 -1
  4. data/app/components/lookbook/button/component.html.erb +2 -1
  5. data/app/components/lookbook/button/component.js +9 -0
  6. data/app/components/lookbook/display_options/editor/component.html.erb +13 -0
  7. data/app/components/lookbook/display_options/editor/component.rb +7 -0
  8. data/app/components/lookbook/display_options/field/component.css +33 -0
  9. data/app/components/lookbook/display_options/field/component.html.erb +8 -0
  10. data/app/components/lookbook/display_options/field/component.js +30 -0
  11. data/app/components/lookbook/display_options/field/component.rb +28 -0
  12. data/app/components/lookbook/inspector_panel/component.html.erb +1 -1
  13. data/app/components/lookbook/inspector_panel/component.rb +10 -11
  14. data/app/components/lookbook/params/editor/component.rb +6 -3
  15. data/app/components/lookbook/params/field/component.rb +1 -5
  16. data/app/components/lookbook/tab_panels/panel/component.html.erb +1 -1
  17. data/app/components/lookbook/tab_panels/panel/component.rb +1 -2
  18. data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +1 -0
  19. data/app/components/lookbook/tabs/tab/component.html.erb +1 -0
  20. data/app/components/lookbook/viewport/component.html.erb +1 -1
  21. data/app/components/lookbook/viewport/component.rb +2 -1
  22. data/app/controllers/lookbook/previews_controller.rb +40 -29
  23. data/app/helpers/lookbook/preview_helper.rb +1 -1
  24. data/app/views/lookbook/previews/panels/_params.html.erb +1 -1
  25. data/app/views/lookbook/previews/panels/_preview.html.erb +9 -6
  26. data/app/views/lookbook/previews/show.html.erb +29 -11
  27. data/config/app.yml +36 -0
  28. data/config/hooks.yml +4 -0
  29. data/config/inputs.yml +48 -0
  30. data/config/panels.yml +30 -0
  31. data/config/routes.rb +1 -1
  32. data/config/tags.yml +29 -0
  33. data/lib/lookbook/engine.rb +40 -20
  34. data/lib/lookbook/markdown.rb +1 -11
  35. data/lib/lookbook/page.rb +1 -1
  36. data/lib/lookbook/params.rb +0 -7
  37. data/lib/lookbook/parser.rb +3 -10
  38. data/lib/lookbook/preview.rb +7 -3
  39. data/lib/lookbook/preview_example.rb +7 -3
  40. data/lib/lookbook/preview_group.rb +2 -2
  41. data/lib/lookbook/services/config_loader.rb +20 -0
  42. data/lib/lookbook/services/search_param_builder.rb +13 -0
  43. data/lib/lookbook/services/search_param_parser.rb +15 -0
  44. data/lib/lookbook/services/tags/key_value_tag_parser.rb +24 -0
  45. data/lib/lookbook/source_inspector.rb +10 -16
  46. data/lib/lookbook/stores/config_store.rb +80 -0
  47. data/lib/lookbook/stores/hook_store.rb +28 -0
  48. data/lib/lookbook/stores/input_store.rb +58 -0
  49. data/lib/lookbook/stores/panel_store.rb +141 -0
  50. data/lib/lookbook/stores/tag_store.rb +46 -0
  51. data/lib/lookbook/support/errors/config_error.rb +7 -0
  52. data/lib/lookbook/support/errors/lookbook_error.rb +21 -0
  53. data/lib/lookbook/support/errors/parser_error.rb +7 -0
  54. data/lib/lookbook/support/service.rb +7 -0
  55. data/lib/lookbook/support/store.rb +77 -0
  56. data/lib/lookbook/support/utils/attribute_utils.rb +9 -0
  57. data/lib/lookbook/support/utils/path_utils.rb +19 -0
  58. data/lib/lookbook/tags.rb +5 -14
  59. data/lib/lookbook/version.rb +1 -1
  60. data/lib/lookbook.rb +43 -12
  61. data/public/lookbook-assets/css/lookbook.css +33 -0
  62. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  63. data/public/lookbook-assets/js/lookbook.js +145 -4
  64. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  65. metadata +29 -6
  66. data/lib/lookbook/config.rb +0 -278
  67. data/lib/lookbook/hooks.rb +0 -21
  68. data/lib/lookbook/panels.rb +0 -25
  69. data/lib/lookbook/store.rb +0 -34
data/config/panels.yml ADDED
@@ -0,0 +1,30 @@
1
+ shared:
2
+ main:
3
+ - name: preview
4
+ partial: lookbook/previews/panels/preview
5
+ label: Preview
6
+ hotkey: v
7
+
8
+ - name: output
9
+ partial: lookbook/previews/panels/output
10
+ label: HTML
11
+ hotkey: h
12
+
13
+ drawer:
14
+ - name: source
15
+ partial: lookbook/previews/panels/source
16
+ label: Source
17
+ hotkey: s
18
+ copy: "->(data) { data.examples.map { |e| e.source }.join(\n) }"
19
+
20
+ - name: notes
21
+ partial: lookbook/previews/panels/notes
22
+ label: Notes
23
+ hotkey: n
24
+ disabled: ->(data) { data.examples.select { |e| e.notes.present? }.none? }
25
+
26
+ - name: params
27
+ partial: lookbook/previews/panels/params
28
+ label: Params
29
+ hotkey: p
30
+ disabled: ->(data) { data.preview.params.none? }
data/config/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  Lookbook::Engine.routes.draw do
2
2
  if Lookbook::Engine.websocket?
3
- mount Lookbook::Engine.websocket => Lookbook.config.cable_mount_path, :as => :cable
3
+ mount Lookbook::Engine.websocket => "/cable", :as => :cable
4
4
  end
5
5
 
6
6
  root to: "application#index", as: :lookbook_home
data/config/tags.yml ADDED
@@ -0,0 +1,29 @@
1
+ shared:
2
+ hidden:
3
+ label: Hidden status
4
+ opts: {}
5
+
6
+ label:
7
+ label: Label
8
+ opts: {}
9
+
10
+ display:
11
+ label: Display
12
+ opts: {}
13
+
14
+ position:
15
+ label: Position
16
+ opts: {}
17
+
18
+ id:
19
+ label: Id
20
+ opts: {}
21
+
22
+ component:
23
+ label: Component
24
+ opts: {}
25
+
26
+ param:
27
+ label: Param
28
+ yard_parser: with_name
29
+ opts: {}
@@ -6,30 +6,33 @@ module Lookbook
6
6
  class Engine < Rails::Engine
7
7
  isolate_namespace Lookbook
8
8
 
9
- config.autoload_paths << File.expand_path(Lookbook::Engine.root.join("app/components"))
10
- config.lookbook = Lookbook.config
9
+ config.autoload_paths << File.expand_path(root.join("app/components"))
11
10
 
12
11
  initializer "lookbook.viewcomponent.config" do
13
- config.lookbook.preview_paths += config.view_component.preview_paths
14
- config.lookbook.preview_controller ||= config.view_component.preview_controller
12
+ Lookbook.config.preview_paths += config.view_component.preview_paths
13
+ Lookbook.config.preview_controller ||= config.view_component.preview_controller
15
14
 
16
- config.lookbook.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present?
15
+ Lookbook.config.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present?
17
16
 
18
- config.lookbook.listen_paths += config.lookbook.preview_paths
19
- config.lookbook.listen_paths << config.lookbook.components_path
17
+ Lookbook.config.listen_paths += Lookbook.config.preview_paths
18
+ Lookbook.config.listen_paths << Lookbook.config.components_path
20
19
  end
21
20
 
22
21
  initializer "lookbook.parser.tags" do
23
- Lookbook::Parser.define_tags(Lookbook.config.preview_tags)
22
+ Lookbook::Parser.define_tags(Engine.tags)
24
23
  end
25
24
 
26
25
  initializer "lookbook.assets.serve" do
27
26
  config.app_middleware.use(
28
27
  Rack::Static,
29
- urls: ["/lookbook-assets"], root: Lookbook::Engine.root.join("public").to_s
28
+ urls: ["/lookbook-assets"], root: root.join("public").to_s
30
29
  )
31
30
  end
32
31
 
32
+ config.before_configuration do
33
+ config.lookbook = Lookbook.config
34
+ end
35
+
33
36
  config.after_initialize do
34
37
  @preview_controller = Lookbook.config.preview_controller.constantize
35
38
  @preview_controller.include(Lookbook::PreviewController)
@@ -46,22 +49,22 @@ module Lookbook
46
49
  end
47
50
  else
48
51
  # Fallback for older Rails versions - don't start listeners if running in a rake task.
49
- unless Lookbook::Engine.prevent_listening?
52
+ unless prevent_listening?
50
53
  init_listeners
51
54
  end
52
55
  end
53
56
 
54
57
  parser.parse do
55
- Lookbook::Engine.run_hooks(:after_initialize)
58
+ run_hooks(:after_initialize)
56
59
  end
57
60
  end
58
61
 
59
62
  at_exit do
60
- if Lookbook::Engine.listeners.any?
63
+ if listeners.any?
61
64
  Lookbook.logger.debug "Stopping listeners"
62
- Lookbook::Engine.stop_listeners
65
+ stop_listeners
63
66
  end
64
- Lookbook::Engine.run_hooks(:before_exit)
67
+ run_hooks(:before_exit)
65
68
  end
66
69
 
67
70
  class << self
@@ -69,7 +72,7 @@ module Lookbook
69
72
  config = Lookbook.config
70
73
  return unless config.listen == true
71
74
 
72
- listen_paths = config.listen_paths.uniq
75
+ listen_paths = PathUtils.normalize_all(config.listen_paths)
73
76
  if listen_paths.any?
74
77
  preview_listener = Listen.to(*listen_paths,
75
78
  only: /\.(#{config.listen_extensions.join("|")})$/,
@@ -82,7 +85,7 @@ module Lookbook
82
85
  register_listener(preview_listener)
83
86
  end
84
87
 
85
- page_paths = config.page_paths.uniq
88
+ page_paths = PathUtils.normalize_all(config.page_paths)
86
89
  if page_paths.any?
87
90
  page_listener = Listen.to(*page_paths,
88
91
  only: /\.(html.*|md.*)$/,
@@ -117,7 +120,7 @@ module Lookbook
117
120
  end
118
121
 
119
122
  def websocket_mount_path
120
- "#{mounted_path}#{config.lookbook.cable_mount_path}".gsub("//", "/") if websocket?
123
+ "#{mounted_path}/cable".gsub("//", "/") if websocket?
121
124
  end
122
125
 
123
126
  def websocket?
@@ -125,11 +128,12 @@ module Lookbook
125
128
  end
126
129
 
127
130
  def mounted_path
128
- Lookbook::Engine.routes.find_script_name({})
131
+ routes.find_script_name({})
129
132
  end
130
133
 
131
134
  def parser
132
- @parser ||= Lookbook::Parser.new(config.lookbook.preview_paths)
135
+ preview_paths = PathUtils.normalize_all(Lookbook.config.preview_paths)
136
+ @parser ||= Lookbook::Parser.new(preview_paths)
133
137
  end
134
138
 
135
139
  def log_level
@@ -159,7 +163,7 @@ module Lookbook
159
163
  end
160
164
 
161
165
  def run_hooks(event_name, *args)
162
- config.lookbook.hooks[event_name].each do |hook|
166
+ hooks.for_event(event_name).each do |hook|
163
167
  hook.call(Lookbook, *args)
164
168
  end
165
169
  end
@@ -180,6 +184,22 @@ module Lookbook
180
184
  end
181
185
  end
182
186
 
187
+ def panels
188
+ @panels ||= PanelStore.init_from_config
189
+ end
190
+
191
+ def inputs
192
+ @inputs ||= InputStore.init_from_config
193
+ end
194
+
195
+ def tags
196
+ @tags ||= TagStore.init_from_config
197
+ end
198
+
199
+ def hooks
200
+ @hooks ||= HookStore.init_from_config
201
+ end
202
+
183
203
  attr_reader :preview_controller
184
204
  end
185
205
  end
@@ -2,19 +2,9 @@ require "redcarpet"
2
2
 
3
3
  module Lookbook
4
4
  class Markdown
5
- DEFAULT_OPTIONS = {
6
- tables: true,
7
- fenced_code_blocks: true,
8
- disable_indented_code_blocks: true,
9
- strikethrough: true,
10
- highlight: true,
11
- with_toc_data: true,
12
- lax_spacing: true
13
- }
14
-
15
5
  def self.render(text)
16
6
  Utils.strip_action_view_annotations!(text)
17
- markdown = Redcarpet::Markdown.new(Renderer, Lookbook.config.markdown_options)
7
+ markdown = Redcarpet::Markdown.new(Renderer, Lookbook.config.markdown_options.to_h)
18
8
  markdown.render(text).html_safe
19
9
  end
20
10
 
data/lib/lookbook/page.rb CHANGED
@@ -180,7 +180,7 @@ module Lookbook
180
180
  end
181
181
 
182
182
  def page_paths
183
- Lookbook.config.page_paths.select { |dir| Dir.exist? dir }
183
+ PathUtils.normalize_all(Lookbook.config.page_paths)
184
184
  end
185
185
 
186
186
  def section_path?(path)
@@ -117,13 +117,6 @@ module Lookbook
117
117
  end
118
118
  end
119
119
 
120
- def inputs
121
- @inputs ||= Lookbook.config.preview_param_inputs.map do |name, config|
122
- config = {partial: config} if config.is_a?(String)
123
- [name, {input_options: {}}.merge(config)]
124
- end.to_h
125
- end
126
-
127
120
  private
128
121
 
129
122
  def guess_input(value_type, default)
@@ -32,16 +32,9 @@ module Lookbook
32
32
  end
33
33
 
34
34
  class << self
35
- def define_tags(custom = {})
36
- YARD::Tags::Library.define_tag("Hidden status", :hidden)
37
- YARD::Tags::Library.define_tag("Label", :label)
38
- YARD::Tags::Library.define_tag("Display", :display)
39
- YARD::Tags::Library.define_tag("Position", :position)
40
- YARD::Tags::Library.define_tag("ID", :id)
41
- YARD::Tags::Library.define_tag("Component", :component)
42
- YARD::Tags::Library.define_tag("Param", :param, :with_name)
43
- custom.each do |name, opts|
44
- YARD::Tags::Library.define_tag(name.to_s.titleize, name)
35
+ def define_tags(tags = nil)
36
+ tags.to_h.each do |name, tag|
37
+ YARD::Tags::Library.define_tag(tag[:label], name, tag[:yard_parser])
45
38
  end
46
39
  end
47
40
  end
@@ -70,7 +70,7 @@ module Lookbook
70
70
  end
71
71
 
72
72
  def full_path
73
- base_path = Array(Lookbook.config.preview_paths).detect do |preview_path|
73
+ base_path = preview_paths.detect do |preview_path|
74
74
  Dir["#{preview_path}/#{rel_path}"].first
75
75
  end
76
76
  Pathname.new(Dir["#{base_path}/#{rel_path}"].first)
@@ -92,8 +92,8 @@ module Lookbook
92
92
  @preview.instance_variable_get(:@layout)
93
93
  end
94
94
 
95
- def display_params
96
- Lookbook.config.preview_display_params.deep_merge(@preview_inspector&.display_params)
95
+ def display_options
96
+ Lookbook.config.preview_display_options.deep_merge(@preview_inspector&.display_options)
97
97
  end
98
98
 
99
99
  def collapsible?
@@ -111,6 +111,10 @@ module Lookbook
111
111
  end
112
112
  end
113
113
 
114
+ def preview_paths
115
+ PathUtils.normalize_all(Lookbook.config.preview_paths)
116
+ end
117
+
114
118
  protected
115
119
 
116
120
  @preview_objects = nil
@@ -22,8 +22,8 @@ module Lookbook
22
22
  @example_inspector.label.presence || name.titleize
23
23
  end
24
24
 
25
- def display_params
26
- @preview.display_params.merge(@example_inspector.display_params)
25
+ def display_options
26
+ @preview.display_options.merge(@example_inspector.display_options)
27
27
  end
28
28
 
29
29
  def method_source
@@ -63,13 +63,17 @@ module Lookbook
63
63
 
64
64
  def full_template_path(template_path)
65
65
  template_path = strip_ext template_path
66
- base_path = Array(Lookbook.config.preview_paths).detect do |p|
66
+ base_path = preview_paths.detect do |p|
67
67
  Dir["#{p}/#{template_path}.html.*"].first
68
68
  end
69
69
  path = Dir["#{base_path}/#{template_path}.html.*"].first
70
70
  path ? Pathname.new(path) : nil
71
71
  end
72
72
 
73
+ def preview_paths
74
+ PathUtils.normalize_all(Lookbook.config.preview_paths)
75
+ end
76
+
73
77
  class << self
74
78
  def all
75
79
  Preview.all.map { |preview| preview.examples }.flatten
@@ -25,10 +25,10 @@ module Lookbook
25
25
  examples.map(&:params).flatten.uniq { |param| param[:name] }
26
26
  end
27
27
 
28
- def display_params
28
+ def display_options
29
29
  merged = {}
30
30
  examples.reverse.map do |example|
31
- merged.merge! example.display_params
31
+ merged.merge! example.display_options
32
32
  end
33
33
  merged
34
34
  end
@@ -0,0 +1,20 @@
1
+ module Lookbook
2
+ class ConfigLoader < Service
3
+ attr_reader :file, :env
4
+
5
+ def initialize(path, env: Rails.env)
6
+ @file = Engine.root.join(path)
7
+ @env = env.to_sym
8
+ end
9
+
10
+ def call
11
+ if file.exist?
12
+ config = YAML.load_file(file).deep_symbolize_keys
13
+ env_config = config[:shared].to_h.deep_merge(config[env].to_h)
14
+ Store.new(env_config)
15
+ else
16
+ raise ConfigError.new("Could not load configuration. No such file - #{file}")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module Lookbook
2
+ class SearchParamBuilder < Service
3
+ attr_reader :data
4
+
5
+ def initialize(data)
6
+ @data = data
7
+ end
8
+
9
+ def call
10
+ data.map { "#{_1}:#{_2}" }.join("|")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Lookbook
2
+ class SearchParamParser < Service
3
+ attr_reader :param_value
4
+
5
+ def initialize(param_value)
6
+ @param_value = param_value.strip
7
+ end
8
+
9
+ def call
10
+ pairs_str = param_value.split("|")
11
+ pairs = pairs_str.map { [*_1.split(":").map(&:strip)] }
12
+ pairs.to_h.symbolize_keys
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ module Lookbook
2
+ class KeyValueTagParser < Service
3
+ KEY_VALUE_REGEX = /^([^\s]+)\s+(.+)$/
4
+
5
+ attr_reader :text
6
+
7
+ def initialize(text)
8
+ @text = text.to_s
9
+ end
10
+
11
+ def call
12
+ text.strip.match(KEY_VALUE_REGEX) do |matches|
13
+ key = matches[1]
14
+ value = begin
15
+ YAML.safe_load(matches[2] || "~")
16
+ rescue ::Psych::SyntaxError => exception
17
+ raise ParserError.new("Invalid YAML in tag text '#{@text}'", scope: "key_value_tag.parser", original: exception)
18
+ end
19
+ return [key, value]
20
+ end
21
+ raise ParserError.new("Could not parse key:value pair from '#{@text}'", scope: "key_value_tag.parser")
22
+ end
23
+ end
24
+ end
@@ -52,22 +52,16 @@ module Lookbook
52
52
  end
53
53
  end
54
54
 
55
- def display_params
56
- return @display_params unless @display_params.nil?
57
- @display_params = {}.with_indifferent_access
58
- if code_object&.tags(:display).present?
59
- code_object.tags(:display).each do |tag|
60
- parts = tag.text.strip.match(/^([^\s]*)\s?(.*)$/)
61
- if parts.present?
62
- begin
63
- display_params[parts[1]] = YAML.safe_load(parts[2] || "~")
64
- rescue SyntaxError => err
65
- Lookbook.logger.error("\n👀 [Lookbook] Invalid JSON in @display tag.\n👀 [Lookbook] (#{err})\n")
66
- end
67
- end
68
- end
69
- end
70
- @display_params
55
+ def display_options
56
+ return @display_options unless @display_options.nil?
57
+ tags = code_object.tags(:display).to_a
58
+ pairs = tags.map { KeyValueTagParser.call(_1.text) }
59
+
60
+ # dynamic params set at the entity level are
61
+ # not (yet) supported so filter them out.
62
+ pairs.select! { |pair| !pair[1].is_a?(Array) && !pair[1].is_a?(Hash) }
63
+
64
+ pairs.to_h.symbolize_keys
71
65
  end
72
66
 
73
67
  def parameter_defaults
@@ -0,0 +1,80 @@
1
+ module Lookbook
2
+ class ConfigStore
3
+ CONFIG_FILE = "config/app.yml"
4
+
5
+ delegate_missing_to :store
6
+ attr_reader :store
7
+
8
+ def initialize(config = nil)
9
+ @store = Store.new(config, recursive: true)
10
+ end
11
+
12
+ def project_name=(name)
13
+ store[:project_name] = name == false ? nil : name
14
+ end
15
+
16
+ def page_paths=(paths = nil)
17
+ store[:page_paths] ||= []
18
+ store[:page_paths] += paths.to_a
19
+ end
20
+
21
+ def preview_paths=(paths = nil)
22
+ store[:preview_paths] ||= []
23
+ store[:preview_paths] += paths.to_a
24
+ end
25
+
26
+ def preview_display_params
27
+ Lookbook.logger.warn "The `preview_display_params` config option has been renamed to `preview_display_options` and will be removed in v2.0"
28
+ store[:preview_display_options]
29
+ end
30
+
31
+ def preview_display_params=(options)
32
+ Lookbook.logger.warn "The `preview_display_params` config option has been renamed to `preview_display_options` and will be removed in v2.0"
33
+ store[:preview_display_options] = options.to_h
34
+ end
35
+
36
+ def listen_extensions=(extensions = nil)
37
+ store[:listen_extensions] ||= []
38
+ store[:listen_extensions] += extensions.to_a
39
+ store[:listen_extensions].uniq!
40
+ end
41
+
42
+ def markdown_options=(options = nil)
43
+ store[:markdown_options] ||= {}
44
+ store[:markdown_options].merge!(options.to_h)
45
+ end
46
+
47
+ def ui_theme=(name)
48
+ name = name.to_s
49
+ if Theme.valid_theme?(name)
50
+ store[:ui_theme] = name
51
+ else
52
+ raise ConfigError.new("'#{name}' is not a valid Lookbook theme. ", scope: "app.config")
53
+ end
54
+ end
55
+
56
+ def ui_theme_overrides(&block)
57
+ if block
58
+ yield store[:ui_theme_overrides]
59
+ else
60
+ store[:ui_theme_overrides]
61
+ end
62
+ end
63
+
64
+ def runtime_parsing=(value)
65
+ Lookbook.logger.warn "The `runtime_parsing` config option has been deprecated and will be removed in v2.0"
66
+ end
67
+
68
+ def preview_srcdoc=(enable)
69
+ Lookbook.logger.warn "The `preview_srcdoc` config option is deprecated and will be removed in v2.0"
70
+ end
71
+
72
+ def self.init_from_config(env: Rails.env)
73
+ new(default_config(env: env))
74
+ end
75
+
76
+ def self.default_config(env: Rails.env)
77
+ ConfigLoader.call(CONFIG_FILE, env: env)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,28 @@
1
+ module Lookbook
2
+ class HookStore
3
+ CONFIG_FILE = "config/hooks.yml"
4
+
5
+ attr_reader :store
6
+ delegate :to_h, to: :store
7
+
8
+ def initialize(config = nil)
9
+ @store = {}
10
+ end
11
+
12
+ def add_hook(event_name, callback)
13
+ for_event(event_name) << callback
14
+ end
15
+
16
+ def for_event(event_name)
17
+ store[event_name.to_sym] ||= []
18
+ end
19
+
20
+ def self.init_from_config
21
+ new(default_config)
22
+ end
23
+
24
+ def self.default_config
25
+ ConfigLoader.call(CONFIG_FILE)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,58 @@
1
+ module Lookbook
2
+ class InputStore
3
+ CONFIG_FILE = "config/inputs.yml"
4
+
5
+ DEFAULTS = {
6
+ # TODO
7
+ }
8
+
9
+ attr_reader :store
10
+ delegate :to_h, to: :store
11
+
12
+ def initialize(config = nil)
13
+ @store = {}
14
+
15
+ config.to_h.each do |name, opts|
16
+ add_input(name, opts[:partial], opts.except(:partial))
17
+ end
18
+ end
19
+
20
+ def add_input(input, *args)
21
+ store[input.to_sym] = build_config(input, *args)
22
+ end
23
+
24
+ def get_input(input)
25
+ store[input.to_sym]
26
+ end
27
+
28
+ def self.init_from_config
29
+ new(default_config)
30
+ end
31
+
32
+ def self.default_config
33
+ ConfigLoader.call(CONFIG_FILE)
34
+ end
35
+
36
+ protected
37
+
38
+ def build_config(name, *args)
39
+ partial = nil
40
+ opts = nil
41
+ if args.many? && args.last.is_a?(Hash)
42
+ partial = args.first
43
+ opts = args.last
44
+ elsif args.first.is_a?(String)
45
+ partial = args.first
46
+ end
47
+ if partial.present?
48
+ Store.new({
49
+ name: name.to_sym,
50
+ partial: partial,
51
+ opts: DEFAULTS.merge(opts.to_h)
52
+ })
53
+ else
54
+ raise ConfigError.new("inputs must define a partial path", scope: "inputs.config")
55
+ end
56
+ end
57
+ end
58
+ end