bridgetown-core 1.1.0 → 1.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bridgetown +1 -3
  3. data/bridgetown-core.gemspec +7 -6
  4. data/lib/bridgetown-core/collection.rb +5 -2
  5. data/lib/bridgetown-core/commands/base.rb +1 -1
  6. data/lib/bridgetown-core/commands/build.rb +18 -5
  7. data/lib/bridgetown-core/commands/clean.rb +1 -1
  8. data/lib/bridgetown-core/commands/concerns/actions.rb +2 -4
  9. data/lib/bridgetown-core/commands/concerns/configuration_overridable.rb +7 -8
  10. data/lib/bridgetown-core/commands/console.rb +20 -1
  11. data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +5 -0
  12. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +8 -7
  13. data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +1 -1
  14. data/lib/bridgetown-core/commands/plugins.rb +46 -32
  15. data/lib/bridgetown-core/commands/serve.rb +1 -2
  16. data/lib/bridgetown-core/commands/start.rb +0 -8
  17. data/lib/bridgetown-core/component.rb +50 -0
  18. data/lib/bridgetown-core/concerns/site/configurable.rb +22 -18
  19. data/lib/bridgetown-core/concerns/site/localizable.rb +2 -6
  20. data/lib/bridgetown-core/concerns/site/processable.rb +0 -1
  21. data/lib/bridgetown-core/concerns/site/ssr.rb +0 -1
  22. data/lib/bridgetown-core/concerns/transformable.rb +5 -2
  23. data/lib/bridgetown-core/configuration/configuration_dsl.rb +146 -0
  24. data/lib/bridgetown-core/configuration.rb +90 -15
  25. data/lib/bridgetown-core/configurations/gh-pages/gh-pages.yml +3 -1
  26. data/lib/bridgetown-core/configurations/lit/esbuild-plugins.js +5 -2
  27. data/lib/bridgetown-core/configurations/minitesting.rb +1 -1
  28. data/lib/bridgetown-core/converter.rb +8 -0
  29. data/lib/bridgetown-core/converters/identity.rb +2 -0
  30. data/lib/bridgetown-core/converters/liquid_templates.rb +1 -0
  31. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
  32. data/lib/bridgetown-core/converters/markdown.rb +2 -0
  33. data/lib/bridgetown-core/current.rb +19 -5
  34. data/lib/bridgetown-core/deprecator.rb +4 -37
  35. data/lib/bridgetown-core/filters.rb +1 -3
  36. data/lib/bridgetown-core/generated_page.rb +5 -0
  37. data/lib/bridgetown-core/helpers.rb +119 -8
  38. data/lib/bridgetown-core/hooks.rb +1 -0
  39. data/lib/bridgetown-core/kramdown/parser/gfm.rb +1 -1
  40. data/lib/bridgetown-core/layout.rb +1 -1
  41. data/lib/bridgetown-core/model/base.rb +11 -12
  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 +1 -1
  45. data/lib/bridgetown-core/model/repo_origin.rb +7 -7
  46. data/lib/bridgetown-core/plugin.rb +2 -6
  47. data/lib/bridgetown-core/plugin_manager.rb +120 -41
  48. data/lib/bridgetown-core/rack/boot.rb +3 -7
  49. data/lib/bridgetown-core/rack/logger.rb +1 -0
  50. data/lib/bridgetown-core/rack/roda.rb +39 -45
  51. data/lib/bridgetown-core/rack/routes.rb +2 -6
  52. data/lib/bridgetown-core/rack/static_indexes.rb +1 -2
  53. data/lib/bridgetown-core/reader.rb +39 -50
  54. data/lib/bridgetown-core/readers/layout_reader.rb +1 -1
  55. data/lib/bridgetown-core/resource/base.rb +17 -1
  56. data/lib/bridgetown-core/ruby_template_view.rb +12 -8
  57. data/lib/bridgetown-core/site.rb +10 -3
  58. data/lib/bridgetown-core/slot.rb +41 -0
  59. data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +23 -9
  60. data/lib/bridgetown-core/utils/ansi.rb +1 -1
  61. data/lib/bridgetown-core/utils/aux.rb +7 -6
  62. data/lib/bridgetown-core/utils/initializers.rb +45 -0
  63. data/lib/bridgetown-core/utils/loaders_manager.rb +2 -2
  64. data/lib/bridgetown-core/utils/require_gems.rb +11 -35
  65. data/lib/bridgetown-core/utils/ruby_front_matter.rb +2 -3
  66. data/lib/bridgetown-core/{converters/smartypants.rb → utils/smarty_pants_converter.rb} +5 -24
  67. data/lib/bridgetown-core/utils.rb +1 -0
  68. data/lib/bridgetown-core/version.rb +2 -2
  69. data/lib/bridgetown-core/watcher.rb +1 -8
  70. data/lib/bridgetown-core.rb +89 -6
  71. data/lib/roda/plugins/bridgetown_boot.rb +25 -0
  72. data/lib/roda/plugins/bridgetown_ssr.rb +23 -0
  73. data/lib/roda/plugins/initializers.rb +17 -0
  74. data/lib/site_template/.gitignore +1 -0
  75. data/lib/site_template/Gemfile.erb +1 -1
  76. data/lib/site_template/TEMPLATES/erb/_layouts/default.erb +2 -2
  77. data/lib/site_template/TEMPLATES/erb/_layouts/page.erb +1 -1
  78. data/lib/site_template/TEMPLATES/erb/_layouts/post.erb +1 -1
  79. data/lib/site_template/TEMPLATES/liquid/_layouts/default.liquid +2 -2
  80. data/lib/site_template/TEMPLATES/liquid/_layouts/page.liquid +1 -1
  81. data/lib/site_template/TEMPLATES/liquid/_layouts/post.liquid +1 -1
  82. data/lib/site_template/TEMPLATES/serbea/_layouts/default.serb +2 -2
  83. data/lib/site_template/TEMPLATES/serbea/_layouts/page.serb +1 -1
  84. data/lib/site_template/TEMPLATES/serbea/_layouts/post.serb +1 -1
  85. data/lib/site_template/config/initializers.rb +43 -0
  86. data/lib/site_template/package.json.erb +1 -1
  87. data/lib/site_template/server/roda_app.rb +2 -8
  88. metadata +17 -9
