bridgetown-core 1.0.0.alpha1 → 1.0.0.alpha5
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 +35 -0
- data/Rakefile +5 -5
- data/lib/bridgetown-core/cache.rb +3 -5
- data/lib/bridgetown-core/cleaner.rb +2 -2
- data/lib/bridgetown-core/collection.rb +4 -6
- data/lib/bridgetown-core/commands/base.rb +4 -3
- data/lib/bridgetown-core/commands/build.rb +20 -19
- data/lib/bridgetown-core/commands/concerns/actions.rb +2 -2
- data/lib/bridgetown-core/commands/console.rb +3 -3
- data/lib/bridgetown-core/commands/doctor.rb +10 -8
- data/lib/bridgetown-core/commands/new.rb +5 -3
- data/lib/bridgetown-core/commands/plugins.rb +7 -9
- data/lib/bridgetown-core/commands/serve/servlet.rb +4 -4
- data/lib/bridgetown-core/commands/serve.rb +25 -27
- data/lib/bridgetown-core/commands/start.rb +6 -6
- data/lib/bridgetown-core/commands/webpack.rb +1 -1
- data/lib/bridgetown-core/component.rb +2 -6
- data/lib/bridgetown-core/concerns/liquid_renderable.rb +2 -2
- data/lib/bridgetown-core/concerns/site/configurable.rb +1 -6
- data/lib/bridgetown-core/concerns/site/content.rb +2 -2
- data/lib/bridgetown-core/concerns/site/extensible.rb +3 -4
- data/lib/bridgetown-core/concerns/site/localizable.rb +1 -1
- data/lib/bridgetown-core/concerns/site/ssr.rb +1 -1
- data/lib/bridgetown-core/concerns/site/writable.rb +1 -1
- data/lib/bridgetown-core/configuration.rb +1 -2
- data/lib/bridgetown-core/converter.rb +1 -0
- data/lib/bridgetown-core/converters/erb_templates.rb +6 -4
- data/lib/bridgetown-core/converters/liquid_templates.rb +2 -0
- data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
- data/lib/bridgetown-core/converters/smartypants.rb +1 -0
- data/lib/bridgetown-core/drops/drop.rb +4 -4
- data/lib/bridgetown-core/entry_filter.rb +1 -0
- data/lib/bridgetown-core/filters/url_filters.rb +1 -1
- data/lib/bridgetown-core/filters.rb +11 -12
- data/lib/bridgetown-core/frontmatter_defaults.rb +5 -7
- data/lib/bridgetown-core/generated_page.rb +1 -3
- data/lib/bridgetown-core/generators/prototype_generator.rb +36 -37
- data/lib/bridgetown-core/helpers.rb +1 -1
- data/lib/bridgetown-core/hooks.rb +2 -2
- data/lib/bridgetown-core/liquid_renderer.rb +1 -3
- data/lib/bridgetown-core/log_adapter.rb +1 -1
- data/lib/bridgetown-core/log_writer.rb +1 -1
- data/lib/bridgetown-core/model/base.rb +2 -2
- data/lib/bridgetown-core/model/builder_origin.rb +3 -3
- data/lib/bridgetown-core/model/plugin_origin.rb +1 -1
- data/lib/bridgetown-core/plugin_manager.rb +2 -2
- data/lib/bridgetown-core/publisher.rb +1 -1
- data/lib/bridgetown-core/rack/boot.rb +8 -0
- data/lib/bridgetown-core/rack/routes.rb +1 -5
- data/lib/bridgetown-core/rack/static_indexes.rb +2 -2
- data/lib/bridgetown-core/readers/layout_reader.rb +2 -2
- data/lib/bridgetown-core/renderer.rb +1 -1
- data/lib/bridgetown-core/resource/base.rb +7 -7
- data/lib/bridgetown-core/resource/permalink_processor.rb +3 -2
- data/lib/bridgetown-core/resource/taxonomy_term.rb +1 -5
- data/lib/bridgetown-core/resource/transformer.rb +7 -5
- data/lib/bridgetown-core/ruby_template_view.rb +1 -3
- data/lib/bridgetown-core/static_file.rb +5 -7
- data/lib/bridgetown-core/tags/find.rb +6 -6
- data/lib/bridgetown-core/tags/highlight.rb +5 -5
- data/lib/bridgetown-core/tags/post_url.rb +6 -6
- data/lib/bridgetown-core/tags/render_content.rb +2 -2
- data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +7 -1
- data/lib/bridgetown-core/url.rb +3 -3
- data/lib/bridgetown-core/utils.rb +7 -9
- data/lib/bridgetown-core/version.rb +1 -1
- data/lib/bridgetown-core/watcher.rb +2 -2
- data/lib/bridgetown-core.rb +2 -1
- data/lib/site_template/src/_layouts/default.liquid +1 -1
- metadata +3 -3
- data/lib/bridgetown-core/tags/include.rb +0 -213
@@ -53,7 +53,7 @@ module Bridgetown
|
|
53
53
|
@layout = site.layouts[data.layout].tap do |layout|
|
54
54
|
unless layout
|
55
55
|
Bridgetown.logger.warn "Resource:", "Layout '#{data.layout}' " \
|
56
|
-
|
56
|
+
"requested via #{relative_path} does not exist."
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -267,7 +267,7 @@ module Bridgetown
|
|
267
267
|
# Comparison is a comparison between the 2 dates or paths of the resources.
|
268
268
|
#
|
269
269
|
# @return [Integer] -1, 0, or +1
|
270
|
-
def <=>(other) # rubocop:todo Metrics/AbcSize
|
270
|
+
def <=>(other) # rubocop:todo Metrics/AbcSize
|
271
271
|
return nil unless other.respond_to?(:data)
|
272
272
|
|
273
273
|
cmp = if data.date.respond_to?(:to_datetime) && other.data.date.respond_to?(:to_datetime)
|
@@ -293,7 +293,7 @@ module Bridgetown
|
|
293
293
|
|
294
294
|
private
|
295
295
|
|
296
|
-
def ensure_default_data
|
296
|
+
def ensure_default_data # rubocop:todo Metrics/AbcSize
|
297
297
|
determine_locale
|
298
298
|
|
299
299
|
slug = if matches = relative_path.to_s.match(DATE_FILENAME_MATCHER) # rubocop:disable Lint/AssignmentInCondition
|
@@ -337,14 +337,14 @@ module Bridgetown
|
|
337
337
|
end
|
338
338
|
end
|
339
339
|
|
340
|
-
def determine_locale
|
340
|
+
def determine_locale # rubocop:todo Metrics/AbcSize
|
341
341
|
unless data.locale
|
342
342
|
data.locale = locale_from_alt_data_or_filename.presence || site.config.default_locale
|
343
343
|
end
|
344
344
|
|
345
|
-
|
346
|
-
|
347
|
-
|
345
|
+
return unless data.locale_overrides.is_a?(Hash) && data.locale_overrides&.key?(data.locale)
|
346
|
+
|
347
|
+
data.merge!(data.locale_overrides[data.locale])
|
348
348
|
end
|
349
349
|
|
350
350
|
# Look for alternative front matter or look at the filename pattern: slug.locale.ext
|
@@ -46,9 +46,10 @@ module Bridgetown
|
|
46
46
|
segment = segment.to_sym
|
47
47
|
if self.class.placeholder_processors[segment]
|
48
48
|
segment_value = self.class.placeholder_processors[segment].(resource)
|
49
|
-
|
49
|
+
case segment_value
|
50
|
+
when Hash
|
50
51
|
segment_value[:raw_value]
|
51
|
-
|
52
|
+
when Array
|
52
53
|
segment_value.map do |subsegment|
|
53
54
|
Utils.slugify(subsegment, mode: slugify_mode)
|
54
55
|
end.join("/")
|
@@ -103,10 +103,12 @@ module Bridgetown
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def warn_on_missing_layout(layout, layout_name)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
+
)
|
110
112
|
end
|
111
113
|
|
112
114
|
### Transformation Actions
|
@@ -152,7 +154,7 @@ module Bridgetown
|
|
152
154
|
layout_input = layout.content.dup
|
153
155
|
|
154
156
|
layout_converters.inject(layout_input) do |content, converter|
|
155
|
-
next(content) unless [2, -2].include?(converter.method(:convert).arity)
|
157
|
+
next(content) unless [2, -2].include?(converter.method(:convert).arity) # rubocop:disable Performance/CollectionLiteralInLoop
|
156
158
|
|
157
159
|
layout.current_document = resource
|
158
160
|
layout.current_document_output = output
|
@@ -61,7 +61,6 @@ module Bridgetown
|
|
61
61
|
@helpers ||= Helpers.new(self, site)
|
62
62
|
end
|
63
63
|
|
64
|
-
# rubocop:disable Style/MissingRespondToMissing
|
65
64
|
ruby2_keywords def method_missing(method_name, *args, &block)
|
66
65
|
if helpers.respond_to?(method_name.to_sym)
|
67
66
|
helpers.send method_name.to_sym, *args, &block
|
@@ -73,7 +72,6 @@ module Bridgetown
|
|
73
72
|
def respond_to_missing?(method_name, include_private = false)
|
74
73
|
helpers.respond_to?(method_name.to_sym, include_private) || super
|
75
74
|
end
|
76
|
-
# rubocop:enable Style/MissingRespondToMissing
|
77
75
|
|
78
76
|
private
|
79
77
|
|
@@ -84,7 +82,7 @@ module Bridgetown
|
|
84
82
|
["{% render \"#{component}\""]
|
85
83
|
end
|
86
84
|
unless options.empty?
|
87
|
-
render_statement << ",
|
85
|
+
render_statement << ", #{options.keys.map { |k| "#{k}: #{k}" }.join(", ")}"
|
88
86
|
end
|
89
87
|
render_statement << " %}"
|
90
88
|
if options[:_block_content]
|
@@ -36,7 +36,7 @@ module Bridgetown
|
|
36
36
|
@extname = File.extname(@name)
|
37
37
|
@data = @site.frontmatter_defaults.all(relative_path, type).with_dot_access
|
38
38
|
data.permalink ||= if collection && !collection.builtin?
|
39
|
-
collection.default_permalink.chomp("/").chomp(".*")
|
39
|
+
"#{collection.default_permalink.chomp("/").chomp(".*")}.*"
|
40
40
|
else
|
41
41
|
"/:path.*"
|
42
42
|
end
|
@@ -44,9 +44,7 @@ module Bridgetown
|
|
44
44
|
|
45
45
|
# Returns source file path.
|
46
46
|
def path
|
47
|
-
@path ||=
|
48
|
-
File.join(*[@base, @dir, @name].compact)
|
49
|
-
end
|
47
|
+
@path ||= File.join(*[@base, @dir, @name].compact)
|
50
48
|
end
|
51
49
|
|
52
50
|
# Obtain destination path.
|
@@ -207,9 +205,9 @@ module Bridgetown
|
|
207
205
|
def copy_file(dest_path)
|
208
206
|
FileUtils.copy_entry(path, dest_path)
|
209
207
|
|
210
|
-
|
211
|
-
|
212
|
-
|
208
|
+
return if File.symlink?(dest_path)
|
209
|
+
|
210
|
+
File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
|
213
211
|
end
|
214
212
|
end
|
215
213
|
end
|
@@ -11,12 +11,7 @@ module Bridgetown
|
|
11
11
|
|
12
12
|
def initialize(tag_name, markup, tokens)
|
13
13
|
super
|
14
|
-
|
15
|
-
@new_var_name = Regexp.last_match(1).strip
|
16
|
-
@single_or_group = Regexp.last_match(2)
|
17
|
-
@arr_name = Regexp.last_match(3).strip
|
18
|
-
@conditions = process_conditions(Regexp.last_match(4).strip)
|
19
|
-
else
|
14
|
+
unless markup.strip =~ SYNTAX
|
20
15
|
raise SyntaxError, <<~MSG
|
21
16
|
Syntax Error in tag 'find' while parsing the following markup:
|
22
17
|
|
@@ -25,6 +20,11 @@ module Bridgetown
|
|
25
20
|
Valid syntax: find <varname> where|in <array>, <condition(s)>
|
26
21
|
MSG
|
27
22
|
end
|
23
|
+
|
24
|
+
@new_var_name = Regexp.last_match(1).strip
|
25
|
+
@single_or_group = Regexp.last_match(2)
|
26
|
+
@arr_name = Regexp.last_match(3).strip
|
27
|
+
@conditions = process_conditions(Regexp.last_match(4).strip)
|
28
28
|
end
|
29
29
|
|
30
30
|
def render(context)
|
@@ -14,10 +14,7 @@ module Bridgetown
|
|
14
14
|
|
15
15
|
def initialize(tag_name, markup, tokens)
|
16
16
|
super
|
17
|
-
|
18
|
-
@lang = Regexp.last_match(1).downcase
|
19
|
-
@highlight_options = parse_options(Regexp.last_match(2))
|
20
|
-
else
|
17
|
+
unless markup.strip =~ SYNTAX
|
21
18
|
raise SyntaxError, <<~MSG
|
22
19
|
Syntax Error in tag 'highlight' while parsing the following markup:
|
23
20
|
|
@@ -26,6 +23,9 @@ module Bridgetown
|
|
26
23
|
Valid syntax: highlight <lang> [linenos]
|
27
24
|
MSG
|
28
25
|
end
|
26
|
+
|
27
|
+
@lang = Regexp.last_match(1).downcase
|
28
|
+
@highlight_options = parse_options(Regexp.last_match(2))
|
29
29
|
end
|
30
30
|
|
31
31
|
LEADING_OR_TRAILING_LINE_TERMINATORS = %r!\A(\n|\r)+|(\n|\r)+\z!.freeze
|
@@ -89,7 +89,7 @@ module Bridgetown
|
|
89
89
|
"data-lang=\"#{@lang}\"",
|
90
90
|
].join(" ")
|
91
91
|
"<figure class=\"highlight\"><pre><code #{code_attributes}>"\
|
92
|
-
|
92
|
+
"#{code.chomp}</code></pre></figure>"
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -74,19 +74,19 @@ module Bridgetown
|
|
74
74
|
|
75
75
|
site.collections.posts.resources.each do |document|
|
76
76
|
return relative_url(document) if @post == document
|
77
|
-
end
|
78
|
-
|
79
|
-
# New matching method did not match, fall back to old method
|
80
|
-
# with deprecation warning if this matches
|
81
77
|
|
82
|
-
|
78
|
+
# New matching method did not match, fall back to old method
|
79
|
+
# with deprecation warning if this matches
|
83
80
|
next unless @post.deprecated_equality document
|
84
81
|
|
85
|
-
Bridgetown::Deprecator.deprecation_message
|
82
|
+
Bridgetown::Deprecator.deprecation_message(
|
83
|
+
"A call to "\
|
86
84
|
"'{% post_url #{@post.name} %}' did not match " \
|
87
85
|
"a post using the new matching method of checking name " \
|
88
86
|
"(path-date-slug) equality. Please make sure that you " \
|
89
87
|
"change this tag to match the post's name exactly."
|
88
|
+
)
|
89
|
+
|
90
90
|
return relative_url(document)
|
91
91
|
end
|
92
92
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Bridgetown
|
4
4
|
module Tags
|
5
5
|
class BlockRenderTag < Liquid::Block
|
6
|
-
# rubocop:disable Metrics/MethodLength
|
6
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
7
7
|
def render(context)
|
8
8
|
context.stack({}) do
|
9
9
|
# unindent the incoming text
|
@@ -37,7 +37,7 @@ module Bridgetown
|
|
37
37
|
.render_tag(context, +"")
|
38
38
|
end
|
39
39
|
end
|
40
|
-
# rubocop:enable Metrics/MethodLength
|
40
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
41
41
|
|
42
42
|
private
|
43
43
|
|
@@ -1,5 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
desc "Generate a secret key for use in sessions, token generation, and beyond"
|
4
|
+
task :secret do
|
5
|
+
require "securerandom"
|
6
|
+
puts SecureRandom.hex(64) # rubocop:disable Bridgetown/NoPutsAllowed
|
7
|
+
end
|
8
|
+
|
3
9
|
namespace :frontend do
|
4
10
|
desc "Run frontend bundler independently"
|
5
11
|
task :watcher, :sidecar do |_task, args|
|
@@ -23,7 +29,7 @@ end
|
|
23
29
|
|
24
30
|
desc "Prerequisite task which loads site and provides automation"
|
25
31
|
task :environment do
|
26
|
-
class HammerActions < Thor
|
32
|
+
class HammerActions < Thor # rubocop:disable Lint/ConstantDefinitionInBlock
|
27
33
|
include Thor::Actions
|
28
34
|
include Bridgetown::Commands::Actions
|
29
35
|
|
data/lib/bridgetown-core/url.rb
CHANGED
@@ -28,9 +28,9 @@ module Bridgetown
|
|
28
28
|
@placeholders = options[:placeholders] || {}
|
29
29
|
@permalink = options[:permalink]
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
return unless (@template || @permalink).nil?
|
32
|
+
|
33
|
+
raise ArgumentError, "One of :template or :permalink must be supplied."
|
34
34
|
end
|
35
35
|
|
36
36
|
# The generated relative URL of the resource
|
@@ -12,7 +12,7 @@ module Bridgetown
|
|
12
12
|
|
13
13
|
# Constants for use in #slugify
|
14
14
|
SLUGIFY_MODES = %w(raw default pretty simple ascii latin).freeze
|
15
|
-
SLUGIFY_RAW_REGEXP = Regexp.new(
|
15
|
+
SLUGIFY_RAW_REGEXP = Regexp.new("\\s+").freeze
|
16
16
|
SLUGIFY_DEFAULT_REGEXP = Regexp.new("[^\\p{M}\\p{L}\\p{Nd}]+").freeze
|
17
17
|
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^\\p{M}\\p{L}\\p{Nd}._~!$&'()+,;=@]+").freeze
|
18
18
|
SLUGIFY_ASCII_REGEXP = Regexp.new("[^[A-Za-z0-9]]+").freeze
|
@@ -203,7 +203,7 @@ module Bridgetown
|
|
203
203
|
slug = replace_character_sequence_with_hyphen(string, mode: mode)
|
204
204
|
|
205
205
|
# Remove leading/trailing hyphen
|
206
|
-
slug.gsub!(%r
|
206
|
+
slug.gsub!(%r!^-|-$!i, "")
|
207
207
|
|
208
208
|
slug.downcase! unless cased
|
209
209
|
|
@@ -316,9 +316,7 @@ module Bridgetown
|
|
316
316
|
lines.map do |line|
|
317
317
|
continue_processing = !skip_pre_lines
|
318
318
|
|
319
|
-
if skip_pre_lines
|
320
|
-
skip_pre_lines = false if line.include?("</pre>")
|
321
|
-
end
|
319
|
+
skip_pre_lines = false if skip_pre_lines && line.include?("</pre>")
|
322
320
|
if line.include?("<pre")
|
323
321
|
skip_pre_lines = true
|
324
322
|
continue_processing = false
|
@@ -340,7 +338,7 @@ module Bridgetown
|
|
340
338
|
else
|
341
339
|
line
|
342
340
|
end
|
343
|
-
end.join
|
341
|
+
end.join
|
344
342
|
end
|
345
343
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
|
346
344
|
|
@@ -448,9 +446,9 @@ module Bridgetown
|
|
448
446
|
end
|
449
447
|
|
450
448
|
def merge_default_proc(target, overwrite)
|
451
|
-
|
452
|
-
|
453
|
-
|
449
|
+
return unless target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
|
450
|
+
|
451
|
+
target.default_proc = overwrite.default_proc
|
454
452
|
end
|
455
453
|
|
456
454
|
def duplicate_frozen_values(target)
|
@@ -116,7 +116,7 @@ module Bridgetown
|
|
116
116
|
rescue ArgumentError
|
117
117
|
# Could not find a relative path
|
118
118
|
end
|
119
|
-
end.compact + [%r!^\.bridgetown
|
119
|
+
end.compact + [%r!^\.bridgetown-metadata!]
|
120
120
|
end
|
121
121
|
|
122
122
|
def sleep_forever
|
@@ -132,7 +132,7 @@ module Bridgetown
|
|
132
132
|
site.plugin_manager.reload_component_loaders
|
133
133
|
site.process
|
134
134
|
Bridgetown.logger.info "Done! 🎉", "#{"Completed".green} in less than" \
|
135
|
-
|
135
|
+
" #{(Time.now - time).ceil(2)} seconds."
|
136
136
|
rescue Exception => e
|
137
137
|
Bridgetown.logger.error "Error:", e.message
|
138
138
|
|
data/lib/bridgetown-core.rb
CHANGED
@@ -249,12 +249,13 @@ end
|
|
249
249
|
|
250
250
|
module Bridgetown
|
251
251
|
module Model; end
|
252
|
+
|
252
253
|
module Resource
|
253
254
|
def self.register_extension(mod)
|
254
255
|
if mod.const_defined?(:LiquidResource)
|
255
256
|
Bridgetown::Drops::ResourceDrop.include mod.const_get(:LiquidResource)
|
256
257
|
end
|
257
|
-
if mod.const_defined?(:RubyResource)
|
258
|
+
if mod.const_defined?(:RubyResource) # rubocop:disable Style/GuardClause
|
258
259
|
Bridgetown::Resource::Base.include mod.const_get(:RubyResource)
|
259
260
|
end
|
260
261
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bridgetown-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.alpha5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bridgetown Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -340,6 +340,7 @@ executables:
|
|
340
340
|
extensions: []
|
341
341
|
extra_rdoc_files: []
|
342
342
|
files:
|
343
|
+
- ".rubocop.yml"
|
343
344
|
- ".yardopts"
|
344
345
|
- Rakefile
|
345
346
|
- bin/bridgetown
|
@@ -475,7 +476,6 @@ files:
|
|
475
476
|
- lib/bridgetown-core/tags/class_map.rb
|
476
477
|
- lib/bridgetown-core/tags/find.rb
|
477
478
|
- lib/bridgetown-core/tags/highlight.rb
|
478
|
-
- lib/bridgetown-core/tags/include.rb
|
479
479
|
- lib/bridgetown-core/tags/link.rb
|
480
480
|
- lib/bridgetown-core/tags/live_reload_dev_js.rb
|
481
481
|
- lib/bridgetown-core/tags/post_url.rb
|
@@ -1,213 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Bridgetown
|
4
|
-
module Tags
|
5
|
-
class IncludeTag < Liquid::Tag
|
6
|
-
class << self
|
7
|
-
attr_accessor :deprecation_message_shown
|
8
|
-
end
|
9
|
-
|
10
|
-
VALID_SYNTAX = %r!
|
11
|
-
([\w-]+)\s*=\s*
|
12
|
-
(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))
|
13
|
-
!x.freeze
|
14
|
-
VARIABLE_SYNTAX = %r!
|
15
|
-
(?<variable>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+)
|
16
|
-
(?<params>.*)
|
17
|
-
!mx.freeze
|
18
|
-
|
19
|
-
FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
|
20
|
-
VALID_FILENAME_CHARS = %r!^[\w/\.-]+$!.freeze
|
21
|
-
INVALID_SEQUENCES = %r![./]{2,}!.freeze
|
22
|
-
|
23
|
-
def initialize(tag_name, markup, tokens)
|
24
|
-
super
|
25
|
-
|
26
|
-
unless self.class.deprecation_message_shown
|
27
|
-
Bridgetown.logger.warn "NOTICE: the {% include %} tag is deprecated and" \
|
28
|
-
" will be removed in Bridgetown 1.0. You should" \
|
29
|
-
" use the {% render %} tag instead."
|
30
|
-
self.class.deprecation_message_shown = true
|
31
|
-
end
|
32
|
-
|
33
|
-
matched = markup.strip.match(VARIABLE_SYNTAX)
|
34
|
-
if matched
|
35
|
-
@file = matched["variable"].strip
|
36
|
-
@params = matched["params"].strip
|
37
|
-
else
|
38
|
-
@file, @params = markup.strip.split(%r!\s+!, 2)
|
39
|
-
end
|
40
|
-
validate_params if @params
|
41
|
-
@tag_name = tag_name
|
42
|
-
end
|
43
|
-
|
44
|
-
def syntax_example
|
45
|
-
"{% #{@tag_name} file.ext param='value' param2='value' %}"
|
46
|
-
end
|
47
|
-
|
48
|
-
def parse_params(context)
|
49
|
-
params = {}
|
50
|
-
markup = @params
|
51
|
-
|
52
|
-
while (match = VALID_SYNTAX.match(markup))
|
53
|
-
markup = markup[match.end(0)..-1]
|
54
|
-
|
55
|
-
value = if match[2]
|
56
|
-
match[2].gsub('\\"', '"')
|
57
|
-
elsif match[3]
|
58
|
-
match[3].gsub("\\'", "'")
|
59
|
-
elsif match[4]
|
60
|
-
context[match[4]]
|
61
|
-
end
|
62
|
-
|
63
|
-
params[match[1]] = value
|
64
|
-
end
|
65
|
-
params
|
66
|
-
end
|
67
|
-
|
68
|
-
def validate_file_name(file)
|
69
|
-
if INVALID_SEQUENCES.match?(file) || !VALID_FILENAME_CHARS.match?(file)
|
70
|
-
raise ArgumentError, <<~MSG
|
71
|
-
Invalid syntax for include tag. File contains invalid characters or sequences:
|
72
|
-
|
73
|
-
#{file}
|
74
|
-
|
75
|
-
Valid syntax:
|
76
|
-
|
77
|
-
#{syntax_example}
|
78
|
-
|
79
|
-
MSG
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def validate_params
|
84
|
-
unless FULL_VALID_SYNTAX.match?(@params)
|
85
|
-
raise ArgumentError, <<~MSG
|
86
|
-
Invalid syntax for include tag:
|
87
|
-
|
88
|
-
#{@params}
|
89
|
-
|
90
|
-
Valid syntax:
|
91
|
-
|
92
|
-
#{syntax_example}
|
93
|
-
|
94
|
-
MSG
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Grab file read opts in the context
|
99
|
-
def file_read_opts(context)
|
100
|
-
context.registers[:site].file_read_opts
|
101
|
-
end
|
102
|
-
|
103
|
-
# Render the variable if required
|
104
|
-
def render_variable(context)
|
105
|
-
Liquid::Template.parse(@file).render(context) if VARIABLE_SYNTAX.match?(@file)
|
106
|
-
end
|
107
|
-
|
108
|
-
def tag_includes_dirs(context)
|
109
|
-
context.registers[:site].includes_load_paths.freeze
|
110
|
-
end
|
111
|
-
|
112
|
-
def locate_include_file(context, file)
|
113
|
-
includes_dirs = tag_includes_dirs(context)
|
114
|
-
includes_dirs.each do |dir|
|
115
|
-
path = File.join(dir, file)
|
116
|
-
return path if valid_include_file?(path, dir.to_s)
|
117
|
-
end
|
118
|
-
raise IOError, could_not_locate_message(file, includes_dirs)
|
119
|
-
end
|
120
|
-
|
121
|
-
def render(context)
|
122
|
-
file = render_variable(context) || @file
|
123
|
-
validate_file_name(file)
|
124
|
-
|
125
|
-
path = locate_include_file(context, file)
|
126
|
-
return unless path
|
127
|
-
|
128
|
-
partial = load_cached_partial(path, context)
|
129
|
-
|
130
|
-
context.stack do
|
131
|
-
context["include"] = parse_params(context) if @params
|
132
|
-
begin
|
133
|
-
partial.render!(context)
|
134
|
-
rescue Liquid::Error => e
|
135
|
-
e.template_name = path
|
136
|
-
e.markup_context = "included " if e.markup_context.nil?
|
137
|
-
raise e
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def load_cached_partial(path, context)
|
143
|
-
context.registers[:cached_partials] ||= {}
|
144
|
-
cached_partial = context.registers[:cached_partials]
|
145
|
-
|
146
|
-
if cached_partial.key?(path)
|
147
|
-
cached_partial[path]
|
148
|
-
else
|
149
|
-
unparsed_file = context.registers[:site]
|
150
|
-
.liquid_renderer
|
151
|
-
.file(path)
|
152
|
-
begin
|
153
|
-
cached_partial[path] = unparsed_file.parse(read_file(path, context))
|
154
|
-
rescue Liquid::Error => e
|
155
|
-
e.template_name = path
|
156
|
-
e.markup_context = "included " if e.markup_context.nil?
|
157
|
-
raise e
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def valid_include_file?(path, _dir)
|
163
|
-
File.file?(path)
|
164
|
-
end
|
165
|
-
|
166
|
-
def realpath_prefixed_with?(path, dir)
|
167
|
-
File.exist?(path) && File.realpath(path).start_with?(dir)
|
168
|
-
rescue StandardError
|
169
|
-
false
|
170
|
-
end
|
171
|
-
|
172
|
-
# This method allows to modify the file content by inheriting from the class.
|
173
|
-
def read_file(file, context)
|
174
|
-
File.read(file, **file_read_opts(context))
|
175
|
-
end
|
176
|
-
|
177
|
-
private
|
178
|
-
|
179
|
-
def could_not_locate_message(file, includes_dirs)
|
180
|
-
"Could not locate the included file '#{file}' in any of #{includes_dirs}." \
|
181
|
-
" Ensure it exists in one of those directories."
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
class IncludeRelativeTag < IncludeTag
|
186
|
-
def tag_includes_dirs(context)
|
187
|
-
Array(page_path(context)).freeze
|
188
|
-
end
|
189
|
-
|
190
|
-
def page_path(context)
|
191
|
-
if context.registers[:page].nil?
|
192
|
-
context.registers[:site].source
|
193
|
-
else
|
194
|
-
site = context.registers[:site]
|
195
|
-
page_payload = context.registers[:page]
|
196
|
-
resource_path = \
|
197
|
-
if page_payload["collection"].nil?
|
198
|
-
page_payload["path"]
|
199
|
-
else
|
200
|
-
File.join(site.config["collections_dir"], page_payload["path"])
|
201
|
-
end
|
202
|
-
# rubocop:disable Performance/DeleteSuffix
|
203
|
-
resource_path.sub!(%r!/#excerpt\z!, "")
|
204
|
-
# rubocop:enable Performance/DeleteSuffix
|
205
|
-
site.in_source_dir File.dirname(resource_path)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
Liquid::Template.register_tag("include", Bridgetown::Tags::IncludeTag)
|
213
|
-
Liquid::Template.register_tag("include_relative", Bridgetown::Tags::IncludeRelativeTag)
|