bridgetown-core 1.0.0.alpha5 → 1.0.0.alpha9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/bin/bridgetown +8 -1
  4. data/bridgetown-core.gemspec +2 -3
  5. data/lib/bridgetown-core/cache.rb +1 -1
  6. data/lib/bridgetown-core/collection.rb +1 -1
  7. data/lib/bridgetown-core/commands/concerns/configuration_overridable.rb +7 -0
  8. data/lib/bridgetown-core/commands/configure.rb +7 -0
  9. data/lib/bridgetown-core/commands/console.rb +38 -12
  10. data/lib/bridgetown-core/commands/doctor.rb +8 -5
  11. data/lib/bridgetown-core/commands/new.rb +3 -2
  12. data/lib/bridgetown-core/commands/start.rb +4 -2
  13. data/lib/bridgetown-core/component.rb +2 -2
  14. data/lib/bridgetown-core/concerns/front_matter_importer.rb +1 -1
  15. data/lib/bridgetown-core/concerns/site/configurable.rb +6 -3
  16. data/lib/bridgetown-core/concerns/site/extensible.rb +2 -1
  17. data/lib/bridgetown-core/concerns/site/ssr.rb +38 -16
  18. data/lib/bridgetown-core/configuration.rb +77 -46
  19. data/lib/bridgetown-core/configurations/bt-postcss.rb +1 -3
  20. data/lib/bridgetown-core/configurations/cypress/cypress.json +4 -0
  21. data/lib/bridgetown-core/configurations/cypress/cypress_dir/fixtures/example.json +5 -0
  22. data/lib/bridgetown-core/configurations/cypress/cypress_dir/integration/navbar.spec.js +17 -0
  23. data/lib/bridgetown-core/configurations/cypress/cypress_dir/plugins/index.js +21 -0
  24. data/lib/bridgetown-core/configurations/cypress/cypress_dir/support/commands.js +25 -0
  25. data/lib/bridgetown-core/configurations/cypress/cypress_dir/support/index.js +20 -0
  26. data/lib/bridgetown-core/configurations/cypress/cypress_tasks +33 -0
  27. data/lib/bridgetown-core/configurations/cypress.rb +13 -0
  28. data/lib/bridgetown-core/configurations/minitesting.rb +19 -15
  29. data/lib/bridgetown-core/configurations/netlify/netlify.toml +2 -2
  30. data/lib/bridgetown-core/configurations/netlify.rb +2 -4
  31. data/lib/bridgetown-core/configurations/purgecss.rb +2 -2
  32. data/lib/bridgetown-core/configurations/render/render.yaml.erb +26 -0
  33. data/lib/bridgetown-core/configurations/render.rb +6 -0
  34. data/lib/bridgetown-core/configurations/tailwindcss.rb +3 -5
  35. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
  36. data/lib/bridgetown-core/converters/serbea_templates.rb +71 -0
  37. data/lib/bridgetown-core/core_ext/psych.rb +1 -5
  38. data/lib/bridgetown-core/frontmatter_defaults.rb +2 -2
  39. data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -3
  40. data/lib/bridgetown-core/liquid_renderer.rb +1 -1
  41. data/lib/bridgetown-core/model/base.rb +23 -26
  42. data/lib/bridgetown-core/model/builder_origin.rb +8 -6
  43. data/lib/bridgetown-core/model/origin.rb +10 -1
  44. data/lib/bridgetown-core/model/plugin_origin.rb +1 -1
  45. data/lib/bridgetown-core/plugin_manager.rb +9 -36
  46. data/lib/bridgetown-core/rack/boot.rb +46 -23
  47. data/lib/bridgetown-core/rack/roda.rb +2 -1
  48. data/lib/bridgetown-core/rack/routes.rb +2 -2
  49. data/lib/bridgetown-core/readers/layout_reader.rb +1 -1
  50. data/lib/bridgetown-core/readers/plugin_content_reader.rb +1 -1
  51. data/lib/bridgetown-core/renderer.rb +2 -2
  52. data/lib/bridgetown-core/resource/base.rb +3 -3
  53. data/lib/bridgetown-core/resource/relations.rb +1 -1
  54. data/lib/bridgetown-core/resource/taxonomy_term.rb +2 -2
  55. data/lib/bridgetown-core/resource/taxonomy_type.rb +2 -2
  56. data/lib/bridgetown-core/ruby_template_view.rb +2 -2
  57. data/lib/bridgetown-core/site.rb +15 -5
  58. data/lib/bridgetown-core/utils/loaders_manager.rb +72 -0
  59. data/lib/bridgetown-core/utils.rb +13 -14
  60. data/lib/bridgetown-core/version.rb +1 -1
  61. data/lib/bridgetown-core/watcher.rb +16 -7
  62. data/lib/bridgetown-core/yaml_parser.rb +1 -5
  63. data/lib/bridgetown-core.rb +0 -1
  64. data/lib/site_template/README.md +1 -1
  65. data/lib/site_template/Rakefile +3 -3
  66. metadata +31 -19
