bridgetown-core 2.0.0.beta3 → 2.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/bridgetown-core.gemspec +43 -42
  3. data/lib/bridgetown-core/collection.rb +5 -4
  4. data/lib/bridgetown-core/commands/base.rb +7 -0
  5. data/lib/bridgetown-core/commands/build.rb +29 -5
  6. data/lib/bridgetown-core/commands/console.rb +0 -1
  7. data/lib/bridgetown-core/commands/start.rb +12 -2
  8. data/lib/bridgetown-core/concerns/intuitive_expectations.rb +67 -0
  9. data/lib/bridgetown-core/concerns/site/fast_refreshable.rb +15 -7
  10. data/lib/bridgetown-core/concerns/site/ssr.rb +1 -1
  11. data/lib/bridgetown-core/concerns/site/writable.rb +1 -0
  12. data/lib/bridgetown-core/concerns/viewable.rb +46 -0
  13. data/lib/bridgetown-core/configuration.rb +21 -9
  14. data/lib/bridgetown-core/configurations/gh-pages/gh-pages.yml +5 -5
  15. data/lib/bridgetown-core/configurations/minitesting.rb +24 -64
  16. data/lib/bridgetown-core/converters/erb_templates.rb +11 -7
  17. data/lib/bridgetown-core/converters/serbea_templates.rb +7 -4
  18. data/lib/bridgetown-core/front_matter/defaults.rb +6 -6
  19. data/lib/bridgetown-core/helpers.rb +2 -2
  20. data/lib/bridgetown-core/rack/boot.rb +7 -57
  21. data/lib/bridgetown-core/rack/default_config.ru +14 -0
  22. data/lib/bridgetown-core/rack/loader_hooks.rb +83 -0
  23. data/lib/bridgetown-core/rack/routes.rb +3 -2
  24. data/lib/bridgetown-core/resource/relations.rb +3 -1
  25. data/lib/bridgetown-core/utils/initializers.rb +2 -2
  26. data/lib/bridgetown-core.rb +28 -8
  27. data/lib/roda/plugins/bridgetown_server.rb +12 -23
  28. data/lib/roda/plugins/bridgetown_ssr.rb +21 -3
  29. data/lib/roda/plugins/flashier.rb +57 -0
  30. data/lib/roda/plugins/generic_index.html +127 -0
  31. data/lib/roda/plugins/ssg.rb +3 -2
  32. data/lib/site_template/config/initializers.rb +2 -0
  33. metadata +24 -5
  34. data/lib/bridgetown-core/commands/doctor.rb +0 -147
@@ -7,93 +7,53 @@ say_status :minitesting, "Adding test gems and examples"
7
7
  append_to_file "Gemfile" do
8
8
  <<~GEMS
9
9
  \n
10
- group :test, optional: true do
11
- gem "nokogiri"
10
+ group :test do
12
11
  gem "minitest"
13
- gem "minitest-profile"
14
12
  gem "minitest-reporters"
15
- gem "shoulda"
16
- gem "rails-dom-testing"
13
+ gem "rack-test"
17
14
  end
18
15
  GEMS
19
16
  end
20
17
 
21
- create_file "test/helper.rb" do
22
- <<~RUBY
23
- require "nokogiri"
24
- require "minitest/autorun"
25
- require "minitest/reporters"
26
- require "minitest/profile"
27
- require "shoulda"
28
- require "rails-dom-testing"
18
+ gsub_file "Gemfile", '# gem "nokolexbor"', 'gem "nokolexbor"'
29
19
 
30
- # Report with color.
31
- Minitest::Reporters.use! [
32
- Minitest::Reporters::DefaultReporter.new(
33
- color: true
34
- ),
35
- ]
36
-
37
- Minitest::Test.class_eval do
38
- include Rails::Dom::Testing::Assertions
39
-
40
- def site
41
- @site ||= Bridgetown::Current.site
42
- end
43
-
44
- def nokogiri(input)
45
- input.respond_to?(:output) ? Nokogiri::HTML(input.output) : Nokogiri::HTML(input)
46
- end
47
-
48
- def document_root(root)
49
- @document_root = root.is_a?(Nokogiri::XML::Document) ? root : nokogiri(root)
50
- end
20
+ insert_into_file "Rakefile", after: %(ENV["BRIDGETOWN_ENV"] = "test"\n Bridgetown::Commands::Build.start\nend\n) do
21
+ <<~RUBY
51
22
 
