bridgetown-core 2.0.5 → 2.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -2
  3. data/bin/bridgetown +19 -7
  4. data/bridgetown-core.gemspec +8 -6
  5. data/lib/bridgetown-core/collection.rb +4 -3
  6. data/lib/bridgetown-core/command.rb +97 -0
  7. data/lib/bridgetown-core/commands/application.rb +208 -0
  8. data/lib/bridgetown-core/commands/apply.rb +17 -29
  9. data/lib/bridgetown-core/commands/build.rb +9 -16
  10. data/lib/bridgetown-core/commands/clean.rb +7 -10
  11. data/lib/bridgetown-core/commands/concerns/{actions.rb → automations.rb} +103 -17
  12. data/lib/bridgetown-core/commands/concerns/build_options.rb +24 -60
  13. data/lib/bridgetown-core/commands/concerns/configuration_overridable.rb +2 -4
  14. data/lib/bridgetown-core/commands/configure.rb +24 -24
  15. data/lib/bridgetown-core/commands/console.rb +38 -34
  16. data/lib/bridgetown-core/commands/esbuild.rb +14 -24
  17. data/lib/bridgetown-core/commands/help.rb +24 -0
  18. data/lib/bridgetown-core/commands/new.rb +38 -60
  19. data/lib/bridgetown-core/commands/plugins.rb +237 -211
  20. data/lib/bridgetown-core/commands/registrations.rb +10 -1
  21. data/lib/bridgetown-core/commands/start.rb +23 -31
  22. data/lib/bridgetown-core/commands/thor_shim.rb +94 -0
  23. data/lib/bridgetown-core/component.rb +3 -3
  24. data/lib/bridgetown-core/concerns/publishable.rb +1 -3
  25. data/lib/bridgetown-core/concerns/site/localizable.rb +2 -0
  26. data/lib/bridgetown-core/configuration/configuration_dsl.rb +2 -2
  27. data/lib/bridgetown-core/configuration.rb +27 -7
  28. data/lib/bridgetown-core/converters/erb_templates.rb +31 -21
  29. data/lib/bridgetown-core/converters/ruby_templates.rb +14 -13
  30. data/lib/bridgetown-core/converters/serbea_templates.rb +5 -2
  31. data/lib/bridgetown-core/entry_filter.rb +1 -4
  32. data/lib/bridgetown-core/front_matter/defaults.rb +1 -1
  33. data/lib/bridgetown-core/front_matter/importer.rb +7 -1
  34. data/lib/bridgetown-core/front_matter/loaders.rb +1 -1
  35. data/lib/bridgetown-core/front_matter/ruby.rb +3 -9
  36. data/lib/bridgetown-core/generated_page.rb +2 -2
  37. data/lib/bridgetown-core/generators/prototype_generator.rb +1 -1
  38. data/lib/bridgetown-core/helpers.rb +10 -11
  39. data/lib/bridgetown-core/hooks.rb +2 -3
  40. data/lib/bridgetown-core/locale/en.yml +30 -0
  41. data/lib/bridgetown-core/model/base.rb +5 -5
  42. data/lib/bridgetown-core/model/builder_origin.rb +1 -1
  43. data/lib/bridgetown-core/model/origin.rb +5 -1
  44. data/lib/bridgetown-core/model/plugin_origin.rb +3 -1
  45. data/lib/bridgetown-core/model/repo_origin.rb +3 -1
  46. data/lib/bridgetown-core/rack/routes.rb +1 -1
  47. data/lib/bridgetown-core/reader.rb +2 -2
  48. data/lib/bridgetown-core/readers/plugin_content_reader.rb +31 -7
  49. data/lib/bridgetown-core/resource/base.rb +16 -7
  50. data/lib/bridgetown-core/resource/destination.rb +1 -1
  51. data/lib/bridgetown-core/resource/permalink_processor.rb +4 -4
  52. data/lib/bridgetown-core/static_file.rb +1 -1
  53. data/lib/bridgetown-core/tags/class_map.rb +0 -2
  54. data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +8 -11
  55. data/lib/bridgetown-core/{ruby_template_view.rb → template_view.rb} +108 -4
  56. data/lib/bridgetown-core/utils/initializers.rb +28 -1
  57. data/lib/bridgetown-core/utils/loaders_manager.rb +2 -1
  58. data/lib/bridgetown-core/utils.rb +19 -1
  59. data/lib/bridgetown-core/watcher.rb +16 -8
  60. data/lib/bridgetown-core.rb +5 -10
  61. data/lib/roda/plugins/bridgetown_server.rb +1 -1
  62. data/lib/site_template/README.md +10 -8
  63. metadata +84 -70
  64. data/lib/bridgetown-core/commands/base.rb +0 -123
  65. data/lib/bridgetown-core/commands/concerns/summarizable.rb +0 -13
  66. data/lib/bridgetown-core/configurations/.keep +0 -0
  67. data/lib/bridgetown-core/configurations/stimulus.rb +0 -59
  68. data/lib/bridgetown-core/configurations/turbo/turbo_transitions.js +0 -48
  69. data/lib/bridgetown-core/configurations/turbo.rb +0 -35
  70. data/lib/bridgetown-core/configurations/vercel/vercel.json +0 -45
  71. data/lib/bridgetown-core/configurations/vercel/vercel_url.rb +0 -12
  72. data/lib/bridgetown-core/configurations/vercel.rb +0 -4
  73. data/lib/bridgetown-core/inflector.rb +0 -40