@@ -0,0 +1,25 @@
1
+ // ***********************************************
2
+ // This example commands.js shows you how to
3
+ // create various custom commands and overwrite
4
+ // existing commands.
5
+ //
6
+ // For more comprehensive examples of custom
7
+ // commands please read more here:
8
+ // https://on.cypress.io/custom-commands
9
+ // ***********************************************
10
+ //
11
+ //
12
+ // -- This is a parent command --
13
+ // Cypress.Commands.add("login", (email, password) => { ... })
14
+ //
15
+ //
16
+ // -- This is a child command --
17
+ // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18
+ //
19
+ //
20
+ // -- This is a dual command --
21
+ // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22
+ //
23
+ //
24
+ // -- This will overwrite an existing command --
25
+ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
@@ -0,0 +1,20 @@
1
+ // ***********************************************************
2
+ // This example support/index.js is processed and
3
+ // loaded automatically before your test files.
4
+ //
5
+ // This is a great place to put global configuration and
6
+ // behavior that modifies Cypress.
7
+ //
8
+ // You can change the location of this file or turn off
9
+ // automatically serving support files with the
10
+ // 'supportFile' configuration option.
11
+ //
12
+ // You can read more here:
13
+ // https://on.cypress.io/configuration
14
+ // ***********************************************************
15
+
16
+ // Import commands.js using ES2015 syntax:
17
+ import './commands'
18
+
19
+ // Alternatively you can use CommonJS syntax:
20
+ // require('./commands')
@@ -0,0 +1,33 @@
1
+ namespace :cy do
2
+ desc "Open Cypress test runner"
3
+ task :open do
4
+ system "yarn run cypress open"
5
+ end
6
+
7
+ desc "Run Cypress tests headless"
8
+ task :run do
9
+ system "yarn run cypress run"
10
+ end
11
+
12
+ desc "Start server and open Cypress test runner"
13
+ task :test do
14
+ ENV["BRIDGETOWN_ENV"] = "test"
15
+ server_pid = fork { Bridgetown::Commands::Start.start }
16
+ Rake::Task["cy:open"].execute
17
+ Process.kill "SIGTERM", server_pid
18
+ sleep 1 # give processes time to clean up
19
+ puts
20
+ end
21
+
22
+ namespace :test do
23
+ desc "Start server and run Cypress tests headless"
24
+ task :ci do
25
+ ENV["BRIDGETOWN_ENV"] = "test"
26
+ server_pid = fork { Bridgetown::Commands::Start.start }
27
+ Rake::Task["cy:run"].execute
28
+ Process.kill "SIGTERM", server_pid
29
+ sleep 1 # give processes time to clean up
30
+ puts
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Install packages
4
+
5
+ say "Installing Cypress...", :green
6
+ run "yarn add -D cypress"
7
+
8
+ # Copy cypress files and tasks into place
9
+ cypress_tasks = File.read(in_templates_dir("cypress_tasks"))
10
+
11
+ copy_file in_templates_dir("cypress.json"), "cypress.json"
12
+ inject_into_file("Rakefile", "\n#{cypress_tasks}")
13
+ directory in_templates_dir("cypress_dir"), "cypress"
@@ -2,7 +2,7 @@
2
2
 
3
3
  # rubocop:disable all
4
4
 
5
- say_status :minitesting, "Adding test gems, package.json scripts, and examples"
5
+ say_status :minitesting, "Adding test gems and examples"
6
6
 
7
7
  append_to_file "Gemfile" do
8
8
  <<~GEMS
@@ -18,12 +18,6 @@ append_to_file "Gemfile" do
18
18
  GEMS