@@ -1,57 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- # If it's in the Gemfile's :bridgetown_plugins group it's already been required, but we'll try
5
- # again just to be on the safe side:
6
- require "bridgetown-routes"
7
- rescue LoadError
3
+ unless Bridgetown::Current.preloaded_configuration
4
+ raise "You must supply a preloaded configuration before loading Bridgetown's Roda superclass"
8
5
  end
9
6
 
10
- class Roda
11
- module RodaPlugins
12
- module BridgetownSSR
13
- module InstanceMethods
14
- # Helper shorthand for Bridgetown::Current.site
15
- # @return [Bridgetown::Site]
16
- def bridgetown_site
17
- Bridgetown::Current.site
7
+ module Bridgetown
8
+ module Rack
9
+ class Roda < ::Roda
10
+ class << self
11
+ def inherited(klass)
12
+ super
13
+ klass.plugin :initializers
18
14
  end
19
- end
20
15
 
21
- def self.configure(app, _opts = {}, &block)
22
- app.include Bridgetown::Filters::URLFilters
23
- app.opts[:bridgetown_site] =
24
- Bridgetown::Site.start_ssr!(loaders_manager: Bridgetown::Rack.loaders_manager, &block)
25
- end
26
- end
27
-
28
- register_plugin :bridgetown_ssr, BridgetownSSR
16
+ # rubocop:disable Bridgetown/NoPutsAllowed
17
+ def print_routes
18
+ # TODO: this needs to be fully documented
19
+ routes = begin
20
+ JSON.parse(
21
+ File.read(
22
+ File.join(Bridgetown::Current.preloaded_configuration.root_dir, ".routes.json")
23
+ )
24
+ )
25
+ rescue StandardError
26
+ []
27
+ end
28
+ puts
29
+ puts "Routes:"
30
+ puts "======="
31
+ if routes.blank?
32
+ puts "No routes found. Have you commented all of your routes?"
33
+ puts "Documentation: https://github.com/jeremyevans/roda-route_list#basic-usage-"
34
+ end
29
35
 
