liquid 5.5.1 → 5.6.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -3
- data/lib/liquid/block_body.rb +11 -8
- data/lib/liquid/const.rb +8 -0
- data/lib/liquid/context.rb +10 -8
- data/lib/liquid/deprecations.rb +22 -0
- data/lib/liquid/environment.rb +159 -0
- data/lib/liquid/lexer.rb +177 -1
- data/lib/liquid/parse_context.rb +4 -3
- data/lib/liquid/parse_tree_visitor.rb +1 -1
- data/lib/liquid/parser.rb +1 -1
- data/lib/liquid/standardfilters.rb +1 -3
- data/lib/liquid/tag.rb +3 -0
- data/lib/liquid/tags/assign.rb +0 -2
- data/lib/liquid/tags/break.rb +0 -2
- data/lib/liquid/tags/capture.rb +0 -2
- data/lib/liquid/tags/case.rb +0 -2
- data/lib/liquid/tags/comment.rb +0 -2
- data/lib/liquid/tags/continue.rb +0 -2
- data/lib/liquid/tags/cycle.rb +0 -2
- data/lib/liquid/tags/decrement.rb +0 -2
- data/lib/liquid/tags/echo.rb +0 -2
- data/lib/liquid/tags/for.rb +0 -2
- data/lib/liquid/tags/if.rb +0 -2
- data/lib/liquid/tags/ifchanged.rb +0 -2
- data/lib/liquid/tags/include.rb +0 -2
- data/lib/liquid/tags/increment.rb +0 -2
- data/lib/liquid/tags/inline_comment.rb +0 -2
- data/lib/liquid/tags/raw.rb +0 -2
- data/lib/liquid/tags/render.rb +0 -2
- data/lib/liquid/tags/table_row.rb +6 -2
- data/lib/liquid/tags/unless.rb +0 -2
- data/lib/liquid/tags.rb +47 -0
- data/lib/liquid/template.rb +51 -56
- data/lib/liquid/variable.rb +13 -7
- data/lib/liquid/version.rb +1 -1
- data/lib/liquid.rb +10 -14
- metadata +37 -6
- data/lib/liquid/strainer_factory.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e610d96aad5d08594f89119400b89c2667825d9a4e69936a315f8d5ae4f460ae
|
4
|
+
data.tar.gz: dadd1ed95abb4eab1c4a1186a251b5598698bc93ce21415fb8894a5f3a188382
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd5f73dd9cf3d9d6c49d96712eb413152bc61b935c496135374c1b0970d7ac6912adaa18d99d3ad6a0eb1fd87bfc9f57d2907dec68237f2bd46c5a1e69a6184e
|
7
|
+
data.tar.gz: 3cfd49dc70c4ee2456569bda9fe7f5e700d88f471bed88045da6d4e1eef396a9050c6e045d0c2e715ffb509653d06ff507240e158aa4f34dc15d42c1cec23a05
|
data/README.md
CHANGED
@@ -52,6 +52,47 @@ For standard use you can just pass it the content of a file and call render with
|
|
52
52
|
@template.render('name' => 'tobi') # => "hi tobi"
|
53
53
|
```
|
54
54
|
|
55
|
+
### Concept of Environments
|
56
|
+
|
57
|
+
In Liquid, a "Environment" is a scoped environment that encapsulates custom tags, filters, and other configurations. This allows you to define and isolate different sets of functionality for different contexts, avoiding global overrides that can lead to conflicts and unexpected behavior.
|
58
|
+
|
59
|
+
By using environments, you can:
|
60
|
+
|
61
|
+
1. **Encapsulate Logic**: Keep the logic for different parts of your application separate.
|
62
|
+
2. **Avoid Conflicts**: Prevent custom tags and filters from clashing with each other.
|
63
|
+
3. **Improve Maintainability**: Make it easier to manage and understand the scope of customizations.
|
64
|
+
4. **Enhance Security**: Limit the availability of certain tags and filters to specific contexts.
|
65
|
+
|
66
|
+
We encourage the use of Environments over globally overriding things because it promotes better software design principles such as modularity, encapsulation, and separation of concerns.
|
67
|
+
|
68
|
+
Here's an example of how you can define and use Environments in Liquid:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
user_environment = Liquid::Environment.build do |environment|
|
72
|
+
environment.register_tag("renderobj", RenderObjTag)
|
73
|
+
end
|
74
|
+
|
75
|
+
Liquid::Template.parse(<<~LIQUID, environment: user_environment)
|
76
|
+
{% renderobj src: "path/to/model.obj" %}
|
77
|
+
LIQUID
|
78
|
+
```
|
79
|
+
|
80
|
+
In this example, `RenderObjTag` is a custom tag that is only available within the `user_environment`.
|
81
|
+
|
82
|
+
Similarly, you can define another environment for a different context, such as email templates:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
email_environment = Liquid::Environment.build do |environment|
|
86
|
+
environment.register_tag("unsubscribe_footer", UnsubscribeFooter)
|
87
|
+
end
|
88
|
+
|
89
|
+
Liquid::Template.parse(<<~LIQUID, environment: email_environment)
|
90
|
+
{% unsubscribe_footer %}
|
91
|
+
LIQUID
|
92
|
+
```
|
93
|
+
|
94
|
+
By using Environments, you ensure that custom tags and filters are only available in the contexts where they are needed, making your Liquid templates more robust and easier to manage.
|
95
|
+
|
55
96
|
### Error Modes
|
56
97
|
|
57
98
|
Setting the error mode of Liquid lets you specify how strictly you want your templates to be interpreted.
|
@@ -62,9 +103,10 @@ Liquid also comes with a stricter parser that can be used when editing templates
|
|
62
103
|
when templates are invalid. You can enable this new parser like this:
|
63
104
|
|
64
105
|
```ruby
|
65
|
-
Liquid::
|
66
|
-
Liquid::
|
67
|
-
Liquid::
|
106
|
+
Liquid::Environment.default.error_mode = :strict
|
107
|
+
Liquid::Environment.default.error_mode = :strict # Raises a SyntaxError when invalid syntax is used
|
108
|
+
Liquid::Environment.default.error_mode = :warn # Adds strict errors to template.errors but continues as normal
|
109
|
+
Liquid::Environment.default.error_mode = :lax # The default mode, accepts almost anything.
|
68
110
|
```
|
69
111
|
|
70
112
|
If you want to set the error mode only on specific templates you can pass `:error_mode` as an option to `parse`:
|
data/lib/liquid/block_body.rb
CHANGED
@@ -52,7 +52,7 @@ module Liquid
|
|
52
52
|
next parse_liquid_tag(markup, parse_context)
|
53
53
|
end
|
54
54
|
|
55
|
-
unless (tag =
|
55
|
+
unless (tag = parse_context.environment.tag_for_name(tag_name))
|
56
56
|
# end parsing if we reach an unknown tag and let the caller decide
|
57
57
|
# determine how to proceed
|
58
58
|
return yield tag_name, markup
|
@@ -147,7 +147,7 @@ module Liquid
|
|
147
147
|
next
|
148
148
|
end
|
149
149
|
|
150
|
-
unless (tag =
|
150
|
+
unless (tag = parse_context.environment.tag_for_name(tag_name))
|
151
151
|
# end parsing if we reach an unknown tag and let the caller decide
|
152
152
|
# determine how to proceed
|
153
153
|
return yield tag_name, markup
|
@@ -246,10 +246,17 @@ module Liquid
|
|
246
246
|
end
|
247
247
|
|
248
248
|
def create_variable(token, parse_context)
|
249
|
-
if token
|
250
|
-
|
249
|
+
if token.end_with?("}}")
|
250
|
+
i = 2
|
251
|
+
i = 3 if token[i] == "-"
|
252
|
+
parse_end = token.length - 3
|
253
|
+
parse_end -= 1 if token[parse_end] == "-"
|
254
|
+
markup_end = parse_end - i + 1
|
255
|
+
markup = markup_end <= 0 ? "" : token.slice(i, markup_end)
|
256
|
+
|
251
257
|
return Variable.new(markup, parse_context)
|
252
258
|
end
|
259
|
+
|
253
260
|
BlockBody.raise_missing_variable_terminator(token, parse_context)
|
254
261
|
end
|
255
262
|
|
@@ -262,9 +269,5 @@ module Liquid
|
|
262
269
|
def raise_missing_variable_terminator(token, parse_context)
|
263
270
|
BlockBody.raise_missing_variable_terminator(token, parse_context)
|
264
271
|
end
|
265
|
-
|
266
|
-
def registered_tags
|
267
|
-
Template.tags
|
268
|
-
end
|
269
272
|
end
|
270
273
|
end
|
data/lib/liquid/const.rb
ADDED
data/lib/liquid/context.rb
CHANGED
@@ -15,14 +15,15 @@ module Liquid
|
|
15
15
|
# context['bob'] #=> nil class Context
|
16
16
|
class Context
|
17
17
|
attr_reader :scopes, :errors, :registers, :environments, :resource_limits, :static_registers, :static_environments
|
18
|
-
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
18
|
+
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters, :environment
|
19
19
|
|
20
20
|
# rubocop:disable Metrics/ParameterLists
|
21
|
-
def self.build(environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {}, &block)
|
22
|
-
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_environments, &block)
|
21
|
+
def self.build(environment: Environment.default, environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {}, &block)
|
22
|
+
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_environments, environment, &block)
|
23
23
|
end
|
24
24
|
|
25
|
-
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {})
|
25
|
+
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {}, environment = Environment.default)
|
26
|
+
@environment = environment
|
26
27
|
@environments = [environments]
|
27
28
|
@environments.flatten!
|
28
29
|
|
@@ -32,7 +33,7 @@ module Liquid
|
|
32
33
|
@errors = []
|
33
34
|
@partial = false
|
34
35
|
@strict_variables = false
|
35
|
-
@resource_limits = resource_limits || ResourceLimits.new(
|
36
|
+
@resource_limits = resource_limits || ResourceLimits.new(environment.default_resource_limits)
|
36
37
|
@base_scope_depth = 0
|
37
38
|
@interrupts = []
|
38
39
|
@filters = []
|
@@ -40,10 +41,10 @@ module Liquid
|
|
40
41
|
@disabled_tags = {}
|
41
42
|
|
42
43
|
@registers.static[:cached_partials] ||= {}
|
43
|
-
@registers.static[:file_system] ||=
|
44
|
+
@registers.static[:file_system] ||= environment.file_system
|
44
45
|
@registers.static[:template_factory] ||= Liquid::TemplateFactory.new
|
45
46
|
|
46
|
-
self.exception_renderer =
|
47
|
+
self.exception_renderer = environment.exception_renderer
|
47
48
|
if rethrow_errors
|
48
49
|
self.exception_renderer = Liquid::RAISE_EXCEPTION_LAMBDA
|
49
50
|
end
|
@@ -60,7 +61,7 @@ module Liquid
|
|
60
61
|
end
|
61
62
|
|
62
63
|
def strainer
|
63
|
-
@strainer ||=
|
64
|
+
@strainer ||= @environment.create_strainer(self, @filters)
|
64
65
|
end
|
65
66
|
|
66
67
|
# Adds filters to this context.
|
@@ -142,6 +143,7 @@ module Liquid
|
|
142
143
|
check_overflow
|
143
144
|
|
144
145
|
self.class.build(
|
146
|
+
environment: @environment,
|
145
147
|
resource_limits: resource_limits,
|
146
148
|
static_environments: static_environments,
|
147
149
|
registers: Registers.new(registers),
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module Liquid
|
6
|
+
class Deprecations
|
7
|
+
class << self
|
8
|
+
attr_accessor :warned
|
9
|
+
|
10
|
+
Deprecations.warned = Set.new
|
11
|
+
|
12
|
+
def warn(name, alternative)
|
13
|
+
return if warned.include?(name)
|
14
|
+
|
15
|
+
warned << name
|
16
|
+
|
17
|
+
caller_location = caller_locations(2, 1).first
|
18
|
+
Warning.warn("[DEPRECATION] #{name} is deprecated. Use #{alternative} instead. Called from #{caller_location}\n")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Liquid
|
4
|
+
# The Environment is the container for all configuration options of Liquid, such as
|
5
|
+
# the registered tags, filters, and the default error mode.
|
6
|
+
class Environment
|
7
|
+
# The default error mode for all templates. This can be overridden on a
|
8
|
+
# per-template basis.
|
9
|
+
attr_accessor :error_mode
|
10
|
+
|
11
|
+
# The tags that are available to use in the template.
|
12
|
+
attr_accessor :tags
|
13
|
+
|
14
|
+
# The strainer template which is used to store filters that are available to
|
15
|
+
# use in templates.
|
16
|
+
attr_accessor :strainer_template
|
17
|
+
|
18
|
+
# The exception renderer that is used to render exceptions that are raised
|
19
|
+
# when rendering a template
|
20
|
+
attr_accessor :exception_renderer
|
21
|
+
|
22
|
+
# The default file system that is used to load templates from.
|
23
|
+
attr_accessor :file_system
|
24
|
+
|
25
|
+
# The default resource limits that are used to limit the resources that a
|
26
|
+
# template can consume.
|
27
|
+
attr_accessor :default_resource_limits
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# Creates a new environment instance.
|
31
|
+
#
|
32
|
+
# @param tags [Hash] The tags that are available to use in
|
33
|
+
# the template.
|
34
|
+
# @param file_system The default file system that is used
|
35
|
+
# to load templates from.
|
36
|
+
# @param error_mode [Symbol] The default error mode for all templates
|
37
|
+
# (either :strict, :warn, or :lax).
|
38
|
+
# @param exception_renderer [Proc] The exception renderer that is used to
|
39
|
+
# render exceptions.
|
40
|
+
# @yieldparam environment [Environment] The environment instance that is being built.
|
41
|
+
# @return [Environment] The new environment instance.
|
42
|
+
def build(tags: nil, file_system: nil, error_mode: nil, exception_renderer: nil)
|
43
|
+
ret = new
|
44
|
+
ret.tags = tags if tags
|
45
|
+
ret.file_system = file_system if file_system
|
46
|
+
ret.error_mode = error_mode if error_mode
|
47
|
+
ret.exception_renderer = exception_renderer if exception_renderer
|
48
|
+
yield ret if block_given?
|
49
|
+
ret.freeze
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the default environment instance.
|
53
|
+
#
|
54
|
+
# @return [Environment] The default environment instance.
|
55
|
+
def default
|
56
|
+
@default ||= new
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sets the default environment instance for the duration of the block
|
60
|
+
#
|
61
|
+
# @param environment [Environment] The environment instance to use as the default for the
|
62
|
+
# duration of the block.
|
63
|
+
# @yield
|
64
|
+
# @return [Object] The return value of the block.
|
65
|
+
def dangerously_override(environment)
|
66
|
+
original_default = @default
|
67
|
+
@default = environment
|
68
|
+
yield
|
69
|
+
ensure
|
70
|
+
@default = original_default
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Initializes a new environment instance.
|
75
|
+
# @api private
|
76
|
+
def initialize
|
77
|
+
@tags = Tags::STANDARD_TAGS.dup
|
78
|
+
@error_mode = :lax
|
79
|
+
@strainer_template = Class.new(StrainerTemplate).tap do |klass|
|
80
|
+
klass.add_filter(StandardFilters)
|
81
|
+
end
|
82
|
+
@exception_renderer = ->(exception) { exception }
|
83
|
+
@file_system = BlankFileSystem.new
|
84
|
+
@default_resource_limits = Const::EMPTY_HASH
|
85
|
+
@strainer_template_class_cache = {}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Registers a new tag with the environment.
|
89
|
+
#
|
90
|
+
# @param name [String] The name of the tag.
|
91
|
+
# @param klass [Liquid::Tag] The class that implements the tag.
|
92
|
+
# @return [void]
|
93
|
+
def register_tag(name, klass)
|
94
|
+
@tags[name] = klass
|
95
|
+
end
|
96
|
+
|
97
|
+
# Registers a new filter with the environment.
|
98
|
+
#
|
99
|
+
# @param filter [Module] The module that contains the filter methods.
|
100
|
+
# @return [void]
|
101
|
+
def register_filter(filter)
|
102
|
+
@strainer_template_class_cache.clear
|
103
|
+
@strainer_template.add_filter(filter)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Registers multiple filters with this environment.
|
107
|
+
#
|
108
|
+
# @param filters [Array<Module>] The modules that contain the filter methods.
|
109
|
+
# @return [self]
|
110
|
+
def register_filters(filters)
|
111
|
+
@strainer_template_class_cache.clear
|
112
|
+
filters.each { |f| @strainer_template.add_filter(f) }
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
# Creates a new strainer instance with the given filters, caching the result
|
117
|
+
# for faster lookup.
|
118
|
+
#
|
119
|
+
# @param context [Liquid::Context] The context that the strainer will be
|
120
|
+
# used in.
|
121
|
+
# @param filters [Array<Module>] The filters that the strainer will have
|
122
|
+
# access to.
|
123
|
+
# @return [Liquid::Strainer] The new strainer instance.
|
124
|
+
def create_strainer(context, filters = Const::EMPTY_ARRAY)
|
125
|
+
return @strainer_template.new(context) if filters.empty?
|
126
|
+
|
127
|
+
strainer_template = @strainer_template_class_cache[filters] ||= begin
|
128
|
+
klass = Class.new(@strainer_template)
|
129
|
+
filters.each { |f| klass.add_filter(f) }
|
130
|
+
klass
|
131
|
+
end
|
132
|
+
|
133
|
+
strainer_template.new(context)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns the names of all the filter methods that are available to use in
|
137
|
+
# the strainer template.
|
138
|
+
#
|
139
|
+
# @return [Array<String>] The names of all the filter methods.
|
140
|
+
def filter_method_names
|
141
|
+
@strainer_template.filter_method_names
|
142
|
+
end
|
143
|
+
|
144
|
+
# Returns the tag class for the given tag name.
|
145
|
+
#
|
146
|
+
# @param name [String] The name of the tag.
|
147
|
+
# @return [Liquid::Tag] The tag class.
|
148
|
+
def tag_for_name(name)
|
149
|
+
@tags[name]
|
150
|
+
end
|
151
|
+
|
152
|
+
def freeze
|
153
|
+
@tags.freeze
|
154
|
+
# TODO: freeze the tags, currently this is not possible because of liquid-c
|
155
|
+
# @strainer_template.freeze
|
156
|
+
super
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/liquid/lexer.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "strscan"
|
4
|
+
|
4
5
|
module Liquid
|
5
|
-
class
|
6
|
+
class Lexer1
|
6
7
|
SPECIALS = {
|
7
8
|
'|' => :pipe,
|
8
9
|
'.' => :dot,
|
@@ -58,4 +59,179 @@ module Liquid
|
|
58
59
|
@output << [:end_of_string]
|
59
60
|
end
|
60
61
|
end
|
62
|
+
|
63
|
+
class Lexer2
|
64
|
+
CLOSE_ROUND = [:close_round, ")"].freeze
|
65
|
+
CLOSE_SQUARE = [:close_square, "]"].freeze
|
66
|
+
COLON = [:colon, ":"].freeze
|
67
|
+
COMMA = [:comma, ","].freeze
|
68
|
+
COMPARISION_NOT_EQUAL = [:comparison, "!="].freeze
|
69
|
+
COMPARISON_CONTAINS = [:comparison, "contains"].freeze
|
70
|
+
COMPARISON_EQUAL = [:comparison, "=="].freeze
|
71
|
+
COMPARISON_GREATER_THAN = [:comparison, ">"].freeze
|
72
|
+
COMPARISON_GREATER_THAN_OR_EQUAL = [:comparison, ">="].freeze
|
73
|
+
COMPARISON_LESS_THAN = [:comparison, "<"].freeze
|
74
|
+
COMPARISON_LESS_THAN_OR_EQUAL = [:comparison, "<="].freeze
|
75
|
+
COMPARISON_NOT_EQUAL_ALT = [:comparison, "<>"].freeze
|
76
|
+
DASH = [:dash, "-"].freeze
|
77
|
+
DOT = [:dot, "."].freeze
|
78
|
+
DOTDOT = [:dotdot, ".."].freeze
|
79
|
+
DOT_ORD = ".".ord
|
80
|
+
DOUBLE_STRING_LITERAL = /"[^\"]*"/
|
81
|
+
EOS = [:end_of_string].freeze
|
82
|
+
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
|
83
|
+
NUMBER_LITERAL = /-?\d+(\.\d+)?/
|
84
|
+
OPEN_ROUND = [:open_round, "("].freeze
|
85
|
+
OPEN_SQUARE = [:open_square, "["].freeze
|
86
|
+
PIPE = [:pipe, "|"].freeze
|
87
|
+
QUESTION = [:question, "?"].freeze
|
88
|
+
RUBY_WHITESPACE = [" ", "\t", "\r", "\n", "\f"].freeze
|
89
|
+
SINGLE_STRING_LITERAL = /'[^\']*'/
|
90
|
+
WHITESPACE_OR_NOTHING = /\s*/
|
91
|
+
|
92
|
+
SINGLE_COMPARISON_TOKENS = [].tap do |table|
|
93
|
+
table["<".ord] = COMPARISON_LESS_THAN
|
94
|
+
table[">".ord] = COMPARISON_GREATER_THAN
|
95
|
+
end
|
96
|
+
|
97
|
+
TWO_CHARS_COMPARISON_JUMP_TABLE = [].tap do |table|
|
98
|
+
table["=".ord] = [].tap do |sub_table|
|
99
|
+
sub_table["=".ord] = COMPARISON_EQUAL
|
100
|
+
sub_table.freeze
|
101
|
+
end
|
102
|
+
table["!".ord] = [].tap do |sub_table|
|
103
|
+
sub_table["=".ord] = COMPARISION_NOT_EQUAL
|
104
|
+
sub_table.freeze
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
COMPARISON_JUMP_TABLE = [].tap do |table|
|
109
|
+
table["<".ord] = [].tap do |sub_table|
|
110
|
+
sub_table["=".ord] = COMPARISON_LESS_THAN_OR_EQUAL
|
111
|
+
sub_table[">".ord] = COMPARISON_NOT_EQUAL_ALT
|
112
|
+
RUBY_WHITESPACE.each { |c| sub_table[c.ord] = COMPARISON_LESS_THAN }
|
113
|
+
sub_table.freeze
|
114
|
+
end
|
115
|
+
table[">".ord] = [].tap do |sub_table|
|
116
|
+
sub_table["=".ord] = COMPARISON_GREATER_THAN_OR_EQUAL
|
117
|
+
RUBY_WHITESPACE.each { |c| sub_table[c.ord] = COMPARISON_GREATER_THAN }
|
118
|
+
sub_table.freeze
|
119
|
+
end
|
120
|
+
table.freeze
|
121
|
+
end
|
122
|
+
|
123
|
+
NEXT_MATCHER_JUMP_TABLE = [].tap do |table|
|
124
|
+
"a".upto("z") do |c|
|
125
|
+
table[c.ord] = [:id, IDENTIFIER].freeze
|
126
|
+
table[c.upcase.ord] = [:id, IDENTIFIER].freeze
|
127
|
+
end
|
128
|
+
table["_".ord] = [:id, IDENTIFIER].freeze
|
129
|
+
|
130
|
+
"0".upto("9") do |c|
|
131
|
+
table[c.ord] = [:number, NUMBER_LITERAL].freeze
|
132
|
+
end
|
133
|
+
table["-".ord] = [:number, NUMBER_LITERAL].freeze
|
134
|
+
|
135
|
+
table["'".ord] = [:string, SINGLE_STRING_LITERAL].freeze
|
136
|
+
table["\"".ord] = [:string, DOUBLE_STRING_LITERAL].freeze
|
137
|
+
table.freeze
|
138
|
+
end
|
139
|
+
|
140
|
+
SPECIAL_TABLE = [].tap do |table|
|
141
|
+
table["|".ord] = PIPE
|
142
|
+
table[".".ord] = DOT
|
143
|
+
table[":".ord] = COLON
|
144
|
+
table[",".ord] = COMMA
|
145
|
+
table["[".ord] = OPEN_SQUARE
|
146
|
+
table["]".ord] = CLOSE_SQUARE
|
147
|
+
table["(".ord] = OPEN_ROUND
|
148
|
+
table[")".ord] = CLOSE_ROUND
|
149
|
+
table["?".ord] = QUESTION
|
150
|
+
table["-".ord] = DASH
|
151
|
+
end
|
152
|
+
|
153
|
+
NUMBER_TABLE = [].tap do |table|
|
154
|
+
"0".upto("9") do |c|
|
155
|
+
table[c.ord] = true
|
156
|
+
end
|
157
|
+
table.freeze
|
158
|
+
end
|
159
|
+
|
160
|
+
def initialize(input)
|
161
|
+
@ss = StringScanner.new(input)
|
162
|
+
end
|
163
|
+
|
164
|
+
# rubocop:disable Metrics/BlockNesting
|
165
|
+
def tokenize
|
166
|
+
@output = []
|
167
|
+
|
168
|
+
until @ss.eos?
|
169
|
+
@ss.skip(WHITESPACE_OR_NOTHING)
|
170
|
+
|
171
|
+
break if @ss.eos?
|
172
|
+
|
173
|
+
start_pos = @ss.pos
|
174
|
+
peeked = @ss.peek_byte
|
175
|
+
|
176
|
+
if (special = SPECIAL_TABLE[peeked])
|
177
|
+
@ss.scan_byte
|
178
|
+
# Special case for ".."
|
179
|
+
if special == DOT && @ss.peek_byte == DOT_ORD
|
180
|
+
@ss.scan_byte
|
181
|
+
@output << DOTDOT
|
182
|
+
elsif special == DASH
|
183
|
+
# Special case for negative numbers
|
184
|
+
if (peeked_byte = @ss.peek_byte) && NUMBER_TABLE[peeked_byte]
|
185
|
+
@ss.pos -= 1
|
186
|
+
@output << [:number, @ss.scan(NUMBER_LITERAL)]
|
187
|
+
else
|
188
|
+
@output << special
|
189
|
+
end
|
190
|
+
else
|
191
|
+
@output << special
|
192
|
+
end
|
193
|
+
elsif (sub_table = TWO_CHARS_COMPARISON_JUMP_TABLE[peeked])
|
194
|
+
@ss.scan_byte
|
195
|
+
if (peeked_byte = @ss.peek_byte) && (found = sub_table[peeked_byte])
|
196
|
+
@output << found
|
197
|
+
@ss.scan_byte
|
198
|
+
else
|
199
|
+
raise_syntax_error(start_pos)
|
200
|
+
end
|
201
|
+
elsif (sub_table = COMPARISON_JUMP_TABLE[peeked])
|
202
|
+
@ss.scan_byte
|
203
|
+
if (peeked_byte = @ss.peek_byte) && (found = sub_table[peeked_byte])
|
204
|
+
@output << found
|
205
|
+
@ss.scan_byte
|
206
|
+
else
|
207
|
+
@output << SINGLE_COMPARISON_TOKENS[peeked]
|
208
|
+
end
|
209
|
+
else
|
210
|
+
type, pattern = NEXT_MATCHER_JUMP_TABLE[peeked]
|
211
|
+
|
212
|
+
if type && (t = @ss.scan(pattern))
|
213
|
+
# Special case for "contains"
|
214
|
+
@output << if type == :id && t == "contains" && @output.last&.first != :dot
|
215
|
+
COMPARISON_CONTAINS
|
216
|
+
else
|
217
|
+
[type, t]
|
218
|
+
end
|
219
|
+
else
|
220
|
+
raise_syntax_error(start_pos)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
# rubocop:enable Metrics/BlockNesting
|
225
|
+
|
226
|
+
@output << EOS
|
227
|
+
end
|
228
|
+
|
229
|
+
def raise_syntax_error(start_pos)
|
230
|
+
@ss.pos = start_pos
|
231
|
+
# the character could be a UTF-8 character, use getch to get all the bytes
|
232
|
+
raise SyntaxError, "Unexpected character #{@ss.getch}"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
Lexer = StringScanner.instance_methods.include?(:scan_byte) ? Lexer2 : Lexer1
|
61
237
|
end
|
data/lib/liquid/parse_context.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
module Liquid
|
4
4
|
class ParseContext
|
5
5
|
attr_accessor :locale, :line_number, :trim_whitespace, :depth
|
6
|
-
attr_reader :partial, :warnings, :error_mode
|
6
|
+
attr_reader :partial, :warnings, :error_mode, :environment
|
7
7
|
|
8
|
-
def initialize(options =
|
8
|
+
def initialize(options = Const::EMPTY_HASH)
|
9
|
+
@environment = options.fetch(:environment, Environment.default)
|
9
10
|
@template_options = options ? options.dup : {}
|
10
11
|
|
11
12
|
@locale = @template_options[:locale] ||= I18n.new
|
@@ -35,7 +36,7 @@ module Liquid
|
|
35
36
|
@partial = value
|
36
37
|
@options = value ? partial_options : @template_options
|
37
38
|
|
38
|
-
@error_mode = @options[:error_mode] ||
|
39
|
+
@error_mode = @options[:error_mode] || @environment.error_mode
|
39
40
|
end
|
40
41
|
|
41
42
|
def partial_options
|
data/lib/liquid/parser.rb
CHANGED
@@ -877,7 +877,7 @@ module Liquid
|
|
877
877
|
# - [`nil`](/docs/api/liquid/basics#nil)
|
878
878
|
# @liquid_syntax variable | default: variable
|
879
879
|
# @liquid_return [untyped]
|
880
|
-
# @liquid_optional_param allow_false [boolean] Whether to use false values instead of the default.
|
880
|
+
# @liquid_optional_param allow_false: [boolean] Whether to use false values instead of the default.
|
881
881
|
def default(input, default_value = '', options = {})
|
882
882
|
options = {} unless options.is_a?(Hash)
|
883
883
|
false_check = options['allow_false'] ? input.nil? : !Liquid::Utils.to_liquid_value(input)
|
@@ -1001,6 +1001,4 @@ module Liquid
|
|
1001
1001
|
end
|
1002
1002
|
end
|
1003
1003
|
end
|
1004
|
-
|
1005
|
-
Template.register_filter(StandardFilters)
|
1006
1004
|
end
|
data/lib/liquid/tag.rb
CHANGED
data/lib/liquid/tags/assign.rb
CHANGED
data/lib/liquid/tags/break.rb
CHANGED
data/lib/liquid/tags/capture.rb
CHANGED
data/lib/liquid/tags/case.rb
CHANGED
data/lib/liquid/tags/comment.rb
CHANGED
data/lib/liquid/tags/continue.rb
CHANGED
data/lib/liquid/tags/cycle.rb
CHANGED
data/lib/liquid/tags/echo.rb
CHANGED
data/lib/liquid/tags/for.rb
CHANGED
data/lib/liquid/tags/if.rb
CHANGED
data/lib/liquid/tags/include.rb
CHANGED
data/lib/liquid/tags/raw.rb
CHANGED
data/lib/liquid/tags/render.rb
CHANGED
@@ -65,6 +65,12 @@ module Liquid
|
|
65
65
|
super
|
66
66
|
output << '</td>'
|
67
67
|
|
68
|
+
# Handle any interrupts if they exist.
|
69
|
+
if context.interrupt?
|
70
|
+
interrupt = context.pop_interrupt
|
71
|
+
break if interrupt.is_a?(BreakInterrupt)
|
72
|
+
end
|
73
|
+
|
68
74
|
if tablerowloop.col_last && !tablerowloop.last
|
69
75
|
output << "</tr>\n<tr class=\"row#{tablerowloop.row + 1}\">"
|
70
76
|
end
|
@@ -91,6 +97,4 @@ module Liquid
|
|
91
97
|
raise Liquid::ArgumentError, "invalid integer"
|
92
98
|
end
|
93
99
|
end
|
94
|
-
|
95
|
-
Template.register_tag('tablerow', TableRow)
|
96
100
|
end
|
data/lib/liquid/tags/unless.rb
CHANGED
data/lib/liquid/tags.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "tags/table_row"
|
4
|
+
require_relative "tags/echo"
|
5
|
+
require_relative "tags/if"
|
6
|
+
require_relative "tags/break"
|
7
|
+
require_relative "tags/inline_comment"
|
8
|
+
require_relative "tags/for"
|
9
|
+
require_relative "tags/assign"
|
10
|
+
require_relative "tags/ifchanged"
|
11
|
+
require_relative "tags/case"
|
12
|
+
require_relative "tags/include"
|
13
|
+
require_relative "tags/continue"
|
14
|
+
require_relative "tags/capture"
|
15
|
+
require_relative "tags/decrement"
|
16
|
+
require_relative "tags/unless"
|
17
|
+
require_relative "tags/increment"
|
18
|
+
require_relative "tags/comment"
|
19
|
+
require_relative "tags/raw"
|
20
|
+
require_relative "tags/render"
|
21
|
+
require_relative "tags/cycle"
|
22
|
+
|
23
|
+
module Liquid
|
24
|
+
module Tags
|
25
|
+
STANDARD_TAGS = {
|
26
|
+
'cycle' => Cycle,
|
27
|
+
'render' => Render,
|
28
|
+
'raw' => Raw,
|
29
|
+
'comment' => Comment,
|
30
|
+
'increment' => Increment,
|
31
|
+
'unless' => Unless,
|
32
|
+
'decrement' => Decrement,
|
33
|
+
'capture' => Capture,
|
34
|
+
'continue' => Continue,
|
35
|
+
'include' => Include,
|
36
|
+
'case' => Case,
|
37
|
+
'ifchanged' => Ifchanged,
|
38
|
+
'assign' => Assign,
|
39
|
+
'for' => For,
|
40
|
+
'#' => InlineComment,
|
41
|
+
'break' => Break,
|
42
|
+
'if' => If,
|
43
|
+
'echo' => Echo,
|
44
|
+
'tablerow' => TableRow,
|
45
|
+
}.freeze
|
46
|
+
end
|
47
|
+
end
|
data/lib/liquid/template.rb
CHANGED
@@ -18,89 +18,78 @@ module Liquid
|
|
18
18
|
attr_accessor :root, :name
|
19
19
|
attr_reader :resource_limits, :warnings
|
20
20
|
|
21
|
-
|
22
|
-
include Enumerable
|
21
|
+
attr_reader :profiler
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
class << self
|
24
|
+
# Sets how strict the parser should be.
|
25
|
+
# :lax acts like liquid 2.5 and silently ignores malformed tags in most cases.
|
26
|
+
# :warn is the default and will give deprecation warnings when invalid syntax is used.
|
27
|
+
# :strict will enforce correct syntax.
|
28
|
+
def error_mode=(mode)
|
29
|
+
Deprecations.warn("Template.error_mode=", "Environment#error_mode=")
|
30
|
+
Environment.default.error_mode = mode
|
27
31
|
end
|
28
32
|
|
29
|
-
def
|
30
|
-
|
31
|
-
return @cache[tag_name] if Liquid.cache_classes
|
32
|
-
|
33
|
-
lookup_class(@tags[tag_name]).tap { |o| @cache[tag_name] = o }
|
33
|
+
def error_mode
|
34
|
+
Environment.default.error_mode
|
34
35
|
end
|
35
36
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
37
|
+
def default_exception_renderer=(renderer)
|
38
|
+
Deprecations.warn("Template.default_exception_renderer=", "Environment#exception_renderer=")
|
39
|
+
Environment.default.exception_renderer = renderer
|
39
40
|
end
|
40
41
|
|
41
|
-
def
|
42
|
-
|
43
|
-
@cache.delete(tag_name)
|
42
|
+
def default_exception_renderer
|
43
|
+
Environment.default.exception_renderer
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
47
|
-
|
46
|
+
def file_system=(file_system)
|
47
|
+
Deprecations.warn("Template.file_system=", "Environment#file_system=")
|
48
|
+
Environment.default.file_system = file_system
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
def lookup_class(name)
|
53
|
-
Object.const_get(name)
|
51
|
+
def file_system
|
52
|
+
Environment.default.file_system
|
54
53
|
end
|
55
|
-
end
|
56
|
-
|
57
|
-
attr_reader :profiler
|
58
54
|
|
59
|
-
|
60
|
-
|
61
|
-
# :lax acts like liquid 2.5 and silently ignores malformed tags in most cases.
|
62
|
-
# :warn is the default and will give deprecation warnings when invalid syntax is used.
|
63
|
-
# :strict will enforce correct syntax.
|
64
|
-
attr_accessor :error_mode
|
65
|
-
Template.error_mode = :lax
|
66
|
-
|
67
|
-
attr_accessor :default_exception_renderer
|
68
|
-
Template.default_exception_renderer = lambda do |exception|
|
69
|
-
exception
|
55
|
+
def tags
|
56
|
+
Environment.default.tags
|
70
57
|
end
|
71
58
|
|
72
|
-
attr_accessor :file_system
|
73
|
-
Template.file_system = BlankFileSystem.new
|
74
|
-
|
75
|
-
attr_accessor :tags
|
76
|
-
Template.tags = TagRegistry.new
|
77
|
-
private :tags=
|
78
|
-
|
79
59
|
def register_tag(name, klass)
|
80
|
-
|
60
|
+
Deprecations.warn("Template.register_tag", "Environment#register_tag")
|
61
|
+
Environment.default.register_tag(name, klass)
|
81
62
|
end
|
82
63
|
|
83
64
|
# Pass a module with filter methods which should be available
|
84
65
|
# to all liquid views. Good for registering the standard library
|
85
66
|
def register_filter(mod)
|
86
|
-
|
67
|
+
Deprecations.warn("Template.register_filter", "Environment#register_filter")
|
68
|
+
Environment.default.register_filter(mod)
|
87
69
|
end
|
88
70
|
|
89
|
-
|
90
|
-
|
91
|
-
|
71
|
+
private def default_resource_limits=(limits)
|
72
|
+
Deprecations.warn("Template.default_resource_limits=", "Environment#default_resource_limits=")
|
73
|
+
Environment.default.default_resource_limits = limits
|
74
|
+
end
|
75
|
+
|
76
|
+
def default_resource_limits
|
77
|
+
Environment.default.default_resource_limits
|
78
|
+
end
|
92
79
|
|
93
80
|
# creates a new <tt>Template</tt> object from liquid source code
|
94
81
|
# To enable profiling, pass in <tt>profile: true</tt> as an option.
|
95
82
|
# See Liquid::Profiler for more information
|
96
83
|
def parse(source, options = {})
|
97
|
-
|
84
|
+
environment = options[:environment] || Environment.default
|
85
|
+
new(environment: environment).parse(source, options)
|
98
86
|
end
|
99
87
|
end
|
100
88
|
|
101
|
-
def initialize
|
89
|
+
def initialize(environment: Environment.default)
|
90
|
+
@environment = environment
|
102
91
|
@rethrow_errors = false
|
103
|
-
@resource_limits = ResourceLimits.new(
|
92
|
+
@resource_limits = ResourceLimits.new(environment.default_resource_limits)
|
104
93
|
end
|
105
94
|
|
106
95
|
# Parse source code.
|
@@ -162,11 +151,11 @@ module Liquid
|
|
162
151
|
c
|
163
152
|
when Liquid::Drop
|
164
153
|
drop = args.shift
|
165
|
-
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
|
154
|
+
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits, {}, @environment)
|
166
155
|
when Hash
|
167
|
-
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
|
156
|
+
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits, {}, @environment)
|
168
157
|
when nil
|
169
|
-
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits)
|
158
|
+
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits, {}, @environment)
|
170
159
|
else
|
171
160
|
raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
|
172
161
|
end
|
@@ -226,8 +215,14 @@ module Liquid
|
|
226
215
|
@options = options
|
227
216
|
@profiling = profiling
|
228
217
|
@line_numbers = options[:line_numbers] || @profiling
|
229
|
-
parse_context = options.is_a?(ParseContext)
|
230
|
-
|
218
|
+
parse_context = if options.is_a?(ParseContext)
|
219
|
+
options
|
220
|
+
else
|
221
|
+
opts = options.key?(:environment) ? options : options.merge(environment: @environment)
|
222
|
+
ParseContext.new(opts)
|
223
|
+
end
|
224
|
+
|
225
|
+
@warnings = parse_context.warnings
|
231
226
|
parse_context
|
232
227
|
end
|
233
228
|
|
data/lib/liquid/variable.rb
CHANGED
@@ -68,7 +68,7 @@ module Liquid
|
|
68
68
|
@name = parse_context.parse_expression(p.expression)
|
69
69
|
while p.consume?(:pipe)
|
70
70
|
filtername = p.consume(:id)
|
71
|
-
filterargs = p.consume?(:colon) ? parse_filterargs(p) :
|
71
|
+
filterargs = p.consume?(:colon) ? parse_filterargs(p) : Const::EMPTY_ARRAY
|
72
72
|
@filters << parse_filter_expressions(filtername, filterargs)
|
73
73
|
end
|
74
74
|
p.consume(:end_of_string)
|
@@ -95,15 +95,21 @@ module Liquid
|
|
95
95
|
|
96
96
|
def render_to_output_buffer(context, output)
|
97
97
|
obj = render(context)
|
98
|
+
render_obj_to_output(obj, output)
|
99
|
+
output
|
100
|
+
end
|
98
101
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
102
|
+
def render_obj_to_output(obj, output)
|
103
|
+
case obj
|
104
|
+
when NilClass
|
105
|
+
# Do nothing
|
106
|
+
when Array
|
107
|
+
obj.each do |o|
|
108
|
+
render_obj_to_output(o, output)
|
109
|
+
end
|
110
|
+
when
|
103
111
|
output << obj.to_s
|
104
112
|
end
|
105
|
-
|
106
|
-
output
|
107
113
|
end
|
108
114
|
|
109
115
|
def disabled?(_context)
|
data/lib/liquid/version.rb
CHANGED
data/lib/liquid.rb
CHANGED
@@ -44,13 +44,20 @@ module Liquid
|
|
44
44
|
VariableParser = /\[(?>[^\[\]]+|\g<0>)*\]|#{VariableSegment}+\??/o
|
45
45
|
|
46
46
|
RAISE_EXCEPTION_LAMBDA = ->(_e) { raise }
|
47
|
-
|
48
|
-
singleton_class.send(:attr_accessor, :cache_classes)
|
49
|
-
self.cache_classes = true
|
50
47
|
end
|
51
48
|
|
52
49
|
require "liquid/version"
|
50
|
+
require "liquid/deprecations"
|
51
|
+
require "liquid/const"
|
52
|
+
require 'liquid/standardfilters'
|
53
|
+
require 'liquid/file_system'
|
54
|
+
require 'liquid/parser_switching'
|
55
|
+
require 'liquid/tag'
|
56
|
+
require 'liquid/block'
|
53
57
|
require 'liquid/parse_tree_visitor'
|
58
|
+
require 'liquid/interrupts'
|
59
|
+
require 'liquid/tags'
|
60
|
+
require "liquid/environment"
|
54
61
|
require 'liquid/lexer'
|
55
62
|
require 'liquid/parser'
|
56
63
|
require 'liquid/i18n'
|
@@ -61,23 +68,16 @@ require 'liquid/extensions'
|
|
61
68
|
require 'liquid/errors'
|
62
69
|
require 'liquid/interrupts'
|
63
70
|
require 'liquid/strainer_template'
|
64
|
-
require 'liquid/strainer_factory'
|
65
71
|
require 'liquid/expression'
|
66
72
|
require 'liquid/context'
|
67
|
-
require 'liquid/parser_switching'
|
68
73
|
require 'liquid/tag'
|
69
|
-
require 'liquid/tag/disabler'
|
70
|
-
require 'liquid/tag/disableable'
|
71
|
-
require 'liquid/block'
|
72
74
|
require 'liquid/block_body'
|
73
75
|
require 'liquid/document'
|
74
76
|
require 'liquid/variable'
|
75
77
|
require 'liquid/variable_lookup'
|
76
78
|
require 'liquid/range_lookup'
|
77
|
-
require 'liquid/file_system'
|
78
79
|
require 'liquid/resource_limits'
|
79
80
|
require 'liquid/template'
|
80
|
-
require 'liquid/standardfilters'
|
81
81
|
require 'liquid/condition'
|
82
82
|
require 'liquid/utils'
|
83
83
|
require 'liquid/tokenizer'
|
@@ -86,7 +86,3 @@ require 'liquid/partial_cache'
|
|
86
86
|
require 'liquid/usage'
|
87
87
|
require 'liquid/registers'
|
88
88
|
require 'liquid/template_factory'
|
89
|
-
|
90
|
-
# Load all the tags of the standard library
|
91
|
-
#
|
92
|
-
Dir["#{__dir__}/liquid/tags/*.rb"].each { |f| require f }
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: liquid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.6.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Lütke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: strscan
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
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: bigdecimal
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: rake
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -54,9 +82,12 @@ files:
|
|
54
82
|
- lib/liquid/block.rb
|
55
83
|
- lib/liquid/block_body.rb
|
56
84
|
- lib/liquid/condition.rb
|
85
|
+
- lib/liquid/const.rb
|
57
86
|
- lib/liquid/context.rb
|
87
|
+
- lib/liquid/deprecations.rb
|
58
88
|
- lib/liquid/document.rb
|
59
89
|
- lib/liquid/drop.rb
|
90
|
+
- lib/liquid/environment.rb
|
60
91
|
- lib/liquid/errors.rb
|
61
92
|
- lib/liquid/expression.rb
|
62
93
|
- lib/liquid/extensions.rb
|
@@ -77,12 +108,12 @@ files:
|
|
77
108
|
- lib/liquid/registers.rb
|
78
109
|
- lib/liquid/resource_limits.rb
|
79
110
|
- lib/liquid/standardfilters.rb
|
80
|
-
- lib/liquid/strainer_factory.rb
|
81
111
|
- lib/liquid/strainer_template.rb
|
82
112
|
- lib/liquid/tablerowloop_drop.rb
|
83
113
|
- lib/liquid/tag.rb
|
84
114
|
- lib/liquid/tag/disableable.rb
|
85
115
|
- lib/liquid/tag/disabler.rb
|
116
|
+
- lib/liquid/tags.rb
|
86
117
|
- lib/liquid/tags/assign.rb
|
87
118
|
- lib/liquid/tags/break.rb
|
88
119
|
- lib/liquid/tags/capture.rb
|
@@ -110,7 +141,7 @@ files:
|
|
110
141
|
- lib/liquid/variable.rb
|
111
142
|
- lib/liquid/variable_lookup.rb
|
112
143
|
- lib/liquid/version.rb
|
113
|
-
homepage:
|
144
|
+
homepage: https://shopify.github.io/liquid/
|
114
145
|
licenses:
|
115
146
|
- MIT
|
116
147
|
metadata:
|
@@ -123,14 +154,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
123
154
|
requirements:
|
124
155
|
- - ">="
|
125
156
|
- !ruby/object:Gem::Version
|
126
|
-
version:
|
157
|
+
version: 3.0.0
|
127
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
159
|
requirements:
|
129
160
|
- - ">="
|
130
161
|
- !ruby/object:Gem::Version
|
131
162
|
version: 1.3.7
|
132
163
|
requirements: []
|
133
|
-
rubygems_version: 3.5.
|
164
|
+
rubygems_version: 3.5.23
|
134
165
|
signing_key:
|
135
166
|
specification_version: 4
|
136
167
|
summary: A secure, non-evaling end user template engine with aesthetic markup.
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Liquid
|
4
|
-
# StrainerFactory is the factory for the filters system.
|
5
|
-
module StrainerFactory
|
6
|
-
extend self
|
7
|
-
|
8
|
-
def add_global_filter(filter)
|
9
|
-
strainer_class_cache.clear
|
10
|
-
GlobalCache.add_filter(filter)
|
11
|
-
end
|
12
|
-
|
13
|
-
def create(context, filters = [])
|
14
|
-
strainer_from_cache(filters).new(context)
|
15
|
-
end
|
16
|
-
|
17
|
-
def global_filter_names
|
18
|
-
GlobalCache.filter_method_names
|
19
|
-
end
|
20
|
-
|
21
|
-
GlobalCache = Class.new(StrainerTemplate)
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def strainer_from_cache(filters)
|
26
|
-
if filters.empty?
|
27
|
-
GlobalCache
|
28
|
-
else
|
29
|
-
strainer_class_cache[filters] ||= begin
|
30
|
-
klass = Class.new(GlobalCache)
|
31
|
-
filters.each { |f| klass.add_filter(f) }
|
32
|
-
klass
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def strainer_class_cache
|
38
|
-
@strainer_class_cache ||= {}
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|