@@ -27,7 +27,9 @@ module Bridgetown
27
27
  end
28
28
 
29
29
  def original_path
30
- @original_path ||= relative_path.expand_path(manifest.content)
30
+ @original_path ||= relative_path.expand_path(
31
+ manifest.dig(:contents, collection.label.to_sym)
32
+ )
31
33
  end
32
34
  end
33
35
  end
@@ -36,7 +36,9 @@ module Bridgetown
36
36
 
37
37
  def read
38
38
  begin
39
- @data = (in_data_collection? ? read_file_data : read_front_matter(original_path)) || {}
39
+ @data = (
40
+ in_data_collection? ? read_file_data : read_front_matter(original_path, bare_text:)
41
+ ) || {}
40
42
  rescue SyntaxError => e
41
43
  Bridgetown.logger.error "Error:",
42
44
  "Ruby Exception in #{e.message}"
@@ -29,7 +29,7 @@ module Bridgetown
29
29
  puts
30
30
  puts "Routes:"
31
31
  puts "=======\n"
32
- if routes.blank?
32
+ if routes.empty?
33
33
  puts "No routes found. Have you commented all of your routes?"
34
34
  puts "Documentation: https://github.com/jeremyevans/roda-route_list#basic-usage-"
35
35
  end
@@ -20,7 +20,7 @@ module Bridgetown
20
20
  read_includes
21
21
  sort_files!
22
22
  read_collections
23
- site.config.source_manifests.select(&:content).each do |manifest|
23
+ site.config.source_manifests.each do |manifest|
24
24
  PluginContentReader.new(site, manifest).read
25
25
  end
26
26
  end
@@ -66,7 +66,7 @@ module Bridgetown
66
66
 
67
67
  entries = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
68
68
  entries.each do |entry|
69
- file_path = @site.in_source_dir(base, entry)
69
+ file_path = site.in_source_dir(base, entry)
70
70
  if File.directory?(file_path)
71
71
  entries_dirs << entry
72
72
  elsif FrontMatter::Loaders.front_matter?(file_path)
@@ -2,37 +2,61 @@
2
2
 
3
3
  module Bridgetown
4
4
  class PluginContentReader
5
- attr_reader :site, :manifest, :content_dir
5
+ attr_reader :site, :manifest, :content_dirs
6
6
 
7
7
  # @param site [Bridgetown::Site]
8
8
  # @param manifest [Bridgetown::Plugin::SourceManifest]
9
9
  def initialize(site, manifest)
10
10
  @site = site
11
11
  @manifest = manifest
12
- @content_dir = manifest.content
12
+ @content_dirs = manifest.contents
13
13
  @content_files = Set.new
14
+ @supports_bare_text = manifest.bare_text
15
+ @bare_text_extensions = site.config.markdown_ext.split(",").map { ".#{_1}" } + [".html"]
14
16
  end
15
17
 
16
18
  def read
17
- return unless content_dir
19
+ return if content_dirs.empty?
20
+
21
+ content_dirs.each do |collection_name, root|
22
+ read_content_root collection_name, root
23
+ end
24
+ end
25
+
26
+ def read_content_root(collection_name, content_dir)
27
+ collection = site.collections[collection_name]
28
+ unless collection
29
+ Bridgetown.logger.warn(
30
+ "Reading",
31
+ "Plugin requested missing collection #{collection_name}, cannot continue"
32
+ )
33
+ return
34
+ end
18
35
 
