require "lookbook/markdown" require "lookbook/theme" require "lookbook/store" module Lookbook class Config def initialize @options = Store.new @options.set({ project_name: "Lookbook", log_level: 2, auto_refresh: true, components_path: "app/components", page_controller: "Lookbook::PageController", page_route: "pages", page_paths: ["test/components/docs"], page_options: {}, markdown_options: Markdown::DEFAULT_OPTIONS, preview_paths: [], preview_display_params: {}, preview_srcdoc: nil, preview_tags: {}, sort_examples: false, listen: Rails.env.development?, listen_paths: [], listen_extensions: ["rb", "html.*"], listen_use_polling: false, cable_mount_path: "/lookbook-cable", cable_logger: Lookbook.logger, runtime_parsing: !Rails.env.production?, parser_registry_path: "tmp/storage/.yardoc", ui_theme: "indigo", ui_theme_overrides: {}, ui_favicon: true, hooks: { after_initialize: [], before_exit: [], after_change: [] }, debug_menu: Rails.env.development?, experimental_features: false, inspector_panels: { preview: { pane: :main, position: 1, partial: "lookbook/previews/panels/preview", hotkey: "v", panel_classes: "overflow-hidden", padded: false, system: true }, output: { pane: :main, position: 2, partial: "lookbook/previews/panels/output", label: "HTML", hotkey: "h", padded: false, system: true }, source: { pane: :drawer, position: 1, partial: "lookbook/previews/panels/source", label: "Source", hotkey: "s", copy: ->(data) { data.examples.map { |e| e.source }.join("\n") }, padded: false, system: true }, notes: { pane: :drawer, position: 2, partial: "lookbook/previews/panels/notes", label: "Notes", hotkey: "n", disabled: ->(data) { data.examples.select { |e| e.notes.present? }.none? }, padded: false, system: true }, params: { pane: :drawer, position: 3, partial: "lookbook/previews/panels/params", label: "Params", hotkey: "p", disabled: ->(data) { data.preview.params.none? }, padded: false, system: true } } }) end def project_name @options.project_name == false ? nil : @options.project_name end def components_path absolute_path(@options.components_path) end def page_paths=(paths = []) @options.page_paths += paths if paths.is_a? Array end def page_paths normalize_paths(@options.page_paths) end def preview_paths=(paths = []) @options.preview_paths += paths if paths.is_a? Array end def preview_paths normalize_paths(@options.preview_paths) end def preview_srcdoc=(enable) Lookbook.logger.warn "The `preview_srcdoc` config option is deprecated and will be removed in v2.0" end def listen_paths normalize_paths(@options.listen_paths) end def listen_extensions=(extensions = []) @options.listen_extensions += extensions if extensions.is_a? Array @options.listen_extensions.uniq! end def parser_registry_path absolute_path(@options.parser_registry_path) end def inspector_panels(&block) panels = Store.new(@options.inspector_panels.select { |key, panel| panel != false }) if block yield panels else panels end end def define_inspector_panel(name, opts = {}) pane = opts[:pane].presence || :drawer siblings = inspector_panels.select { |key, panel| panel.pane == pane } opts[:position] ||= siblings.size + 1 @options.inspector_panels[name] = opts siblings.each do |key, panel| if panel.position >= opts[:position] panel.position += 1 end end end def amend_inspector_panel(name, opts = {}) if opts == false @options.inspector_panels[name] = false else @options.inspector_panels[name].merge!(opts) end end def remove_inspector_panel(name) amend_inspector_panel(name, false) end def inspector_panel_defaults { id: ->(data) { "inspector-panel-#{data.name}" }, partial: "lookbook/previews/panels/content", content: nil, label: ->(data) { data.name.titleize }, pane: :drawer, position: ->(data) { data.index_position }, hotkey: nil, disabled: false, show: true, copy: nil, panel_classes: nil, locals: {}, system: false } end def ui_theme=(name) name = name.to_s if Theme.valid_theme?(name) @options.ui_theme = name else Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Theme setting not changed." end end def ui_theme_overrides(&block) if block yield @options.ui_theme_overrides else @options.ui_theme_overrides end end def [](key) if respond_to? key.to_sym public_send(key.to_sym) else @options[key.to_sym] end end def []=(key, value) setter_key = "#{key}=".to_sym if respond_to? setter_key public_send(setter_key, value) else @options[key.to_sym] = value end end def to_h @options.to_h end def to_json(*a) to_h.to_json(*a) end protected def normalize_paths(paths) paths.map! do |path| full_path = absolute_path(path) full_path if Dir.exist?(full_path) end.compact! paths end def absolute_path(path) File.absolute_path(path.to_s, Rails.root) end def method_missing(name, *args) @options.send(name, *args) end def respond_to_missing?(name, *) to_h.key? name end end end