liquid-render-tag 0.1.0
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 +7 -0
- data/.gitignore +8 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +23 -0
- data/Rakefile +2 -0
- data/lib/liquid-render-tag.rb +20 -0
- data/lib/liquid-render-tag/block_body.rb +219 -0
- data/lib/liquid-render-tag/context.rb +261 -0
- data/lib/liquid-render-tag/partial_cache.rb +24 -0
- data/lib/liquid-render-tag/register.rb +6 -0
- data/lib/liquid-render-tag/registers/disabled_tags.rb +32 -0
- data/lib/liquid-render-tag/static_registers.rb +36 -0
- data/lib/liquid-render-tag/strainer_factory.rb +36 -0
- data/lib/liquid-render-tag/strainer_template.rb +53 -0
- data/lib/liquid-render-tag/tag.rb +73 -0
- data/lib/liquid-render-tag/tags/render.rb +84 -0
- data/lib/liquid-render-tag/template.rb +274 -0
- data/lib/liquid-render-tag/template_factory.rb +9 -0
- data/lib/liquid-render-tag/tokenizer.rb +39 -0
- data/lib/liquid-render-tag/variable.rb +170 -0
- data/lib/liquid-render-tag/version.rb +3 -0
- data/liquid-render-tag.gemspec +27 -0
- metadata +108 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Liquid
|
4
|
+
class Tokenizer
|
5
|
+
attr_reader :line_number, :for_liquid_tag
|
6
|
+
|
7
|
+
def initialize(source, line_numbers = false, line_number: nil, for_liquid_tag: false)
|
8
|
+
@source = source
|
9
|
+
@line_number = line_number || (line_numbers ? 1 : nil)
|
10
|
+
@for_liquid_tag = for_liquid_tag
|
11
|
+
@tokens = tokenize
|
12
|
+
end
|
13
|
+
|
14
|
+
def shift
|
15
|
+
(token = @tokens.shift) || return
|
16
|
+
|
17
|
+
if @line_number
|
18
|
+
@line_number += @for_liquid_tag ? 1 : token.count("\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
token
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def tokenize
|
27
|
+
return [] if @source.to_s.empty?
|
28
|
+
|
29
|
+
return @source.split("\n") if @for_liquid_tag
|
30
|
+
|
31
|
+
tokens = @source.split(TemplateParser)
|
32
|
+
|
33
|
+
# removes the rogue empty element at the beginning of the array
|
34
|
+
tokens.shift if tokens[0]&.empty?
|
35
|
+
|
36
|
+
tokens
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Liquid
|
4
|
+
# Holds variables. Variables are only loaded "just in time"
|
5
|
+
# and are not evaluated as part of the render stage
|
6
|
+
#
|
7
|
+
# {{ monkey }}
|
8
|
+
# {{ user.name }}
|
9
|
+
#
|
10
|
+
# Variables can be combined with filters:
|
11
|
+
#
|
12
|
+
# {{ user | link }}
|
13
|
+
#
|
14
|
+
class Variable
|
15
|
+
FilterMarkupRegex = /#{FilterSeparator}\s*(.*)/om
|
16
|
+
FilterParser = /(?:\s+|#{QuotedFragment}|#{ArgumentSeparator})+/o
|
17
|
+
FilterArgsRegex = /(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*((?:\w+\s*\:\s*)?#{QuotedFragment})/o
|
18
|
+
JustTagAttributes = /\A#{TagAttributes}\z/o
|
19
|
+
MarkupWithQuotedFragment = /(#{QuotedFragment})(.*)/om
|
20
|
+
|
21
|
+
attr_accessor :filters, :name, :line_number
|
22
|
+
attr_reader :parse_context
|
23
|
+
alias_method :options, :parse_context
|
24
|
+
|
25
|
+
include ParserSwitching
|
26
|
+
|
27
|
+
def initialize(markup, parse_context)
|
28
|
+
@markup = markup
|
29
|
+
@name = nil
|
30
|
+
@parse_context = parse_context
|
31
|
+
@line_number = parse_context.line_number
|
32
|
+
|
33
|
+
parse_with_selected_parser(markup)
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw
|
37
|
+
@markup
|
38
|
+
end
|
39
|
+
|
40
|
+
def markup_context(markup)
|
41
|
+
"in \"{{#{markup}}}\""
|
42
|
+
end
|
43
|
+
|
44
|
+
def lax_parse(markup)
|
45
|
+
@filters = []
|
46
|
+
return unless markup =~ MarkupWithQuotedFragment
|
47
|
+
|
48
|
+
name_markup = Regexp.last_match(1)
|
49
|
+
filter_markup = Regexp.last_match(2)
|
50
|
+
@name = Expression.parse(name_markup)
|
51
|
+
if filter_markup =~ FilterMarkupRegex
|
52
|
+
filters = Regexp.last_match(1).scan(FilterParser)
|
53
|
+
filters.each do |f|
|
54
|
+
next unless f =~ /\w+/
|
55
|
+
filtername = Regexp.last_match(0)
|
56
|
+
filterargs = f.scan(FilterArgsRegex).flatten
|
57
|
+
@filters << parse_filter_expressions(filtername, filterargs)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def strict_parse(markup)
|
63
|
+
@filters = []
|
64
|
+
p = Parser.new(markup)
|
65
|
+
|
66
|
+
@name = Expression.parse(p.expression)
|
67
|
+
while p.consume?(:pipe)
|
68
|
+
filtername = p.consume(:id)
|
69
|
+
filterargs = p.consume?(:colon) ? parse_filterargs(p) : []
|
70
|
+
@filters << parse_filter_expressions(filtername, filterargs)
|
71
|
+
end
|
72
|
+
p.consume(:end_of_string)
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_filterargs(p)
|
76
|
+
# first argument
|
77
|
+
filterargs = [p.argument]
|
78
|
+
# followed by comma separated others
|
79
|
+
filterargs << p.argument while p.consume?(:comma)
|
80
|
+
filterargs
|
81
|
+
end
|
82
|
+
|
83
|
+
def render(context)
|
84
|
+
obj = @filters.inject(context.evaluate(@name)) do |output, (filter_name, filter_args, filter_kwargs)|
|
85
|
+
filter_args = evaluate_filter_expressions(context, filter_args, filter_kwargs)
|
86
|
+
context.invoke(filter_name, output, *filter_args)
|
87
|
+
end
|
88
|
+
|
89
|
+
obj = context.apply_global_filter(obj)
|
90
|
+
taint_check(context, obj)
|
91
|
+
obj
|
92
|
+
end
|
93
|
+
|
94
|
+
def render_to_output_buffer(context, output)
|
95
|
+
obj = render(context)
|
96
|
+
|
97
|
+
if obj.is_a?(Array)
|
98
|
+
output << obj.join
|
99
|
+
elsif obj.nil?
|
100
|
+
else
|
101
|
+
output << obj.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
output
|
105
|
+
end
|
106
|
+
|
107
|
+
def disabled?(_context)
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
111
|
+
def disabled_tags
|
112
|
+
[]
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def parse_filter_expressions(filter_name, unparsed_args)
|
118
|
+
filter_args = []
|
119
|
+
keyword_args = nil
|
120
|
+
unparsed_args.each do |a|
|
121
|
+
if (matches = a.match(JustTagAttributes))
|
122
|
+
keyword_args ||= {}
|
123
|
+
keyword_args[matches[1]] = Expression.parse(matches[2])
|
124
|
+
else
|
125
|
+
filter_args << Expression.parse(a)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
result = [filter_name, filter_args]
|
129
|
+
result << keyword_args if keyword_args
|
130
|
+
result
|
131
|
+
end
|
132
|
+
|
133
|
+
def evaluate_filter_expressions(context, filter_args, filter_kwargs)
|
134
|
+
parsed_args = filter_args.map { |expr| context.evaluate(expr) }
|
135
|
+
if filter_kwargs
|
136
|
+
parsed_kwargs = {}
|
137
|
+
filter_kwargs.each do |key, expr|
|
138
|
+
parsed_kwargs[key] = context.evaluate(expr)
|
139
|
+
end
|
140
|
+
parsed_args << parsed_kwargs
|
141
|
+
end
|
142
|
+
parsed_args
|
143
|
+
end
|
144
|
+
|
145
|
+
def taint_check(context, obj)
|
146
|
+
return if Template.taint_mode == :lax
|
147
|
+
return unless obj.tainted?
|
148
|
+
|
149
|
+
@markup =~ QuotedFragment
|
150
|
+
name = Regexp.last_match(0)
|
151
|
+
|
152
|
+
error = TaintedError.new("variable '#{name}' is tainted and was not escaped")
|
153
|
+
error.line_number = line_number
|
154
|
+
error.template_name = context.template_name
|
155
|
+
|
156
|
+
case Template.taint_mode
|
157
|
+
when :warn
|
158
|
+
context.warnings << error
|
159
|
+
when :error
|
160
|
+
raise error
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
165
|
+
def children
|
166
|
+
[@node.name] + @node.filters.flatten
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "liquid-render-tag/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "liquid-render-tag"
|
8
|
+
spec.version = LiquidRenderTag::VERSION
|
9
|
+
spec.authors = "Bridgetown Team"
|
10
|
+
spec.email = "maintainers@bridgetownrb.com"
|
11
|
+
|
12
|
+
spec.summary = %q{Backported Render tag and related changes from Liquid master to work with 4.0.3}
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = "https://github.com/bridgetownrb/liquid-render-tag"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
end
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
26
|
+
spec.add_development_dependency "liquid", "~> 4.0.3"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: liquid-render-tag
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bridgetown Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: liquid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 4.0.3
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.0.3
|
55
|
+
description: Backported Render tag and related changes from Liquid master to work
|
56
|
+
with 4.0.3
|
57
|
+
email: maintainers@bridgetownrb.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- lib/liquid-render-tag.rb
|
68
|
+
- lib/liquid-render-tag/block_body.rb
|
69
|
+
- lib/liquid-render-tag/context.rb
|
70
|
+
- lib/liquid-render-tag/partial_cache.rb
|
71
|
+
- lib/liquid-render-tag/register.rb
|
72
|
+
- lib/liquid-render-tag/registers/disabled_tags.rb
|
73
|
+
- lib/liquid-render-tag/static_registers.rb
|
74
|
+
- lib/liquid-render-tag/strainer_factory.rb
|
75
|
+
- lib/liquid-render-tag/strainer_template.rb
|
76
|
+
- lib/liquid-render-tag/tag.rb
|
77
|
+
- lib/liquid-render-tag/tags/render.rb
|
78
|
+
- lib/liquid-render-tag/template.rb
|
79
|
+
- lib/liquid-render-tag/template_factory.rb
|
80
|
+
- lib/liquid-render-tag/tokenizer.rb
|
81
|
+
- lib/liquid-render-tag/variable.rb
|
82
|
+
- lib/liquid-render-tag/version.rb
|
83
|
+
- liquid-render-tag.gemspec
|
84
|
+
homepage: https://github.com/bridgetownrb/liquid-render-tag
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubygems_version: 3.0.6
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Backported Render tag and related changes from Liquid master to work with
|
107
|
+
4.0.3
|
108
|
+
test_files: []
|