30
- module BridgetownBoot
31
- Roda::RodaRequest.alias_method :_previous_roda_cookies, :cookies
32
-
33
- module RequestMethods
34
- # Monkeypatch Roda/Rack's Request object so it returns a hash which allows for
35
- # indifferent access
36
- def cookies
37
- # TODO: maybe replace with a simpler hash that offers an overloaded `[]` method
38
- _previous_roda_cookies.with_indifferent_access
39
- end
40
-
41
- # Starts up the Bridgetown routing system
42
- def bridgetown
43
- Bridgetown::Rack::Routes.start!(scope)
36
+ routes.each do |route|
37
+ puts [
38
+ route["methods"]&.join("|") || "GET",
39
+ route["path"],
40
+ route["file"] ? "\n File: #{route["file"]}" : nil,
41
+ ].compact.join(" ")
42
+ end
43
+ puts
44
44
  end
45
+ # rubocop:enable Bridgetown/NoPutsAllowed
45
46
  end
46
- end
47
-
48
- register_plugin :bridgetown_boot, BridgetownBoot
49
- end
50
- end
51
47
 
52
- module Bridgetown
53
- module Rack
54
- class Roda < ::Roda
55
48
  SiteContext = Struct.new(:registers) # for use by Liquid-esque URL helpers
56
49
 
57
50
  plugin :hooks
@@ -142,7 +135,8 @@ module Bridgetown
142
135
  before do
143
136
  if self.class.opts[:bridgetown_site]
144
137
  # The site had previously been initialized via the bridgetown_ssr plugin
145
- Bridgetown::Current.site ||= self.class.opts[:bridgetown_site]
138
+ Bridgetown::Current.sites[self.class.opts[:bridgetown_site].label] =
139
+ self.class.opts[:bridgetown_site]
146
140
  @context ||= SiteContext.new({ site: self.class.opts[:bridgetown_site] })
147
141
  end
148
142
  Bridgetown::Current.preloaded_configuration ||=
@@ -125,16 +125,12 @@ module Bridgetown
125
125
  Bridgetown::Rack::Routes.sorted_subclasses&.each do |klass|
126
126
  klass.merge roda_app
127
127
  end
128
-
129
- return unless defined?(Bridgetown::Routes::RodaRouter)
130
-
131
- Bridgetown::Routes::RodaRouter.start!(roda_app)
132
128
  end
133
129
 
134
130
  # @param app [Bridgetown::Rack::Roda]
135
131
  def setup_live_reload(app) # rubocop:disable Metrics/AbcSize
136
132
  sleep_interval = 0.2
137
- file_to_check = File.join(app.class.opts[:bridgetown_preloaded_config].destination,
133
+ file_to_check = File.join(Bridgetown::Current.preloaded_configuration.destination,
138
134
  "index.html")
139
135
 
140
136
  app.request.get "_bridgetown/live_reload" do
@@ -190,7 +186,7 @@ module Bridgetown
190
186
  end
191
187
  end
192
188
 
193
- if Bridgetown.env.development? &&
189
+ if defined?(Puma) && Bridgetown.env.development? &&
194
190
  !Bridgetown::Current.preloaded_configuration.skip_live_reload
195
191
  Puma::Launcher.class_eval do
196
192
  alias_method :_old_stop, :stop
@@ -2,8 +2,7 @@
2
2
 
3
3
  require "roda/plugins/public"
4
4
 
5
- # NOTE: once this upstreamed PR is merged in we can remove this file.
6
- # https://github.com/jeremyevans/roda/pull/215
5
+ # TODO: extract out to a standalone Roda plugin
7
6
  Roda::RodaPlugins::Public::RequestMethods.module_eval do
8
7
  SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact) # rubocop:disable Lint/ConstantDefinitionInBlock
9
8
  def public_path_segments(path) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
@@ -5,30 +5,35 @@ module Bridgetown
5
5
  # @return [Bridgetown::Site]