52
- def document_root_element
53
- if @document_root.nil?
54
- raise "Call `document_root' with a Nokogiri document before testing your assertions"
55
- end
56
- @document_root
57
- end
23
+ require "minitest/test_task"
24
+ Minitest::TestTask.create(:test) do |t| # add on to the test task
25
+ t.warning = false
58
26
  end
59
27
  RUBY
60
28
  end
61
29
 
62
- create_file "test/test_homepage.rb" do
30
+ create_file "test/minitest_helper.rb" do
63
31
  <<~RUBY
64
- require_relative "./helper"
65
-
66
- class TestHomepage < Minitest::Test
67
- context "homepage" do
68
- setup do
69
- page = site.collections.pages.resources.find { |doc| doc.relative_url == "/" }
70
- document_root page
71
- end
32
+ ENV["MT_NO_EXPECTATIONS"] = "true"
33
+ require "minitest/autorun"
34
+ require "minitest/reporters"
35
+ Minitest::Reporters.use! [Minitest::Reporters::ProgressReporter.new]
72
36
 
73
- should "exist" do
74
- assert_select "body"
75
- end
76
- end
77
- end
37
+ require "bridgetown/test"
78
38
  RUBY
79
39
  end
80
40
 
81
- create_file "plugins/test_output.rb" do
41
+ create_file "test/test_homepage.rb" do
82
42
  <<~RUBY
83
- module TestOutput
84
- unless Bridgetown.env.development?
85
- Bridgetown::Hooks.register_one :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
43
+ require "minitest_helper"
44
+
45
+ class TestHomepage < Bridgetown::Test
46
+ def test_homepage
47
+ html get "/"
48
+
49
+ assert document.query_selector("body")
92
50
  end
93
51
  end
94
52
  RUBY
95
53
  end
96
54
 
55
+ run "bundle install", env: { "BUNDLE_GEMFILE" => Bundler::SharedHelpers.in_bundle? }
56
+
97
57
  say_status :minitesting, "All set! To get started, look at test/test_homepage.rb and then run \`bin/bridgetown test\`"
98
58
 
99
59
  # rubocop:enable all
@@ -119,13 +119,17 @@ module Bridgetown
119
119
  def convert(content, convertible)
120
120
  erb_view = Bridgetown::ERBView.new(convertible)
121
121
 
122
- erb_renderer = Tilt::ErubiTemplate.new(
123
- convertible.path,
124
- line_start(convertible),
125
- outvar: "@_erbout",
126
- bufval: "Bridgetown::OutputBuffer.new",
127
- engine_class: ERBEngine
128
- ) { content }
122
+ erb_renderer =
123
+ convertible.site.tmp_cache["erb-tmpl:#{convertible.path}:#{content.hash}"] ||=
124
+ Tilt::ErubiTemplate.new(
125
+ convertible.path,
126
+ line_start(convertible),
127
+ outvar: "@_erbout",
128
+ bufval: "Bridgetown::OutputBuffer.new",
129
+ engine_class: ERBEngine
130
+ ) do
131
+ content
132
+ end
129
133
 
130
134
  if convertible.is_a?(Bridgetown::Layout)
131
135
  erb_renderer.render(erb_view) do
@@ -34,10 +34,13 @@ module Bridgetown
34
34
  # @return [String] The converted content
35
35
  def convert(content, convertible)
36
36
  serb_view = Bridgetown::SerbeaView.new(convertible)
