bridgetown-core 1.0.0.beta2 → 1.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/lib/bridgetown-core/collection.rb +37 -20
  4. data/lib/bridgetown-core/commands/concerns/actions.rb +3 -2
  5. data/lib/bridgetown-core/commands/configure.rb +1 -1
  6. data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +20 -16
  7. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +95 -12
  8. data/lib/bridgetown-core/commands/new.rb +10 -9
  9. data/lib/bridgetown-core/commands/plugins.rb +2 -0
  10. data/lib/bridgetown-core/commands/start.rb +3 -0
  11. data/lib/bridgetown-core/commands/webpack/update.rb +2 -2
  12. data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +11 -2
  13. data/lib/bridgetown-core/component.rb +13 -7
  14. data/lib/bridgetown-core/concerns/localizable.rb +20 -0
  15. data/lib/bridgetown-core/concerns/prioritizable.rb +44 -0
  16. data/lib/bridgetown-core/concerns/publishable.rb +11 -1
  17. data/lib/bridgetown-core/concerns/site/configurable.rb +2 -10
  18. data/lib/bridgetown-core/concerns/site/localizable.rb +5 -1
  19. data/lib/bridgetown-core/concerns/site/renderable.rb +27 -16
  20. data/lib/bridgetown-core/concerns/site/ssr.rb +3 -3
  21. data/lib/bridgetown-core/concerns/site/writable.rb +28 -0
  22. data/lib/bridgetown-core/concerns/transformable.rb +62 -0
  23. data/lib/bridgetown-core/configuration.rb +2 -0
  24. data/lib/bridgetown-core/configurations/bt-postcss/postcss.config.js +5 -3
  25. data/lib/bridgetown-core/configurations/bt-postcss.rb +1 -1
  26. data/lib/bridgetown-core/configurations/gh-pages/gh-pages.yml +33 -0
  27. data/lib/bridgetown-core/configurations/gh-pages.rb +16 -0
  28. data/lib/bridgetown-core/configurations/lit/esbuild-plugins.js +21 -0
  29. data/lib/bridgetown-core/configurations/lit/happy-days.lit.js +26 -0
  30. data/lib/bridgetown-core/configurations/lit/lit-components-entry.js +1 -0
  31. data/lib/bridgetown-core/configurations/lit/lit-ssr.config.js +6 -0
  32. data/lib/bridgetown-core/configurations/lit.rb +95 -0
  33. data/lib/bridgetown-core/configurations/open-props/variables.css.erb +11 -0
  34. data/lib/bridgetown-core/configurations/open-props.rb +21 -0
  35. data/lib/bridgetown-core/configurations/ruby2js/hello_world.js.rb +9 -0
  36. data/lib/bridgetown-core/configurations/ruby2js.rb +67 -0
  37. data/lib/bridgetown-core/configurations/shoelace.rb +50 -0
  38. data/lib/bridgetown-core/configurations/tailwindcss.rb +16 -2
  39. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
  40. data/lib/bridgetown-core/drops/generated_page_drop.rb +2 -1
  41. data/lib/bridgetown-core/drops/resource_drop.rb +2 -1
  42. data/lib/bridgetown-core/errors.rb +5 -5
  43. data/lib/bridgetown-core/filters/translation_filters.rb +11 -0
  44. data/lib/bridgetown-core/filters/url_filters.rb +37 -10
  45. data/lib/bridgetown-core/filters.rb +3 -0
  46. data/lib/bridgetown-core/frontmatter_defaults.rb +14 -8
  47. data/lib/bridgetown-core/generated_page.rb +82 -17
  48. data/lib/bridgetown-core/kramdown/parser/gfm.rb +36 -0
  49. data/lib/bridgetown-core/model/base.rb +1 -2
  50. data/lib/bridgetown-core/plugin.rb +6 -37
  51. data/lib/bridgetown-core/plugin_manager.rb +3 -2
  52. data/lib/bridgetown-core/rack/boot.rb +5 -0
  53. data/lib/bridgetown-core/rack/logger.rb +14 -4
  54. data/lib/bridgetown-core/rack/roda.rb +102 -10
  55. data/lib/bridgetown-core/rack/routes.rb +87 -6
  56. data/lib/bridgetown-core/resource/base.rb +4 -6
  57. data/lib/bridgetown-core/resource/destination.rb +18 -0
  58. data/lib/bridgetown-core/resource/permalink_processor.rb +6 -4
  59. data/lib/bridgetown-core/resource/relations.rb +1 -1
  60. data/lib/bridgetown-core/resource/transformer.rb +21 -85
  61. data/lib/bridgetown-core/utils/aux.rb +2 -1
  62. data/lib/bridgetown-core/utils/require_gems.rb +3 -6
  63. data/lib/bridgetown-core/utils.rb +25 -12
  64. data/lib/bridgetown-core/version.rb +2 -2
  65. data/lib/bridgetown-core/watcher.rb +19 -6
  66. data/lib/bridgetown-core.rb +9 -3
  67. data/lib/site_template/Gemfile.erb +1 -1
  68. data/lib/site_template/README.md +2 -2
  69. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +4 -4
  70. data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +4 -4
  71. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +4 -4
  72. data/lib/site_template/bridgetown.config.yml +10 -3
  73. data/lib/site_template/frontend/javascript/index.js.erb +1 -0
  74. data/lib/site_template/frontend/styles/syntax-highlighting.css +77 -0
  75. data/lib/site_template/package.json.erb +18 -17
  76. data/lib/site_template/server/roda_app.rb +3 -6
  77. data/lib/site_template/src/404.html +2 -1
  78. data/lib/site_template/src/500.html +10 -0
  79. metadata +21 -4
  80. data/lib/bridgetown-core/publisher.rb +0 -29
  81. data/lib/bridgetown-core/renderer.rb +0 -169