6
6
  attr_reader :site
7
7
 
8
+ # @param site [Bridgetown::Site]
8
9
  def initialize(site)
9
10
  @site = site
10
11
  end
11
12
 
12
- # Read Site data from disk and load it into internal data structures.
13
- #
14
- # Returns nothing.
13
+ # Read data and resources from disk and load it into internal data structures.
14
+ # @return [void]
15
15
  def read
16
16
  site.defaults_reader.read
17
+ site.data = site.collections.data.read.merge_data_resources
17
18
  read_layouts
18
19
  read_directories
19
20
  read_includes
20
21
  sort_files!
21
- site.data = site.collections.data.read.merge_data_resources
22
22
  read_collections
23
- Bridgetown::PluginManager.source_manifests.select(&:content).each do |manifest|
23
+ site.config.source_manifests.select(&:content).each do |manifest|
24
24
  PluginContentReader.new(site, manifest).read
25
25
  end
26
26
  end
27
27
 
28
+ # Read in layouts
29
+ # @see LayoutReader
30
+ # @return [void]
28
31
  def read_layouts
29
32
  site.layouts = LayoutReader.new(site).read
30
33
  end
31
34
 
35
+ # Read in collections (other than the data collection)
36
+ # @return [void]
32
37
  def read_collections
33
38
  site.collections.each_value do |collection|
34
39
  next if collection.data?
@@ -38,6 +43,7 @@ module Bridgetown
38
43
  end
39
44
 
40
45
  # Sorts generated pages and static files.
46
+ # @return [void]
41
47
  def sort_files!
42
48
  site.generated_pages.sort_by!(&:name)
43
49
  site.static_files.sort_by!(&:relative_path)
@@ -47,59 +53,55 @@ module Bridgetown
47
53
  # that will become part of the site according to the rules in
48
54
  # filter_entries.
49
55
  #
50
- # dir - The String relative path of the directory to read. Default: ''.
51
- #
52
- # Returns nothing.
56
+ # @param dir [String] relative path of the directory to read. Default: ''
57
+ # @return [void]
53
58
  def read_directories(dir = "")
54
59
  base = site.in_source_dir(dir)
55
60
 
56
61
  return unless File.directory?(base)
57
62
 
58
- dot_dirs = []
59
- dot_pages = []
60
- dot_static_files = []
63
+ entries_dirs = []
64
+ entries_pages = []
65
+ entries_static_files = []
61
66
 
62
- dot = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
63
- dot.each do |entry|
67
+ entries = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
68
+ entries.each do |entry|
64
69
  file_path = @site.in_source_dir(base, entry)
65
70
  if File.directory?(file_path)
66
- dot_dirs << entry
71
+ entries_dirs << entry
67
72
  elsif Utils.has_yaml_header?(file_path) || Utils.has_rbfm_header?(file_path)
68
- dot_pages << entry
73
+ entries_pages << entry
69
74
  else
70
- dot_static_files << entry
75
+ entries_static_files << entry
71
76
  end
72
77
  end
73
78
 
74
- retrieve_dirs(base, dir, dot_dirs)
75
- retrieve_pages(dir, dot_pages)
76
- retrieve_static_files(dir, dot_static_files)
79
+ retrieve_dirs(dir, entries_dirs)
80
+ retrieve_pages(dir, entries_pages)
81
+ retrieve_static_files(dir, entries_static_files)
77
82
  end
78
83
 
79
84
  # Recursively traverse directories with the read_directories function.
80
85
  #
81
- # base - The String representing the site's base directory.
82
- # dir - The String representing the directory to traverse down.
83
- # dot_dirs - The Array of subdirectories in the dir.
84
- #
85
- # Returns nothing.
86
- def retrieve_dirs(_base, dir, dot_dirs)
87
- dot_dirs.each do |file|
86
+ # @param dir [String] the directory to traverse down
87
+ # @param entries_dirs [Array<String>] subdirectories in the directory
88
+ # @return [void]
89
+ def retrieve_dirs(dir, entries_dirs)
90
+ entries_dirs.each do |file|
88
91
  dir_path = site.in_source_dir(dir, file)