37
- serb_renderer = Tilt::SerbeaTemplate.new(
38
- convertible.path,
39
- line_start(convertible)
40
- ) { content }
37
+
38
+ serb_renderer =
39
+ convertible.site.tmp_cache["serb-tmpl:#{convertible.path}:#{content.hash}"] ||=
40
+ Tilt::SerbeaTemplate.new(
41
+ convertible.path,
42
+ line_start(convertible)
43
+ ) { content }
41
44
 
42
45
  if convertible.is_a?(Bridgetown::Layout)
43
46
  serb_renderer.render(serb_view) do
@@ -5,6 +5,8 @@ module Bridgetown
5
5
  # This class handles custom defaults for front matter settings.
6
6
  # It is exposed via the frontmatter_defaults method on the site class.
7
7
  class Defaults
8
+ using Bridgetown::Refinements
9
+
8
10
  # @return [Bridgetown::Site]
9
11
  attr_reader :site
10
12
 
@@ -16,6 +18,7 @@ module Bridgetown
16
18
  def reset
17
19
  @glob_cache = {}
18
20
  @defaults_cache = {}
21
+ @sets = nil
19
22
  end
20
23
 
21
24
  def ensure_time!(set)
@@ -175,15 +178,12 @@ module Bridgetown
175
178
 
176
179
  # Returns a list of valid sets
177
180
  #
178
- # This is not cached to allow plugins to modify the configuration
179
- # and have their changes take effect
180
- #
181
181
  # @return [Array<Hash>]
182
182
  def valid_sets
183
- sets = site.config["defaults"]
184
- return [] unless sets.is_a?(Array)
183
+ @sets ||= site.config["defaults"].map(&:as_dots)
184
+ return [] unless @sets.is_a?(Array)
185
185
 
186
- sets.filter_map do |set|
186
+ @sets.filter_map do |set|
187
187
  if valid?(set)
188
188
  massage_scope!(set)
189
189
  # TODO: is this trip really necessary?
@@ -11,7 +11,7 @@ module Bridgetown
11
11
  include ::Streamlined::Helpers
12
12
  include Inclusive
13
13
 
14
- # @return [Bridgetown::RubyTemplateView]
14
+ # @return [Bridgetown::RubyTemplateView, Bridgetown::Component]
15
15
  attr_reader :view
16
16
 
17
17
  # @return [Bridgetown::Site]
@@ -22,7 +22,7 @@ module Bridgetown
22
22
  # @return [Bridgetown::Foundation::SafeTranslations]
23
23
  packages def translate_package = [Bridgetown::Foundation::Packages::SafeTranslations]
24
24
 
25
- # @param view [Bridgetown::RubyTemplateView]
25
+ # @param view [Bridgetown::RubyTemplateView, Bridgetown::Component]
26
26
  # @param site [Bridgetown::Site]
27
27
  def initialize(view = nil, site = nil)
28
28
  @view = view
@@ -3,14 +3,16 @@
3
3
  require "zeitwerk"
4
4
  require "roda"
5
5
  require "json"
6
+ require "bridgetown"
6
7
 
7
- Bridgetown::Current.preloaded_configuration ||= Bridgetown.configuration
8
-
8
+ require_relative "loader_hooks"
9
9
  require_relative "logger"
10
10
  require_relative "routes"
11
11
 
12
12
  module Bridgetown
13
13
  module Rack
14
+ Bridgetown.begin!(with_config: :initializers)
15
+
14
16
  class << self
15
17
  # @return [Bridgetown::Utils::LoadersManager]
16
18
  attr_accessor :loaders_manager
@@ -23,61 +25,9 @@ module Bridgetown
23
25
  self.loaders_manager =
24
26
  Bridgetown::Utils::LoadersManager.new(Bridgetown::Current.preloaded_configuration)
25
27
  Bridgetown::Current.preloaded_configuration.run_initializers! context: :server
