bridgetown-core 1.0.0.alpha3 → 1.0.0.alpha7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bridgetown-core.gemspec +1 -2
- data/lib/bridgetown-core/cache.rb +1 -1
- data/lib/bridgetown-core/collection.rb +1 -1
- data/lib/bridgetown-core/commands/configure.rb +7 -0
- data/lib/bridgetown-core/commands/new.rb +3 -2
- data/lib/bridgetown-core/commands/start.rb +10 -8
- data/lib/bridgetown-core/component.rb +2 -2
- data/lib/bridgetown-core/concerns/front_matter_importer.rb +1 -1
- data/lib/bridgetown-core/concerns/site/configurable.rb +6 -8
- data/lib/bridgetown-core/concerns/site/extensible.rb +2 -1
- data/lib/bridgetown-core/concerns/site/ssr.rb +38 -16
- data/lib/bridgetown-core/configuration.rb +77 -47
- data/lib/bridgetown-core/configurations/bt-postcss.rb +1 -3
- data/lib/bridgetown-core/configurations/cypress/cypress.json +4 -0
- data/lib/bridgetown-core/configurations/cypress/cypress_dir/fixtures/example.json +5 -0
- data/lib/bridgetown-core/configurations/cypress/cypress_dir/integration/navbar.spec.js +17 -0
- data/lib/bridgetown-core/configurations/cypress/cypress_dir/plugins/index.js +21 -0
- data/lib/bridgetown-core/configurations/cypress/cypress_dir/support/commands.js +25 -0
- data/lib/bridgetown-core/configurations/cypress/cypress_dir/support/index.js +20 -0
- data/lib/bridgetown-core/configurations/cypress/cypress_tasks +33 -0
- data/lib/bridgetown-core/configurations/cypress.rb +13 -0
- data/lib/bridgetown-core/configurations/minitesting.rb +19 -15
- data/lib/bridgetown-core/configurations/netlify/netlify.toml +2 -2
- data/lib/bridgetown-core/configurations/netlify.rb +2 -4
- data/lib/bridgetown-core/configurations/purgecss.rb +2 -2
- data/lib/bridgetown-core/configurations/render/render.yaml.erb +26 -0
- data/lib/bridgetown-core/configurations/render.rb +6 -0
- data/lib/bridgetown-core/configurations/tailwindcss.rb +3 -5
- data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
- data/lib/bridgetown-core/core_ext/psych.rb +1 -5
- data/lib/bridgetown-core/frontmatter_defaults.rb +2 -2
- data/lib/bridgetown-core/liquid_renderer.rb +1 -1
- data/lib/bridgetown-core/model/base.rb +23 -26
- data/lib/bridgetown-core/model/builder_origin.rb +8 -6
- data/lib/bridgetown-core/model/origin.rb +10 -1
- data/lib/bridgetown-core/model/plugin_origin.rb +1 -1
- data/lib/bridgetown-core/plugin_manager.rb +7 -34
- data/lib/bridgetown-core/rack/boot.rb +54 -23
- data/lib/bridgetown-core/rack/roda.rb +2 -1
- data/lib/bridgetown-core/rack/routes.rb +2 -2
- data/lib/bridgetown-core/readers/layout_reader.rb +1 -1
- data/lib/bridgetown-core/readers/plugin_content_reader.rb +1 -1
- data/lib/bridgetown-core/renderer.rb +2 -2
- data/lib/bridgetown-core/resource/base.rb +3 -3
- data/lib/bridgetown-core/resource/relations.rb +1 -1
- data/lib/bridgetown-core/resource/taxonomy_term.rb +2 -2
- data/lib/bridgetown-core/resource/taxonomy_type.rb +2 -2
- data/lib/bridgetown-core/ruby_template_view.rb +2 -2
- data/lib/bridgetown-core/site.rb +15 -5
- data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +6 -0
- data/lib/bridgetown-core/utils/loaders_manager.rb +72 -0
- data/lib/bridgetown-core/utils.rb +13 -14
- data/lib/bridgetown-core/version.rb +1 -1
- data/lib/bridgetown-core/watcher.rb +16 -7
- data/lib/bridgetown-core/yaml_parser.rb +1 -5
- data/lib/site_template/README.md +1 -1
- data/lib/site_template/Rakefile +3 -3
- data/lib/site_template/src/_layouts/default.liquid +1 -1
- metadata +16 -6
- data/lib/bridgetown-core/tags/include.rb +0 -216
@@ -61,9 +61,9 @@ module Bridgetown
|
|
61
61
|
@helpers ||= Helpers.new(self, site)
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
def method_missing(method_name, *args, **kwargs, &block)
|
65
65
|
if helpers.respond_to?(method_name.to_sym)
|
66
|
-
helpers.send method_name.to_sym, *args, &block
|
66
|
+
helpers.send method_name.to_sym, *args, **kwargs, &block
|
67
67
|
else
|
68
68
|
super
|
69
69
|
end
|
data/lib/bridgetown-core/site.rb
CHANGED
@@ -13,9 +13,10 @@ module Bridgetown
|
|
13
13
|
include SSR
|
14
14
|
include Writable
|
15
15
|
|
16
|
-
attr_reader
|
17
|
-
|
18
|
-
|
16
|
+
attr_reader :root_dir, :source, :dest, :cache_dir, :config, :liquid_renderer
|
17
|
+
|
18
|
+
# @return [Bridgetown::Utils::LoadersManager]
|
19
|
+
attr_reader :loaders_manager
|
19
20
|
|
20
21
|
# All files not pages/documents or structured data in the source folder
|
21
22
|
# @return [Array<StaticFile>]
|
@@ -33,11 +34,20 @@ module Bridgetown
|
|
33
34
|
|
34
35
|
# Initialize a new Site.
|
35
36
|
#
|
36
|
-
# config
|
37
|
-
|
37
|
+
# @param config [Bridgetown::Configuration]
|
38
|
+
# @param loaders_manager [Bridgetown::Utils::LoadersManager] initialized if none provided
|
39
|
+
def initialize(config, loaders_manager: nil)
|
38
40
|
self.config = config
|
39
41
|
locale
|
40
42
|
|
43
|
+
loaders_manager = if loaders_manager
|
44
|
+
loaders_manager.config = self.config
|
45
|
+
loaders_manager
|
46
|
+
else
|
47
|
+
Bridgetown::Utils::LoadersManager.new(self.config)
|
48
|
+
end
|
49
|
+
@loaders_manager = loaders_manager
|
50
|
+
|
41
51
|
@plugin_manager = PluginManager.new(self)
|
42
52
|
@cleaner = Cleaner.new(self)
|
43
53
|
@reader = Reader.new(self)
|
@@ -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|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
module Utils
|
5
|
+
class LoadersManager
|
6
|
+
attr_accessor :config
|
7
|
+
|
8
|
+
attr_reader :loaders, :root_dir
|
9
|
+
|
10
|
+
# @param config [Bridgetown::Configuration]
|
11
|
+
# @param root_dir [String] root of the current site
|
12
|
+
def initialize(config, root_dir = Dir.pwd)
|
13
|
+
@config = config
|
14
|
+
@loaders = {}
|
15
|
+
@root_dir = root_dir
|
16
|
+
end
|
17
|
+
|
18
|
+
def unload_loaders
|
19
|
+
return if @loaders.keys.empty?
|
20
|
+
|
21
|
+
@loaders.each do |_path, loader|
|
22
|
+
loader.unload
|
23
|
+
end
|
24
|
+
@loaders = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def reloading_enabled?(load_path)
|
28
|
+
load_path.start_with?(root_dir) && ENV["BRIDGETOWN_ENV"] != "production"
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup_loaders(autoload_paths = []) # rubocop:todo Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
32
|
+
(autoload_paths.presence || config.autoload_paths).each do |load_path|
|
33
|
+
if @loaders.key?(load_path)
|
34
|
+
raise "Zeitwerk loader already added for `#{load_path}'. Please check your config"
|
35
|
+
end
|
36
|
+
|
37
|
+
next unless Dir.exist? load_path
|
38
|
+
|
39
|
+
loader = Zeitwerk::Loader.new
|
40
|
+
begin
|
41
|
+
loader.push_dir(load_path)
|
42
|
+
rescue Zeitwerk::Error
|
43
|
+
next
|
44
|
+
end
|
45
|
+
loader.enable_reloading if reloading_enabled?(load_path)
|
46
|
+
loader.ignore(File.join(load_path, "**", "*.js.rb"))
|
47
|
+
config.autoloader_collapsed_paths.each do |collapsed_path|
|
48
|
+
next unless collapsed_path.starts_with?(load_path)
|
49
|
+
|
50
|
+
loader.collapse(collapsed_path)
|
51
|
+
end
|
52
|
+
Bridgetown::Hooks.trigger :loader, :pre_setup, loader, load_path
|
53
|
+
loader.setup
|
54
|
+
loader.eager_load if config.eager_load_paths.include?(load_path)
|
55
|
+
Bridgetown::Hooks.trigger :loader, :post_setup, loader, load_path
|
56
|
+
@loaders[load_path] = loader
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def reload_loaders
|
61
|
+
@loaders.each do |load_path, loader|
|
62
|
+
next unless reloading_enabled?(load_path)
|
63
|
+
|
64
|
+
Bridgetown::Hooks.trigger :loader, :pre_reload, loader, load_path
|
65
|
+
loader.reload
|
66
|
+
loader.eager_load if config.eager_load_paths.include?(load_path)
|
67
|
+
Bridgetown::Hooks.trigger :loader, :post_reload, loader, load_path
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -5,6 +5,7 @@ module Bridgetown
|
|
5
5
|
extend self
|
6
6
|
autoload :Ansi, "bridgetown-core/utils/ansi"
|
7
7
|
autoload :Aux, "bridgetown-core/utils/aux"
|
8
|
+
autoload :LoadersManager, "bridgetown-core/utils/loaders_manager"
|
8
9
|
autoload :RequireGems, "bridgetown-core/utils/require_gems"
|
9
10
|
autoload :RubyExec, "bridgetown-core/utils/ruby_exec"
|
10
11
|
autoload :RubyFrontMatter, "bridgetown-core/utils/ruby_front_matter"
|
@@ -120,15 +121,11 @@ module Bridgetown
|
|
120
121
|
# @return [Boolean] if the YAML front matter is present.
|
121
122
|
# rubocop: disable Naming/PredicateName
|
122
123
|
def has_yaml_header?(file)
|
123
|
-
File.open(file, "rb", &:
|
124
|
-
rescue EOFError
|
125
|
-
false
|
124
|
+
File.open(file, "rb", &:gets)&.match?(Bridgetown::FrontMatterImporter::YAML_HEADER) || false
|
126
125
|
end
|
127
126
|
|
128
127
|
def has_rbfm_header?(file)
|
129
|
-
File.open(file, "rb", &:
|
130
|
-
rescue EOFError
|
131
|
-
false
|
128
|
+
File.open(file, "rb", &:gets)&.match?(Bridgetown::FrontMatterImporter::RUBY_HEADER) || false
|
132
129
|
end
|
133
130
|
|
134
131
|
# Determine whether the given content string contains Liquid Tags or Vaiables
|
@@ -354,7 +351,7 @@ module Bridgetown
|
|
354
351
|
# @raise [WebpackAssetError] if unable to find css or js in the manifest
|
355
352
|
# file
|
356
353
|
def parse_webpack_manifest_file(site, asset_type)
|
357
|
-
return log_webpack_asset_error("Webpack manifest") if site.frontend_manifest.nil?
|
354
|
+
return log_webpack_asset_error(site, "Webpack manifest") if site.frontend_manifest.nil?
|
358
355
|
|
359
356
|
asset_path = if %w(js css).include?(asset_type)
|
360
357
|
site.frontend_manifest["main.#{asset_type}"]
|
@@ -364,7 +361,7 @@ module Bridgetown
|
|
364
361
|
end&.last
|
365
362
|
end
|
366
363
|
|
367
|
-
return log_webpack_asset_error(asset_type) if asset_path.nil?
|
364
|
+
return log_webpack_asset_error(site, asset_type) if asset_path.nil?
|
368
365
|
|
369
366
|
static_frontend_path site, ["js", asset_path]
|
370
367
|
end
|
@@ -379,12 +376,14 @@ module Bridgetown
|
|
379
376
|
Addressable::URI.parse(path_parts.join("/")).normalize.to_s
|
380
377
|
end
|
381
378
|
|
382
|
-
def log_webpack_asset_error(asset_type)
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
379
|
+
def log_webpack_asset_error(site, asset_type)
|
380
|
+
site.data[:__webpack_asset_errors] ||= {}
|
381
|
+
site.data[:__webpack_asset_errors][asset_type] ||=
|
382
|
+
Bridgetown.logger.warn(
|
383
|
+
"Webpack:",
|
384
|
+
"There was an error parsing your #{asset_type} file. \
|
385
|
+
Please check your #{asset_type} file for any errors."
|
386
|
+
)
|
388
387
|
|
389
388
|
"MISSING_WEBPACK_MANIFEST_FILE"
|
390
389
|
end
|
@@ -41,10 +41,12 @@ module Bridgetown
|
|
41
41
|
Dir.exist?(path)
|
42
42
|
end
|
43
43
|
|
44
|
+
paths_to_watch = (plugin_paths_to_watch + options.autoload_paths).uniq
|
45
|
+
|
44
46
|
Listen.to(
|
45
47
|
options["source"],
|
46
48
|
webpack_path,
|
47
|
-
*
|
49
|
+
*paths_to_watch,
|
48
50
|
ignore: listen_ignore_paths(options),
|
49
51
|
force_polling: options["force_polling"],
|
50
52
|
&listen_handler(site, options)
|
@@ -57,10 +59,12 @@ module Bridgetown
|
|
57
59
|
c = modified + added + removed
|
58
60
|
n = c.length
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
+
unless site.ssr?
|
63
|
+
Bridgetown.logger.info "Regenerating…"
|
64
|
+
Bridgetown.logger.info "", "#{n} file(s) changed at #{t.strftime("%Y-%m-%d %H:%M:%S")}"
|
65
|
+
c.each { |path| Bridgetown.logger.info "", path["#{site.root_dir}/".length..] }
|
66
|
+
end
|
62
67
|
|
63
|
-
c.each { |path| Bridgetown.logger.info "", path["#{site.root_dir}/".length..-1] }
|
64
68
|
process(site, t, options)
|
65
69
|
end
|
66
70
|
end
|
@@ -101,7 +105,7 @@ module Bridgetown
|
|
101
105
|
source = Pathname.new(options["source"]).expand_path
|
102
106
|
paths = to_exclude(options)
|
103
107
|
|
104
|
-
paths.
|
108
|
+
paths.filter_map do |p|
|
105
109
|
absolute_path = Pathname.new(normalize_encoding(p, options["source"].encoding)).expand_path
|
106
110
|
next unless absolute_path.exist?
|
107
111
|
|
@@ -116,20 +120,25 @@ module Bridgetown
|
|
116
120
|
rescue ArgumentError
|
117
121
|
# Could not find a relative path
|
118
122
|
end
|
119
|
-
end
|
123
|
+
end + [%r!^\.bridgetown-metadata!]
|
120
124
|
end
|
121
125
|
|
122
126
|
def sleep_forever
|
123
127
|
loop { sleep 1000 }
|
124
128
|
end
|
125
129
|
|
130
|
+
# @param site [Bridgetown::Site]
|
126
131
|
def process(site, time, options)
|
127
132
|
begin
|
128
133
|
I18n.reload! # make sure any locale files get read again
|
134
|
+
Bridgetown::Current.site = site # needed in SSR mode apparently
|
129
135
|
Bridgetown::Hooks.trigger :site, :pre_reload, site
|
130
136
|
Bridgetown::Hooks.clear_reloadable_hooks
|
131
137
|
site.plugin_manager.reload_plugin_files
|
132
|
-
site.
|
138
|
+
site.loaders_manager.reload_loaders
|
139
|
+
|
140
|
+
return site.ssr_reload if site.ssr?
|
141
|
+
|
133
142
|
site.process
|
134
143
|
Bridgetown.logger.info "Done! 🎉", "#{"Completed".green} in less than" \
|
135
144
|
" #{(Time.now - time).ceil(2)} seconds."
|
@@ -11,11 +11,7 @@ module Bridgetown
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def load(yaml)
|
14
|
-
|
15
|
-
YAML.safe_load yaml, PERMITTED_CLASSES
|
16
|
-
else
|
17
|
-
YAML.safe_load yaml, permitted_classes: PERMITTED_CLASSES
|
18
|
-
end
|
14
|
+
YAML.safe_load yaml, permitted_classes: PERMITTED_CLASSES
|
19
15
|
end
|
20
16
|
end
|
21
17
|
end
|
data/lib/site_template/README.md
CHANGED
@@ -16,7 +16,7 @@ Welcome to your new Bridgetown website! You can update this README file to provi
|
|
16
16
|
- [GCC](https://gcc.gnu.org/install/)
|
17
17
|
- [Make](https://www.gnu.org/software/make/)
|
18
18
|
- [Ruby](https://www.ruby-lang.org/en/downloads/)
|
19
|
-
- `>= 2.
|
19
|
+
- `>= 2.7`
|
20
20
|
- [Bridgetown Gem](https://rubygems.org/gems/bridgetown)
|
21
21
|
- `gem install bridgetown -N`
|
22
22
|
- [Node](https://nodejs.org)
|
data/lib/site_template/Rakefile
CHANGED
@@ -2,6 +2,9 @@ require "bridgetown"
|
|
2
2
|
|
3
3
|
Bridgetown.load_tasks
|
4
4
|
|
5
|
+
# Run rake without specifying any command to execute a deploy build by default.
|
6
|
+
task default: :deploy
|
7
|
+
|
5
8
|
#
|
6
9
|
# Standard set of tasks, which you can customize if you wish:
|
7
10
|
#
|
@@ -44,6 +47,3 @@ end
|
|
44
47
|
# say_status :rake, "I'm a Rake tast =) #{site.config.url}"
|
45
48
|
# end
|
46
49
|
# end
|
47
|
-
|
48
|
-
# Run rake without specifying any command to execute a deploy build by default.
|
49
|
-
task default: :deploy
|
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.alpha7
|
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-
|
11
|
+
date: 2021-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -390,11 +390,21 @@ files:
|
|
390
390
|
- lib/bridgetown-core/configurations/.keep
|
391
391
|
- lib/bridgetown-core/configurations/bt-postcss.rb
|
392
392
|
- lib/bridgetown-core/configurations/bt-postcss/postcss.config.js
|
393
|
+
- lib/bridgetown-core/configurations/cypress.rb
|
394
|
+
- lib/bridgetown-core/configurations/cypress/cypress.json
|
395
|
+
- lib/bridgetown-core/configurations/cypress/cypress_dir/fixtures/example.json
|
396
|
+
- lib/bridgetown-core/configurations/cypress/cypress_dir/integration/navbar.spec.js
|
397
|
+
- lib/bridgetown-core/configurations/cypress/cypress_dir/plugins/index.js
|
398
|
+
- lib/bridgetown-core/configurations/cypress/cypress_dir/support/commands.js
|
399
|
+
- lib/bridgetown-core/configurations/cypress/cypress_dir/support/index.js
|
400
|
+
- lib/bridgetown-core/configurations/cypress/cypress_tasks
|
393
401
|
- lib/bridgetown-core/configurations/minitesting.rb
|
394
402
|
- lib/bridgetown-core/configurations/netlify.rb
|
395
403
|
- lib/bridgetown-core/configurations/netlify/netlify.sh
|
396
404
|
- lib/bridgetown-core/configurations/netlify/netlify.toml
|
397
405
|
- lib/bridgetown-core/configurations/purgecss.rb
|
406
|
+
- lib/bridgetown-core/configurations/render.rb
|
407
|
+
- lib/bridgetown-core/configurations/render/render.yaml.erb
|
398
408
|
- lib/bridgetown-core/configurations/stimulus.rb
|
399
409
|
- lib/bridgetown-core/configurations/swup.rb
|
400
410
|
- lib/bridgetown-core/configurations/tailwindcss.rb
|
@@ -476,7 +486,6 @@ files:
|
|
476
486
|
- lib/bridgetown-core/tags/class_map.rb
|
477
487
|
- lib/bridgetown-core/tags/find.rb
|
478
488
|
- lib/bridgetown-core/tags/highlight.rb
|
479
|
-
- lib/bridgetown-core/tags/include.rb
|
480
489
|
- lib/bridgetown-core/tags/link.rb
|
481
490
|
- lib/bridgetown-core/tags/live_reload_dev_js.rb
|
482
491
|
- lib/bridgetown-core/tags/post_url.rb
|
@@ -489,6 +498,7 @@ files:
|
|
489
498
|
- lib/bridgetown-core/utils.rb
|
490
499
|
- lib/bridgetown-core/utils/ansi.rb
|
491
500
|
- lib/bridgetown-core/utils/aux.rb
|
501
|
+
- lib/bridgetown-core/utils/loaders_manager.rb
|
492
502
|
- lib/bridgetown-core/utils/require_gems.rb
|
493
503
|
- lib/bridgetown-core/utils/ruby_exec.rb
|
494
504
|
- lib/bridgetown-core/utils/ruby_front_matter.rb
|
@@ -543,12 +553,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
543
553
|
requirements:
|
544
554
|
- - ">="
|
545
555
|
- !ruby/object:Gem::Version
|
546
|
-
version: 2.
|
556
|
+
version: 2.7.0
|
547
557
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
548
558
|
requirements:
|
549
|
-
- - "
|
559
|
+
- - ">"
|
550
560
|
- !ruby/object:Gem::Version
|
551
|
-
version:
|
561
|
+
version: 1.3.1
|
552
562
|
requirements: []
|
553
563
|
rubygems_version: 3.1.4
|
554
564
|
signing_key:
|
@@ -1,216 +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
|
-
|
15
|
-
# rubocop:disable Lint/MixedRegexpCaptureTypes
|
16
|
-
VARIABLE_SYNTAX = %r!
|
17
|
-
(?<variable>[^{]*(\{\{\s*[\w\-.]+\s*(\|.*)?\}\}[^\s{}]*)+)
|
18
|
-
(?<params>.*)
|
19
|
-
!mx.freeze
|
20
|
-
# rubocop:enable Lint/MixedRegexpCaptureTypes
|
21
|
-
|
22
|
-
FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
|
23
|
-
VALID_FILENAME_CHARS = %r!^[\w/.-]+$!.freeze
|
24
|
-
INVALID_SEQUENCES = %r![./]{2,}!.freeze
|
25
|
-
|
26
|
-
def initialize(tag_name, markup, tokens)
|
27
|
-
super
|
28
|
-
|
29
|
-
unless self.class.deprecation_message_shown
|
30
|
-
Bridgetown.logger.warn "NOTICE: the {% include %} tag is deprecated and" \
|
31
|
-
" will be removed in Bridgetown 1.0. You should" \
|
32
|
-
" use the {% render %} tag instead."
|
33
|
-
self.class.deprecation_message_shown = true
|
34
|
-
end
|
35
|
-
|
36
|
-
matched = markup.strip.match(VARIABLE_SYNTAX)
|
37
|
-
if matched
|
38
|
-
@file = matched["variable"].strip
|
39
|
-
@params = matched["params"].strip
|
40
|
-
else
|
41
|
-
@file, @params = markup.strip.split(%r!\s+!, 2)
|
42
|
-
end
|
43
|
-
validate_params if @params
|
44
|
-
@tag_name = tag_name
|
45
|
-
end
|
46
|
-
|
47
|
-
def syntax_example
|
48
|
-
"{% #{@tag_name} file.ext param='value' param2='value' %}"
|
49
|
-
end
|
50
|
-
|
51
|
-
def parse_params(context)
|
52
|
-
params = {}
|
53
|
-
markup = @params
|
54
|
-
|
55
|
-
while (match = VALID_SYNTAX.match(markup))
|
56
|
-
markup = markup[match.end(0)..-1]
|
57
|
-
|
58
|
-
value = if match[2]
|
59
|
-
match[2].gsub('\\"', '"')
|
60
|
-
elsif match[3]
|
61
|
-
match[3].gsub("\\'", "'")
|
62
|
-
elsif match[4]
|
63
|
-
context[match[4]]
|
64
|
-
end
|
65
|
-
|
66
|
-
params[match[1]] = value
|
67
|
-
end
|
68
|
-
params
|
69
|
-
end
|
70
|
-
|
71
|
-
def validate_file_name(file)
|
72
|
-
return unless INVALID_SEQUENCES.match?(file) || !VALID_FILENAME_CHARS.match?(file)
|
73
|
-
|
74
|
-
raise ArgumentError, <<~MSG
|
75
|
-
Invalid syntax for include tag. File contains invalid characters or sequences:
|
76
|
-
|
77
|
-
#{file}
|
78
|
-
|
79
|
-
Valid syntax:
|
80
|
-
|
81
|
-
#{syntax_example}
|
82
|
-
|
83
|
-
MSG
|
84
|
-
end
|
85
|
-
|
86
|
-
def validate_params
|
87
|
-
return if FULL_VALID_SYNTAX.match?(@params)
|
88
|
-
|
89
|
-
raise ArgumentError, <<~MSG
|
90
|
-
Invalid syntax for include tag:
|
91
|
-
|
92
|
-
#{@params}
|
93
|
-
|
94
|
-
Valid syntax:
|
95
|
-
|
96
|
-
#{syntax_example}
|
97
|
-
|
98
|
-
MSG
|
99
|
-
end
|
100
|
-
|
101
|
-
# Grab file read opts in the context
|
102
|
-
def file_read_opts(context)
|
103
|
-
context.registers[:site].file_read_opts
|
104
|
-
end
|
105
|
-
|
106
|
-
# Render the variable if required
|
107
|
-
def render_variable(context)
|
108
|
-
Liquid::Template.parse(@file).render(context) if VARIABLE_SYNTAX.match?(@file)
|
109
|
-
end
|
110
|
-
|
111
|
-
def tag_includes_dirs(context)
|
112
|
-
context.registers[:site].includes_load_paths.freeze
|
113
|
-
end
|
114
|
-
|
115
|
-
def locate_include_file(context, file)
|
116
|
-
includes_dirs = tag_includes_dirs(context)
|
117
|
-
includes_dirs.each do |dir|
|
118
|
-
path = File.join(dir, file)
|
119
|
-
return path if valid_include_file?(path, dir.to_s)
|
120
|
-
end
|
121
|
-
raise IOError, could_not_locate_message(file, includes_dirs)
|
122
|
-
end
|
123
|
-
|
124
|
-
def render(context)
|
125
|
-
file = render_variable(context) || @file
|
126
|
-
validate_file_name(file)
|
127
|
-
|
128
|
-
path = locate_include_file(context, file)
|
129
|
-
return unless path
|
130
|
-
|
131
|
-
partial = load_cached_partial(path, context)
|
132
|
-
|
133
|
-
context.stack do
|
134
|
-
context["include"] = parse_params(context) if @params
|
135
|
-
begin
|
136
|
-
partial.render!(context)
|
137
|
-
rescue Liquid::Error => e
|
138
|
-
e.template_name = path
|
139
|
-
e.markup_context = "included " if e.markup_context.nil?
|
140
|
-
raise e
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def load_cached_partial(path, context)
|
146
|
-
context.registers[:cached_partials] ||= {}
|
147
|
-
cached_partial = context.registers[:cached_partials]
|
148
|
-
|
149
|
-
if cached_partial.key?(path)
|
150
|
-
cached_partial[path]
|
151
|
-
else
|
152
|
-
unparsed_file = context.registers[:site]
|
153
|
-
.liquid_renderer
|
154
|
-
.file(path)
|
155
|
-
begin
|
156
|
-
cached_partial[path] = unparsed_file.parse(read_file(path, context))
|
157
|
-
rescue Liquid::Error => e
|
158
|
-
e.template_name = path
|
159
|
-
e.markup_context = "included " if e.markup_context.nil?
|
160
|
-
raise e
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def valid_include_file?(path, _dir)
|
166
|
-
File.file?(path)
|
167
|
-
end
|
168
|
-
|
169
|
-
def realpath_prefixed_with?(path, dir)
|
170
|
-
File.exist?(path) && File.realpath(path).start_with?(dir)
|
171
|
-
rescue StandardError
|
172
|
-
false
|
173
|
-
end
|
174
|
-
|
175
|
-
# This method allows to modify the file content by inheriting from the class.
|
176
|
-
def read_file(file, context)
|
177
|
-
File.read(file, **file_read_opts(context))
|
178
|
-
end
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
def could_not_locate_message(file, includes_dirs)
|
183
|
-
"Could not locate the included file '#{file}' in any of #{includes_dirs}." \
|
184
|
-
" Ensure it exists in one of those directories."
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
class IncludeRelativeTag < IncludeTag
|
189
|
-
def tag_includes_dirs(context)
|
190
|
-
Array(page_path(context)).freeze
|
191
|
-
end
|
192
|
-
|
193
|
-
def page_path(context)
|
194
|
-
if context.registers[:page].nil?
|
195
|
-
context.registers[:site].source
|
196
|
-
else
|
197
|
-
site = context.registers[:site]
|
198
|
-
page_payload = context.registers[:page]
|
199
|
-
resource_path = \
|
200
|
-
if page_payload["collection"].nil?
|
201
|
-
page_payload["path"]
|
202
|
-
else
|
203
|
-
File.join(site.config["collections_dir"], page_payload["path"])
|
204
|
-
end
|
205
|
-
# rubocop:disable Performance/DeleteSuffix
|
206
|
-
resource_path.sub!(%r!/#excerpt\z!, "")
|
207
|
-
# rubocop:enable Performance/DeleteSuffix
|
208
|
-
site.in_source_dir File.dirname(resource_path)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
Liquid::Template.register_tag("include", Bridgetown::Tags::IncludeTag)
|
216
|
-
Liquid::Template.register_tag("include_relative", Bridgetown::Tags::IncludeRelativeTag)
|