bridgetown-core 0.15.0 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|