26
- autoload_server_folder
27
- rescue Roda::RodaError => e
28
- if e.message.include?("sessions plugin :secret option")
29
- raise Bridgetown::Errors::InvalidConfigurationError,
30
- "The Roda sessions plugin can't find a valid secret. Run `bin/bridgetown secret' " \
31
- "and put the key in a ENV var you can use to configure the session in the Roda app"
32
- end
33
-
34
- raise e
35
- end
36
-
37
- # @param root [String] root of Bridgetown site, defaults to config value
38
- def self.autoload_server_folder( # rubocop:todo Metrics
39
- root: Bridgetown::Current.preloaded_configuration.root_dir
40
- )
41
- server_folder = File.join(root, "server")
42
-
43
- Bridgetown::Hooks.register_one(
44
- :loader, :post_setup, reloadable: false
45
- ) do |loader, load_path|
46
- next unless load_path == server_folder
47
-
48
- loader.eager_load
49
- loader.do_not_eager_load(File.join(server_folder, "roda_app.rb"))
50
-
51
- unless ENV["BRIDGETOWN_ENV"] == "production"
52
- Listen.to(server_folder) do |modified, added, removed|
53
- c = modified + added + removed
54
- n = c.length
55
-
56
- Bridgetown.logger.info(
57
- "Reloading…",
58
- "#{n} file#{"s" if n > 1} changed at #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
59
- )
60
- c.each do |path|
61
- Bridgetown.logger.info "", "- #{path["#{File.dirname(server_folder)}/".length..]}"
62
- end
63
-
64
- loader.reload
65
- loader.eager_load
66
- rescue SyntaxError => e
67
- Bridgetown::Errors.print_build_error(e)
68
- end.start
69
- end
70
- end
71
-
72
- Bridgetown::Hooks.register_one(
73
- :loader, :post_reload, reloadable: false
74
- ) do |loader, load_path|
75
- next unless load_path == server_folder
76
-
77
- loader.eager_load
78
- end
79
-
80
- loaders_manager.setup_loaders([server_folder])
28
+ LoaderHooks.autoload_server_folder(
29
+ File.join(Bridgetown::Current.preloaded_configuration.root_dir, "server")
30
+ )
81
31
  end
82
32
  end
83
33
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bridgetown-core/rack/boot"
4
+
5
+ Bridgetown::Rack.boot
6
+
7
+ unless defined?(RodaApp)
8
+ class RodaApp < Roda
9
+ plugin :bridgetown_server
10
+ route(&:bridgetown)
11
+ end
12
+ end
13
+
14
+ run RodaApp.freeze.app
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Rack
5
+ module LoaderHooks
6
+ # Sets up a Zeitwerk loader for the Roda routes in the server folder. Called by the server
7
+ # boot process when Rack starts up
8
+ #
9
+ # @param server_folder [String] typically `server` within the site root
10
+ def self.autoload_server_folder(server_folder)
11
+ reload_file_path = Bridgetown.live_reload_path
12
+
13
+ register_hooks server_folder, reload_file_path
14
+
15
+ Bridgetown::Rack.loaders_manager.setup_loaders([server_folder])
16
+ end
17
+
18
+ # Registers a `post_setup` and `post_reload` hook for the Zeitwerk loader in order to handle
19
+ # eager loading and, in development, the live reload watcher
20
+ #
21
+ # @param server_folder [String]
22
+ # @param reload_file_path [String] path to the special live reload txt file
23
+ def self.register_hooks(server_folder, reload_file_path) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
24
+ Bridgetown::Hooks.register_one(
25
+ :loader, :post_setup, reloadable: false
26
+ ) do |loader, load_path|
27
+ next unless load_path == server_folder
28
+
29
+ loader.eager_load
30
+ subclass_names = Roda.subclasses.map(&:name)
31
+ subclass_paths = Set.new
32
+
33
+ loader.all_expected_cpaths.each do |cpath, cname|
34
+ if subclass_names.include?(cname) && cpath.start_with?(server_folder)
35
+ subclass_paths << cpath
36
+ loader.do_not_eager_load cpath
37
+ end
38
+ end
39
+
40
+ unless ENV["BRIDGETOWN_ENV"] == "production"
41
+ setup_autoload_listener loader, server_folder, subclass_paths
42
+ end
43
+ end
44
+
45
+ Bridgetown::Hooks.register_one(
46
+ :loader, :post_reload, reloadable: false
47
+ ) do |loader, load_path|
48
+ next unless load_path == server_folder
49
+
50
+ loader.eager_load
51
+ Bridgetown.touch_live_reload_file(reload_file_path)
52
+ end
53
+ end
54
+
55
+ # Creates a listener to detect file changes within the server folder and notify Zeitwerk
56
+ #
57
+ # @param loader [Zeitwerk::Loader]
58
+ # @param server_loader [String]
59
+ # @param subclass_paths [Array<string>]
60
+ def self.setup_autoload_listener(loader, server_folder, subclass_paths)
61
+ Listen.to(server_folder) do |modified, added, removed|
62
+ c = modified + added + removed
63
+ n = c.length
64
+
65
+ unless n == 1 && subclass_paths.include?(c.first)
66
+ Bridgetown.logger.info(
67
+ "Reloading…",
68
+ "#{n} file#{"s" if n > 1} changed at #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
69
+ )
70
+ c.each do |path|
71
+ Bridgetown.logger.info "", "- #{path["#{File.dirname(server_folder)}/".length..]}"
72
+ end
73
+ end
74
+
75
+ loader.reload
76
+ Bridgetown::Hooks.trigger :loader, :post_reload, loader, server_folder
77
+ rescue SyntaxError => e
78
+ Bridgetown::Errors.print_build_error(e)
79
+ end.start
80
+ end
81
+ end
82
+ end
83
+ end
@@ -101,13 +101,14 @@ module Bridgetown
101
101
  Bridgetown::Rack::Routes.sorted_subclasses&.each do |klass|
