bridgetown-core 1.1.0.beta3 → 1.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/bridgetown +1 -3
- data/bridgetown-core.gemspec +7 -6
- data/lib/bridgetown-core/collection.rb +5 -2
- data/lib/bridgetown-core/commands/base.rb +1 -1
- data/lib/bridgetown-core/commands/build.rb +18 -5
- data/lib/bridgetown-core/commands/clean.rb +1 -1
- data/lib/bridgetown-core/commands/concerns/actions.rb +2 -4
- data/lib/bridgetown-core/commands/concerns/configuration_overridable.rb +7 -8
- data/lib/bridgetown-core/commands/console.rb +20 -1
- data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +5 -0
- data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +8 -7
- data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +1 -1
- data/lib/bridgetown-core/commands/plugins.rb +46 -32
- data/lib/bridgetown-core/commands/serve.rb +1 -2
- data/lib/bridgetown-core/commands/start.rb +0 -8
- data/lib/bridgetown-core/component.rb +50 -0
- data/lib/bridgetown-core/concerns/site/configurable.rb +22 -18
- data/lib/bridgetown-core/concerns/site/localizable.rb +2 -6
- data/lib/bridgetown-core/concerns/site/processable.rb +0 -1
- data/lib/bridgetown-core/concerns/site/ssr.rb +0 -1
- data/lib/bridgetown-core/concerns/transformable.rb +5 -2
- data/lib/bridgetown-core/configuration/configuration_dsl.rb +146 -0
- data/lib/bridgetown-core/configuration.rb +92 -16
- data/lib/bridgetown-core/configurations/gh-pages/gh-pages.yml +3 -1
- data/lib/bridgetown-core/configurations/lit/esbuild-plugins.js +5 -2
- data/lib/bridgetown-core/configurations/minitesting.rb +1 -1
- data/lib/bridgetown-core/configurations/purgecss.rb +37 -25
- data/lib/bridgetown-core/configurations/shoelace.rb +25 -3
- data/lib/bridgetown-core/configurations/tailwindcss.rb +6 -4
- data/lib/bridgetown-core/converter.rb +8 -0
- data/lib/bridgetown-core/converters/identity.rb +2 -0
- data/lib/bridgetown-core/converters/liquid_templates.rb +1 -0
- data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
- data/lib/bridgetown-core/converters/markdown.rb +2 -0
- data/lib/bridgetown-core/current.rb +19 -5
- data/lib/bridgetown-core/deprecator.rb +4 -37
- data/lib/bridgetown-core/filters.rb +1 -3
- data/lib/bridgetown-core/generated_page.rb +5 -0
- data/lib/bridgetown-core/helpers.rb +119 -8
- data/lib/bridgetown-core/hooks.rb +1 -0
- data/lib/bridgetown-core/kramdown/parser/gfm.rb +1 -1
- data/lib/bridgetown-core/layout.rb +1 -1
- data/lib/bridgetown-core/model/base.rb +11 -12
- data/lib/bridgetown-core/model/builder_origin.rb +1 -1
- data/lib/bridgetown-core/model/origin.rb +5 -1
- data/lib/bridgetown-core/model/plugin_origin.rb +1 -1
- data/lib/bridgetown-core/model/repo_origin.rb +7 -7
- data/lib/bridgetown-core/plugin.rb +2 -6
- data/lib/bridgetown-core/plugin_manager.rb +120 -41
- data/lib/bridgetown-core/rack/boot.rb +3 -7
- data/lib/bridgetown-core/rack/logger.rb +1 -0
- data/lib/bridgetown-core/rack/roda.rb +39 -45
- data/lib/bridgetown-core/rack/routes.rb +2 -6
- data/lib/bridgetown-core/rack/static_indexes.rb +1 -2
- data/lib/bridgetown-core/reader.rb +39 -50
- data/lib/bridgetown-core/readers/layout_reader.rb +1 -1
- data/lib/bridgetown-core/resource/base.rb +17 -1
- data/lib/bridgetown-core/ruby_template_view.rb +12 -8
- data/lib/bridgetown-core/site.rb +10 -3
- data/lib/bridgetown-core/slot.rb +41 -0
- data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +23 -9
- data/lib/bridgetown-core/utils/ansi.rb +1 -1
- data/lib/bridgetown-core/utils/aux.rb +7 -6
- data/lib/bridgetown-core/utils/initializers.rb +45 -0
- data/lib/bridgetown-core/utils/loaders_manager.rb +2 -2
- data/lib/bridgetown-core/utils/require_gems.rb +11 -35
- data/lib/bridgetown-core/utils/ruby_front_matter.rb +2 -3
- data/lib/bridgetown-core/{converters/smartypants.rb → utils/smarty_pants_converter.rb} +5 -24
- data/lib/bridgetown-core/utils.rb +1 -0
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/bridgetown-core/watcher.rb +1 -8
- data/lib/bridgetown-core.rb +89 -6
- data/lib/roda/plugins/bridgetown_boot.rb +25 -0
- data/lib/roda/plugins/bridgetown_ssr.rb +23 -0
- data/lib/roda/plugins/initializers.rb +17 -0
- data/lib/site_template/.gitignore +1 -0
- data/lib/site_template/Gemfile.erb +1 -1
- data/lib/site_template/TEMPLATES/erb/_layouts/default.erb +2 -2
- data/lib/site_template/TEMPLATES/erb/_layouts/page.erb +1 -1
- data/lib/site_template/TEMPLATES/erb/_layouts/post.erb +1 -1
- data/lib/site_template/TEMPLATES/liquid/_layouts/default.liquid +2 -2
- data/lib/site_template/TEMPLATES/liquid/_layouts/page.liquid +1 -1
- data/lib/site_template/TEMPLATES/liquid/_layouts/post.liquid +1 -1
- data/lib/site_template/TEMPLATES/serbea/_layouts/default.serb +2 -2
- data/lib/site_template/TEMPLATES/serbea/_layouts/page.serb +1 -1
- data/lib/site_template/TEMPLATES/serbea/_layouts/post.serb +1 -1
- data/lib/site_template/config/initializers.rb +43 -0
- data/lib/site_template/package.json.erb +1 -1
- data/lib/site_template/server/roda_app.rb +2 -8
- metadata +15 -7
@@ -65,6 +65,11 @@ module Bridgetown
|
|
65
65
|
data[property]
|
66
66
|
end
|
67
67
|
|
68
|
+
# @return [Array<Bridgetown::Slot>]
|
69
|
+
def slots
|
70
|
+
@slots ||= []
|
71
|
+
end
|
72
|
+
|
68
73
|
# The generated directory into which the page will be placed
|
69
74
|
# upon generation. This is derived from the permalink or, if
|
70
75
|
# permalink is absent, will be '/'
|
@@ -14,6 +14,8 @@ module Bridgetown
|
|
14
14
|
|
15
15
|
Context = Struct.new(:registers)
|
16
16
|
|
17
|
+
# @param view [Bridgetown::RubyTemplateView]
|
18
|
+
# @param site [Bridgetown::Site]
|
17
19
|
def initialize(view, site)
|
18
20
|
@view = view
|
19
21
|
@site = site
|
@@ -96,23 +98,35 @@ module Bridgetown
|
|
96
98
|
# @return [String] the anchor tag HTML
|
97
99
|
# @raise [ArgumentError] if the file cannot be found
|
98
100
|
def link_to(text, relative_path, options = {})
|
101
|
+
segments = attributes_from_options({ href: url_for(relative_path) }.merge(options))
|
102
|
+
|
103
|
+
safe("<a #{segments}>#{text}</a>")
|
104
|
+
end
|
105
|
+
|
106
|
+
# Create a set of attributes from a hash.
|
107
|
+
#
|
108
|
+
# @param options [Hash] key-value pairs of HTML attributes
|
109
|
+
# @return [String]
|
110
|
+
def attributes_from_options(options)
|
99
111
|
segments = []
|
100
|
-
segments << "a"
|
101
|
-
segments << "href=\"#{url_for(relative_path)}\""
|
102
112
|
options.each do |attr, option|
|
103
|
-
attr = attr
|
104
|
-
|
113
|
+
attr = dashed(attr)
|
114
|
+
if option.is_a?(Hash)
|
115
|
+
option = option.transform_keys { |key| "#{attr}-#{dashed(key)}" }
|
116
|
+
segments << attributes_from_options(option)
|
117
|
+
else
|
118
|
+
segments << attribute_segment(attr, option)
|
119
|
+
end
|
105
120
|
end
|
106
|
-
|
107
|
-
safe("<#{segments.join(" ")}>#{text}</a>")
|
121
|
+
safe(segments.join(" "))
|
108
122
|
end
|
109
123
|
|
110
124
|
# Forward all arguments to I18n.t method
|
111
125
|
#
|
112
126
|
# @return [String] the translated string
|
113
127
|
# @see I18n
|
114
|
-
def t(*args)
|
115
|
-
I18n.send :t, *args
|
128
|
+
def t(*args, **kwargs)
|
129
|
+
I18n.send :t, *args, **kwargs
|
116
130
|
end
|
117
131
|
|
118
132
|
# For template contexts where ActiveSupport's output safety is loaded, we
|
@@ -124,6 +138,103 @@ module Bridgetown
|
|
124
138
|
input.to_s.html_safe
|
125
139
|
end
|
126
140
|
alias_method :raw, :safe
|
141
|
+
|
142
|
+
# Define a new content slot
|
143
|
+
#
|
144
|
+
# @param name [String, Symbol] name of the slot
|
145
|
+
# @param input [String] content if not supplying a block
|
146
|
+
# @param replace [Boolean] set to true to replace any previously defined slot with same name
|
147
|
+
# @param transform [Boolean] set to false to avoid template-based transforms (Markdown, etc.)
|
148
|
+
# @return [void]
|
149
|
+
def slot(name, input = nil, replace: false, transform: true, &block)
|
150
|
+
content = Bridgetown::Utils.reindent_for_markdown(
|
151
|
+
block.nil? ? input.to_s : view.capture(&block)
|
152
|
+
)
|
153
|
+
|
154
|
+
resource = if view.respond_to?(:resource)
|
155
|
+
# We're in a resource rendering context
|
156
|
+
view.resource
|
157
|
+
elsif view.respond_to?(:view_context)
|
158
|
+
# We're in a component rendering context, although it's
|
159
|
+
# likely the component's own `slot` method will be called
|
160
|
+
# in this context
|
161
|
+
view.view_context.resource
|
162
|
+
end
|
163
|
+
|
164
|
+
name = name.to_s
|
165
|
+
resource.slots.reject! { _1.name == name } if replace
|
166
|
+
resource.slots << Slot.new(
|
167
|
+
name: name,
|
168
|
+
content: content,
|
169
|
+
context: resource,
|
170
|
+
transform: transform
|
171
|
+
)
|
172
|
+
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
|
176
|
+
# Render out a content slot
|
177
|
+
#
|
178
|
+
# @param name [String, Symbol] name of the slot
|
179
|
+
# @param input [String] default content if slot isn't defined and no block provided
|
180
|
+
# @return [String]
|
181
|
+
def slotted(name, default_input = nil, &default_block) # rubocop:todo Metrics
|
182
|
+
resource = if view.respond_to?(:resource)
|
183
|
+
view.resource
|
184
|
+
elsif view.respond_to?(:view_context)
|
185
|
+
view.view_context.resource
|
186
|
+
end
|
187
|
+
|
188
|
+
return unless resource
|
189
|
+
|
190
|
+
name = name.to_s
|
191
|
+
filtered_slots = resource.slots.select do |slot|
|
192
|
+
slot.name == name
|
193
|
+
end
|
194
|
+
|
195
|
+
return filtered_slots.map(&:content).join.html_safe if filtered_slots.length.positive?
|
196
|
+
|
197
|
+
default_block.nil? ? default_input.to_s : view.capture(&default_block)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Check if a content slot has been defined
|
201
|
+
#
|
202
|
+
# @return [Boolean]
|
203
|
+
def slotted?(name)
|
204
|
+
resource = if view.respond_to?(:resource)
|
205
|
+
view.resource
|
206
|
+
elsif view.respond_to?(:view_context)
|
207
|
+
view.view_context.resource
|
208
|
+
end
|
209
|
+
|
210
|
+
return unless resource
|
211
|
+
|
212
|
+
name = name.to_s
|
213
|
+
resource.slots.any? do |slot|
|
214
|
+
slot.name == name
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
|
220
|
+
# Covert an underscored value into a dashed string.
|
221
|
+
#
|
222
|
+
# @example "foo_bar_baz" => "foo-bar-baz"
|
223
|
+
#
|
224
|
+
# @param value [String|Symbol]
|
225
|
+
# @return [String]
|
226
|
+
def dashed(value)
|
227
|
+
value.to_s.tr("_", "-")
|
228
|
+
end
|
229
|
+
|
230
|
+
# Create an attribute segment for a tag.
|
231
|
+
#
|
232
|
+
# @param attr [String] the HTML attribute name
|
233
|
+
# @param value [String] the attribute value
|
234
|
+
# @return [String]
|
235
|
+
def attribute_segment(attr, value)
|
236
|
+
"#{attr}=\"#{Utils.xml_escape(value)}\""
|
237
|
+
end
|
127
238
|
end
|
128
239
|
end
|
129
240
|
end
|
@@ -70,6 +70,7 @@ module Bridgetown
|
|
70
70
|
# @yield the block will be called when the event is triggered. Typically it receives at
|
71
71
|
# least one argument.
|
72
72
|
# @yieldparam obj the object which triggered the event hook
|
73
|
+
# @return [Proc] the block that was pased in
|
73
74
|
def self.register_one(owner, event, priority: DEFAULT_PRIORITY, reloadable: true, &block)
|
74
75
|
@registry[owner] ||= []
|
75
76
|
|
@@ -10,16 +10,14 @@ module Bridgetown
|
|
10
10
|
define_model_callbacks :load, :save, :destroy
|
11
11
|
|
12
12
|
class << self
|
13
|
-
def find(id)
|
14
|
-
|
15
|
-
raise "A Bridgetown site must be initialized and added to Current"
|
16
|
-
end
|
13
|
+
def find(id, site: Bridgetown::Current.site)
|
14
|
+
raise "A Bridgetown site must be initialized and added to Current" unless site
|
17
15
|
|
18
|
-
origin = origin_for_id(id)
|
16
|
+
origin = origin_for_id(id, site: site)
|
19
17
|
klass_for_id(id, origin: origin).new(origin.read)
|
20
18
|
end
|
21
19
|
|
22
|
-
def origin_for_id(id)
|
20
|
+
def origin_for_id(id, site: Bridgetown::Current.site)
|
23
21
|
scheme = URI.parse(id).scheme
|
24
22
|
origin_klass = Origin.descendants.find do |klass|
|
25
23
|
klass.handle_scheme?(scheme)
|
@@ -27,7 +25,7 @@ module Bridgetown
|
|
27
25
|
|
28
26
|
raise "No origin could be found for #{id}" unless origin_klass
|
29
27
|
|
30
|
-
origin_klass.new(id)
|
28
|
+
origin_klass.new(id, site: site)
|
31
29
|
end
|
32
30
|
|
33
31
|
def klass_for_id(id, origin: nil)
|
@@ -40,14 +38,15 @@ module Bridgetown
|
|
40
38
|
origin ||= origin_for_id(id)
|
41
39
|
origin.verify_model?(self)
|
42
40
|
end
|
43
|
-
end
|
44
41
|
|
45
|
-
|
42
|
+
# @param builder [Bridgetown::Builder]
|
46
43
|
def build(builder, collection_name, path, data)
|
44
|
+
site = builder.site
|
47
45
|
data = Bridgetown::Model::BuilderOrigin.new(
|
48
|
-
Bridgetown::Model::BuilderOrigin.id_for_builder_path(builder, path)
|
46
|
+
Bridgetown::Model::BuilderOrigin.id_for_builder_path(builder, path),
|
47
|
+
site: site
|
49
48
|
).read do
|
50
|
-
data[:_collection_] =
|
49
|
+
data[:_collection_] = site.collections[collection_name]
|
51
50
|
data
|
52
51
|
end
|
53
52
|
new(data)
|
@@ -106,7 +105,7 @@ module Bridgetown
|
|
106
105
|
# override if need be
|
107
106
|
# @return [Bridgetown::Site]
|
108
107
|
def site
|
109
|
-
|
108
|
+
origin.site
|
110
109
|
end
|
111
110
|
|
112
111
|
# @return [Bridgetown::Collection]
|
@@ -11,13 +11,17 @@ module Bridgetown
|
|
11
11
|
# @return [String]
|
12
12
|
attr_accessor :id
|
13
13
|
|
14
|
+
# @return [Bridgetown::Site]
|
15
|
+
attr_accessor :site
|
16
|
+
|
14
17
|
# You must implement in subclasses
|
15
18
|
def self.handle_scheme?(_scheme)
|
16
19
|
false
|
17
20
|
end
|
18
21
|
|
19
|
-
def initialize(id)
|
22
|
+
def initialize(id, site: Bridgetown::Current.site)
|
20
23
|
self.id = id
|
24
|
+
self.site = site
|
21
25
|
end
|
22
26
|
|
23
27
|
# You can override in subclass
|
@@ -12,7 +12,7 @@ module Bridgetown
|
|
12
12
|
def manifest
|
13
13
|
@manifest ||= begin
|
14
14
|
manifest_origin = Addressable::URI.unescape(url.path.delete_prefix("/")).split("/").first
|
15
|
-
|
15
|
+
site.config.source_manifests.find do |manifest|
|
16
16
|
manifest.origin.to_s == manifest_origin
|
17
17
|
end.tap do |manifest|
|
18
18
|
raise "Unable to locate a source manifest for #{manifest_origin}" unless manifest
|
@@ -32,10 +32,10 @@ module Bridgetown
|
|
32
32
|
# @param collection [Bridgetown::Collection, String, Symbol] either a collection
|
33
33
|
# label or Collection object
|
34
34
|
# @param relative_path [Pathname, String] the source path of the file to save
|
35
|
-
def new_with_collection_path(collection, relative_path)
|
35
|
+
def new_with_collection_path(collection, relative_path, site: Bridgetown::Current.site)
|
36
36
|
collection = collection.label if collection.is_a?(Bridgetown::Collection)
|
37
37
|
|
38
|
-
new("repo://#{collection}.collection/#{relative_path}")
|
38
|
+
new("repo://#{collection}.collection/#{relative_path}", site: site)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -93,11 +93,11 @@ module Bridgetown
|
|
93
93
|
else
|
94
94
|
"pages"
|
95
95
|
end
|
96
|
-
@collection =
|
96
|
+
@collection = site.collections[collection_name]
|
97
97
|
end
|
98
98
|
|
99
99
|
def original_path
|
100
|
-
@original_path ||= relative_path.expand_path(
|
100
|
+
@original_path ||= relative_path.expand_path(site.source)
|
101
101
|
end
|
102
102
|
|
103
103
|
def exists?
|
@@ -118,7 +118,7 @@ module Bridgetown
|
|
118
118
|
rows:
|
119
119
|
CSV.read(original_path,
|
120
120
|
headers: true,
|
121
|
-
encoding:
|
121
|
+
encoding: site.config["encoding"]).map(&:to_hash),
|
122
122
|
}
|
123
123
|
when ".tsv"
|
124
124
|
{
|
@@ -126,7 +126,7 @@ module Bridgetown
|
|
126
126
|
CSV.read(original_path,
|
127
127
|
col_sep: "\t",
|
128
128
|
headers: true,
|
129
|
-
encoding:
|
129
|
+
encoding: site.config["encoding"]).map(&:to_hash),
|
130
130
|
}
|
131
131
|
when ".rb"
|
132
132
|
process_ruby_data(File.read(original_path), original_path, 1)
|
@@ -145,7 +145,7 @@ module Bridgetown
|
|
145
145
|
"could not read file #{original_path}: #{error.message}"
|
146
146
|
end
|
147
147
|
|
148
|
-
if
|
148
|
+
if site.config["strict_front_matter"] ||
|
149
149
|
error.is_a?(Bridgetown::Errors::FatalException)
|
150
150
|
raise error
|
151
151
|
end
|
@@ -13,13 +13,9 @@ module Bridgetown
|
|
13
13
|
lowest: -100,
|
14
14
|
}.freeze
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
# Initialize a new plugin. This should be overridden by the subclass.
|
19
|
-
#
|
20
|
-
# config - The Hash of configuration options.
|
16
|
+
# Initialize a new plugin. This should be overridden by the subclass (generator or converter)
|
21
17
|
#
|
22
|
-
#
|
18
|
+
# @param config [Bridgetown::Configuration] the configuration for the site
|
23
19
|
def initialize(config = {}) # rubocop:disable Style/RedundantInitialize
|
24
20
|
# no-op for default
|
25
21
|
end
|
@@ -2,24 +2,42 @@
|
|
2
2
|
|
3
3
|
module Bridgetown
|
4
4
|
class PluginManager
|
5
|
-
|
5
|
+
LEGACY_PLUGINS_GROUP = :bridgetown_plugins
|
6
6
|
YARN_DEPENDENCY_REGEXP = %r!(.+)@([^@]*)$!.freeze
|
7
7
|
|
8
8
|
attr_reader :site, :loaders_manager
|
9
9
|
|
10
|
-
@source_manifests = Set.new
|
11
10
|
@registered_plugins = Set.new
|
12
11
|
|
12
|
+
# @param source_manifest [Bridgetown::Configuration::SourceManifest]
|
13
13
|
def self.add_source_manifest(source_manifest)
|
14
|
-
unless source_manifest.is_a?(Bridgetown::
|
14
|
+
unless source_manifest.is_a?(Bridgetown::Configuration::SourceManifest)
|
15
15
|
raise "You must add a SourceManifest instance"
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
unless Bridgetown::Current.preloaded_configuration
|
19
|
+
raise "A preloaded configuration must be present before adding source manifests"
|
20
|
+
end
|
21
|
+
|
22
|
+
Bridgetown::Deprecator.deprecation_message(
|
23
|
+
"The #{source_manifest.origin} plugin should switch from using `add_source_manifest' to " \
|
24
|
+
"the `source_manifest` initializer method"
|
25
|
+
)
|
26
|
+
|
27
|
+
Bridgetown::Current.preloaded_configuration.source_manifests << source_manifest
|
19
28
|
end
|
20
29
|
|
21
|
-
def self.new_source_manifest(*
|
22
|
-
|
30
|
+
def self.new_source_manifest(*_args, **kwargs)
|
31
|
+
unless Bridgetown::Current.preloaded_configuration
|
32
|
+
raise "A preloaded configuration must be present before adding source manifests"
|
33
|
+
end
|
34
|
+
|
35
|
+
Bridgetown::Deprecator.deprecation_message(
|
36
|
+
"The #{kwargs[:origin]} plugin should switch from using `new_source_manifest' to the " \
|
37
|
+
"`source_manifest` initializer method"
|
38
|
+
)
|
39
|
+
|
40
|
+
add_source_manifest(Bridgetown::Configuration::SourceManifest.new(**kwargs))
|
23
41
|
end
|
24
42
|
|
25
43
|
def self.add_registered_plugin(gem_or_plugin_file)
|
@@ -27,56 +45,101 @@ module Bridgetown
|
|
27
45
|
end
|
28
46
|
|
29
47
|
class << self
|
30
|
-
attr_reader :
|
31
|
-
end
|
48
|
+
attr_reader :registered_plugins
|
32
49
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
50
|
+
def bundler_specs
|
51
|
+
@bundler_specs ||= Bundler.load.requested_specs
|
52
|
+
end
|
53
|
+
|
54
|
+
def source_manifests
|
55
|
+
Bridgetown::Deprecator.deprecation_message(
|
56
|
+
"Use the configuration's `source_manifests` method instead of the plugin manager"
|
57
|
+
)
|
58
|
+
|
59
|
+
Bridgetown::Current.preloaded_configuration.source_manifests
|
60
|
+
end
|
41
61
|
end
|
42
62
|
|
43
|
-
def self.
|
44
|
-
# NOTE: investigate why this ENV var is really necessary
|
63
|
+
def self.setup_bundler(skip_yarn: false)
|
45
64
|
if !ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile")
|
46
65
|
require "bundler"
|
47
66
|
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
install_yarn_dependencies(required_gems) unless skip_yarn
|
67
|
+
require_relative "utils/initializers"
|
68
|
+
load_determined_bundler_environment(skip_yarn: skip_yarn)
|
53
69
|
|
54
|
-
required_gems.each do |installed_gem|
|
55
|
-
add_registered_plugin installed_gem
|
56
|
-
end
|
57
|
-
|
58
|
-
Bridgetown.logger.debug("PluginManager:",
|
59
|
-
"Required #{required_gems.map(&:name).join(", ")}")
|
60
70
|
ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] = "true"
|
61
|
-
|
62
71
|
true
|
63
72
|
else
|
64
73
|
false
|
65
74
|
end
|
66
75
|
end
|
76
|
+
class << self
|
77
|
+
alias_method :require_from_bundler, :setup_bundler
|
78
|
+
end
|
67
79
|
|
68
|
-
|
80
|
+
def self.load_determined_bundler_environment(skip_yarn: false)
|
81
|
+
boot_file = File.join("config", "boot.rb")
|
82
|
+
|
83
|
+
if File.file?(boot_file)
|
84
|
+
# We'll let config/boot.rb take care of Bundler setup
|
85
|
+
require File.expand_path(boot_file)
|
86
|
+
elsif File.file?(File.join("config", "initializers.rb"))
|
87
|
+
# We'll just make sure the default and environmental gems are available.
|
88
|
+
# Note: the default Bundler config will set up all gem groups,
|
89
|
+
# see: https://bundler.io/guides/groups.html
|
90
|
+
Bundler.setup(:default, Bridgetown.env)
|
91
|
+
else
|
92
|
+
# Only setup and require :bridgetown_plugins
|
93
|
+
legacy_yarn_and_register(legacy_require, skip_yarn: skip_yarn)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.require_gem(name)
|
98
|
+
Bridgetown::Utils::RequireGems.require_with_graceful_fail(name)
|
99
|
+
plugins = Bridgetown::PluginManager.install_yarn_dependencies(name: name)
|
100
|
+
|
101
|
+
plugin_to_register = if plugins.length == 1
|
102
|
+
plugins.first
|
103
|
+
else
|
104
|
+
bundler_specs.find do |loaded_gem|
|
105
|
+
loaded_gem.to_spec&.name == name.to_s
|
106
|
+
end
|
107
|
+
end
|
108
|
+
add_registered_plugin plugin_to_register
|
109
|
+
|
110
|
+
Bridgetown.logger.debug("PluginManager:",
|
111
|
+
"Registered #{plugin_to_register.name}")
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.legacy_require
|
115
|
+
Bundler.require(LEGACY_PLUGINS_GROUP).select do |dep|
|
116
|
+
(dep.groups & [LEGACY_PLUGINS_GROUP]).any? && dep.should_include?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.legacy_yarn_and_register(required_gems, skip_yarn: false)
|
121
|
+
install_yarn_dependencies(required_gems) unless skip_yarn
|
122
|
+
|
123
|
+
required_gems.each do |installed_gem|
|
124
|
+
add_registered_plugin installed_gem
|
125
|
+
end
|
126
|
+
|
127
|
+
Bridgetown.logger.debug("PluginManager:",
|
128
|
+
"Required #{required_gems.map(&:name).join(", ")}")
|
129
|
+
end
|
130
|
+
|
131
|
+
# Iterates through loaded gems and finds yard-add gemspec metadata.
|
69
132
|
# If that exact package hasn't been installed, execute yarn add
|
70
133
|
#
|
71
|
-
#
|
72
|
-
def self.install_yarn_dependencies(required_gems,
|
73
|
-
return unless File.exist?("package.json")
|
134
|
+
# @return [Bundler::SpecSet]
|
135
|
+
def self.install_yarn_dependencies(required_gems = bundler_specs, name: nil)
|
136
|
+
return required_gems unless File.exist?("package.json")
|
74
137
|
|
75
138
|
package_json = JSON.parse(File.read("package.json"))
|
76
139
|
|
77
|
-
gems_to_search = if
|
140
|
+
gems_to_search = if name
|
78
141
|
required_gems.select do |loaded_gem|
|
79
|
-
loaded_gem.to_spec&.name ==
|
142
|
+
loaded_gem.to_spec&.name == name.to_s
|
80
143
|
end
|
81
144
|
else
|
82
145
|
required_gems
|
@@ -90,6 +153,8 @@ module Bridgetown
|
|
90
153
|
cmd = "yarn add #{yarn_dependency.join("@")}"
|
91
154
|
system cmd
|
92
155
|
end
|
156
|
+
|
157
|
+
gems_to_search
|
93
158
|
end
|
94
159
|
|
95
160
|
def self.find_yarn_dependency(loaded_gem)
|
@@ -115,9 +180,16 @@ module Bridgetown
|
|
115
180
|
current_version.nil? || (current_version != dep_version && !current_version.include?("/"))
|
116
181
|
end
|
117
182
|
|
118
|
-
#
|
183
|
+
# Provides a plugin manager for the site
|
184
|
+
#
|
185
|
+
# @param site [Bridgetown::Site]
|
186
|
+
def initialize(site)
|
187
|
+
@site = site
|
188
|
+
end
|
189
|
+
|
190
|
+
# Finds and registers plugins in the local folder(s)
|
119
191
|
#
|
120
|
-
#
|
192
|
+
# @return [void]
|
121
193
|
def require_plugin_files
|
122
194
|
plugins_path.each do |plugin_search_path|
|
123
195
|
plugin_files = Utils.safe_glob(plugin_search_path, File.join("**", "*.rb"))
|
@@ -135,11 +207,18 @@ module Bridgetown
|
|
135
207
|
end
|
136
208
|
next if site.config[:plugins_use_zeitwerk]
|
137
209
|
|
210
|
+
Deprecator.deprecation_message(
|
211
|
+
"The `plugins_use_zeitwerk' configuration option will be removed in the next version " \
|
212
|
+
"of Bridgetown (aka will be permanently set to \"true\")"
|
213
|
+
)
|
138
214
|
Bridgetown::Utils::RequireGems.require_with_graceful_fail(sorted_plugin_files)
|
139
215
|
end
|
140
216
|
end
|
141
217
|
|
142
|
-
#
|
218
|
+
# Reloads .rb plugin files via the watcher
|
219
|
+
# DEPRECATED (not necessary with Zeitwerk)
|
220
|
+
#
|
221
|
+
# @return [void]
|
143
222
|
def reload_plugin_files
|
144
223
|
return if site.config[:plugins_use_zeitwerk]
|
145
224
|
|
@@ -153,9 +232,9 @@ module Bridgetown
|
|
153
232
|
end
|
154
233
|
end
|
155
234
|
|
156
|
-
#
|
235
|
+
# Expands the path(s) of the plugins_dir config value
|
157
236
|
#
|
158
|
-
#
|
237
|
+
# @return [Array<String>] one or more plugin search paths
|
159
238
|
def plugins_path
|
160
239
|
if site.config["plugins_dir"].eql? Bridgetown::Configuration::DEFAULTS["plugins_dir"]
|
161
240
|
[site.in_root_dir(site.config["plugins_dir"])]
|
@@ -22,19 +22,16 @@ module Bridgetown
|
|
22
22
|
# Start up the Roda Rack application and the Zeitwerk autoloaders. Ensure the
|
23
23
|
# Roda app is provided the preloaded Bridgetown site configuration. Handle
|
24
24
|
# any uncaught Roda errors.
|
25
|
-
|
26
|
-
# @param [Bridgetown::Rack::Roda] optional, defaults to the `RodaApp` constant
|
27
|
-
def self.boot(roda_app = nil)
|
25
|
+
def self.boot(*)
|
28
26
|
self.loaders_manager =
|
29
27
|
Bridgetown::Utils::LoadersManager.new(Bridgetown::Current.preloaded_configuration)
|
28
|
+
Bridgetown::Current.preloaded_configuration.run_initializers! context: :server
|
30
29
|
autoload_server_folder
|
31
|
-
(roda_app || RodaApp).opts[:bridgetown_preloaded_config] =
|
32
|
-
Bridgetown::Current.preloaded_configuration
|
33
30
|
rescue Roda::RodaError => e
|
34
31
|
if e.message.include?("sessions plugin :secret option")
|
35
32
|
raise Bridgetown::Errors::InvalidConfigurationError,
|
36
33
|
"The Roda sessions plugin can't find a valid secret. Run `bin/bridgetown secret' " \
|
37
|
-
"and put the key in a ENV var you can use to configure the session in
|
34
|
+
"and put the key in a ENV var you can use to configure the session in the Roda app"
|
38
35
|
end
|
39
36
|
|
40
37
|
raise e
|
@@ -45,7 +42,6 @@ module Bridgetown
|
|
45
42
|
root: Bridgetown::Current.preloaded_configuration.root_dir
|
46
43
|
)
|
47
44
|
server_folder = File.join(root, "server")
|
48
|
-
# Bridgetown::Current.preloaded_configuration.autoload_paths << server_folder
|
49
45
|
|
50
46
|
Bridgetown::Hooks.register_one(
|
51
47
|
:loader, :post_setup, reloadable: false
|