19
36
  Find.find(content_dir) do |path|
20
- next if File.directory?(path)
37
+ if File.directory?(path)
38
+ Find.prune if EntryFilter::SPECIAL_LEADING_CHAR_REGEX.match?(File.basename(path))
39
+ next
40
+ end
21
41
 
22
42
  if File.symlink?(path)
23
43
  Bridgetown.logger.warn "Plugin content reader:", "Ignored symlinked asset: #{path}"
24
44
  else
25
- read_content_file(path)
45
+ read_content_file(content_dir, path, collection)
26
46
  end
27
47
  end
28
48
  end
29
49
 
30
- def read_content_file(path)
50
+ # @param collection [Bridgetown::Collection]
51
+ def read_content_file(content_dir, path, collection)
31
52
  dir = File.dirname(path.sub("#{content_dir}/", ""))
32
53
  name = File.basename(path)
54
+ extname = File.extname(path)
33
55
 
34
56
  @content_files << if FrontMatter::Loaders.front_matter?(path)
35
- site.collections.pages.read_resource(path, manifest:)
57
+ collection.read_resource(path, manifest:)
58
+ elsif @supports_bare_text && @bare_text_extensions.any? { extname == _1 }
59
+ collection.read_resource(path, manifest:, bare_text: true)
36
60
  else
37
61
  Bridgetown::StaticFile.new(site, content_dir, "/#{dir}", name)
38
62
  end
@@ -19,6 +19,9 @@ module Bridgetown
19
19
  # @return [Bridgetown::Site]
20
20
  attr_reader :site
21
21
 
22
+ # @return [Roda]
23
+ attr_accessor :roda_app
24
+
22
25
  # @return [Array<Bridgetown::Slot>]
23
26
  attr_reader :slots
24
27
 
@@ -170,9 +173,9 @@ module Bridgetown
170
173
  # @return [String]
171
174
  def call(*) = transform!.output
172
175
 
173
- def trigger_hooks(hook_name, *args)
174
- Bridgetown::Hooks.trigger collection.label.to_sym, hook_name, self, *args if collection
175
- Bridgetown::Hooks.trigger :resources, hook_name, self, *args
176
+ def trigger_hooks(hook_name, *)
177
+ Bridgetown::Hooks.trigger(collection.label.to_sym, hook_name, self, *) if collection
178
+ Bridgetown::Hooks.trigger(:resources, hook_name, self, *)
176
179
  end
177
180
 
178
181
  def around_hook(hook_suffix)
@@ -319,8 +322,8 @@ module Bridgetown
319
322
  def <=>(other) # rubocop:todo Metrics/AbcSize
320
323
  return nil unless other.respond_to?(:data)
321
324
 
322
- cmp = if data.date.respond_to?(:to_datetime) && other.data.date.respond_to?(:to_datetime)
323
- data.date.to_datetime <=> other.data.date.to_datetime
325
+ cmp = if data.date.respond_to?(:to_time) && other.data.date.respond_to?(:to_time)
326
+ data.date.to_time <=> other.data.date.to_time
324
327
  end
325
328
 
326
329
  cmp = data["date"] <=> other.data["date"] if cmp.nil?
@@ -387,6 +390,7 @@ module Bridgetown
387
390
  def ensure_default_data
388
391
  determine_locale
389
392
  merge_requested_site_data
393
+ normalize_date_as_time
390
394
 
391
395
  slug = if matches = relative_path.to_s.match(DATE_FILENAME_MATCHER) # rubocop:disable Lint/AssignmentInCondition
392
396
  set_date_from_string(matches[1]) unless data.date
@@ -412,6 +416,11 @@ module Bridgetown
412
416
  end
413
417
  end
414
418
 
419
+ def normalize_date_as_time
420
+ data_date = data.date
421
+ data.date = data_date.to_time if data_date.is_a?(Date)
422
+ end
423
+
415
424
  def set_date_from_string(new_date) # rubocop:disable Naming/AccessorMethodName
416
425
  return unless new_date.is_a?(String)
417
426
 
@@ -441,9 +450,9 @@ module Bridgetown
441
450
  end
442
451
  end
443
452
 
444
- def determine_locale # rubocop:todo Metrics/AbcSize
453
+ def determine_locale
445
454
  unless data.locale