102
102
  klass.merge roda_app
103
103
  end
104
+
105
+ nil # required for proper 404 handling
104
106
  end
105
107
 
106
108
  # @param app [Roda]
107
109
  def setup_live_reload(app) # rubocop:disable Metrics
108
110
  sleep_interval = 0.5
109
- file_to_check = File.join(Bridgetown::Current.preloaded_configuration.destination,
110
- "index.html")
111
+ file_to_check = Bridgetown.live_reload_path
111
112
  errors_file = Bridgetown.build_errors_path
112
113
 
113
114
  app.request.get "_bridgetown/live_reload" do
@@ -20,7 +20,9 @@ module Bridgetown
20
20
 
21
21
  # @return [HashWithDotAccess::Hash]
22
22
  def relation_schema
23
- resource.collection.metadata.relations
23
+ @relation_schema ||= resource.collection.metadata.relations&.transform_values do |value|
24
+ value.is_a?(Array) ? value.map(&:to_s) : value.to_s
25
+ end
24
26
  end
25
27
 
26
28
  # @return [Array<String>]
@@ -4,9 +4,9 @@ Bridgetown.initializer :dotenv do |config|
4
4
  Bridgetown.load_dotenv root: config.root_dir
5
5
  end
6
6
 
7
- Bridgetown.initializer :ssr do |config, setup: nil|
7
+ Bridgetown.initializer :ssr do |config, setup: nil, **options|
8
8
  config.roda do |app|
9
- app.plugin(:bridgetown_ssr, &setup)
9
+ app.plugin(:bridgetown_ssr, options, &setup)
10
10
  end
11
11
  end
12
12
 
@@ -54,8 +54,9 @@ I18n::Backend::Simple.include I18n::Backend::Fallbacks
54
54
 
55
55
  # Monkey patches:
56
56
 
57
+ # @!visibility private
57
58
  module HashWithDotAccess
58
- class Hash # :nodoc:
59
+ class Hash
59
60
  def to_liquid
60
61
  to_h.to_liquid
61
62
  end
@@ -99,6 +100,7 @@ module Bridgetown
99
100
  autoload :Slot, "bridgetown-core/slot"
100
101
  autoload :StaticFile, "bridgetown-core/static_file"