89
92
  rel_path = File.join(dir, file)
90
- @site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path
93
+ read_directories(rel_path) unless @site.destination.chomp("/") == dir_path
91
94
  end
92
95
  end
93
96
 
94
97
  # Retrieve all the pages from the current directory,
95
98
  # add them to the site and sort them.
96
99
  #
97
- # dir - The String representing the directory retrieve the pages from.
98
- # dot_pages - The Array of pages in the dir.
99
- #
100
- # Returns nothing.
101
- def retrieve_pages(dir, dot_pages)
102
- dot_pages.each do |page_path|
100
+ # @param dir [String] the directory to retrieve the pages from
101
+ # @param entries_pages [Array<String>] page paths in the directory
102
+ # @return [void]
103
+ def retrieve_pages(dir, entries_pages)
104
+ entries_pages.each do |page_path|
103
105
  site.collections.pages.read_resource(site.in_source_dir(dir, page_path))
104
106
  end
105
107
  end
@@ -122,8 +124,8 @@ module Bridgetown
122
124
  # or are excluded in the site configuration, unless they are web server
123
125
  # files such as '.htaccess'.
124
126
  #
125
- # entries - The Array of String file/directory entries to filter.
126
- # base_directory - The string representing the optional base directory.
127
+ # @param entries [Array<String>] file/directory entries to filter
128
+ # @param base_directory [String] optional base directory
127
129
  #
128
130
  # Returns the Array of filtered entries.
129
131
  def filter_entries(entries, base_directory = nil)
@@ -132,8 +134,8 @@ module Bridgetown
132
134
 
133
135
  # Read the entries from a particular directory for processing
134
136
  #
135
- # dir - The String representing the relative path of the directory to read.
136
- # subfolder - The String representing the directory to read.
137
+ # @param dir [String] parent directory
138
+ # @param subfolder [String] the directory to read
137
139
  #
138
140
  # Returns the list of entries to process
139
141
  def get_entries(dir, subfolder)
@@ -146,19 +148,6 @@ module Bridgetown
146
148
 
147
149
  private
148
150
 
149
- # Internal
150
- #
151
- # Determine if the directory is supposed to contain posts.
152
- # If the user has defined a custom collections_dir, then attempt to read
153
- # posts only from within that directory.
154
- #
155
- # Returns true if a custom collections_dir has been set but current directory lies
156
- # outside that directory.
157
- def outside_configured_directory?(dir)
158
- collections_dir = site.config["collections_dir"]
159
- !collections_dir.empty? && !dir.start_with?("/#{collections_dir}")
160
- end
161
-
162
151
  def read_includes
163
152
  site.config.include.each do |entry|
164
153
  next if entry == ".htaccess"
@@ -15,7 +15,7 @@ module Bridgetown
15
15
  Layout.new(site, layout_directory, layout_file)
16
16
  end
17
17
 
18
- Bridgetown::PluginManager.source_manifests.filter_map(&:layouts).each do |plugin_layouts|
18
+ site.config.source_manifests.filter_map(&:layouts).each do |plugin_layouts|
19
19
  layout_entries(plugin_layouts).each do |layout_file|
20
20
  @layouts[layout_name(layout_file)] ||= \
21
21
  Layout.new(site, plugin_layouts, layout_file, from_plugin: true)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bridgetown
4
4
  module Resource
5
- class Base
5
+ class Base # rubocop:todo Metrics/ClassLength
6
6
  include Comparable
7
7
  include Bridgetown::Publishable
8
8
  include Bridgetown::LayoutPlaceable
@@ -21,6 +21,9 @@ module Bridgetown
21
21
  # @return [Bridgetown::Site]
22
22
  attr_reader :site
23
23
 
24
+ # @return [Array<Bridgetown::Slot>]
25
+ attr_reader :slots
26
+
24
27
  # @return [String]
25
28
  attr_accessor :content, :untransformed_content, :output
26
29
 
@@ -32,6 +35,7 @@ module Bridgetown
32
35
  @model = model
