bridgetown-core 0.15.0 → 0.17.1
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/Rakefile +14 -0
- data/bridgetown-core.gemspec +4 -1
- data/lib/bridgetown-core.rb +8 -2
- data/lib/bridgetown-core/commands/concerns/actions.rb +2 -1
- data/lib/bridgetown-core/commands/console.rb +4 -4
- data/lib/bridgetown-core/concerns/data_accessible.rb +19 -0
- data/lib/bridgetown-core/concerns/layout_placeable.rb +17 -0
- data/lib/bridgetown-core/concerns/liquid_renderable.rb +20 -0
- data/lib/bridgetown-core/concerns/publishable.rb +10 -0
- data/lib/bridgetown-core/concerns/site/configurable.rb +66 -31
- data/lib/bridgetown-core/concerns/site/content.rb +90 -31
- data/lib/bridgetown-core/concerns/site/extensible.rb +15 -12
- data/lib/bridgetown-core/concerns/site/localizable.rb +20 -0
- data/lib/bridgetown-core/concerns/site/processable.rb +14 -12
- data/lib/bridgetown-core/concerns/site/renderable.rb +21 -2
- data/lib/bridgetown-core/concerns/site/writable.rb +16 -2
- data/lib/bridgetown-core/concerns/validatable.rb +59 -0
- data/lib/bridgetown-core/configuration.rb +10 -3
- data/lib/bridgetown-core/converter.rb +34 -0
- data/lib/bridgetown-core/converters/erb_templates.rb +78 -0
- data/lib/bridgetown-core/converters/markdown.rb +6 -23
- data/lib/bridgetown-core/converters/smartypants.rb +0 -10
- data/lib/bridgetown-core/document.rb +11 -55
- data/lib/bridgetown-core/drops/site_drop.rb +1 -1
- data/lib/bridgetown-core/errors.rb +2 -0
- data/lib/bridgetown-core/excerpt.rb +1 -6
- data/lib/bridgetown-core/filters.rb +11 -48
- data/lib/bridgetown-core/filters/condition_helpers.rb +56 -0
- data/lib/bridgetown-core/frontmatter_defaults.rb +17 -0
- data/lib/bridgetown-core/layout.rb +24 -1
- data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -1
- data/lib/bridgetown-core/page.rb +41 -26
- data/lib/bridgetown-core/plugin_manager.rb +10 -2
- data/lib/bridgetown-core/reader.rb +1 -0
- data/lib/bridgetown-core/readers/collection_reader.rb +1 -0
- data/lib/bridgetown-core/readers/data_reader.rb +4 -3
- data/lib/bridgetown-core/readers/defaults_reader.rb +27 -0
- data/lib/bridgetown-core/readers/layout_reader.rb +1 -0
- data/lib/bridgetown-core/readers/page_reader.rb +1 -0
- data/lib/bridgetown-core/readers/post_reader.rb +1 -0
- data/lib/bridgetown-core/readers/static_file_reader.rb +1 -0
- data/lib/bridgetown-core/regenerator.rb +1 -1
- data/lib/bridgetown-core/renderer.rb +40 -14
- data/lib/bridgetown-core/ruby_template_view.rb +113 -0
- data/lib/bridgetown-core/site.rb +2 -0
- data/lib/bridgetown-core/tags/class_map.rb +90 -0
- data/lib/bridgetown-core/tags/find.rb +86 -0
- data/lib/bridgetown-core/tags/t.rb +14 -0
- data/lib/bridgetown-core/tags/webpack_path.rb +19 -22
- data/lib/bridgetown-core/utils.rb +55 -2
- data/lib/bridgetown-core/utils/ruby_exec.rb +1 -1
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/site_template/src/_layouts/{default.html → default.liquid} +0 -0
- data/lib/site_template/src/_layouts/{home.html → home.liquid} +0 -0
- data/lib/site_template/src/_layouts/{page.html → page.liquid} +0 -0
- data/lib/site_template/src/_layouts/{post.html → post.liquid} +0 -0
- metadata +64 -10
- data/lib/bridgetown-core/concerns/convertible.rb +0 -235
data/lib/bridgetown-core/page.rb
CHANGED
@@ -2,24 +2,19 @@
|
|
2
2
|
|
3
3
|
module Bridgetown
|
4
4
|
class Page
|
5
|
-
include
|
5
|
+
include DataAccessible
|
6
|
+
include LayoutPlaceable
|
7
|
+
include LiquidRenderable
|
8
|
+
include Publishable
|
9
|
+
include Validatable
|
6
10
|
|
7
11
|
attr_writer :dir
|
8
|
-
attr_accessor :site, :pager
|
12
|
+
attr_accessor :site, :paginator, :pager
|
9
13
|
attr_accessor :name, :ext, :basename
|
10
14
|
attr_accessor :data, :content, :output
|
11
15
|
|
12
16
|
alias_method :extname, :ext
|
13
17
|
|
14
|
-
# Attributes for Liquid templates
|
15
|
-
ATTRIBUTES_FOR_LIQUID = %w(
|
16
|
-
content
|
17
|
-
dir
|
18
|
-
name
|
19
|
-
path
|
20
|
-
url
|
21
|
-
).freeze
|
22
|
-
|
23
18
|
# A set of extensions that are considered HTML or HTML-like so we
|
24
19
|
# should not alter them, this includes .xhtml through XHTM5.
|
25
20
|
|
@@ -126,12 +121,18 @@ module Bridgetown
|
|
126
121
|
# desired placeholder replacements. For details see "url.rb"
|
127
122
|
def url_placeholders
|
128
123
|
{
|
129
|
-
path:
|
124
|
+
path: qualified_pages_path_for_url,
|
130
125
|
basename: basename,
|
131
126
|
output_ext: output_ext,
|
132
127
|
}
|
133
128
|
end
|
134
129
|
|
130
|
+
# Strips _pages prefix off if needed for the url/destination generation
|
131
|
+
# @return [String]
|
132
|
+
def qualified_pages_path_for_url
|
133
|
+
@dir.sub(%r!^/_pages!, "")
|
134
|
+
end
|
135
|
+
|
135
136
|
# Extract information from the page filename.
|
136
137
|
#
|
137
138
|
# name - The String filename of the page file.
|
@@ -143,19 +144,6 @@ module Bridgetown
|
|
143
144
|
self.basename = name[0..-ext.length - 1].gsub(%r!\.*\z!, "")
|
144
145
|
end
|
145
146
|
|
146
|
-
# Add any necessary layouts to this post
|
147
|
-
#
|
148
|
-
# layouts - The Hash of {"name" => "layout"}.
|
149
|
-
# site_payload - The site payload Hash.
|
150
|
-
#
|
151
|
-
# Returns String rendered page.
|
152
|
-
def render(layouts, site_payload)
|
153
|
-
site_payload["page"] = to_liquid
|
154
|
-
site_payload["paginator"] = pager.to_liquid
|
155
|
-
|
156
|
-
do_layout(site_payload, layouts)
|
157
|
-
end
|
158
|
-
|
159
147
|
# The path to the source file
|
160
148
|
#
|
161
149
|
# Returns the path to the source file
|
@@ -168,6 +156,16 @@ module Bridgetown
|
|
168
156
|
@relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).delete_prefix("/")
|
169
157
|
end
|
170
158
|
|
159
|
+
# FIXME: spinning up a new Renderer object just to get an extension
|
160
|
+
# seems excessive
|
161
|
+
#
|
162
|
+
# The output extension of the page.
|
163
|
+
#
|
164
|
+
# Returns the output extension
|
165
|
+
def output_ext
|
166
|
+
@output_ext ||= Bridgetown::Renderer.new(site, self).output_ext
|
167
|
+
end
|
168
|
+
|
171
169
|
# Obtain destination path.
|
172
170
|
#
|
173
171
|
# dest - The String path to the destination dir.
|
@@ -180,9 +178,22 @@ module Bridgetown
|
|
180
178
|
path
|
181
179
|
end
|
182
180
|
|
181
|
+
# Write the generated page file to the destination directory.
|
182
|
+
#
|
183
|
+
# dest - The String path to the destination dir.
|
184
|
+
#
|
185
|
+
# Returns nothing.
|
186
|
+
def write(dest)
|
187
|
+
path = destination(dest)
|
188
|
+
FileUtils.mkdir_p(File.dirname(path))
|
189
|
+
Bridgetown.logger.debug "Writing:", path
|
190
|
+
File.write(path, output, mode: "wb")
|
191
|
+
Bridgetown::Hooks.trigger :pages, :post_write, self
|
192
|
+
end
|
193
|
+
|
183
194
|
# Returns the object as a debug String.
|
184
195
|
def inspect
|
185
|
-
"#<#{self.class}
|
196
|
+
"#<#{self.class} #{relative_path}>"
|
186
197
|
end
|
187
198
|
|
188
199
|
# Returns the Boolean of whether this Page is HTML or not.
|
@@ -199,6 +210,10 @@ module Bridgetown
|
|
199
210
|
Bridgetown::Hooks.trigger :pages, hook_name, self, *args
|
200
211
|
end
|
201
212
|
|
213
|
+
def type
|
214
|
+
:pages
|
215
|
+
end
|
216
|
+
|
202
217
|
def write?
|
203
218
|
true
|
204
219
|
end
|
@@ -68,12 +68,20 @@ module Bridgetown
|
|
68
68
|
# If that exact package hasn't been installed, execute yarn add
|
69
69
|
#
|
70
70
|
# Returns nothing.
|
71
|
-
def self.install_yarn_dependencies(required_gems)
|
71
|
+
def self.install_yarn_dependencies(required_gems, single_gemname = nil)
|
72
72
|
return unless File.exist?("package.json")
|
73
73
|
|
74
74
|
package_json = JSON.parse(File.read("package.json"))
|
75
75
|
|
76
|
-
|
76
|
+
gems_to_search = if single_gemname
|
77
|
+
required_gems.select do |loaded_gem|
|
78
|
+
loaded_gem.to_spec&.name == single_gemname.to_s
|
79
|
+
end
|
80
|
+
else
|
81
|
+
required_gems
|
82
|
+
end
|
83
|
+
|
84
|
+
gems_to_search.each do |loaded_gem|
|
77
85
|
yarn_dependency = find_yarn_dependency(loaded_gem)
|
78
86
|
next unless add_yarn_dependency?(yarn_dependency, package_json)
|
79
87
|
|
@@ -3,9 +3,10 @@
|
|
3
3
|
module Bridgetown
|
4
4
|
class DataReader
|
5
5
|
attr_reader :site, :content
|
6
|
+
|
6
7
|
def initialize(site)
|
7
8
|
@site = site
|
8
|
-
@content =
|
9
|
+
@content = {}
|
9
10
|
@entry_filter = EntryFilter.new(site)
|
10
11
|
end
|
11
12
|
|
@@ -19,7 +20,7 @@ module Bridgetown
|
|
19
20
|
base = site.in_source_dir(dir)
|
20
21
|
read_data_to(base, @content)
|
21
22
|
merge_environment_specific_metadata!
|
22
|
-
@content
|
23
|
+
@content = @content.with_dot_access
|
23
24
|
end
|
24
25
|
|
25
26
|
# Read and parse all .yaml, .yml, .json, .csv and .tsv
|
@@ -43,7 +44,7 @@ module Bridgetown
|
|
43
44
|
if File.directory?(path)
|
44
45
|
read_data_to(
|
45
46
|
path,
|
46
|
-
data[sanitize_filename(entry)] =
|
47
|
+
data[sanitize_filename(entry)] = {}
|
47
48
|
)
|
48
49
|
else
|
49
50
|
key = sanitize_filename(File.basename(entry, ".*"))
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
class DefaultsReader
|
5
|
+
attr_reader :site, :path_defaults
|
6
|
+
|
7
|
+
def initialize(site)
|
8
|
+
@site = site
|
9
|
+
@path_defaults = HashWithDotAccess::Hash.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def read
|
13
|
+
return unless File.directory?(site.source)
|
14
|
+
|
15
|
+
entries = Dir.chdir(site.source) do
|
16
|
+
Dir["**/_defaults.{yaml,yml,json}"]
|
17
|
+
end
|
18
|
+
|
19
|
+
entries.each do |entry|
|
20
|
+
path = @site.in_source_dir(entry)
|
21
|
+
@path_defaults[File.dirname(path) + File::SEPARATOR] = SafeYAML.load_file(path)
|
22
|
+
end
|
23
|
+
|
24
|
+
@path_defaults
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -163,7 +163,7 @@ module Bridgetown
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def regenerate_page?(document)
|
166
|
-
document.
|
166
|
+
document.data["regenerate"] ||
|
167
167
|
source_modified_or_dest_missing?(
|
168
168
|
site.in_source_dir(document.relative_path), document.destination(@site.dest)
|
169
169
|
)
|
@@ -58,6 +58,7 @@ module Bridgetown
|
|
58
58
|
Bridgetown.logger.debug "Rendering:", document.relative_path
|
59
59
|
|
60
60
|
assign_pages!
|
61
|
+
# TODO: this can be eliminated I think:
|
61
62
|
assign_current_document!
|
62
63
|
assign_highlighter_options!
|
63
64
|
assign_layout_data!
|
@@ -83,7 +84,7 @@ module Bridgetown
|
|
83
84
|
end
|
84
85
|
|
85
86
|
Bridgetown.logger.debug "Rendering Markup:", document.relative_path
|
86
|
-
output = convert(output.to_s)
|
87
|
+
output = convert(output.to_s, document)
|
87
88
|
document.content = output
|
88
89
|
|
89
90
|
if document.place_in_layout?
|
@@ -140,9 +141,13 @@ module Bridgetown
|
|
140
141
|
# Convert the document using the converters which match this renderer's document.
|
141
142
|
#
|
142
143
|
# Returns String the converted content.
|
143
|
-
def convert(content)
|
144
|
+
def convert(content, document)
|
144
145
|
converters.reduce(content) do |output, converter|
|
145
|
-
converter.convert
|
146
|
+
if converter.method(:convert).arity == 1
|
147
|
+
converter.convert output
|
148
|
+
else
|
149
|
+
converter.convert output, document
|
150
|
+
end
|
146
151
|
rescue StandardError => e
|
147
152
|
Bridgetown.logger.error "Conversion error:",
|
148
153
|
"#{converter.class} encountered an error while "\
|
@@ -202,17 +207,38 @@ module Bridgetown
|
|
202
207
|
# Render layout content into document.output
|
203
208
|
#
|
204
209
|
# Returns String rendered content
|
210
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
205
211
|
def render_layout(output, layout, liquid_context)
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
212
|
+
if layout.render_with_liquid?
|
213
|
+
payload["content"] = output
|
214
|
+
payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
|
215
|
+
|
216
|
+
render_liquid(
|
217
|
+
layout.content,
|
218
|
+
payload,
|
219
|
+
liquid_context,
|
220
|
+
layout.path
|
221
|
+
)
|
222
|
+
else
|
223
|
+
layout_converters ||= site.converters.select { |c| c.matches(layout.ext) }.sort
|
224
|
+
|
225
|
+
layout_content = layout.content.dup
|
226
|
+
layout_converters.reduce(layout_content) do |layout_output, converter|
|
227
|
+
next(layout_output) unless converter.method(:convert).arity == 2
|
228
|
+
|
229
|
+
layout.current_document = document
|
230
|
+
layout.current_document_output = output
|
231
|
+
converter.convert layout_output, layout
|
232
|
+
rescue StandardError => e
|
233
|
+
Bridgetown.logger.error "Conversion error:",
|
234
|
+
"#{converter.class} encountered an error while "\
|
235
|
+
"converting '#{document.relative_path}':"
|
236
|
+
Bridgetown.logger.error("", e.to_s)
|
237
|
+
raise e
|
238
|
+
end
|
239
|
+
end
|
215
240
|
end
|
241
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
216
242
|
|
217
243
|
def add_regenerator_dependencies(layout)
|
218
244
|
return unless document.write?
|
@@ -223,12 +249,12 @@ module Bridgetown
|
|
223
249
|
)
|
224
250
|
end
|
225
251
|
|
226
|
-
# Set page content to payload and assign
|
252
|
+
# Set page content to payload and assign paginator if document has one.
|
227
253
|
#
|
228
254
|
# Returns nothing
|
229
255
|
def assign_pages!
|
230
256
|
payload["page"] = document.to_liquid
|
231
|
-
payload["paginator"] =
|
257
|
+
payload["paginator"] = document.paginator.to_liquid if document.respond_to?(:paginator)
|
232
258
|
end
|
233
259
|
|
234
260
|
# Set related posts to payload if document is a post.
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest"
|
4
|
+
require "active_support/core_ext/hash/keys"
|
5
|
+
|
6
|
+
module Bridgetown
|
7
|
+
class RubyTemplateView
|
8
|
+
class Helpers
|
9
|
+
include Bridgetown::Filters
|
10
|
+
|
11
|
+
attr_reader :view, :site
|
12
|
+
|
13
|
+
Context = Struct.new(:registers)
|
14
|
+
|
15
|
+
def initialize(view, site)
|
16
|
+
@view = view
|
17
|
+
@site = site
|
18
|
+
|
19
|
+
# duck typing for Liquid context
|
20
|
+
@context = Context.new({ site: site })
|
21
|
+
end
|
22
|
+
|
23
|
+
def webpack_path(asset_type)
|
24
|
+
Bridgetown::Utils.parse_webpack_manifest_file(site, asset_type.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param pairs [Hash] A hash of key/value pairs.
|
28
|
+
#
|
29
|
+
# @return [String] Space-separated keys where the values are truthy.
|
30
|
+
def class_map(pairs = {})
|
31
|
+
pairs.select { |_key, truthy| truthy }.keys.join(" ")
|
32
|
+
end
|
33
|
+
|
34
|
+
def t(*args)
|
35
|
+
I18n.send :t, *args
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :layout, :page, :paginator, :site, :content
|
40
|
+
|
41
|
+
def initialize(convertible)
|
42
|
+
if convertible.is_a?(Layout)
|
43
|
+
@layout = convertible
|
44
|
+
@page = layout.current_document
|
45
|
+
@content = layout.current_document_output
|
46
|
+
else
|
47
|
+
@page = convertible
|
48
|
+
end
|
49
|
+
@paginator = page.paginator if page.respond_to?(:paginator)
|
50
|
+
@site = page.site
|
51
|
+
end
|
52
|
+
|
53
|
+
def partial(_partial_name, _options = {})
|
54
|
+
raise "Must be implemented in a subclass"
|
55
|
+
end
|
56
|
+
|
57
|
+
def site_drop
|
58
|
+
site.site_payload.site
|
59
|
+
end
|
60
|
+
|
61
|
+
def liquid_render(component, options = {})
|
62
|
+
render_statement = _render_statement(component, options)
|
63
|
+
|
64
|
+
template = site.liquid_renderer.file(
|
65
|
+
"#{page.path}.#{Digest::SHA2.hexdigest(render_statement)}"
|
66
|
+
).parse(render_statement)
|
67
|
+
template.warnings.each do |e|
|
68
|
+
Bridgetown.logger.warn "Liquid Warning:",
|
69
|
+
LiquidRenderer.format_error(e, path || document.relative_path)
|
70
|
+
end
|
71
|
+
template.render!(options.deep_stringify_keys, _liquid_context)
|
72
|
+
end
|
73
|
+
|
74
|
+
def helpers
|
75
|
+
@helpers ||= Helpers.new(self, site)
|
76
|
+
end
|
77
|
+
|
78
|
+
def method_missing(method, *args, &block)
|
79
|
+
if helpers.respond_to?(method.to_sym)
|
80
|
+
helpers.send method.to_sym, *args, &block
|
81
|
+
else
|
82
|
+
super
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def respond_to_missing?(method, include_private = false)
|
87
|
+
helpers.respond_to?(method.to_sym, include_private) || super
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def _render_statement(component, options)
|
93
|
+
render_statement = ["{% render \"#{component}\""]
|
94
|
+
unless options.empty?
|
95
|
+
render_statement << ", " + options.keys.map { |k| "#{k}: #{k}" }.join(", ")
|
96
|
+
end
|
97
|
+
render_statement << " %}"
|
98
|
+
render_statement.join
|
99
|
+
end
|
100
|
+
|
101
|
+
def _liquid_context
|
102
|
+
{
|
103
|
+
registers: {
|
104
|
+
site: site,
|
105
|
+
page: page,
|
106
|
+
cached_partials: Bridgetown::Renderer.cached_partials,
|
107
|
+
},
|
108
|
+
strict_filters: site.config["liquid"]["strict_filters"],
|
109
|
+
strict_variables: site.config["liquid"]["strict_variables"],
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|