101
102
  autoload :Transformable, "bridgetown-core/concerns/transformable"
103
+ autoload :Viewable, "bridgetown-core/concerns/viewable"
102
104
  autoload :Utils, "bridgetown-core/utils"
103
105
  autoload :VERSION, "bridgetown-core/version"
104
106
  autoload :Watcher, "bridgetown-core/watcher"
@@ -131,10 +133,16 @@ module Bridgetown
131
133
 
132
134
  # Set up the Bridgetown execution environment before attempting to load any
133
135
  # plugins or gems prior to a site build
134
- def begin!
136
+ def begin!(with_config: :preflight)
135
137
  ENV["RACK_ENV"] ||= environment
136
138
 
137
- Bridgetown::Current.preloaded_configuration = Bridgetown::Configuration::Preflight.new
139
+ if with_config == :preflight
140
+ Bridgetown::Current.preloaded_configuration ||= Bridgetown::Configuration::Preflight.new
141
+ elsif with_config == :initializers &&
142
+ !Bridgetown::Current.preloaded_configuration.is_a?(Bridgetown::Configuration)
143
+ Bridgetown::Current.preloaded_configuration = Bridgetown.configuration
144
+ end
145
+
138
146
  Bridgetown::PluginManager.setup_bundler
139
147
  end
140
148
 
@@ -365,11 +373,23 @@ module Bridgetown
365
373
  #
366
374
  # @return [String] the path to the cached errors file
367
375
  def build_errors_path
368
- File.join(
369
- (Bridgetown::Current.site&.config || Bridgetown::Current.preloaded_configuration).root_dir,
370
- ".bridgetown-cache",
371
- "build_errors.txt"
372
- )
376
+ site_config = Bridgetown::Current.site&.config || Bridgetown::Current.preloaded_configuration
377
+ File.join(site_config.root_dir, site_config.cache_dir, "build_errors.txt")
378
+ end
379
+
380
+ # This file gets touched each time there's a new build, which then triggers live reload
381
+ # in the browser.
382
+ #
383
+ # @see Bridgetown::Rack::Routes.setup_live_reload
384
+ # @return [String] the path to the empty file being watched
385
+ def live_reload_path
386
+ site_config = Bridgetown::Current.site&.config || Bridgetown::Current.preloaded_configuration
387
+ File.join(site_config.root_dir, site_config.cache_dir, "live_reload.txt")
388
+ end
389
+
390
+ def touch_live_reload_file(path = live_reload_path)
391
+ FileUtils.mkdir_p File.dirname(path)
392
+ FileUtils.touch path
373
393
  end
374
394
  end
375
395
 
@@ -13,20 +13,15 @@ class Roda
13
13
 
14
14
  app.extend ClassMethods # we need to do this here because Roda hasn't done it yet
15
15
  app.plugin :initializers
16
- app.plugin :method_override
17
- app.plugin :all_verbs
18
- app.plugin :hooks
19
16
  app.plugin :common_logger, Bridgetown::Rack::Logger.new($stdout), method: :info
20
17
  app.plugin :json
21
18
  app.plugin :json_parser
22
- app.plugin :indifferent_params
23
- app.plugin :cookies, path: "/"
24
19
  app.plugin :ssg, root: Bridgetown::Current.preloaded_configuration.destination
25
20
  app.plugin :not_found do
26
21
  output_folder = Bridgetown::Current.preloaded_configuration.destination
27
22
  File.read(File.join(output_folder, "404.html"))
28
23
  rescue Errno::ENOENT
29
- "404 Not Found"
24
+ "<h1>404 Not Found</h1>"
30
25
  end
31
26
  app.plugin :exception_page
32
27
  app.plugin :error_handler do |e|
@@ -35,10 +30,10 @@ class Roda
35
30
  )
36
31
  next exception_page(e) if ENV.fetch("RACK_ENV", nil) == "development"
37
32
 