33
36
  @site = model.site
34
37
  @data = collection.data? ? HashWithDotAccess::Hash.new : front_matter_defaults
38
+ @slots = []
35
39
 
36
40
  trigger_hooks :post_init
37
41
  end
@@ -300,6 +304,7 @@ module Bridgetown
300
304
 
301
305
  def ensure_default_data
302
306
  determine_locale
307
+ merge_requested_site_data
303
308
 
304
309
  slug = if matches = relative_path.to_s.match(DATE_FILENAME_MATCHER) # rubocop:disable Lint/AssignmentInCondition
305
310
  set_date_from_string(matches[1]) unless data.date
@@ -314,6 +319,17 @@ module Bridgetown
314
319
  data.title ||= Bridgetown::Utils.titleize_slug(slug)
315
320
  end
316
321
 
322
+ # Lets you put `site.data.foo.bar` in a front matter variable and it will then get swapped
323
+ # out for the actual site data
324
+ def merge_requested_site_data
325
+ data.each do |k, v|
326
+ next unless v.is_a?(String) && v.starts_with?("site.data.")
327
+
328
+ data_path = v.delete_prefix("site.data.")
329
+ data[k] = site.data.dig(*data_path.split("."))
330
+ end
331
+ end
332
+
317
333
  def set_date_from_string(new_date) # rubocop:disable Naming/AccessorMethodName
318
334
  return unless new_date.is_a?(String)
319
335
 
@@ -6,20 +6,24 @@ module Bridgetown
6
6
  class RubyTemplateView
7
7
  require "bridgetown-core/helpers"
8
8
 
9
- attr_reader :layout, :page, :paginator, :site, :content
10
- alias_method :resource, :page
9
+ attr_reader :layout, :resource, :paginator, :site, :content
10
+ alias_method :page, :resource
11
11
 
12
12
  def initialize(convertible)
13
13
  if convertible.is_a?(Layout)
14
14
  @layout = convertible
15
- @page = layout.current_document
15
+ @resource = layout.current_document
16
16
  @content = layout.current_document_output
17
17
  else
18
18
  @layout = convertible.site.layouts[convertible.data["layout"]]
19
- @page = convertible
19
+ @resource = convertible
20
20
  end
21
- @paginator = page.paginator if page.respond_to?(:paginator)
22
- @site = page.site
21
+ @paginator = resource.paginator if resource.respond_to?(:paginator)
22
+ @site = resource.site
23
+ end
24
+
25
+ def data
26
+ resource.data
23
27
  end
24
28
 
25
29
  def partial(_partial_name = nil, **_options)
@@ -48,7 +52,7 @@ module Bridgetown
48
52
  render_statement = _render_statement(component, options)
49
53
 
50
54
  template = site.liquid_renderer.file(
51
- "#{page.path}.#{Digest::SHA2.hexdigest(render_statement)}"
55
+ "#{resource.path}.#{Digest::SHA2.hexdigest(render_statement)}"
52
56
  ).parse(render_statement)
53
57
  template.warnings.each do |e|
54
58
  Bridgetown.logger.warn "Liquid Warning:",
