lib/lookbook/engine.rb in lookbook-1.2.1 vs lib/lookbook/engine.rb in lookbook-1.3.0

- old
+ new

@@ -1,206 +1,157 @@ require "view_component" require "action_cable/engine" require "listen" +require "yard" module Lookbook class Engine < Rails::Engine isolate_namespace Lookbook config.autoload_paths << File.expand_path(root.join("app/components")) - initializer "lookbook.viewcomponent.config" do - Lookbook.config.preview_paths += config.view_component.preview_paths - Lookbook.config.preview_controller ||= config.view_component.preview_controller + config.before_configuration do + config.lookbook = Lookbook.config + end - Lookbook.config.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present? + initializer "lookbook.viewcomponent.config_sync" do + opts.preview_paths += config.view_component.preview_paths + opts.preview_controller ||= config.view_component.preview_controller - Lookbook.config.listen_paths += Lookbook.config.preview_paths - Lookbook.config.listen_paths << Lookbook.config.components_path + if config.view_component.view_component_path.present? + opts.components_path = config.view_component.view_component_path + end end - initializer "lookbook.parser.tags" do - Lookbook::Parser.define_tags(Engine.tags) - end - initializer "lookbook.assets.serve" do config.app_middleware.use( Rack::Static, urls: ["/lookbook-assets"], root: root.join("public").to_s ) end - config.before_configuration do - config.lookbook = Lookbook.config + initializer "lookbook.file_watcher.paths" do + opts.listen_paths += opts.preview_paths + opts.listen_paths << opts.components_path end - config.after_initialize do - @preview_controller = Lookbook.config.preview_controller.constantize - @preview_controller.include(Lookbook::PreviewController) - - parser.after_parse do |registry| - Preview.load!(registry.all(:class)) - reload_ui + initializer "lookbook.file_watcher.previews" do + file_watcher.watch(opts.listen_paths, opts.listen_extensions, wait_for_delay: 0.5) do |changes| + parser.parse { run_hooks(:after_change, changes) } end + end - if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1.3.1") - # Rails.application.server is only available for newer Rails versions - Rails.application.server do - init_listeners - end - else - # Fallback for older Rails versions - don't start listeners if running in a rake task. - unless prevent_listening? - init_listeners - end + initializer "lookbook.file_watcher.pages" do + file_watcher.watch(opts.page_paths, opts.page_extensions) do |changes| + self.class.websocket.broadcast(:reload) + run_hooks(:after_change, changes) end + end - parser.parse do - run_hooks(:after_initialize) + initializer "lookbook.parser.preview_load_callback" do + parser.after_parse do |registry| + Preview.load!(registry.all(:class)) + self.class.websocket.broadcast(:reload) end end - at_exit do - if listeners.any? - Lookbook.logger.debug "Stopping listeners" - stop_listeners - end - run_hooks(:before_exit) + # The preview controller handles the rendering of individual previews. + # + # Lookbook injects some actions into whichever controller has been + # specified by the user in order to render previews within the context of + # the particular controller class instance so that any before_action/after_action + # callbacks will be correctly processed. + config.after_initialize do + @preview_controller = opts.preview_controller.constantize + @preview_controller.class_eval { include Lookbook::PreviewActions } end - class << self - def init_listeners - config = Lookbook.config - return unless config.listen == true - - listen_paths = PathUtils.normalize_all(config.listen_paths) - if listen_paths.any? - preview_listener = Listen.to(*listen_paths, - only: /\.(#{config.listen_extensions.join("|")})$/, - wait_for_delay: 0.5, - force_polling: config.listen_use_polling) do |modified, added, removed| - parser.parse do - run_hooks(:after_change, {modified: modified, added: added, removed: removed}) - end - end - register_listener(preview_listener) - end - - page_paths = PathUtils.normalize_all(config.page_paths) - if page_paths.any? - page_listener = Listen.to(*page_paths, - only: /\.(html.*|md.*)$/, - force_polling: config.listen_use_polling) do |modified, added, removed| - changes = {modified: modified, added: added, removed: removed} - reload_ui - run_hooks(:after_change, changes) - end - register_listener(page_listener) - end + config.after_initialize do + if Rails.application.respond_to?(:server) + Rails.application.server { file_watcher.start if listen? } + elsif process.supports_listening? + file_watcher.start if listen? end + end - def websocket - config = Lookbook.config - return @websocket unless @websocket.nil? - return unless config.auto_refresh == true && config.listen == true && !Rails.env.test? - Lookbook.logger.info "Initializing websocket" + config.after_initialize do + parser.parse { run_hooks(:after_initialize) } + end - cable = ActionCable::Server::Configuration.new - cable.cable = {adapter: "async"}.with_indifferent_access - cable.mount_path = nil - cable.connection_class = -> { Lookbook::Connection } - cable.logger = Lookbook.logger + def opts + Lookbook.config + end - @websocket ||= if Gem::Version.new(Rails.version) >= Gem::Version.new(6.0) - ActionCable::Server::Base.new(config: cable) - else - ws = ActionCable::Server::Base.new - ws.config = cable - ws - end + def run_hooks(event_name, *args) + self.class.hooks.for_event(event_name).each do |hook| + hook.call(Lookbook, *args) end + end - def websocket_mount_path - "#{mounted_path}/cable".gsub("//", "/") if websocket? - end + def parser + @parser ||= PreviewParser.new(opts.preview_paths, Engine.tags) + end - def websocket? - websocket.present? - end + def file_watcher + @file_watcher ||= FileWatcher.new(force_polling: opts.listen_use_polling) + end - def mounted_path - routes.find_script_name({}) - end + def process + @process ||= Process.new(env: Rails.env) + end - def parser - preview_paths = PathUtils.normalize_all(Lookbook.config.preview_paths) - @parser ||= Lookbook::Parser.new(preview_paths) - end + def listen? + opts.listen && process.supports_listening? + end - def log_level - Lookbook.logger.level - end + def self.mount_path + routes.find_script_name({}) + end - def app_name - name = if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1") - Rails.application.class.module_parent_name - else - Rails.application.class.parent_name - end - name.underscore - end + def self.mounted? + mount_path.present? + end - def register_listener(listener) - listener.start - listeners << listener + def self.app_name + name = if Rails.application.class.respond_to?(:module_parent_name) + Rails.application.class.module_parent_name + else + Rails.application.class.parent_name end + name.underscore + end - def listeners - @listeners ||= [] + def self.websocket + if mounted? + use_websocket = opts.auto_refresh && opts.listen && process.supports_listening? + @websocket ||= use_websocket ? Websocket.new(mount_path, logger: Lookbook.logger) : Websocket.noop + else + Websocket.noop end + end - def stop_listeners - listeners.each { |listener| listener.stop } - end + def self.panels + @panels ||= PanelStore.init_from_config + end - def run_hooks(event_name, *args) - hooks.for_event(event_name).each do |hook| - hook.call(Lookbook, *args) - end - end + def self.inputs + @inputs ||= InputStore.init_from_config + end - def reload_ui - websocket&.broadcast("reload", {}) - end + def self.tags + @tags ||= TagStore.init_from_config + end - def prevent_listening? - Rails.env.test? || running_in_rake_task? - end + def self.hooks + @hooks ||= HookStore.init_from_config + end - def running_in_rake_task? - if defined?(Rake) && Rake.respond_to?(:application) - File.basename($0) == "rake" || Rake.application.top_level_tasks.any? - else - false - end - end + def self.preview_controller + @preview_controller + end - def panels - @panels ||= PanelStore.init_from_config - end - - def inputs - @inputs ||= InputStore.init_from_config - end - - def tags - @tags ||= TagStore.init_from_config - end - - def hooks - @hooks ||= HookStore.init_from_config - end - - attr_reader :preview_controller + at_exit do + file_watcher.stop + run_hooks(:before_exit) end end end