19
19
  end
20
20
 
21
- new_scripts = ' "test": "BRIDGETOWN_ENV=test yarn build",'
22
- new_scripts += "\n" + ' "deploy:test": "bundle install --with test && yarn deploy"'
23
- package_json = "package.json"
24
- script_regex = %r{"scripts": \{(\s+".*,?)*}
25
- inject_into_file(package_json, ",\n" + new_scripts, after: script_regex)
26
-
27
21
  create_file "test/helper.rb" do
28
22
  <<~RUBY
29
23
  require "nokogiri"
@@ -32,23 +26,29 @@ create_file "test/helper.rb" do
32
26
  require "minitest/profile"
33
27
  require "shoulda"
34
28
  require "rails-dom-testing"
29
+
35
30
  # Report with color.
36
31
  Minitest::Reporters.use! [
37
32
  Minitest::Reporters::DefaultReporter.new(
38
33
  color: true
39
34
  ),
40
35
  ]
36
+
41
37
  Minitest::Test.class_eval do
42
38
  include Rails::Dom::Testing::Assertions
39
+
43
40
  def site
44
41
  @site ||= Bridgetown.sites.first
45
42
  end
43
+
46
44
  def nokogiri(input)
47
45
  input.respond_to?(:output) ? Nokogiri::HTML(input.output) : Nokogiri::HTML(input)
48
46
  end
47
+
49
48
  def document_root(root)
50
49
  @document_root = root.is_a?(Nokogiri::XML::Document) ? root : nokogiri(root)
51
50
  end
51
+
52
52
  def document_root_element
53
53
  if @document_root.nil?
54
54
  raise "Call `document_root' with a Nokogiri document before testing your assertions"
@@ -62,12 +62,14 @@ end
62
62
  create_file "test/test_homepage.rb" do
63
63
  <<~RUBY
64
64
  require_relative "./helper"
65
+
65
66
  class TestHomepage < Minitest::Test
66
67
  context "homepage" do
67
68
  setup do
68
69
  page = site.collections.pages.resources.find { |doc| doc.relative_url == "/" }
69
70
  document_root page
70
71
  end
72
+
71
73
  should "exist" do
72
74
  assert_select "body"
73
75
  end
@@ -78,18 +80,20 @@ end
78
80
 
79
81
  create_file "plugins/test_output.rb" do
80
82
  <<~RUBY
81
- unless Bridgetown.environment == "development"
82
- Bridgetown::Hooks.register :site, :post_write do
83
- # Load test suite to run on exit
84
- require "nokogiri"
85
- Dir["test/**/*.rb"].each { |file| require_relative("../\#{file}") }
86
- rescue LoadError
87
- Bridgetown.logger.warn "Testing:", "To run tests, you must first run \`bundle install --with test\`"
83
+ module TestOutput
84
+ unless Bridgetown.env.development?
85
+ Bridgetown::Hooks.register :site, :post_write do
86
+ # Load test suite to run on exit
87
+ require "nokogiri"
88
+ Dir["test/**/*.rb"].each { |file| require_relative("../\#{file}") }
89
+ rescue LoadError
90
+ Bridgetown.logger.warn "Testing:", "To run tests, you must first run \`bundle install --with test\`"
91
+ end
88
92
  end
89
93
  end
90
94
  RUBY
91
95
  end
92
96
 
93
- say_status :minitesting, "All set! To get started, look at test/test_homepage.rb and then run \`yarn test\`"
97
+ say_status :minitesting, "All set! To get started, look at test/test_homepage.rb and then run \`bin/bridgetown test\`"
94
98
 
95
99
  # rubocop:enable all
@@ -1,5 +1,5 @@
1
1
  [build]
2
- command = "yarn deploy && ./bin/netlify.sh"
2
+ command = "bin/bridgetown deploy && bin/netlify.sh"
3
3
  publish = "output"
4
4
 
5
5
  [build.environment]
@@ -41,4 +41,4 @@
41
41
  [[headers]]
42
42
  for = "/*.(png|jpg|js|css|svg|woff|ttf|eot|ico|woff2)"
43
43
  [headers.values]
44
- Cache-Control = "public, max-age=31536000, s-max-age=31536000"
44
+ Cache-Control = "public, max-age=31536000, s-max-age=31536000"
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- TEMPLATE_PATH = File.expand_path("./netlify", __dir__)
4
-
5
- copy_file "#{TEMPLATE_PATH}/netlify.toml", "netlify.toml"
6
- copy_file "#{TEMPLATE_PATH}/netlify.sh", "bin/netlify.sh"
3
+ copy_file in_templates_dir("netlify.toml"), "netlify.toml"
4
+ copy_file in_templates_dir("netlify.sh"), "bin/netlify.sh"
7
5
  `chmod a+x ./bin/netlify.sh`
@@ -6,9 +6,9 @@ say_status :purgecss, "Installing PurgeCSS"
6
6
 
7
7
  run "yarn add -D purgecss"
8
8
 
9
- create_builder "purgecss_builder.rb" do
9
+ create_builder "purgecss.rb" do
10
10
  <<~RUBY
11
- class PurgeCSS < SiteBuilder
11
+ class Builders::Purgecss < SiteBuilder
12
12
  def build
13
13
  unless config[:watch] # don't run in "watch mode"
14
14
  hook :site, :post_write do
@@ -0,0 +1,26 @@
1
+ services:
2
+ - type: web
3
+ name: <%= @render_service_name %>
4
+ env: static
5
+ buildCommand: bin/bridgetown deploy
6
+ staticPublishPath: ./output
7
+ pullRequestPreviewsEnabled: true
8
+ headers:
9
+ - path: /*
10
+ name: X-Frame-Options
11
+ value: DENY
12
+ - path: /*
13
+ name: X-XSS-Protection
14
+ value: "1; mode=block"
15
+ - path: /*
16
+ name: X-Content-Type-Options
17
+ value: "nosniff"
18
+ - path: /*
19
+ name: Strict-Transport-Security
20
+ value: "max-age=15552000; includeSubDomains"
21
+ - path: /*
22
+ name: Referrer-Policy
23
+ value: "no-referrer-when-downgrade"
24
+ - path: /*
25
+ name: Cache-Control
26
+ value: "public, max-age=86400, s-max-age=86400"
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ @render_service_name = ask "What would like to call your Render service?"
4
+ template in_templates_dir("render.yaml.erb"), "render.yaml"
5
+
6
+ say "All done. Just create a new blueprint from the Render dashboard and connect this repo."
@@ -2,8 +2,6 @@
2
2
 
3
3
  # rubocop:disable all
4
4
 
5
- TEMPLATE_PATH = File.expand_path("./tailwindcss", __dir__)
6
-
7
5
  unless File.exist?("postcss.config.js")
8
6
  error_message = "#{"postcss.config.js".bold} not found. Please configure postcss in your project."
9
7
 
@@ -19,16 +17,16 @@ return unless confirm.casecmp?("Y")
19
17
  run "yarn add -D tailwindcss"
20
18
  run "npx tailwindcss init"
21
19
 
22
- copy_file "#{TEMPLATE_PATH}/postcss.config.js", "postcss.config.js", force: true
20
+ copy_file in_templates_dir("postcss.config.js"), "postcss.config.js", force: true
23
21
 
24
22
  run "bundle exec bridgetown configure purgecss"
25
23
 
26
24
  if File.exist?("frontend/styles/index.css")
27
25
  prepend_to_file "frontend/styles/index.css",
28
- File.read("#{TEMPLATE_PATH}/css_imports.css")
26
+ File.read(in_templates_dir("css_imports.css"))
29
27
  else
30
28
  say "\nPlease add the following lines to your CSS index file:"
31
- say File.read("#{TEMPLATE_PATH}/css_imports.css")
29
+ say File.read(in_templates_dir("/css_imports.css"))
32
30
  end
33
31
 
34
32
  # rubocop:enable all
@@ -23,7 +23,7 @@ module Kramdown
23
23
  @options ||= Options.merge(options).freeze
24
24
  @parser ||= begin
25
25
  parser_name = (@options[:input] || "kramdown").to_s
26
- parser_name = parser_name[0..0].upcase + parser_name[1..-1]
26
+ parser_name = parser_name[0..0].upcase + parser_name[1..]
27
27
  try_require("parser", parser_name)
28
28
 
29
29
  if Parser.const_defined?(parser_name)
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "serbea"
4
+ require "rouge/lexers/serbea"
5
+
6
+ module Bridgetown
7
+ class SerbeaView < ERBView
8
+ include Serbea::Helpers
9
+
10
+ def partial(partial_name, options = {}, &block)
11
+ options.merge!(options[:locals]) if options[:locals]
12
+ options[:content] = capture(&block) if block
13
+
14
+ partial_segments = partial_name.split("/")
15
+ partial_segments.last.sub!(%r!^!, "_")
16
+ partial_name = partial_segments.join("/")
17
+
18
+ Tilt::SerbeaTemplate.new(
19
+ site.in_source_dir(site.config[:partials_dir], "#{partial_name}.serb")
20
+ ).render(self, options)
21
+ end
22
+ end
23
+
24
+ module Converters
25
+ class SerbeaTemplates < Converter
26
+ priority :highest
27
+ input :serb
28
+
29
+ # Logic to do the Serbea content conversion.
30
+ #
31
+ # @param content [String] Content of the file (without front matter).
32
+ # @param convertible [
33
+ # Bridgetown::GeneratedPage, Bridgetown::Resource::Base, Bridgetown::Layout]
34
+ # The instantiated object which is processing the file.
35
+ #
36
+ # @return [String] The converted content.
37
+ def convert(content, convertible)
38
+ return content if convertible.data[:template_engine].to_s != "serbea"
39
+
40
+ serb_view = Bridgetown::SerbeaView.new(convertible)
41
+
42
+ serb_renderer = Tilt::SerbeaTemplate.new(convertible.relative_path) { content }
43
+
44
+ if convertible.is_a?(Bridgetown::Layout)
45
+ serb_renderer.render(serb_view) do
46
+ convertible.current_document_output
47
+ end
48
+ else
49
+ serb_renderer.render(serb_view)
50
+ end
51
+ end
52
+
53
+ def matches(ext, convertible)
54
+ if convertible.data[:template_engine].to_s == "serbea" ||
55
+ (convertible.data[:template_engine].nil? &&
56
+ @config[:template_engine].to_s == "serbea")
57
+ convertible.data[:template_engine] = "serbea"
58
+ return true
59
+ end
60
+
61
+ super(ext).tap do |ext_matches|
62
+ convertible.data[:template_engine] = "serbea" if ext_matches
63
+ end
64
+ end
65
+
66
+ def output_ext(ext)
67
+ ext == ".serb" ? ".html" : ext
68
+ end
69
+ end
70
+ end
71
+ end
@@ -6,11 +6,7 @@ module Bridgetown
6
6
  module SafeLoadFile
7
7
  def safe_load_file(filename, **kwargs)
8
8
  File.open(filename, "r:bom|utf-8") do |f|
9
- if RUBY_VERSION.start_with?("2.5")
10
- safe_load f, kwargs[:permitted_classes], [], false, filename
11
- else
12
- safe_load f, filename: filename, **kwargs
13
- end
9
+ safe_load f, filename: filename, **kwargs
14
10
  end
15
11
  end
16
12
  end
@@ -181,7 +181,7 @@ module Bridgetown
181
181
  sets = site.config["defaults"]
182
182
  return [] unless sets.is_a?(Array)
183
183
 
184
- sets.map do |set|
184
+ sets.filter_map do |set|
185
185
  if valid?(set)
186
186
  massage_scope!(set)
187
187
  # TODO: is this trip really necessary?
@@ -191,7 +191,7 @@ module Bridgetown
191
191
  Bridgetown.logger.warn set.to_s
192
192
  nil
193
193
  end
194
- end.compact
194
+ end
195
195
  end
196
196
 
197
197
  # Set path to blank if not specified and alias older type to collection
@@ -31,9 +31,7 @@ module Bridgetown
31
31
  raise Liquid::FileSystemError, "No such template '#{template_path}'" if found_paths.empty?
32
32
 
33
33
  # Last path in the list wins
34
- LiquidComponent.parse(
35
- ::File.read(found_paths.last, **site.file_read_opts)
36
- ).content
34
+ ::File.read(found_paths.last, **site.file_read_opts)
37
35
  end
38
36
  end
39
37
  end
@@ -15,7 +15,7 @@ module Bridgetown
15
15
 
16
16
  # Set up Liquid file system access to components for the Render tag
17
17
  Liquid::Template.file_system = LiquidRenderer::FileSystem.new(
18
- @site.components_load_paths, "%s.liquid"
18
+ @site.config.components_load_paths, "%s.liquid"
19
19
  )
20
20
  Liquid::Template.file_system.site = site
21
21
 
@@ -9,40 +9,37 @@ module Bridgetown
9
9
  extend ActiveModel::Callbacks # also extends with DescendantsTracker
10
10
  define_model_callbacks :load, :save, :destroy
11
11
 
12
- def self.loads_id?(id)
13
- name == ActiveSupport::Inflector.classify(
14
- URI.parse(id).host.chomp(".collection")
15
- )
16
- end
12
+ class << self
13
+ def find(id)
14
+ unless Bridgetown::Current.site
15
+ raise "A Bridgetown site must be initialized and added to Current"
16
+ end
17
17
 
18
- def self.find(id)
19
- unless Bridgetown::Current.site
20
- raise "A Bridgetown site must be initialized and added to Current"
18
+ origin = origin_for_id(id)
19
+ klass_for_id(id, origin: origin).new(origin.read)
21
20
  end
22
21
 
23
- model_klass = klass_for_id(id)
24
- model_klass.new(read_data_for_id(id))
25
- end
26
-
27
- def self.klass_for_id(id)
28
- descendants.find do |klass|
29
- klass.loads_id?(id)
30
- end || self
31
- end
22
+ def origin_for_id(id)
23
+ scheme = URI.parse(id).scheme
24
+ origin_klass = Origin.descendants.find do |klass|
25
+ klass.handle_scheme?(scheme)
26
+ end
32
27
 
33
- def self.read_data_for_id(id)
34
- origin_for_id(id).read
35
- end
28
+ raise "No origin could be found for #{id}" unless origin_klass
36
29
 
37
- def self.origin_for_id(id)
38
- scheme = URI.parse(id).scheme
39
- origin_klass = Origin.descendants.find do |klass|
40
- klass.handle_scheme?(scheme)
30
+ origin_klass.new(id)
41
31
  end
42
32
 
43
- raise "No origin could be found for #{id}" unless origin_klass
33
+ def klass_for_id(id, origin: nil)
34
+ Bridgetown::Model::Base.descendants.find do |klass|
35
+ klass.will_load_id?(id, origin: origin)
36
+ end || Bridgetown::Model::Base
37
+ end
44
38
 
45
- origin_klass.new(id)
39
+ def will_load_id?(id, origin: nil)
40
+ origin ||= origin_for_id(id)
41
+ origin.verify_model?(self)
42
+ end
46
43
  end
47
44
 
48
45
  class << self
@@ -6,12 +6,14 @@ module Bridgetown
6
6
  # @return [Pathname]
7
7
  attr_reader :relative_path
8
8
 
9
- def self.handle_scheme?(scheme)
10
- scheme == "builder"
11
- end
12
-
13
- def self.id_for_builder_path(builder, path)
14
- "builder://#{builder.class.name.gsub("::", ".")}/#{path}"
9
+ class << self
10
+ def handle_scheme?(scheme)
11
+ scheme == "builder"
12
+ end
13
+
14
+ def id_for_builder_path(builder, path)
15
+ "builder://#{builder.class.name.gsub("::", ".")}/#{path}"
16
+ end
15
17
  end
16
18
 
17
19
  def initialize(id)
@@ -11,7 +11,7 @@ module Bridgetown
11
11
  # @return [String]
12
12
  attr_accessor :id
13
13
 
14
- # Override in subclass
14
+ # You must implement in subclasses
15
15
  def self.handle_scheme?(_scheme)
16
16
  false
17
17
  end
@@ -20,6 +20,15 @@ module Bridgetown
20
20
  self.id = id
21
21
  end
22
22
 
23
+ # You can override in subclass
24
+ def verify_model?(klass)
25
+ collection_name = URI.parse(id).host.chomp(".collection")
26
+
27
+ return klass.collection_name.to_s == collection_name if klass.respond_to?(:collection_name)
28
+
29
+ klass.name == ActiveSupport::Inflector.classify(collection_name)
30
+ end
31
+
23
32
  def read
24
33
  raise "Implement #read in a subclass of Bridgetown::Model::Origin"
25
34
  end
@@ -22,7 +22,7 @@ module Bridgetown
22
22
 
23
23
  def relative_path
24
24
  @relative_path ||= Pathname.new(
25
- Addressable::URI.unescape(url.path.delete_prefix("/")).split("/")[1..-1].join("/")
25
+ Addressable::URI.unescape(url.path.delete_prefix("/")).split("/")[1..].join("/")
26
26
  )
27
27
  end
28
28
 
@@ -5,7 +5,7 @@ module Bridgetown
5
5
  PLUGINS_GROUP = :bridgetown_plugins
6
6
  YARN_DEPENDENCY_REGEXP = %r!(.+)@([^@]*)$!.freeze
7
7
 
8
- attr_reader :site, :component_loaders
8
+ attr_reader :site, :loaders_manager
9
9
 
10
10
  @source_manifests = Set.new
11
11
  @registered_plugins = Set.new
@@ -18,8 +18,8 @@ module Bridgetown
18
18
  @source_manifests << source_manifest
19
19
  end
20
20
 
21
- def self.new_source_manifest(*args)
22
- add_source_manifest(Bridgetown::Plugin::SourceManifest.new(*args))
21
+ def self.new_source_manifest(*args, **kwargs)
22
+ add_source_manifest(Bridgetown::Plugin::SourceManifest.new(*args, **kwargs))
23
23
  end
24
24
 
25
25
  def self.add_registered_plugin(gem_or_plugin_file)
@@ -37,15 +37,14 @@ module Bridgetown
37
37
  # Returns nothing
38
38
  def initialize(site)
39
39
  @site = site
40
- @component_loaders = {}
40
+ @loaders_manager = Bridgetown::Utils::LoadersManager.new(site.config)
41
41
  end
42
42
 
43
43
  def self.require_from_bundler
44
44
  if !ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile")
45
45
  require "bundler"
46
46
 
47
- required_gems = Bundler.require PLUGINS_GROUP
48
- required_gems.select! do |dep|
47
+ required_gems = Bundler.require(PLUGINS_GROUP).select do |dep|
49
48
  (dep.groups & [PLUGINS_GROUP]).any? && dep.should_include?
50
49
  end
51
50
 
@@ -133,12 +132,16 @@ module Bridgetown
133
132
  sorted_plugin_files.each do |plugin_file|
134
133
  self.class.add_registered_plugin plugin_file
135
134
  end
135
+ next if site.config[:plugins_use_zeitwerk]
136
+
136
137
  Bridgetown::Utils::RequireGems.require_with_graceful_fail(sorted_plugin_files)
137
138
  end
138
139
  end
139
140
 
140
141
  # Reload .rb plugin files via the watcher
141
142
  def reload_plugin_files
143
+ return if site.config[:plugins_use_zeitwerk]
144
+
142
145
  plugins_path.each do |plugin_search_path|
143
146
  plugin_files = Utils.safe_glob(plugin_search_path, File.join("**", "*.rb"))
144
147
  Array(plugin_files).each do |name|
@@ -159,35 +162,5 @@ module Bridgetown
159
162
  Array(site.config["plugins_dir"]).map { |d| File.expand_path(d) }
160
163
  end
161
164
  end
162
-
163
- def setup_component_loaders
164
- unless @component_loaders.keys.empty?
165
- @component_loaders.each do |_path, loader|
166
- loader.unload
167
- end
168
- @component_loaders = {}
169
- end
170
-
171
- # Because "first constant wins" in Zeitwerk, we need to load the local
172
- # source components _before_ we load any from plugins
173
- site.components_load_paths.reverse_each do |load_path|
174
- next unless Dir.exist? load_path
175
-
176
- begin
177
- @component_loaders[load_path] = Zeitwerk::Loader.new
178
- @component_loaders[load_path].push_dir(load_path)
179
- @component_loaders[load_path].enable_reloading if load_path.start_with?(site.root_dir)
180
- @component_loaders[load_path].ignore(File.join(load_path, "**", "*.js.rb"))
181
- @component_loaders[load_path].setup
182
- rescue Zeitwerk::Error # rubocop:disable Lint/SuppressedException
183
- end
184
- end
185
- end
186
-
187
- def reload_component_loaders
188
- @component_loaders.each do |path, loader|
189
- loader.reload if path.start_with?(site.root_dir)
190
- end
191
- end
192
165
  end
193
166
  end