446
- data.locale = locale_from_alt_data_or_filename.presence || site.config.default_locale
455
+ data.locale = locale_from_alt_data_or_filename || site.config.default_locale
447
456
  end
448
457
 
449
458
  return unless data.locale_overrides.is_a?(Hash) && data.locale_overrides&.key?(data.locale)
@@ -33,7 +33,7 @@ module Bridgetown
33
33
 
34
34
  def output_path
35
35
  path = Utils.unencode_uri(relative_url)
36
- if resource.site.base_path.present?
36
+ unless resource.site.base_path.empty?
37
37
  path = path.delete_prefix resource.site.base_path(strip_slash_only: true)
38
38
  end
39
39
  path = resource.site.in_dest_dir(path)
@@ -33,9 +33,9 @@ module Bridgetown
33
33
  # Strip out file extension and process each segment of a URL to swap out
34
34
  # placeholders such as :categories or :title
35
35
  url_segments = Bridgetown::Filters::URLFilters.strip_extname(permalink).split("/")
36
- new_url = url_segments.map do |segment|
36
+ new_url = url_segments.filter_map do |segment|
37
37
  segment.starts_with?(":") ? process_segment(segment.sub(%r{^:}, "")) : segment
38
- end.select(&:present?).join("/")
38
+ end.reject(&:empty?).join("/")
39
39
  # No relative URLs should ever end in /index.html
40
40
  new_url.sub!(%r{/index$}, "") if final_ext == ".html"
41
41
 
@@ -97,7 +97,7 @@ module Bridgetown
97
97
  end
98
98
 
99
99
  def ensure_base_path(permalink)
100
- if resource.site.base_path.present?
100
+ unless resource.site.base_path.empty?
101
101
  return "#{resource.site.base_path(strip_slash_only: true)}#{permalink}"
102
102
  end
103
103
 
@@ -110,7 +110,7 @@ module Bridgetown
110
110
  register_placeholder :path, ->(resource) do
