bridgetown-core 1.0.0.beta2 → 1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -1
- data/lib/bridgetown-core/collection.rb +37 -20
- data/lib/bridgetown-core/commands/concerns/actions.rb +3 -2
- data/lib/bridgetown-core/commands/configure.rb +1 -1
- data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +20 -16
- data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +95 -12
- data/lib/bridgetown-core/commands/new.rb +10 -9
- data/lib/bridgetown-core/commands/plugins.rb +2 -0
- data/lib/bridgetown-core/commands/start.rb +3 -0
- data/lib/bridgetown-core/commands/webpack/update.rb +2 -2
- data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +11 -2
- data/lib/bridgetown-core/component.rb +13 -7
- data/lib/bridgetown-core/concerns/localizable.rb +20 -0
- data/lib/bridgetown-core/concerns/prioritizable.rb +44 -0
- data/lib/bridgetown-core/concerns/publishable.rb +11 -1
- data/lib/bridgetown-core/concerns/site/configurable.rb +2 -10
- data/lib/bridgetown-core/concerns/site/localizable.rb +5 -1
- data/lib/bridgetown-core/concerns/site/renderable.rb +27 -16
- data/lib/bridgetown-core/concerns/site/ssr.rb +3 -3
- data/lib/bridgetown-core/concerns/site/writable.rb +28 -0
- data/lib/bridgetown-core/concerns/transformable.rb +62 -0
- data/lib/bridgetown-core/configuration.rb +2 -0
- data/lib/bridgetown-core/configurations/bt-postcss/postcss.config.js +5 -3
- data/lib/bridgetown-core/configurations/bt-postcss.rb +1 -1
- data/lib/bridgetown-core/configurations/gh-pages/gh-pages.yml +33 -0
- data/lib/bridgetown-core/configurations/gh-pages.rb +16 -0
- data/lib/bridgetown-core/configurations/lit/esbuild-plugins.js +21 -0
- data/lib/bridgetown-core/configurations/lit/happy-days.lit.js +26 -0
- data/lib/bridgetown-core/configurations/lit/lit-components-entry.js +1 -0
- data/lib/bridgetown-core/configurations/lit/lit-ssr.config.js +6 -0
- data/lib/bridgetown-core/configurations/lit.rb +95 -0
- data/lib/bridgetown-core/configurations/open-props/variables.css.erb +11 -0
- data/lib/bridgetown-core/configurations/open-props.rb +21 -0
- data/lib/bridgetown-core/configurations/ruby2js/hello_world.js.rb +9 -0
- data/lib/bridgetown-core/configurations/ruby2js.rb +67 -0
- data/lib/bridgetown-core/configurations/shoelace.rb +50 -0
- data/lib/bridgetown-core/configurations/tailwindcss.rb +16 -2
- data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
- data/lib/bridgetown-core/drops/generated_page_drop.rb +2 -1
- data/lib/bridgetown-core/drops/resource_drop.rb +2 -1
- data/lib/bridgetown-core/errors.rb +5 -5
- data/lib/bridgetown-core/filters/translation_filters.rb +11 -0
- data/lib/bridgetown-core/filters/url_filters.rb +37 -10
- data/lib/bridgetown-core/filters.rb +3 -0
- data/lib/bridgetown-core/frontmatter_defaults.rb +14 -8
- data/lib/bridgetown-core/generated_page.rb +82 -17
- data/lib/bridgetown-core/kramdown/parser/gfm.rb +36 -0
- data/lib/bridgetown-core/model/base.rb +1 -2
- data/lib/bridgetown-core/plugin.rb +6 -37
- data/lib/bridgetown-core/plugin_manager.rb +3 -2
- data/lib/bridgetown-core/rack/boot.rb +5 -0
- data/lib/bridgetown-core/rack/logger.rb +14 -4
- data/lib/bridgetown-core/rack/roda.rb +102 -10
- data/lib/bridgetown-core/rack/routes.rb +87 -6
- data/lib/bridgetown-core/resource/base.rb +4 -6
- data/lib/bridgetown-core/resource/destination.rb +18 -0
- data/lib/bridgetown-core/resource/permalink_processor.rb +6 -4
- data/lib/bridgetown-core/resource/relations.rb +1 -1
- data/lib/bridgetown-core/resource/transformer.rb +21 -85
- data/lib/bridgetown-core/utils/aux.rb +2 -1
- data/lib/bridgetown-core/utils/require_gems.rb +3 -6
- data/lib/bridgetown-core/utils.rb +25 -12
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/bridgetown-core/watcher.rb +19 -6
- data/lib/bridgetown-core.rb +9 -3
- data/lib/site_template/Gemfile.erb +1 -1
- data/lib/site_template/README.md +2 -2
- data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +4 -4
- data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +4 -4
- data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +4 -4
- data/lib/site_template/bridgetown.config.yml +10 -3
- data/lib/site_template/frontend/javascript/index.js.erb +1 -0
- data/lib/site_template/frontend/styles/syntax-highlighting.css +77 -0
- data/lib/site_template/package.json.erb +18 -17
- data/lib/site_template/server/roda_app.rb +3 -6
- data/lib/site_template/src/404.html +2 -1
- data/lib/site_template/src/500.html +10 -0
- metadata +21 -4
- data/lib/bridgetown-core/publisher.rb +0 -29
- 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
|
-
|
36
|
-
|
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
|
-
|
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.
|
125
|
+
Bridgetown::Rack::Routes.sorted_subclasses&.each do |klass|
|
50
126
|
klass.merge roda_app
|
51
127
|
end
|
52
128
|
|
53
|
-
|
54
|
-
Bridgetown::Routes::RodaRouter.start!(roda_app)
|
55
|
-
end
|
129
|
+
return unless defined?(Bridgetown::Routes::RodaRouter)
|
56
130
|
|
57
|
-
|
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
|
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
|
-
|
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
|
-
|
117
|
-
|
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
|
-
|
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).
|
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
|
-
|
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
|
-
|
147
|
-
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(
|
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
|
-
|
45
|
-
|
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'
|
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!^ +!).
|
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 =
|
399
|
-
|
400
|
-
site.frontend_manifest["
|
401
|
-
site.frontend_manifest["
|
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)
|