38
- output_folder = Bridgetown::Current.preloaded_configuration.destination
33
+ output_folder = self.class.opts[:bridgetown_preloaded_config].destination
39
34
  File.read(File.join(output_folder, "500.html"))
40
35
  rescue Errno::ENOENT
41
- "500 Internal Server Error"
36
+ "<h1>500 Internal Server Error</h1>"
42
37
  end
43
38
 
44
39
  # TODO: there may be a better way to do this, see `exception_page_css` instance method
@@ -123,9 +118,12 @@ class Roda
123
118
  hook_result = instance_exec(&self.class.opts[:root_hook]) if self.class.opts[:root_hook]
124
119
  next hook_result if hook_result
125
120
 
126
- status, headers, body = self.class.opts[:ssg_server].serving(
127
- request, File.join(self.class.opts[:ssg_root], "index.html")
128
- )
121
+ root_file = [
122
+ File.join(self.class.opts[:ssg_root], "index.html"),
123
+ File.expand_path("generic_index.html", __dir__),
124
+ ].find { File.exist?(_1) }
125
+
126
+ status, headers, body = self.class.opts[:ssg_server].serving(request, root_file)
129
127
  response_headers = response.headers
130
128
  response_headers.replace(headers)
131
129
 
@@ -133,7 +131,7 @@ class Roda
133
131
  rescue StandardError => e
134
132
  Bridgetown.logger.debug("Root handler error: #{e.message}")
135
133
  response.status = 500
136
- "<p>ERROR: cannot find <code>index.html</code> in the output folder.</p>"
134
+ "<p>ERROR: cannot serve the root <code>index</code> file.</p>"
137
135
  end
138
136
  end
139
137
 
@@ -158,20 +156,11 @@ class Roda
158
156
  scope.initialize_bridgetown_context
159
157
  scope.initialize_bridgetown_root
160
158
 
161
- # There are two different code paths depending on if there's a site `base_path` configured
162
- if Bridgetown::Current.preloaded_configuration.base_path == "/"
159
+ base_path = Bridgetown::Current.preloaded_configuration.base_path.delete_prefix("/")
160
+ on(base_path.empty? ? true : base_path) do
163
161
  ssg # static file server
164
162
  Bridgetown::Rack::Routes.load_all scope
165
- return
166
163
  end
167
-
168
- # Support custom base_path configurations
169
- on(Bridgetown::Current.preloaded_configuration.base_path.delete_prefix("/")) do
170
- ssg # static file server
171
- Bridgetown::Rack::Routes.load_all scope
172
- end
173
-
174
- nil
175
164
  end
176
165
  end
177
166
  end
@@ -13,13 +13,31 @@ class Roda
13
13
  alias_method :site, :bridgetown_site
14
14
  end
15
15
 
16
- def self.load_dependencies(app)
17
- app.plugin :custom_block_results
16
+ def self.load_dependencies(app, opts = { sessions: false })
17
+ app.plugin :all_verbs
18
+ app.plugin :cookies, path: "/"
19
+ app.plugin :indifferent_params
20
+ app.plugin :method_override
21
+ app.plugin :route_csrf
18
22
 
19
23
  # This lets us return callable objects directly in Roda response blocks
24
+ app.plugin :custom_block_results
20
25
  app.handle_block_result(Bridgetown::RodaCallable) do |callable|
21
- callable.(self)
26
+ request.send :block_result_body, callable.(self)
27
+ end
28
+
29
+ return unless opts[:sessions]
30
+
31
+ secret_key = ENV.fetch("RODA_SECRET_KEY", nil)
32
+ unless secret_key
33
+ raise Bridgetown::Errors::InvalidConfigurationError,
34
+ "The Roda sessions plugin can't find a valid secret. Run " \
35
+ "`bin/bridgetown secret' and put the key in your ENV as the " \
36
+ "RODA_SECRET_KEY variable"
22
37
  end
38
+
39
+ app.plugin :sessions, secret: secret_key
40
+ app.plugin :flashier
23
41
  end
24
42
 
25
43
  def self.configure(app, _opts = {}, &)