class Bridgetown::PluginManager

Constants

PLUGINS_GROUP
YARN_DEPENDENCY_REGEXP

Attributes

registered_plugins[R]
source_manifests[R]
component_loaders[R]
site[R]

Public Class Methods

add_registered_plugin(gem_or_plugin_file) click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 25
def self.add_registered_plugin(gem_or_plugin_file)
  @registered_plugins << gem_or_plugin_file
end
add_source_manifest(source_manifest) click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 13
def self.add_source_manifest(source_manifest)
  unless source_manifest.is_a?(Bridgetown::Plugin::SourceManifest)
    raise "You must add a SourceManifest instance"
  end

  @source_manifests << source_manifest
end
add_yarn_dependency?(yarn_dependency, package_json) click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 102
def self.add_yarn_dependency?(yarn_dependency, package_json)
  return false if yarn_dependency.nil?

  # check matching version number is see if it's already installed
  if package_json["dependencies"]
    current_version = package_json["dependencies"].dig(yarn_dependency.first)
    package_requires_updating?(current_version, yarn_dependency.last)
  else
    true
  end
end
find_yarn_dependency(loaded_gem) click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 95
def self.find_yarn_dependency(loaded_gem)
  yarn_dependency = loaded_gem.to_spec&.metadata&.dig("yarn-add")&.match(YARN_DEPENDENCY_REGEXP)
  return nil if yarn_dependency&.length != 3 || yarn_dependency[2] == ""

  yarn_dependency[1..2]
end
install_yarn_dependencies(required_gems, single_gemname = nil) click to toggle source

Iterates through loaded plugins and finds yard-add gemspec metadata. If that exact package hasn't been installed, execute yarn add

Returns nothing.

# File lib/bridgetown-core/plugin_manager.rb, line 72
def self.install_yarn_dependencies(required_gems, single_gemname = nil)
  return unless File.exist?("package.json")

  package_json = JSON.parse(File.read("package.json"))

  gems_to_search = if single_gemname
                     required_gems.select do |loaded_gem|
                       loaded_gem.to_spec&.name == single_gemname.to_s
                     end
                   else
                     required_gems
                   end

  gems_to_search.each do |loaded_gem|
    yarn_dependency = find_yarn_dependency(loaded_gem)
    next unless add_yarn_dependency?(yarn_dependency, package_json)

    # all right, time to install the package
    cmd = "yarn add #{yarn_dependency.join("@")}"
    system cmd
  end
end
new(site) click to toggle source

Create an instance of this class.

site - the instance of Bridgetown::Site we're concerned with

Returns nothing

# File lib/bridgetown-core/plugin_manager.rb, line 38
def initialize(site)
  @site = site
  @component_loaders = {}
end
new_source_manifest(*args) click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 21
def self.new_source_manifest(*args)
  add_source_manifest(Bridgetown::Plugin::SourceManifest.new(*args))
end
package_requires_updating?(current_version, dep_version) click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 114
def self.package_requires_updating?(current_version, dep_version)
  current_version.nil? || current_version != dep_version && !current_version.include?("/")
end
require_from_bundler() click to toggle source
# File lib/bridgetown-core/plugin_manager.rb, line 43
def self.require_from_bundler
  if !ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile")
    require "bundler"

    required_gems = Bundler.require PLUGINS_GROUP
    required_gems.select! do |dep|
      (dep.groups & [PLUGINS_GROUP]).any? && dep.should_include?
    end

    install_yarn_dependencies(required_gems)

    required_gems.each do |installed_gem|
      add_registered_plugin installed_gem
    end

    Bridgetown.logger.debug("PluginManager:",
                            "Required #{required_gems.map(&:name).join(", ")}")
    ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] = "true"

    true
  else
    false
  end
end

Public Instance Methods

plugins_path() click to toggle source

Public: Setup the plugin search path

Returns an Array of plugin search paths

# File lib/bridgetown-core/plugin_manager.rb, line 155
def plugins_path
  if site.config["plugins_dir"].eql? Bridgetown::Configuration::DEFAULTS["plugins_dir"]
    [site.in_root_dir(site.config["plugins_dir"])]
  else
    Array(site.config["plugins_dir"]).map { |d| File.expand_path(d) }
  end
end
reload_component_loaders() click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/bridgetown-core/plugin_manager.rb, line 187
def reload_component_loaders
  @component_loaders.each do |path, loader|
    loader.reload if path.start_with?(site.root_dir)
  end
end
reload_plugin_files() click to toggle source

Reload .rb plugin files via the watcher

# File lib/bridgetown-core/plugin_manager.rb, line 141
def reload_plugin_files
  plugins_path.each do |plugin_search_path|
    plugin_files = Utils.safe_glob(plugin_search_path, File.join("**", "*.rb"))
    Array(plugin_files).each do |name|
      Bridgetown.logger.debug "Reloading:", name.to_s
      self.class.add_registered_plugin name
      load name
    end
  end
end
require_plugin_files() click to toggle source

Require all .rb files

Returns nothing.

# File lib/bridgetown-core/plugin_manager.rb, line 121
def require_plugin_files
  plugins_path.each do |plugin_search_path|
    plugin_files = Utils.safe_glob(plugin_search_path, File.join("**", "*.rb"))

    # Require "site_builder.rb" first if present so subclasses can all
    # inherit from SiteBuilder without needing explicit require statements
    sorted_plugin_files = plugin_files.select do |path|
      path.include?("site_builder.rb")
    end + plugin_files.reject do |path|
      path.include?("site_builder.rb")
    end

    sorted_plugin_files.each do |plugin_file|
      self.class.add_registered_plugin plugin_file
    end
    Bridgetown::Utils::RequireGems.require_with_graceful_fail(sorted_plugin_files)
  end
end
setup_component_loaders() click to toggle source

rubocop:disable Metrics/AbcSize

# File lib/bridgetown-core/plugin_manager.rb, line 164
def setup_component_loaders
  unless @component_loaders.keys.empty?
    @component_loaders.each do |_path, loader|
      loader.unload
    end
    @component_loaders = {}
  end

  # Because "first constant wins" in Zeitwerk, we need to load the local
  # source components _before_ we load any from plugins
  site.components_load_paths.reverse_each do |load_path|
    next unless Dir.exist? load_path
    next if Zeitwerk::Registry.loaders.find { |loader| loader.manages?(load_path) }

    @component_loaders[load_path] = Zeitwerk::Loader.new
    @component_loaders[load_path].push_dir(load_path)
    @component_loaders[load_path].enable_reloading if load_path.start_with?(site.root_dir)
    @component_loaders[load_path].ignore(File.join(load_path, "**", "*.js.rb"))
    @component_loaders[load_path].setup
  end
end