111
111
  {
112
112
  raw_value: resource.relative_path_basename_without_prefix.tap do |path|
113
- if resource.site.config["collections_dir"].present?
113
+ if resource.site.config["collections_dir"].length.positive?
114
114
  path.delete_prefix! "#{resource.site.config["collections_dir"]}/"
115
115
  end
116
116
 
@@ -55,7 +55,7 @@ module Bridgetown
55
55
  def destination(dest)
56
56
  dest = site.in_dest_dir(dest)
57
57
  dest_url = url
58
- if site.base_path.present? && collection
58
+ if site.base_path.length.positive? && collection
59
59
  dest_url = dest_url.delete_prefix site.base_path(strip_slash_only: true)
60
60
  end
61
61
  site.in_dest_dir(dest, Bridgetown::Utils.unencode_uri(dest_url))
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
-
5
3
  module Bridgetown
6
4
  module Tags
7
5
  # A ClassMap class is meant to take a hash and append styles based on if the
@@ -37,14 +37,11 @@ namespace :roda do
37
37
  end
38
38
 
39
39
  desc "Prerequisite task which loads site and provides automation"
40
- task :environment do # rubocop:todo Metrics/BlockLength
41
- class HammerActions < Thor # rubocop:disable Lint/ConstantDefinitionInBlock
42
- include Thor::Actions
43
- include Bridgetown::Commands::Actions
40
+ task :environment do
41
+ require "freyia"
44
42
 
45
- def self.source_root
46
- Dir.pwd
47
- end
43
+ class Hamr < Freyia::Base # rubocop:disable Lint/ConstantDefinitionInBlock
44
+ include Bridgetown::Commands::Automations
48
45
 
49
46
  def self.exit_on_failure?
50
47
  true
@@ -62,14 +59,14 @@ task :environment do # rubocop:todo Metrics/BlockLength
62
59
  end
63
60
 
64
61
  define_singleton_method :automation do |*args, &block|
65
- @hammer ||= HammerActions.new
66
- @hammer.instance_exec(*args, &block)
62
+ @hamr ||= Hamr.new(source: Dir.pwd, dest: Dir.pwd)
63
+ @hamr.instance_exec(*args, &block)
67
64
  end
68
65
 
69
66
  %i(site run_initializers).each do |meth|
70
67
  define_singleton_method meth do |**kwargs|
71
- @hammer ||= HammerActions.new
72
- @hammer.send(:site, **kwargs)
68
+ @hamr ||= Hamr.new(source: Dir.pwd, dest: Dir.pwd)
69
+ @hamr.send(:site, **kwargs)
73
70
  end
74
71
  end
75
72
  end
@@ -19,7 +19,8 @@ module Bridgetown
19
19
  alias_method :macro, :helper
20
20
  end
21
21
 
22
- class RubyTemplateView
22
+ # Holds context for page rendering and is subclassed by various template engines like ERB.
23
+ class TemplateView
23
24
  require "bridgetown-core/helpers"
24
25
 
25
26
  using Bridgetown::Refinements
@@ -28,6 +29,58 @@ module Bridgetown
28
29
  attr_reader :layout, :resource, :paginator, :site, :content
29
30
  alias_method :page, :resource
30
31
 
32
+ class << self
33
+ attr_accessor :extname_list
34
+
35
+ # View renderers can provide one or more extensions they accept. Examples:
36
+ #
37
+ # * `input :erb`
38
+ # * `input %i(rb ruby)`
39
+ #
40
+ # @param extnames [Array<Symbol>] extensions
41
+ def input(extnames)
42
+ extnames = Array(extnames)
43
+ self.extname_list ||= []
44
+ self.extname_list += extnames.map { |e| ".#{e.to_s.downcase}" }
45
+ end
46
+
47
+ # Returns a global "virtual" TemplateView for use in rendering out side of a specific
48
+ # context
49
+ #
50
+ # @return [TemplateView]
51
+ def virtual_view
52
+ # if site object has changed, clear previous state
53
+ @virtual_res = @virtual_view = nil if @virtual_res&.site != Bridgetown::Current.site
54
+
55
+ @virtual_res ||= Bridgetown::Model::Base.build(
56
+ { site: Bridgetown::Current.site }.as_dots, :pages, "VIRTUAL", {}
57
+ ).to_resource.read!
58
+ @virtual_view ||= new(@virtual_res)
59
+ end
60
+
61
+ # Creates a new virtual TemplateView with a "resource" containing the provided data
62
+ #
63
+ # @param virtual_path [String] a fictional "relative URL" for the resource
64
+ # @param **data [Hash] to be passed along to the resource
65
+ # @return [TemplateView]
66
+ def new_with_data(virtual_path = "VIRTUAL", **data)
67
+ res = Bridgetown::Model::Base.build(
68
+ { site: Bridgetown::Current.site }.as_dots, :pages, virtual_path, data
69
+ ).to_resource.read!
70
+
71
+ new(res)
72
+ end
73
+
74
+ # Calls the render method of a global TemplateView which lets you output partials and
75
+ # components outside of a specific rendering context
76
+ #
77
+ # @see {TemplateView#render}
78
+ # @param item [String, Bridgetown::Component]
79
+ # @param **locals [Array] - relevant for partials
80
+ # @return [String]
81
+ def render(...) = virtual_view.render(...)
82
+ end
83
+
31
84
  def initialize(convertible)
32
85
  if convertible.is_a?(Layout)
33
86
  @layout = convertible
@@ -48,14 +101,26 @@ module Bridgetown
48
101
 
49
102
  def site_drop = site.site_payload.site
50
103
 
51
- def partial(_partial_name = nil, **_options) = raise("Must be implemented in a subclass")
104
+ def template_view_classes
105
+ @template_view_classes ||= TemplateView.descendants.each_with_object({}) do |klass, hsh|
106
+ klass.extname_list.each do |ext|
107
+ hsh[ext] = klass
108
+ end
109
+ end
110
+ end
52
111
 
53
- def render(item, **options, &)
112
+ # Renders a partial, or a component object which responds to `render_in`
113
+ #
114
+ # @param item [String, Bridgetown::Component]
115
+ # @param **locals [Array] - relevant for partials
116
+ # @yield optional block which is passed along to the component's `render_in` method
117
+ # @return [String]
118
+ def render(item, **, &)
54
119
  if item.respond_to?(:render_in)
55
120
  result = item.render_in(self, &)
56
121
  result&.html_safe
57
122
  else
58
- partial(item, **options, &)&.html_safe
123
+ partial(item, **, &)&.html_safe
59
124
  end
60
125
  end
61
126
 
@@ -73,6 +138,16 @@ module Bridgetown
73
138
  template.render!(options.as_dots, _liquid_context).html_safe
74
139
  end
75
140
 
141
+ def partial(partial_name = nil, **options, &)
142
+ partial_name = options[:template] if partial_name.nil? && options[:template]
143
+ found_file = _locate_partial(partial_name)
144
+ view_class = _view_class_for_partial(found_file)
145
+
146
+ view_class.new(resource).tap do |view|
147
+ view.resource.roda_app = self.class.virtual_view.resource.roda_app
148
+ end.partial(partial_name, **options, &)
149
+ end
150
+
76
151
  def helpers
77
152
  @helpers ||= Helpers.new(self, site)
78
153
  end
@@ -133,5 +208,34 @@ module Bridgetown
133
208
 
134
209
  site.in_source_dir(site.config[:partials_dir], "#{partial_name}.#{ext}")
135
210
  end
211
+
212
+ def _locate_partial(partial_name)
213
+ found_file = nil
214
+
215
+ # TODO: make this configurable
216
+ %w(erb serb rb slim haml).each do |ext|
217
+ next if found_file
218
+
219
+ path = _partial_path(partial_name, ext)
220
+ found_file = _partial_path_exist?(path) && path
221
+ end
222
+
223
+ raise "No matching partial could be found for #{partial_name}" unless found_file
224
+
225
+ found_file
226
+ end
227
+
228
+ def _partial_path_exist?(path) = site.tmp_cache["partial-tmpl:#{path}"] || File.exist?(path)
229
+
230
+ def _view_class_for_partial(path)
231
+ view_class = template_view_classes[File.extname(path)]
232
+
233
+ raise "No view renderer could be found for #{File.basename(path)}" unless view_class
234
+
235
+ view_class
236
+ end
136
237
  end
238
+
239
+ # TODO: this class alias is deprecated and will be removed in the next major Bridgetown release
240
+ RubyTemplateView = TemplateView
137
241
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Make sure you update REQUIRE_DENYLIST in `Bridgetown::Configuration` for initializers which
4
+ # aren't Gem backed
5
+
3
6
  Bridgetown.initializer :dotenv do |config|
4
7
  Bridgetown.load_dotenv root: config.root_dir
5
8
  end
@@ -10,6 +13,30 @@ Bridgetown.initializer :ssr do |config, setup: nil, **options|
10
13
  end
11
14
  end
12
15
 
16
+ Bridgetown.initializer :external_sources do |config, contents:|
17
+ Bridgetown::ExternalSources = Module.new
18
+
19
+ contents.each do |coll, path|
20
+ contents[coll] = File.expand_path(path, config.root_dir)
21
+ end
22
+
23
+ if config.context == :static
24
+ contents.each_value.with_index do |path, index|
25
+ Bridgetown.logger.info(index.zero? ? "External Sources:" : "", path)
26
+ end
27
+ end
28
+
29
+ config.source_manifest(
30
+ origin: Bridgetown::ExternalSources,
31
+ contents:,
32
+ bare_text: true
33
+ )
34
+
35
+ contents.each_value do |path|
36
+ config.additional_watch_paths << path
37
+ end
38
+ end
39
+
13
40
  Bridgetown.initializer :parse_routes do |config|
14
41
  # This builds upon the work done here:
15
42
  # https://github.com/jeremyevans/roda-route_list/blob/master/bin/roda-parse_routes
@@ -33,7 +60,7 @@ Bridgetown.initializer :parse_routes do |config|
33
60
  file_contents = File.read(route_file)
34
61
  routes = parser.parse(file_contents)
35
62
 
36
- next unless routes.present?
63
+ next if routes.empty?
37
64
 
38
65
  routes.each do |route|
39
66
  route["file"] = route_file
@@ -29,7 +29,8 @@ module Bridgetown
29
29
  end
30
30
 
31
31
  def setup_loaders(autoload_paths = []) # rubocop:todo Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
32
- (autoload_paths.presence || config.autoload_paths).each do |load_path|
32
+ autoload_paths = config.autoload_paths if autoload_paths.empty?
33
+ autoload_paths.each do |load_path|
33
34
  if @loaders.key?(load_path)
34
35
  raise "Zeitwerk loader already added for `#{load_path}'. Please check your config"
35
36
  end
@@ -398,7 +398,7 @@ module Bridgetown
398
398
  end
399
399
 
400
400
  def default_github_branch_name(repo_url)
401
- repo_match = Bridgetown::Commands::Actions::GITHUB_REPO_REGEX.match(repo_url)
401
+ repo_match = Bridgetown::Commands::Automations::GITHUB_REPO_REGEX.match(repo_url)
402
402
  api_endpoint = "https://api.github.com/repos/#{repo_match[1]}"
403
403
  JSON.parse(Faraday.get(api_endpoint).body)["default_branch"] || "main"
404
404
  rescue StandardError => e
@@ -406,6 +406,24 @@ module Bridgetown
406
406
  "main"
407
407
  end
408
408
 
409
+ def default_gitlab_branch_name(repo_url)
410
+ repo_match = Bridgetown::Commands::Automations::GITLAB_REPO_REGEX.match(repo_url)
411
+ api_endpoint = "https://gitlab.com/api/v4/projects/#{repo_match[1].sub("/", "%2F")}"
412
+ JSON.parse(Faraday.get(api_endpoint).body)["default_branch"] || "main"
413
+ rescue StandardError => e
414
+ Bridgetown.logger.warn("Unable to connect to GitLab API: #{e.message}")
415
+ "main"
416
+ end
417
+
418
+ def default_codeberg_branch_name(repo_url)
419
+ repo_match = Bridgetown::Commands::Automations::CODEBERG_REPO_REGEX.match(repo_url)
420
+ api_endpoint = "https://codeberg.org/api/v1/repos/#{repo_match[1]}"
421
+ JSON.parse(Faraday.get(api_endpoint).body)["default_branch"] || "main"
422
+ rescue StandardError => e
423
+ Bridgetown.logger.warn("Unable to connect to Codeberg API: #{e.message}")
424
+ "main"
425
+ end
426
+
409
427
  def live_reload_js(site) # rubocop:disable Metrics/MethodLength
410
428
  return "" unless Bridgetown.env.development? && !site.config.skip_live_reload
411
429
 
@@ -65,12 +65,11 @@ module Bridgetown
65
65
  ignore: listen_ignore_paths(options),
66
66
  force_polling: options["force_polling"]
67
67
  ) do |modified, added, removed|