@@ -2,6 +2,13 @@
2
2
 
3
3
  require "rack/indifferent"
4
4
 
5
+ begin
6
+ # If it's in the Gemfile's :bridgetown_plugins group it's already been required, but we'll try
7
+ # again just to be on the safe side:
8
+ require "bridgetown-routes"
9
+ rescue LoadError
10
+ end
11
+
5
12
  class Roda
6
13
  module RodaPlugins
7
14
  module BridgetownSSR
@@ -12,6 +19,34 @@ class Roda
12
19
  end
13
20
 
14
21
  register_plugin :bridgetown_ssr, BridgetownSSR
22
+
23
+ module BridgetownBoot
24
+ module InstanceMethods
25
+ # Helper shorthand for Bridgetown::Current.site
26
+ # @return [Bridgetown::Site]
27
+ def bridgetown_site
28
+ Bridgetown::Current.site
29
+ end
30
+ end
31
+
32
+ Roda::RodaRequest.alias_method :_previous_roda_cookies, :cookies
33
+
34
+ module RequestMethods
35
+ # Monkeypatch Roda/Rack's Request object so it returns a hash which allows for
36
+ # indifferent access
37
+ def cookies
38
+ # TODO: maybe replace with a simpler hash that offers an overloaded `[]` method
39
+ _previous_roda_cookies.with_indifferent_access
40
+ end
41
+
42
+ # Starts up the Bridgetown routing system
43
+ def bridgetown
44
+ Bridgetown::Rack::Routes.start!(scope)
45
+ end
46
+ end
47
+ end
48
+
49
+ register_plugin :bridgetown_boot, BridgetownBoot
15
50
  end
16
51
  end
17
52
 
@@ -24,6 +59,7 @@ module Bridgetown
24
59
  plugin :json_parser
25
60
  plugin :cookies
26
61
  plugin :streaming
62
+ plugin :bridgetown_boot
27
63
  plugin :public, root: Bridgetown::Current.preloaded_configuration.destination
28
64
  plugin :not_found do
29
65
  output_folder = Bridgetown::Current.preloaded_configuration.destination
@@ -31,15 +67,76 @@ module Bridgetown
31
67
  rescue Errno::ENOENT
32
68
  "404 Not Found"
33
69
  end
70
+ plugin :exception_page
34
71
  plugin :error_handler do |e|
35
- puts "\n#{e.class} (#{e.message}):\n\n"
36
- puts e.backtrace
72
+ Bridgetown::Errors.print_build_error(
73
+ e, logger: Bridgetown::LogAdapter.new(self.class.opts[:common_logger])
74
+ )
75
+ next exception_page(e) if ENV.fetch("RACK_ENV", nil) == "development"
76
+
37
77
  output_folder = Bridgetown::Current.preloaded_configuration.destination
