bridgetown-core 1.0.0 → 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.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/ssr.rb +3 -3
- data/lib/bridgetown-core/concerns/site/writable.rb +28 -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/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 +1 -0
- 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 -8
- data/lib/bridgetown-core/rack/routes.rb +67 -2
- 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/utils/aux.rb +2 -1
- data/lib/bridgetown-core/utils/require_gems.rb +3 -6
- data/lib/bridgetown-core/utils.rb +24 -11
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/bridgetown-core/watcher.rb +19 -6
- data/lib/bridgetown-core.rb +8 -2
- data/lib/site_template/README.md +2 -2
- data/lib/site_template/bridgetown.config.yml +3 -0
- 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 +20 -5
- data/lib/bridgetown-core/publisher.rb +0 -29
@@ -9,10 +9,12 @@ module Bridgetown
|
|
9
9
|
|
10
10
|
def initialize(site)
|
11
11
|
@site = site
|
12
|
+
@defaults_cache = {}
|
12
13
|
end
|
13
14
|
|
14
15
|
def reset
|
15
16
|
@glob_cache = {}
|
17
|
+
@defaults_cache = {}
|
16
18
|
end
|
17
19
|
|
18
20
|
def ensure_time!(set)
|
@@ -29,16 +31,19 @@ module Bridgetown
|
|
29
31
|
# Collects a hash with all default values for a resource
|
30
32
|
#
|
31
33
|
# @param path [String] the relative path of the resource
|
32
|
-
# @param
|
34
|
+
# @param collection_name [Symbol] :posts, :pages, etc.
|
33
35
|
#
|
34
|
-
# @
|
35
|
-
def all(path,
|
36
|
-
|
36
|
+
# @return [Hash] all default values (an empty hash if there are none)
|
37
|
+
def all(path, collection_name)
|
38
|
+
if @defaults_cache.key?([path, collection_name])
|
39
|
+
return @defaults_cache[[path, collection_name]]
|
40
|
+
end
|
37
41
|
|
42
|
+
defaults = {}
|
38
43
|
merge_data_cascade_for_path(path, defaults)
|
39
44
|
|
40
45
|
old_scope = nil
|
41
|
-
matching_sets(path,
|
46
|
+
matching_sets(path, collection_name).each do |set|
|
42
47
|
if has_precedence?(old_scope, set["scope"])
|
43
48
|
defaults = Utils.deep_merge_hashes(defaults, set["values"])
|
44
49
|
old_scope = set["scope"]
|
@@ -46,7 +51,8 @@ module Bridgetown
|
|
46
51
|
defaults = Utils.deep_merge_hashes(set["values"], defaults)
|
47
52
|
end
|
48
53
|
end
|
49
|
-
|
54
|
+
|
55
|
+
@defaults_cache[[path, collection_name]] = defaults
|
50
56
|
end
|
51
57
|
|
52
58
|
private
|
@@ -123,7 +129,7 @@ module Bridgetown
|
|
123
129
|
# @param scope [Hash] the defaults set being asked about
|
124
130
|
# @param collection [Symbol] the collection of the resource being processed
|
125
131
|
#
|
126
|
-
# @
|
132
|
+
# @return [Boolean] whether either of the above conditions are satisfied
|
127
133
|
def applies_collection?(scope, collection)
|
128
134
|
!scope.key?("collection") || scope["collection"].eql?(collection.to_s)
|
129
135
|
end
|
@@ -132,7 +138,7 @@ module Bridgetown
|
|
132
138
|
#
|
133
139
|
# @param set [Hash] the default value hash as defined in bridgetown.config.yml
|
134
140
|
#
|
135
|
-
# @
|
141
|
+
# @return [Boolean] if the set is valid and can be used
|
136
142
|
def valid?(set)
|
137
143
|
set.is_a?(Hash) && set["values"].is_a?(Hash)
|
138
144
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
|
3
|
+
require "kramdown-parser-gfm"
|
4
|
+
|
5
|
+
module Kramdown
|
6
|
+
module Parser
|
7
|
+
class GFM
|
8
|
+
MARK_DELIMITER = %r{(==|::)+}.freeze
|
9
|
+
MARK_MATCH = %r{#{MARK_DELIMITER}(?!\s|=|:).*?[^\s=:]#{MARK_DELIMITER}}m.freeze
|
10
|
+
|
11
|
+
# Monkey-patch GFM initializer to add our new mark parser
|
12
|
+
alias_method :_old_initialize, :initialize
|
13
|
+
def initialize(source, options)
|
14
|
+
_old_initialize(source, options)
|
15
|
+
@span_parsers << :mark if @options[:mark_highlighting]
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_mark
|
19
|
+
line_number = @src.current_line_number
|
20
|
+
|
21
|
+
@src.pos += @src.matched_size
|
22
|
+
el = Element.new(:html_element, "mark", {}, category: :span, line: line_number)
|
23
|
+
@tree.children << el
|
24
|
+
|
25
|
+
env = save_env
|
26
|
+
reset_env(src: Kramdown::Utils::StringScanner.new(@src.matched[2..-3], line_number),
|
27
|
+
text_type: :text)
|
28
|
+
parse_spans(el)
|
29
|
+
restore_env(env)
|
30
|
+
|
31
|
+
el
|
32
|
+
end
|
33
|
+
define_parser(:mark, MARK_MATCH)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -95,8 +95,7 @@ module Bridgetown
|
|
95
95
|
|
96
96
|
# @return [Bridgetown::Resource::Base]
|
97
97
|
def as_resource_in_collection
|
98
|
-
collection.
|
99
|
-
collection.resources.last
|
98
|
+
collection.add_resource_from_model(self)
|
100
99
|
end
|
101
100
|
|
102
101
|
# @return [Bridgetown::Resource::Base]
|
@@ -3,55 +3,24 @@
|
|
3
3
|
module Bridgetown
|
4
4
|
class Plugin
|
5
5
|
extend ActiveSupport::DescendantsTracker
|
6
|
+
include Bridgetown::Prioritizable
|
6
7
|
|
7
|
-
|
8
|
-
low: -10,
|
8
|
+
self.priorities = {
|
9
9
|
highest: 100,
|
10
|
-
lowest: -100,
|
11
|
-
normal: 0,
|
12
10
|
high: 10,
|
11
|
+
normal: 0,
|
12
|
+
low: -10,
|
13
|
+
lowest: -100,
|
13
14
|
}.freeze
|
14
15
|
|
15
16
|
SourceManifest = Struct.new(:origin, :components, :content, :layouts, keyword_init: true)
|
16
17
|
|
17
|
-
# Get or set the priority of this plugin. When called without an
|
18
|
-
# argument it returns the priority. When an argument is given, it will
|
19
|
-
# set the priority.
|
20
|
-
#
|
21
|
-
# priority - The Symbol priority (default: nil). Valid options are:
|
22
|
-
# :lowest, :low, :normal, :high, :highest
|
23
|
-
#
|
24
|
-
# Returns the Symbol priority.
|
25
|
-
def self.priority(priority = nil)
|
26
|
-
@priority ||= nil
|
27
|
-
@priority = priority if priority && PRIORITIES.key?(priority)
|
28
|
-
@priority || :normal
|
29
|
-
end
|
30
|
-
|
31
|
-
# Spaceship is priority [higher -> lower]
|
32
|
-
#
|
33
|
-
# other - The class to be compared.
|
34
|
-
#
|
35
|
-
# Returns -1, 0, 1.
|
36
|
-
def self.<=>(other)
|
37
|
-
PRIORITIES[other.priority] <=> PRIORITIES[priority]
|
38
|
-
end
|
39
|
-
|
40
|
-
# Spaceship is priority [higher -> lower]
|
41
|
-
#
|
42
|
-
# other - The class to be compared.
|
43
|
-
#
|
44
|
-
# Returns -1, 0, 1.
|
45
|
-
def <=>(other)
|
46
|
-
self.class <=> other.class
|
47
|
-
end
|
48
|
-
|
49
18
|
# Initialize a new plugin. This should be overridden by the subclass.
|
50
19
|
#
|
51
20
|
# config - The Hash of configuration options.
|
52
21
|
#
|
53
22
|
# Returns a new instance.
|
54
|
-
def initialize(config = {})
|
23
|
+
def initialize(config = {}) # rubocop:disable Style/RedundantInitialize
|
55
24
|
# no-op for default
|
56
25
|
end
|
57
26
|
end
|
@@ -40,7 +40,8 @@ module Bridgetown
|
|
40
40
|
@loaders_manager = Bridgetown::Utils::LoadersManager.new(site.config)
|
41
41
|
end
|
42
42
|
|
43
|
-
def self.require_from_bundler
|
43
|
+
def self.require_from_bundler(skip_yarn: false) # rubocop:todo Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
44
|
+
# NOTE: investigate why this ENV var is really necessary
|
44
45
|
if !ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile")
|
45
46
|
require "bundler"
|
46
47
|
|
@@ -48,7 +49,7 @@ module Bridgetown
|
|
48
49
|
(dep.groups & [PLUGINS_GROUP]).any? && dep.should_include?
|
49
50
|
end
|
50
51
|
|
51
|
-
install_yarn_dependencies(required_gems)
|
52
|
+
install_yarn_dependencies(required_gems) unless skip_yarn
|
52
53
|
|
53
54
|
required_gems.each do |installed_gem|
|
54
55
|
add_registered_plugin installed_gem
|
@@ -19,6 +19,11 @@ module Bridgetown
|
|
19
19
|
attr_accessor :loaders_manager
|
20
20
|
end
|
21
21
|
|
22
|
+
# Start up the Roda Rack application and the Zeitwerk autoloaders. Ensure the
|
23
|
+
# Roda app is provided the preloaded Bridgetown site configuration. Handle
|
24
|
+
# any uncaught Roda errors.
|
25
|
+
#
|
26
|
+
# @param [Bridgetown::Rack::Roda] optional, defaults to the `RodaApp` constant
|
22
27
|
def self.boot(roda_app = nil)
|
23
28
|
self.loaders_manager =
|
24
29
|
Bridgetown::Utils::LoadersManager.new(Bridgetown::Current.preloaded_configuration)
|
@@ -4,19 +4,29 @@ require "logger"
|
|
4
4
|
|
5
5
|
module Bridgetown
|
6
6
|
module Rack
|
7
|
-
class Logger <
|
7
|
+
class Logger < Bridgetown::LogWriter
|
8
8
|
def self.message_with_prefix(msg)
|
9
|
-
return if msg.include?("/_bridgetown/live_reload")
|
9
|
+
# return if msg.include?("/_bridgetown/live_reload")
|
10
10
|
|
11
11
|
"\e[35m[Server]\e[0m #{msg}"
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
super
|
14
|
+
def enable_prefix
|
16
15
|
@formatter = proc do |_, _, _, msg|
|
17
16
|
self.class.message_with_prefix(msg)
|
18
17
|
end
|
19
18
|
end
|
19
|
+
|
20
|
+
def add(severity, message = nil, progname = nil)
|
21
|
+
return if progname&.include?("/_bridgetown/live_reload")
|
22
|
+
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(*_args)
|
27
|
+
super()
|
28
|
+
enable_prefix
|
29
|
+
end
|
20
30
|
end
|
21
31
|
end
|
22
32
|
end
|
@@ -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
|
@@ -51,14 +148,11 @@ module Bridgetown
|
|
51
148
|
request.root do
|
52
149
|
output_folder = Bridgetown::Current.preloaded_configuration.destination
|
53
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>"
|
54
154
|
end
|
55
155
|
end
|
56
|
-
|
57
|
-
# Helper shorthand for Bridgetown::Current.site
|
58
|
-
# @return [Bridgetown::Site]
|
59
|
-
def bridgetown_site
|
60
|
-
Bridgetown::Current.site
|
61
|
-
end
|
62
156
|
end
|
63
157
|
end
|
64
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,16 +60,38 @@ 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)
|
44
96
|
if Bridgetown::Current.preloaded_configuration.base_path == "/"
|
45
97
|
load_all_routes roda_app
|
@@ -56,6 +108,12 @@ module Bridgetown
|
|
56
108
|
nil
|
57
109
|
end
|
58
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]
|
59
117
|
def load_all_routes(roda_app)
|
60
118
|
roda_app.request.public
|
61
119
|
|
@@ -64,7 +122,7 @@ module Bridgetown
|
|
64
122
|
setup_live_reload roda_app
|
65
123
|
end
|
66
124
|
|
67
|
-
Bridgetown::Rack::Routes.
|
125
|
+
Bridgetown::Rack::Routes.sorted_subclasses&.each do |klass|
|
68
126
|
klass.merge roda_app
|
69
127
|
end
|
70
128
|
|
@@ -73,6 +131,7 @@ module Bridgetown
|
|
73
131
|
Bridgetown::Routes::RodaRouter.start!(roda_app)
|
74
132
|
end
|
75
133
|
|
134
|
+
# @param app [Bridgetown::Rack::Roda]
|
76
135
|
def setup_live_reload(app) # rubocop:disable Metrics/AbcSize
|
77
136
|
sleep_interval = 0.2
|
78
137
|
file_to_check = File.join(app.class.opts[:bridgetown_preloaded_config].destination,
|
@@ -102,14 +161,20 @@ module Bridgetown
|
|
102
161
|
end
|
103
162
|
end
|
104
163
|
|
164
|
+
# @param roda_app [Bridgetown::Rack::Roda]
|
105
165
|
def initialize(roda_app)
|
106
166
|
@_roda_app = roda_app
|
107
167
|
end
|
108
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
|
109
173
|
def handle_routes
|
110
174
|
instance_exec(@_roda_app.request, &self.class.router_block)
|
111
175
|
end
|
112
176
|
|
177
|
+
# Any missing methods are passed along to the underlying Roda app if possible
|
113
178
|
def method_missing(method_name, *args, **kwargs, &block)
|
114
179
|
if @_roda_app.respond_to?(method_name.to_sym)
|
115
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
|
@@ -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
|