@@ -100,7 +104,7 @@ module Bridgetown
100
104
  {
101
105
  registers: {
102
106
  site: site,
103
- page: page.to_liquid,
107
+ page: resource.to_liquid,
104
108
  cached_partials: Bridgetown::Converters::LiquidTemplates.cached_partials,
105
109
  },
106
110
  strict_filters: site.config["liquid"]["strict_filters"],
@@ -13,11 +13,17 @@ module Bridgetown
13
13
  include SSR
14
14
  include Writable
15
15
 
16
- attr_reader :root_dir, :source, :dest, :cache_dir, :config, :liquid_renderer
16
+ # @return [Bridgetown::Configuration]
17
+ attr_reader :config
18
+
19
+ # @return [Symbol]
20
+ attr_reader :label
17
21
 
18
22
  # @return [Bridgetown::Utils::LoadersManager]
19
23
  attr_reader :loaders_manager
20
24
 
25
+ attr_reader :cache_dir, :liquid_renderer
26
+
21
27
  # All files not pages/documents or structured data in the source folder
22
28
  # @return [Array<StaticFile>]
23
29
  attr_accessor :static_files
@@ -36,7 +42,8 @@ module Bridgetown
36
42
  #
37
43
  # @param config [Bridgetown::Configuration]
38
44
  # @param loaders_manager [Bridgetown::Utils::LoadersManager] initialized if none provided
39
- def initialize(config, loaders_manager: nil)
45
+ def initialize(config, label: :main, loaders_manager: nil)
46
+ @label = label.to_sym
40
47
  self.config = config
41
48
  locale
42
49
 
@@ -56,7 +63,7 @@ module Bridgetown
56
63
  Bridgetown::Cache.base_cache["site_tmp"] = {}.with_dot_access
57
64
  ensure_not_in_dest
58
65
 
59
- Bridgetown::Current.site = self
66
+ Bridgetown::Current.sites[@label] = self
60
67
  Bridgetown::Hooks.trigger :site, :after_init, self
61
68
 
62
69
  reset # Processable
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ class Slot
5
+ include Transformable
6
+
7
+ # @return [String]
8
+ attr_reader :name
9
+
10
+ # @return [String]
11
+ attr_accessor :content
12
+
13
+ # @return [Object, nil]
14
+ attr_reader :context
15
+
16
+ def initialize(name:, content:, context:, transform: false)
17
+ @name, @content, @context = name, content, context
18
+
19
+ Bridgetown::Hooks.trigger :slots, :pre_render, self
20
+ transform! if transform
21
+ Bridgetown::Hooks.trigger :slots, :post_render, self
22
+ end
23
+
24
+ def transform!
25
+ self.content = transform_content(context, alternate_content: content)
26
+ end
27
+
28
+ private
29
+
30
+ def converters
31
+ # A private method calling another private method. Hmm.
32
+ document_converters = if context.is_a?(Bridgetown::Resource::Base)
33
+ context.transformer.send(:converters)
34
+ else
35
+ context.send(:converters)
36
+ end
37
+
38
+ document_converters.select { _1.class.supports_slots? }
39
+ end
40
+ end
41
+ end
@@ -11,9 +11,8 @@ namespace :frontend do
11
11
  task :watcher, :sidecar do |_task, args|
12
12
  # sidecar is when the task is running alongside the start command
13
13
  sidecar = args[:sidecar] == true
14
- Bridgetown::Utils::Aux.group do
15
- run_process "Frontend", :yellow, "bundle exec bridgetown frontend:dev"
16
- end
14
+ Bridgetown::Utils::Aux.run_process "Frontend", :yellow, "bundle exec bridgetown frontend:dev"
15
+
17
16
  if sidecar
18
17
  # give FE bundler time to boot before returning control to the start command
19
18
  sleep Bridgetown::Utils.frontend_bundler_type == :esbuild ? 3 : 4
@@ -28,8 +27,17 @@ namespace :frontend do
28
27
  end
29
28
  end
30
29
 
30
+ namespace :roda do
31
+ desc "Prints out the Roda routes file"
32
+ task :routes do
33
+ require "bridgetown-core/rack/boot"
34
+
35
+ Bridgetown::Rack::Roda.print_routes
36
+ end
37
+ end
38
+
31
39
  desc "Prerequisite task which loads site and provides automation"
32
- task :environment do
40
+ task :environment do # rubocop:todo Metrics/BlockLength
33
41
  class HammerActions < Thor # rubocop:disable Lint/ConstantDefinitionInBlock
34
42
  include Thor::Actions
35
43
  include Bridgetown::Commands::Actions
@@ -44,8 +52,12 @@ task :environment do
44
52
 
45
53
  private
46
54
 
47
- def site
48
- @site ||= Bridgetown::Site.new(Bridgetown.configuration)
55
+ def site(context: :rake)
56
+ @site ||= begin
57
+ config = Bridgetown::Current.preloaded_configuration
58
+ config.run_initializers! context: context
59
+ Bridgetown::Site.new(config)
60
+ end
49
61
  end
50
62
  end
51
63
 
@@ -54,8 +66,10 @@ task :environment do
54
66
  @hammer.instance_exec(*args, &block)
55
67
  end
56
68
 
57
- define_singleton_method :site do
58
- @hammer ||= HammerActions.new
59
- @hammer.send(:site)
69
+ %i(site run_initializers).each do |meth|
70
+ define_singleton_method meth do |**kwargs|
71
+ @hammer ||= HammerActions.new
72
+ @hammer.send(:site, **kwargs)
73
+ end
60
74
  end
61
75
  end
@@ -1,4 +1,4 @@
1
- # Frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Bridgetown
4
4
  module Utils
@@ -17,14 +17,14 @@ module Bridgetown
17
17
  running_pids << pid
18
18
  end
19
19
 
20
- def self.run_process(name, color, cmd)
20
+ def self.run_process(name, color, cmd, env: {})
21
+ @mutex ||= Thread::Mutex.new
22
+
21
23
  Thread.new do
22
24
  rd, wr = IO.pipe("BINARY")
23
- pid = Process.spawn({ "BRIDGETOWN_NO_BUNDLER_REQUIRE" => nil },
25
+ pid = Process.spawn({ "BRIDGETOWN_NO_BUNDLER_REQUIRE" => nil }.merge(env),
24
26
  cmd, out: wr, err: wr, pgroup: true)
25
- @mutex.synchronize do
26
- add_pid pid
27
- end
27
+ @mutex.synchronize { add_pid(pid) }
28
28
 
29
29
  loop do
30
30
  line = rd.gets
@@ -42,7 +42,8 @@ module Bridgetown
42
42
  end
43
43
 
44
44
  def self.group(&block)
45
- @mutex = Thread::Mutex.new
45
+ Bridgetown::Deprecator.deprecation_message "Bridgetown::Aux.group method will be removed" \
46
+ "in a future version, use run_process"
46
47
  instance_exec(&block)
47
48
  end
48
49
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ Bridgetown.initializer :dotenv do |config|
4
+ Bridgetown.load_dotenv root: config.root_dir
5
+ end
6
+
7
+ Bridgetown.initializer :ssr do |config, setup: nil|
8
+ config.roda do |app|
9
+ app.plugin(:bridgetown_ssr, &setup)
10
+ end
11
+ end
12
+
13
+ Bridgetown.initializer :parse_routes do |config|
14
+ # This builds upon the work done here:
15
+ # https://github.com/jeremyevans/roda-route_list/blob/master/bin/roda-parse_routes
16
+
17
+ require "roda-route_parser"
18
+
19
+ route_files = Dir["#{config.root_dir}/server/**/*.rb"]
20
+ if config.key?(:routes)
21
+ config.routes.source_paths.each do |routes_dir|
22
+ routes_dir = File.expand_path(routes_dir, config.source)
23
+ route_files += Dir["#{routes_dir}/**/*.*"]
24
+ end
25
+ end
26
+
27
+ parser = RodaRouteParser.new
28
+ json_gen_opts = { indent: " ", space: " ", object_nl: "\n", array_nl: "\n" }
29
+
30
+ routing_tree = []
31
+
32
+ route_files.each do |route_file|
33
+ file_contents = File.read(route_file)
34
+ routes = parser.parse(file_contents)
35
+
36
+ next unless routes.present?
37
+
38
+ routes.each do |route|
39
+ route["file"] = route_file
40
+ end
41
+ routing_tree += routes
42
+ end
43
+
44
+ File.write(File.join(config.root_dir, ".routes.json"), routing_tree.to_json(json_gen_opts))
45
+ end
@@ -9,10 +9,10 @@ module Bridgetown
9
9
 
10
10
  # @param config [Bridgetown::Configuration]
11
11
  # @param root_dir [String] root of the current site
12
- def initialize(config, root_dir = Dir.pwd)
12
+ def initialize(config)
13
13
  @config = config
14
14
  @loaders = {}
15
- @root_dir = root_dir
15
+ @root_dir = config.root_dir
16
16
  end
17
17
 
18
18
  def unload_loaders