38
78
  File.read(File.join(output_folder, "500.html"))
39
79
  rescue Errno::ENOENT
40
80
  "500 Internal Server Error"
41
81
  end
42
82
 
83
+ ::Roda::RodaPlugins::ExceptionPage.class_eval do
84
+ def self.css
85
+ <<~CSS
86
+ html * { padding:0; margin:0; }
87
+ body * { padding:10px 20px; }
88
+ body * * { padding:0; }
89
+ body { font-family: -apple-system, sans-serif; font-size: 90%; }
90
+ body>div { border-bottom:1px solid #ddd; }
91
+ code { font-family: ui-monospace, monospace; }
92
+ h1 { font-weight: bold; margin-block-end: .8em; }
93
+ h2 { margin-block-end:.8em; }
94
+ h2 span { font-size:80%; color:#f7f7db; font-weight:normal; }
95
+ h3 { margin:1em 0 .5em 0; }
96
+ h4 { margin:0 0 .5em 0; font-weight: normal; }
97
+ table {
98
+ border:1px solid #ccc; border-collapse: collapse; background:white; }
99
+ tbody td, tbody th { vertical-align:top; padding:2px 3px; }
100
+ thead th {
101
+ padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
102
+ font-weight:normal; font-size:11px; border:1px solid #ddd; }
103
+ tbody th { text-align:right; opacity: 0.7; padding-right:.5em; }
104
+ table.vars { margin:5px 0 2px 40px; }
105
+ table.vars td, table.req td { font-family: ui-monospace, monospace; }
106
+ table td.code { width:100%;}
107
+ table td.code div { overflow:hidden; }
108
+ table.source th { color:#666; }
109
+ table.source td {
110
+ font-family: ui-monospace, monospace; white-space:pre; border-bottom:1px solid #eee; }
111
+ ul.traceback { list-style-type:none; }
112
+ ul.traceback li.frame { margin-bottom:1em; }
113
+ div.context { margin: 10px 0; }
114
+ div.context ol {
115
+ padding-left:30px; margin:0 10px; list-style-position: inside; }
116
+ div.context ol li {
117
+ font-family: ui-monospace, monospace; white-space:pre; color:#666; cursor:pointer; }
118
+ div.context ol.context-line li { color:black; background-color:#f7f7db; }
119
+ div.context ol.context-line li span { float: right; }
120
+ div.commands { margin-left: 40px; }
121
+ div.commands a { color:black; text-decoration:none; }
122
+ #summary { background: #1D453C; color: white; }
123
+ #summary h2 { font-weight: normal; color: white; }
124
+ #summary ul#quicklinks { list-style-type: none; margin-bottom: 2em; }
125
+ #summary ul#quicklinks li { float: left; padding: 0 1em; }
126
+ #summary ul#quicklinks>li+li { border-left: 1px #666 solid; }
127
+ #summary a { color: #f47c3c; }
128
+ #explanation { background:#eee; }
129
+ #traceback { background: white; }
130
+ #requestinfo { background:#f6f6f6; padding-left:120px; }
131
+ #summary table { border:none; background:transparent; }
132
+ #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
133
+ #requestinfo h3 { margin-bottom:-1em; }
134
+ .error { background: #ffc; }
135
+ .specific { color:#cc3300; font-weight:bold; }
136
+ CSS
137
+ end
138
+ end
139
+
43
140
  before do
44
141
  if self.class.opts[:bridgetown_site]
45
142
  # The site had previously been initialized via the bridgetown_ssr plugin
@@ -48,19 +145,14 @@ module Bridgetown
48
145
  Bridgetown::Current.preloaded_configuration ||=
49
146
  self.class.opts[:bridgetown_preloaded_config]
50
147
 
51
- request.public
52
-
53
148
  request.root do
54
149
  output_folder = Bridgetown::Current.preloaded_configuration.destination
55
150
  File.read(File.join(output_folder, "index.html"))
151
+ rescue StandardError
152
+ response.status = 500
153
+ "<p>ERROR: cannot find <code>index.html</code> in the output folder.</p>"
56
154
  end
57
155
  end
58
-
59
- # Helper shorthand for Bridgetown::Current.site
60
- # @return [Bridgetown::Site]
61
- def bridgetown_site
62
- Bridgetown::Current.site
63
- end
64
156
  end
65
157
  end
66
158
  end
@@ -9,19 +9,49 @@ module Bridgetown
9
9
  end
10
10
 
11
11
  class Routes
12
+ include Bridgetown::Prioritizable
13
+
14
+ self.priorities = {
15
+ highest: "010",
16
+ high: "020",
17
+ normal: "030",
18
+ low: "040",
19
+ lowest: "050",
20
+ }.freeze
21
+
12
22
  class << self
13
- attr_accessor :tracked_subclasses, :router_block
23
+ # @return [Hash<String, Class(Routes)>]
24
+ attr_accessor :tracked_subclasses
25
+
26
+ # @return [Proc]
27
+ attr_accessor :router_block
28
+
29
+ # Spaceship is priority [higher -> lower]
30
+ #
31
+ # @param other [Class(Routes)] The class to be compared.
32
+ # @return [Integer] -1, 0, 1.
33
+ def <=>(other)
34
+ "#{priorities[priority]}#{self}" <=> "#{priorities[other.priority]}#{other}"
35
+ end
14
36
 
37
+ # @param base [Class(Routes)]
15
38
  def inherited(base)
16
39
  Bridgetown::Rack::Routes.track_subclass base
17
40
  super
18
41
  end
19
42
 
43
+ # @param klass [Class(Routes)]
20
44
  def track_subclass(klass)
21
45
  Bridgetown::Rack::Routes.tracked_subclasses ||= {}
22
46
  Bridgetown::Rack::Routes.tracked_subclasses[klass.name] = klass
23
47
  end
24
48
 
49
+ # @return [Array<Class(Routes)>]
50
+ def sorted_subclasses
51
+ Bridgetown::Rack::Routes.tracked_subclasses&.values&.sort
52
+ end
53
+
54
+ # @return [void]
25
55
  def reload_subclasses
26
56
  Bridgetown::Rack::Routes.tracked_subclasses&.each_key do |klassname|
27
57
  Kernel.const_get(klassname)
@@ -30,33 +60,78 @@ module Bridgetown
30
60
  end
31
61
  end
32
62
 
63
+ # Add a router block via the current Routes class
64
+ #
65
+ # Example:
66
+ #
67
+ # class Routes::Hello < Bridgetown::Rack::Routes
68
+ # route do |r|
69
+ # r.get "hello", String do |name|
70
+ # { hello: "friend #{name}" }
71
+ # end
72
+ # end
73
+ # end
74
+ #
75
+ # @param block [Proc]
33
76
  def route(&block)
34
77
  self.router_block = block
35
78
  end
36
79
 
80
+ # Initialize a new Routes instance and execute the route as part of the
81
+ # Roda app request cycle
82
+ #
83
+ # @param roda_app [Bridgetown::Rack::Roda]
37
84
  def merge(roda_app)
38
85
  return unless router_block
39
86
 
40
87
  new(roda_app).handle_routes
41
88
  end
42
89
 
90
+ # Start the Roda app request cycle. There are two different code paths
91
+ # depending on if there's a site `base_path` configured
92
+ #
93
+ # @param roda_app [Bridgetown::Rack::Roda]
94
+ # @return [void]
43
95
  def start!(roda_app)
96
+ if Bridgetown::Current.preloaded_configuration.base_path == "/"
97
+ load_all_routes roda_app
98
+ return
99
+ end
100
+
101
+ # Support custom base_path configurations
102
+ roda_app.request.on(
103
+ Bridgetown::Current.preloaded_configuration.base_path.delete_prefix("/")
104
+ ) do
105
+ load_all_routes roda_app
106
+ end
107
+
108
+ nil
109
+ end
110
+
111
+ # Run the Roda public plugin first, set up live reload if allowed, then
112
+ # run through all the Routes blocks. If the file-based router plugin
113
+ # is available, kick off that request process next.
114
+ #
115
+ # @param roda_app [Bridgetown::Rack::Roda]
116
+ # @return [void]
117
+ def load_all_routes(roda_app)
118
+ roda_app.request.public
119
+
44
120
  if Bridgetown.env.development? &&
45
121
  !Bridgetown::Current.preloaded_configuration.skip_live_reload
46
122
  setup_live_reload roda_app
47
123
  end
48
124
 
49
- Bridgetown::Rack::Routes.tracked_subclasses&.each_value do |klass|
125
+ Bridgetown::Rack::Routes.sorted_subclasses&.each do |klass|
50
126
  klass.merge roda_app
51
127
  end
52
128
 
53
- if defined?(Bridgetown::Routes::RodaRouter)
54
- Bridgetown::Routes::RodaRouter.start!(roda_app)
55
- end
129
+ return unless defined?(Bridgetown::Routes::RodaRouter)
56
130
 
57
- nil
131
+ Bridgetown::Routes::RodaRouter.start!(roda_app)
58
132
  end
59
133
 
134
+ # @param app [Bridgetown::Rack::Roda]
60
135
  def setup_live_reload(app) # rubocop:disable Metrics/AbcSize
61
136
  sleep_interval = 0.2
62
137
  file_to_check = File.join(app.class.opts[:bridgetown_preloaded_config].destination,
@@ -86,14 +161,20 @@ module Bridgetown
86
161
  end
87
162
  end
88
163
 
164
+ # @param roda_app [Bridgetown::Rack::Roda]
89
165
  def initialize(roda_app)
90
166
  @_roda_app = roda_app
91
167
  end
92
168
 
169
+ # Execute the router block via the instance, passing it the Roda request
170
+ #
171
+ # @return [Object] whatever is returned by the router block as expected
172
+ # by the Roda API
93
173
  def handle_routes
94
174
  instance_exec(@_roda_app.request, &self.class.router_block)
95
175
  end
96
176
 
177
+ # Any missing methods are passed along to the underlying Roda app if possible
97
178
  def method_missing(method_name, *args, **kwargs, &block)
98
179
  if @_roda_app.respond_to?(method_name.to_sym)
99
180
  @_roda_app.send method_name.to_sym, *args, **kwargs, &block
@@ -7,6 +7,7 @@ module Bridgetown
7
7
  include Bridgetown::Publishable
8
8
  include Bridgetown::LayoutPlaceable
9
9
  include Bridgetown::LiquidRenderable
10
+ include Bridgetown::Localizable
10
11
 
11
12
  # @return [HashWithDotAccess::Hash]
12
13
  attr_reader :data
@@ -210,10 +211,7 @@ module Bridgetown
210
211
  def requires_destination?
211
212
  collection.write? && data.config&.output != false
212
213
  end
213
-
214
- def write?
215
- requires_destination? && site.publisher.publish?(self)
216
- end
214
+ alias_method :write?, :requires_destination?
217
215
 
218
216
  # Write the generated Document file to the destination directory.
219
217
  #
@@ -295,7 +293,7 @@ module Bridgetown
295
293
 
296
294
  private
297
295
 
298
- def ensure_default_data # rubocop:todo Metrics/AbcSize
296
+ def ensure_default_data
299
297
  determine_locale
300
298
 
301
299
  slug = if matches = relative_path.to_s.match(DATE_FILENAME_MATCHER) # rubocop:disable Lint/AssignmentInCondition
@@ -305,7 +303,7 @@ module Bridgetown
305
303
  basename_without_ext
306
304
  end
307
305
 
308
- slug.chomp!(".#{data.locale}") if data.locale && slug.ends_with?(".#{data.locale}")
306
+ Bridgetown::Utils.chomp_locale_suffix!(slug, data.locale)
309
307
 
310
308
  data.slug ||= slug
311
309
  data.title ||= Bridgetown::Utils.titleize_slug(slug)
@@ -12,6 +12,7 @@ module Bridgetown
12
12
  # @param resource [Bridgetown::Resource::Base]
13
13
  def initialize(resource)
14
14
  @resource = resource
15
+ warn_on_rails_style_extension
15
16
  @output_ext = resource.transformer.final_ext
16
17
  end
17
18
 
@@ -46,6 +47,23 @@ module Bridgetown
46
47
  Bridgetown.logger.debug "Writing:", path
47
48
  File.write(path, output, mode: "wb")
48
49
  end
50
+
51
+ private
52
+
53
+ def warn_on_rails_style_extension
54
+ return unless resource.relative_path.fnmatch?("*.{html,json,js}.*", File::FNM_EXTGLOB)
55
+
56
+ Bridgetown.logger.warn("Uh oh!", "You're using a Rails-style filename extension in:")
57
+ Bridgetown.logger.warn("", resource.relative_path)
58
+ Bridgetown.logger.warn(
59
+ "", "Instead, you can use either the desired output file extension or set a permalink."
60
+ )
61
+ Bridgetown.logger.warn(
62
+ "For more info:",
63
+ "https://www.bridgetownrb.com/docs/template-engines/erb-and-beyond#extensions-and-permalinks"
64
+ )
65
+ Bridgetown.logger.warn("")
66
+ end
49
67
  end
50
68
  end
51
69
  end
@@ -113,9 +113,8 @@ module Bridgetown
113
113
  if resource.site.config["collections_dir"].present?
114
114
  path.delete_prefix! "#{resource.site.config["collections_dir"]}/"
115
115
  end
116
- if resource.data.locale && path.ends_with?(".#{resource.data.locale}")
117
- path.chomp!(".#{resource.data.locale}")
118
- end
116
+
117
+ Bridgetown::Utils.chomp_locale_suffix!(path, resource.data.locale)
119
118
  end,
120
119
  }
121
120
  end
@@ -137,7 +136,10 @@ module Bridgetown
137
136
 
138
137
  # @param resource [Bridgetown::Resource::Base]
139
138
  register_placeholder :locale, ->(resource) do
140
- next nil if resource.data.locale&.to_sym == resource.site.config.default_locale
139
+ if !resource.site.config.prefix_default_locale &&
140
+ resource.data.locale&.to_sym == resource.site.config.default_locale
141
+ next nil
142
+ end
141
143
 
142
144
  locale_data = resource.data.locale&.to_sym
143
145
  resource.site.config.available_locales.include?(locale_data) ? locale_data.to_s : nil
@@ -68,7 +68,7 @@ module Bridgetown
68
68
  # @return [String]
69
69
  def kind_of_relation_for_type(type)
70
70
  relation_schema&.each do |relation_type, collections|
71
- collections = Array(collections).yield_self do |collections_arr|
71
+ collections = Array(collections).then do |collections_arr|
72
72
  collections_arr +
73
73
  collections_arr.map { |item| ActiveSupport::Inflector.pluralize(item) }
74
74
  end.flatten.uniq
@@ -3,6 +3,8 @@
3
3
  module Bridgetown
4
4
  module Resource
5
5
  class Transformer
6
+ include Transformable
7
+
6
8
  # @return [Array<Hash>]
7
9
  attr_reader :conversions
8
10
 
@@ -30,10 +32,18 @@ module Bridgetown
30
32
  permalink_ext || output_ext
31
33
  end
32
34
 
33
- def process!
35
+ def process! # rubocop:disable Metrics/AbcSize
34
36
  Bridgetown.logger.debug "Transforming:", resource.relative_path
35
37
  resource.around_hook :render do
36
- run_conversions
38
+ resource.content = transform_content(resource) do |converter, index, output|
39
+ conversions[index] = {
40
+ type: :content,
41
+ converter: converter,
42
+ output: Bridgetown.env.production? ? nil : output,
43
+ output_ext: conversions[index]&.dig(:output_ext) ||
44
+ converter.output_ext(resource.extname),
45
+ }
46
+ end
37
47
  resource.place_in_layout? ? place_into_layouts : resource.output = resource.content.dup
38
48
  end
39
49
  end
@@ -85,95 +95,21 @@ module Bridgetown
85
95
  .fetch(:output_ext)
86
96
  end
87
97
 
88
- # @return [Array<Bridgetown::Layout>]
89
- def validated_layouts
90
- layout = site.layouts[resource.data.layout]
91
- warn_on_missing_layout layout, resource.data.layout
92
-
93
- layout_list = Set.new([layout])
94
- while layout
95
- layout_name = layout.data.layout
96
- layout = site.layouts[layout_name]
97
- warn_on_missing_layout layout, layout_name
98
-
99
- layout_list << layout
100
- end
101
-
102
- layout_list.to_a.compact
103
- end
104
-
105
- def warn_on_missing_layout(layout, layout_name)
106
- return unless layout.nil? && layout_name
107
-
108
- Bridgetown.logger.warn(
109
- "Build Warning:",
110
- "Layout '#{layout_name}' requested via #{resource.relative_path} does not exist."
111
- )
112
- end
113
-
114
- ### Transformation Actions
115
-
116
- def run_conversions # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
117
- input = resource.content.to_s
118
-
119
- # @param content [String]
120
- # @param converter [Bridgetown::Converter]
121
- resource.content = converters.each_with_index.inject(input) do |content, (converter, index)|
122
- output = if converter.method(:convert).arity == 1
123
- converter.convert content
124
- else
125
- converter.convert content, resource
126
- end
127
- conversions[index] = {
128
- type: :content,
129
- converter: converter,
130
- output: Bridgetown.env.production? ? nil : output,
131
- output_ext: conversions[index]&.dig(:output_ext) ||
132
- converter.output_ext(resource.extname),
133
- }
134
- output.html_safe
135
- rescue StandardError => e
136
- Bridgetown.logger.error "Conversion error:",
137
- "#{converter.class} encountered an error while "\
138
- "converting `#{resource.relative_path}'"
139
- raise e
140
- end
141
- end
142
-
143
98
  def place_into_layouts
144
99
  Bridgetown.logger.debug "Placing in Layouts:", resource.relative_path
145
100
  output = resource.content.dup
146
- validated_layouts.each do |layout|
147
- output = run_layout_conversions layout, output
101
+ site.validated_layouts_for(resource, resource.data.layout).each do |layout|
102
+ output = transform_with_layout(layout, output, resource) do |converter, layout_output|
103
+ conversions << {
104
+ type: :layout,
105
+ layout: layout,
106
+ converter: converter,
107
+ output: Bridgetown.env.production? ? nil : layout_output,
108
+ }
109
+ end
148
110
  end
149
111
  resource.output = output
150
112
  end
151
-
152
- def run_layout_conversions(layout, output)
153
- layout_converters = site.matched_converters_for_convertible(layout)
154
- layout_input = layout.content.dup
155
-
156
- layout_converters.inject(layout_input) do |content, converter|
157
- next(content) unless [2, -2].include?(converter.method(:convert).arity) # rubocop:disable Performance/CollectionLiteralInLoop
158
-
159
- layout.current_document = resource
160
- layout.current_document_output = output
161
- layout_output = converter.convert content, layout
162
-
163
- conversions << {
164
- type: :layout,
165
- layout: layout,
166
- converter: converter,
167
- output: Bridgetown.env.production? ? nil : layout_output,
168
- }
169
- layout_output
170
- rescue StandardError => e
171
- Bridgetown.logger.error "Conversion error:",
172
- "#{converter.class} encountered an error while "\
173
- "converting `#{resource.relative_path}'"
174
- raise e
175
- end
176
- end
177
113
  end
178
114
  end
179
115
  end
@@ -20,7 +20,8 @@ module Bridgetown
20
20
  def self.run_process(name, color, cmd)
21
21
  Thread.new do
22
22
  rd, wr = IO.pipe("BINARY")
23
- pid = Process.spawn(cmd, out: wr, err: wr, pgroup: true)
23
+ pid = Process.spawn({ "BRIDGETOWN_NO_BUNDLER_REQUIRE" => nil },
24
+ cmd, out: wr, err: wr, pgroup: true)
24
25
  @mutex.synchronize do
25
26
  add_pid pid
26
27
  end
@@ -41,15 +41,12 @@ module Bridgetown
41
41
  require name
42
42
  rescue LoadError => e
43
43
  Bridgetown.logger.error "Dependency Error:", <<~MSG
44
- Yikes! It looks like you don't have #{name} or one of its dependencies installed.
45
- In order to use Bridgetown as currently configured, you'll need to install this gem.
44
+ Oops! It looks like you don't have #{name} or one of its dependencies installed.
45
+ Please double-check you've added #{name} to your Gemfile.
46
46
 
47
- If you've run Bridgetown with `bundle exec`, ensure that you have included the #{name}
48
- gem in your Gemfile as well.
47
+ If you're stuck, you can find help at https://www.bridgetownrb.com/community
49
48
 
50
49
  The full error message from Ruby is: '#{e.message}'
51
-
52
- If you run into trouble, you can find helpful resources at https://www.bridgetownrb.com/docs/community/
53
50
  MSG
54
51
  raise Bridgetown::Errors::MissingDependencyException, name
55
52
  end
@@ -320,7 +320,7 @@ module Bridgetown
320
320
  end
321
321
 
322
322
  if continue_processing
323
- line_indentation = line.match(%r!^ +!).yield_self do |indent|
323
+ line_indentation = line.match(%r!^ +!).then do |indent|
324
324
  indent.nil? ? "" : indent[0]
325
325
  end
326
326
  new_indentation = line_indentation.rjust(starting_indent_length, " ")
@@ -339,6 +339,11 @@ module Bridgetown
339
339
  end
340
340
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
341
341
 
342
+ # Return an asset path based on a frontend manifest file
343
+ #
344
+ # @param site [Bridgetown::Site] The current site object
345
+ # @param asset_type [String] js or css, or filename in manifest
346
+ # @return [String, nil]
342
347
  def parse_frontend_manifest_file(site, asset_type)
343
348
  case frontend_bundler_type(site.root_dir)
344
349
  when :webpack
@@ -362,9 +367,6 @@ module Bridgetown
362
367
  # file isnt found
363
368
  # @return [nil] Returns nil if the asset isnt found
364
369
  # @return [String] Returns the path to the asset if no issues parsing
365
- #
366
- # @raise [WebpackAssetError] if unable to find css or js in the manifest
367
- # file
368
370
  def parse_webpack_manifest_file(site, asset_type)
369
371
  return log_frontend_asset_error(site, "Webpack manifest") if site.frontend_manifest.nil?
370
372
 
@@ -389,16 +391,17 @@ module Bridgetown
389
391
  # file isnt found
390
392
  # @return [nil] Returns nil if the asset isnt found
391
393
  # @return [String] Returns the path to the asset if no issues parsing
392
- #
393
- # @raise [WebpackAssetError] if unable to find css or js in the manifest
394
- # file
395
394
  def parse_esbuild_manifest_file(site, asset_type) # rubocop:disable Metrics/PerceivedComplexity
396
395
  return log_frontend_asset_error(site, "esbuild manifest") if site.frontend_manifest.nil?
397
396
 
398
- asset_path = if %w(js css).include?(asset_type)
399
- folder = asset_type == "js" ? "javascript" : "styles"
400
- site.frontend_manifest["#{folder}/index.#{asset_type}"] ||
401
- site.frontend_manifest["#{folder}/index.#{asset_type}.rb"]
397
+ asset_path = case asset_type
398
+ when "css"
399
+ site.frontend_manifest["styles/index.css"] ||
400
+ site.frontend_manifest["styles/index.scss"] ||
401
+ site.frontend_manifest["styles/index.sass"]
402
+ when "js"
403
+ site.frontend_manifest["javascript/index.js"] ||
404
+ site.frontend_manifest["javascript/index.js.rb"]
402
405
  else
403
406
  site.frontend_manifest.find do |item, _|
404
407
  item.sub(%r{^../(frontend/|src/)?}, "") == asset_type
@@ -457,7 +460,7 @@ module Bridgetown
457
460
  code = <<~JAVASCRIPT
458
461
  let lastmod = 0
459
462
  function startReloadConnection() {
460
- const evtSource = new EventSource("/_bridgetown/live_reload")
463
+ const evtSource = new EventSource("#{site.base_path(strip_slash_only: true)}/_bridgetown/live_reload")
461
464
  evtSource.onmessage = event => {
462
465
  if (event.data == "reloaded!") {
463
466
  location.reload()
@@ -488,6 +491,16 @@ module Bridgetown
488
491
  %(<script type="module">#{code}</script>).html_safe
489
492
  end
490
493
 
494
+ def chomp_locale_suffix!(path, locale)
495
+ return path unless locale
496
+
497
+ if path.ends_with?(".#{locale}")
498
+ path.chomp!(".#{locale}")
499
+ elsif path.ends_with?(".multi")
500
+ path.chomp!(".multi")
501
+ end
502
+ end
503
+
491
504
  private
492
505
 
493
506
  def merge_values(target, overwrite)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bridgetown
4
- VERSION = "1.0.0.beta2"
5
- CODE_NAME = "Pearl"
4
+ VERSION = "1.1.0.beta1"
5
+ CODE_NAME = "Belmont"
6
6
  end