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