68
- c = modified + added + removed
68
+ paths = modified + added + removed
69
69
 
70
- # NOTE: inexplicably, this matcher doesn't work with the Listen gem, so
71
- # we have to run it here manually
72
- c.reject! { component_frontend_matcher(options).match? _1 }
73
- n = c.length
70
+ filter_paths(paths, options)
71
+
72
+ n = paths.length
74
73
  next if n.zero?
75
74
 
76
75
  unless site.ssr?
@@ -78,13 +77,13 @@ module Bridgetown
78
77
  "Reloading…",
79
78
  "#{n} file#{"s" if n > 1} changed at #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
80
79
  )
81
- c.each { |path| Bridgetown.logger.info "", "- #{path["#{site.root_dir}/".length..]}" }
80
+ paths.each { Bridgetown.logger.info "", "- #{_1.delete_prefix("#{site.root_dir}/")}" }
82
81
  end
83
82
 
84
83
  reload_site(
85
84
  site,
86
85
  options,
87
- paths: c,
86
+ paths:,
88
87
  fast_refreshable: site.config.fast_refresh && (added + removed).empty?
89
88
  )
90
89
  end.start
@@ -146,7 +145,7 @@ module Bridgetown
146
145
  # rubocop:enable Layout/LineLength
147
146
 
148
147
  def to_exclude(options)
149
- [
148
+ @to_exclude ||= [
150
149
  options["destination"],
151
150
  custom_excludes(options),
152
151
  ].flatten
@@ -178,6 +177,15 @@ module Bridgetown
178
177
  end
179
178
  end
180
179
 
180
+ def filter_paths(paths, options)
181
+ # NOTE: inexplicably, this matcher doesn't work with the Listen gem, so
182
+ # we have to run it here manually
183
+ paths.reject! { component_frontend_matcher(options).match? _1 }
184
+ # Filter again by ignore exclusions, needed for "folder inversion" projects where the
185
+ # Bridgetown root is inside of the main folder being watched
186
+ paths.reject! { |path| to_exclude(options).any? { path == _1 || path.start_with?(_1) } }
187
+ end
188
+
181
189
  def sleep_forever
182
190
  sleep 0.5 until shutdown
183
191
  end
@@ -26,7 +26,6 @@ require "time"
26
26
  require "English"
27
27
  require "pathname"
28
28
  require "logger"
29
- require "set"
30
29
  require "csv"
31
30
  require "json"
32
31
  require "yaml"
@@ -35,10 +34,6 @@ require "yaml"
35
34
  require "bridgetown-foundation"
36
35
 
37
36
  # 3rd party
38
- require "active_support" # TODO: remove by the end of 2025
39
- require "active_support/core_ext/object/blank"
40
- require "active_support/core_ext/string/inflections"
41
- require "active_support/core_ext/string/output_safety"
42
37
  require "addressable/uri"
43
38
  require "liquid"
44
39
  require "listen"
@@ -46,8 +41,8 @@ require "kramdown"
46
41
  require "i18n"
47
42
  require "i18n/backend/fallbacks"
48
43
  require "faraday"
44
+ require "samovar"
49
45
  require "signalize"
50
- require "thor"
51
46
 
52
47
  # Ensure we can set up fallbacks so the default locale gets used
53
48
  I18n::Backend::Simple.include I18n::Backend::Fallbacks
@@ -73,6 +68,7 @@ module Bridgetown
73
68
  autoload :Current, "bridgetown-core/current"
74
69
  autoload :Cleaner, "bridgetown-core/cleaner"
75
70
  autoload :Collection, "bridgetown-core/collection"
71
+ autoload :Command, "bridgetown-core/command"
76
72
  autoload :Component, "bridgetown-core/component"
77
73
  autoload :DefaultsReader, "bridgetown-core/readers/defaults_reader"
78
74
  autoload :Deprecator, "bridgetown-core/deprecator"
@@ -81,7 +77,6 @@ module Bridgetown
81
77
  autoload :FrontMatter, "bridgetown-core/front_matter"
82
78
  autoload :GeneratedPage, "bridgetown-core/generated_page"
83
79
  autoload :Hooks, "bridgetown-core/hooks"
84
- autoload :Inflector, "bridgetown-core/inflector"
85
80
  autoload :Layout, "bridgetown-core/layout"
86
81
  autoload :LayoutPlaceable, "bridgetown-core/concerns/layout_placeable"
87
82
  autoload :LayoutReader, "bridgetown-core/readers/layout_reader"
@@ -93,20 +88,20 @@ module Bridgetown
93
88
  autoload :Prioritizable, "bridgetown-core/concerns/prioritizable"
94
89
  autoload :Publishable, "bridgetown-core/concerns/publishable"
95
90
  autoload :Reader, "bridgetown-core/reader"
96
- autoload :RubyTemplateView, "bridgetown-core/ruby_template_view"
97
91
  autoload :LogWriter, "bridgetown-core/log_writer"
98
92
  autoload :Signals, "bridgetown-core/signals"
99
93
  autoload :Site, "bridgetown-core/site"
100
94
  autoload :Slot, "bridgetown-core/slot"
101
95
  autoload :StaticFile, "bridgetown-core/static_file"
96
+ autoload :TemplateView, "bridgetown-core/template_view"
102
97
  autoload :Transformable, "bridgetown-core/concerns/transformable"
103
98
  autoload :Viewable, "bridgetown-core/concerns/viewable"
104
99
  autoload :Utils, "bridgetown-core/utils"
105
- autoload :VERSION, "bridgetown-core/version"
106
100
  autoload :Watcher, "bridgetown-core/watcher"
107
101
  autoload :YAMLParser, "bridgetown-core/yaml_parser"
108
102
 
109
103
  # extensions
104
+ require "bridgetown-core/commands/thor_shim"
110
105
  require "bridgetown-core/commands/registrations"
111
106
  require "bridgetown-core/plugin"
112
107
  require "bridgetown-core/converter"
@@ -265,7 +260,7 @@ module Bridgetown
265
260
  end
266
261
 
267
262
  def load_tasks
268
- require "bridgetown-core/commands/base"
263
+ require "bridgetown-core/commands/application"
269
264
  unless Bridgetown::Current.preloaded_configuration
270
265
  Bridgetown::Current.preloaded_configuration = Bridgetown::Configuration::Preflight.new
271
266
  end
@@ -3,7 +3,7 @@
3
3
  class Roda
4
4
  module RodaPlugins
5
5
  module BridgetownServer
6
- SiteContext = Struct.new(:registers) # for use by Liquid-esque URL helpers
6
+ SiteContext = Data.define(:registers) # for use by Liquid-esque URL helpers
7
7
 
8
8
  def self.load_dependencies(app) # rubocop:disable Metrics
9
9
  unless Bridgetown::Current.preloaded_configuration