Compare commits

..
Author SHA1 Message Date
Christophe Naud-Dulude 02b6be4025 Potential fix 2021-11-30 14:10:34 -05:00
Christophe Naud-Dulude f3638b3eb4 Test parsing of Liquid code in comments 2021-11-30 11:56:49 -05:00
Anders SøgaardandGitHub db3999a008 Improve where filter tests (#1472) 2021-09-16 10:02:39 -04:00
Marc-André CournoyerandGitHub 10e2aa8d5b Merge pull request #1471 from Shopify/bump-5.1.0
Prep for 5.1.0 release
2021-09-15 15:15:13 -04:00
7c4114671b Remove to_liquid_value fixes in changelog
Co-authored-by: Dylan Thacker-Smith <[email protected]>
2021-09-13 10:53:46 -04:00
Marc-André Cournoyer b01de9d325 Prep for 5.1.0 release 2021-09-09 14:28:45 -04:00
Zac ClayandGitHub a5369c26a8 Add missing quote in comment (#1468) 2021-09-09 14:23:11 -04:00
Charles-Philippe ClermontandGitHub a03de8f9ea Merge pull request #1470 from Shopify/fix/range-parse-tree-visitor
Add ParseTreeVisitor to RangeLookup
2021-09-09 11:39:14 -04:00
Charles-P. Clermont e86fe27259 Fix lint 2021-09-09 11:22:39 -04:00
Charles-P. Clermont c8906d05b9 Add ParseTreeVisitor to RangeLookup 2021-09-09 11:22:39 -04:00
Michael GoandGitHub 50d1a2ffc9 Merge pull request #1458 from Shopify/use-to-liquid-value-with-conditions
use Utils.to_liquid_value on conditionals
2021-06-15 12:18:14 -03:00
Michael Go f686c5dec7 use Utils.to_liquid_value on conditionals 2021-06-14 18:19:37 -03:00
Michael GoandGitHub aa8ce87b96 Merge pull request #1454 from Shopify/default-filter-with-to-liquid-value
utilize input's to_liquid_value on default filter
2021-06-14 15:43:56 -03:00
Peter ZhuandGitHub 698f5e0d96 Merge pull request #1456 from Shopify/pz-psych-4-unsafe-load
Fix benchmark for breaking change in Psych 4
2021-06-10 13:14:13 -04:00
Peter Zhu 996bfe0c82 Fix benchmark for breaking change in Psych 4
Psych 4 introduces a breaking change (ruby/psych#487) where
`Psych#load`/`Psych#load_file` now default to safe loading,
meaning that YAML references are not allowed anymore. This
commit changes the benchmark to use `Psych#unsafe_load_file`
when it's available.
2021-06-10 13:01:16 -04:00
Michael GoandGitHub be81c9ae5a Merge pull request #1457 from Shopify/fix-unless-to-use-to-liquid-value-helper
fix unless to use to_liquid_value helper with multiple conditions
2021-06-10 14:00:19 -03:00
Michael Go edd4d70aee fix unless to use to_liquid_value helper with multiple conditions 2021-06-10 13:28:17 -03:00
Michael Go ac66dbbafe utilize input's to_liquid_value on default filter 2021-06-08 15:20:53 -03:00
Daniel InsleyandGitHub 017c1b5e83 Base64 Decode & Encode Filters (#1450) 2021-06-03 13:23:11 -04:00
Michael GoandGitHub 250555c9a8 Merge pull request #1441 from Shopify/to-raw-value
Implement to_liquid_value to Liquid::Drop
2021-05-27 10:21:05 -03:00
Michael Go e361a4d53c introduce to_liquid_value on variable look and conditional statements 2021-05-26 17:27:18 -03:00
Dylan Thacker-Smith b9e0d28729 rubocop: Clarify that a config is a rubocop-shopify backport 2021-04-20 09:01:06 -07:00
Dylan Thacker-Smith 020f6b93c5 rubocop: Fix unsupported ruby version in TargetRubyVersion error 2021-04-20 09:00:20 -07:00
Dylan Thacker-SmithandGitHub cfe1637bdd Translate RangeError to Liquid::Error for truncatewords with large int (#1431) 2021-04-20 11:48:22 -04:00
Dylan Thacker-Smith eab13a07d9 Add changelog entry for a recent fix 2021-03-29 13:43:01 -07:00
Dylan Thacker-SmithandGitHub ca96ca0fef Fix support for using a String subclass for the liquid source (#1421) 2021-03-29 16:22:05 -04:00
Marc-André CournoyerandGitHub 4e7a953e73 Merge pull request #1417 from Shopify/prep-release
Bump to 5.0.1 and add changelog for release
2021-03-24 16:55:10 -04:00
6ac2499f7f Remove internal tokenizer fix from History.md
Co-authored-by: Dylan Thacker-Smith <[email protected]>
2021-03-24 16:53:45 -04:00
ff70161512 Remove internal fixes from History.md
Co-authored-by: Dylan Thacker-Smith <[email protected]>
2021-03-24 16:52:57 -04:00
Marc-André Cournoyer 026157e128 Bump to 5.0.1 and add changelog for release 2021-03-24 16:19:19 -04:00
Charles-Philippe ClermontandGitHub bf64239ea6 Merge pull request #1414 from Shopify/fix/echo-parse-tree-visitor
Add ParseTreeVisitor to Echo tag
2021-03-24 09:38:48 -04:00
Charles-P. Clermont c270a6f378 Add ParseTreeVisitor to Echo tag
This fixes theme-check#218, wherein variables used in echo tags are not
considered used by the linter. It is because our visitor doesn't see the
:variable_lookup's in the echo tag since the children array is empty.
But this array is empty because it is swallowed by the @variable.
2021-03-24 09:35:43 -04:00
Dylan Thacker-SmithandGitHub 4fba61a802 Merge pull request #1402 from Shopify/rubocop-shopify
Use the rubocop-shopify gem and autocorrect
2021-03-16 17:39:09 -04:00
Dylan Thacker-SmithandGitHub 6b6baece25 Merge pull request #1406 from ADTC/patch-2
Add a line to Sign the CLA as the first step in Workflow
2021-02-26 09:03:40 -05:00
15b2d193ec Add a hint to sign CLA only if it's the first time
The CLA isn't signed per repository. They might have done so for another repository. In which case, they won't need to do that again.

Change attributed to @dylanahsmith

Co-authored-by: Dylan Thacker-Smith <[email protected]>
2021-02-26 16:31:16 +08:00
ADTCandGitHub fd712d134a Give info in the Contributing page about doc updates (#1405)
Please see #1399 for more info and discussion.
2021-02-25 09:31:18 -05:00
ADTCandGitHub 0c2db998cf Add a line to Sign the CLA as the first step in Workflow
If a pull request is created by someone who didn't sign the CLA yet, the tests will fail. It requires the contributor to submit a new PR or add an insignificant commit (like an empty commit) to force the tests to rerun on the same PR. If we gently nudge a new contributor to sign the CLA in advance, we can help them avoid the hassle.
2021-02-25 09:59:51 +08:00
Dylan Thacker-Smith 9dac68cce1 Use the rubocop-shopify gem 2021-02-21 12:22:03 -05:00
Dylan Thacker-Smith c50509b741 Commit rubocop remote configuration update 2021-02-21 12:02:55 -05:00
Dylan Thacker-Smith cd66572514 Rubocop autocorrections to prepare for rubocop config updates 2021-02-21 12:01:59 -05:00
31 changed files with 333 additions and 1139 deletions
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -1,5 +1,7 @@
inherit_gem:
rubocop-shopify: rubocop.yml
inherit_from:
- 'https://shopify.github.io/ruby-style-guide/rubocop.yml'
- .rubocop_todo.yml
require: rubocop-performance
@@ -8,7 +10,7 @@ Performance:
Enabled: true
AllCops:
TargetRubyVersion: 2.4
TargetRubyVersion: 2.5
NewCops: disable
Exclude:
- 'vendor/bundle/**/*'
@@ -16,3 +18,7 @@ AllCops:
Naming/MethodName:
Exclude:
- 'example/server/liquid_servlet.rb'
# Backport https://github.com/Shopify/ruby-style-guide/pull/258
Layout/BeginEndAlignment:
Enabled: true
+4 -1
View File
@@ -5,6 +5,7 @@
* Bugfixes
* Performance improvements
* Features that are likely to be useful to the majority of Liquid users
* Documentation updates that are concise and likely to be useful to the majority of Liquid users
## Things we won't merge
@@ -14,12 +15,14 @@
* Features that can easily be implemented on top of Liquid (for example as a custom filter or custom filesystem)
* Code that does not include tests
* Code that breaks existing tests
* Documentation changes that are verbose, incorrect or not important to most people (we want to keep it simple and easy to understand)
## Workflow
* [Sign the CLA](https://cla.shopify.com/) if you haven't already
* Fork the Liquid repository
* Create a new branch in your fork
* For updating [Liquid documentation](https://shopify.github.io/liquid/), create it from `gh-pages` branch. (You can skip tests.)
* If it makes sense, add tests for your code and/or run a performance benchmark
* Make sure all tests pass (`bundle exec rake`)
* Create a pull request
+2 -1
View File
@@ -19,9 +19,10 @@ end
group :test do
gem 'rubocop', '~> 1.4', require: false
gem 'rubocop-shopify', '~> 1.0.7', require: false
gem 'rubocop-performance', require: false
platform :mri, :truffleruby do
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'inline-comment'
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'master'
end
end
+18 -2
View File
@@ -1,9 +1,25 @@
# Liquid Change Log
## Unreleased
## 5.1.0 / 2021-09-09
### Features
* Allow `#` to be used as an inline comment tag (#1401) [Dylan Thacker-Smith]
* Add `base64_encode`, `base64_decode`, `base64_url_safe_encode`, and `base64_url_safe_decode` filters (#1450) [Daniel Insley]
* Introduce `to_liquid_value` in `Liquid::Drop` (#1441) [Michael Go]
### Fixes
* Fix support for using a String subclass for the liquid source (#1421) [Dylan Thacker-Smith]
* Add `ParseTreeVisitor` to `RangeLookup` (#1470) [CP Clermont]
* Translate `RangeError` to `Liquid::Error` for `truncatewords` with large int (#1431) [Dylan Thacker-Smith]
## 5.0.1 / 2021-03-24
### Fixes
* Add ParseTreeVisitor to Echo tag (#1414) [CP Clermont]
* Test with ruby 3.0 as the latest ruby version (#1398) [Dylan Thacker-Smith]
* Handle carriage return in newlines_to_br (#1391) [Unending]
### Performance Improvements
* Use split limit in truncatewords (#1361) [Dylan Thacker-Smith]
## 5.0.0 / 2021-01-06
+2 -2
View File
@@ -4,8 +4,8 @@ require 'English'
module Liquid
class BlockBody
LiquidTagToken = /\A\s*(\w+|#)\s*(.*?)\z/o
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+|#)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
LiquidTagToken = /\A\s*(\w+)\s*(.*?)\z/o
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om
WhitespaceOrNothing = /\A\s*\z/
TAGSTART = "{%"
+3 -3
View File
@@ -8,7 +8,7 @@ module Liquid
# c = Condition.new(1, '==', 1)
# c.evaluate #=> true
#
class Condition #:nodoc:
class Condition # :nodoc:
@@operators = {
'==' => ->(cond, left, right) { cond.send(:equal_variables, left, right) },
'!=' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
@@ -134,8 +134,8 @@ module Liquid
# return this as the result.
return context.evaluate(left) if op.nil?
left = context.evaluate(left)
right = context.evaluate(right)
left = Liquid::Utils.to_liquid_value(context.evaluate(left))
right = Liquid::Utils.to_liquid_value(context.evaluate(right))
operation = self.class.operators[op] || raise(Liquid::ArgumentError, "Unknown operator #{op}")
+1 -1
View File
@@ -124,7 +124,7 @@ module Liquid
# context['var'] = 'hi'
# end
#
# context['var] #=> nil
# context['var'] #=> nil
def stack(new_scope = {})
push(new_scope)
yield
-1
View File
@@ -22,7 +22,6 @@
tag_never_closed: "'%{block_name}' tag was never closed"
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
render: "Syntax error in tag 'render' - Template name must be a quoted string"
inline_comment_invalid: "Syntax error in tag '#' - Each line of comments must be prefixed by the '#' character"
argument:
include: "Argument error in tag 'include' - Illegal template name"
disabled:
+8
View File
@@ -12,6 +12,8 @@ module Liquid
end
end
attr_reader :start_obj, :end_obj
def initialize(start_obj, end_obj)
@start_obj = start_obj
@end_obj = end_obj
@@ -35,5 +37,11 @@ module Liquid
Utils.to_integer(input)
end
end
class ParseTreeVisitor < Liquid::ParseTreeVisitor
def children
[@node.start_obj, @node.end_obj]
end
end
end
end
+30 -2
View File
@@ -1,10 +1,12 @@
# frozen_string_literal: true
require 'cgi'
require 'base64'
require 'bigdecimal'
module Liquid
module StandardFilters
MAX_INT = (1 << 31) - 1
HTML_ESCAPE = {
'&' => '&amp;',
'>' => '&gt;',
@@ -62,6 +64,26 @@ module Liquid
result
end
def base64_encode(input)
Base64.strict_encode64(input.to_s)
end
def base64_decode(input)
Base64.strict_decode64(input.to_s)
rescue ::ArgumentError
raise Liquid::ArgumentError, "invalid base64 provided to base64_decode"
end
def base64_url_safe_encode(input)
Base64.urlsafe_encode64(input.to_s)
end
def base64_url_safe_decode(input)
Base64.urlsafe_decode64(input.to_s)
rescue ::ArgumentError
raise Liquid::ArgumentError, "invalid base64 provided to base64_url_safe_decode"
end
def slice(input, offset, length = nil)
offset = Utils.to_integer(offset)
length = length ? Utils.to_integer(length) : 1
@@ -93,7 +115,13 @@ module Liquid
words = Utils.to_integer(words)
words = 1 if words <= 0
wordlist = input.split(" ", words + 1)
wordlist = begin
input.split(" ", words + 1)
rescue RangeError
raise if words + 1 < MAX_INT
# e.g. integer #{words} too big to convert to `int'
raise Liquid::ArgumentError, "integer #{words} too big for truncatewords"
end
return input if wordlist.length <= words
wordlist.pop
@@ -440,7 +468,7 @@ module Liquid
#
def default(input, default_value = '', options = {})
options = {} unless options.is_a?(Hash)
false_check = options['allow_false'] ? input.nil? : !input
false_check = options['allow_false'] ? input.nil? : !Liquid::Utils.to_liquid_value(input)
false_check || (input.respond_to?(:empty?) && input.empty?) ? default_value : input
end
+8 -1
View File
@@ -52,7 +52,14 @@ module Liquid
@blocks.each do |block|
if block.else?
block.attachment.render_to_output_buffer(context, output) if execute_else_block
elsif block.evaluate(context)
next
end
result = Liquid::Utils.to_liquid_value(
block.evaluate(context)
)
if result
execute_else_block = false
block.attachment.render_to_output_buffer(context, output)
end
+13
View File
@@ -2,6 +2,19 @@
module Liquid
class Comment < Block
# Potential fix
FullTokenPossiblyInvalid = /\A(.*)#{TagStart}#{WhitespaceControl}?\s*(\w+)\s*(.*)?#{WhitespaceControl}?#{TagEnd}\z/om
def parse(tokens)
while (token = tokens.shift)
if token =~ FullTokenPossiblyInvalid && block_delimiter == Regexp.last_match(2)
return
end
end
raise_tag_never_closed(block_name)
end
def render_to_output_buffer(_context, output)
output
end
+12
View File
@@ -12,14 +12,26 @@ module Liquid
# {% echo user | link %}
#
class Echo < Tag
attr_reader :variable
def initialize(tag_name, markup, parse_context)
puts "Initializing Echo tag"
super
@variable = Variable.new(markup, parse_context)
end
def render(context)
puts "Render Echo tag"
@variable.render_to_output_buffer(context, +'')
end
class ParseTreeVisitor < Liquid::ParseTreeVisitor
puts "ParseTreeVisitor Echo tag"
def children
[@node.variable]
end
end
end
Template.register_tag('echo', Echo)
+5 -1
View File
@@ -50,7 +50,11 @@ module Liquid
def render_to_output_buffer(context, output)
@blocks.each do |block|
if block.evaluate(context)
result = Liquid::Utils.to_liquid_value(
block.evaluate(context)
)
if result
return block.attachment.render_to_output_buffer(context, output)
end
end
-25
View File
@@ -1,25 +0,0 @@
# frozen_string_literal: true
module Liquid
class InlineComment < Tag
def initialize(tag_name, markup, options)
super
# Semantically, a comment should only ignore everything after it on the line.
# Currently, this implementation doesn't support mixing a comment with another tag
# but we need to reserve future support for this.
if markup.match?(/\n\s*[^#]/)
raise SyntaxError, options[:locale].t("errors.syntax.inline_comment_invalid")
end
end
def render_to_output_buffer(_context, output)
output
end
def blank?
true
end
end
Template.register_tag('#', InlineComment)
end
+10 -2
View File
@@ -11,13 +11,21 @@ module Liquid
def render_to_output_buffer(context, output)
# First condition is interpreted backwards ( if not )
first_block = @blocks.first
unless first_block.evaluate(context)
result = Liquid::Utils.to_liquid_value(
first_block.evaluate(context)
)
unless result
return first_block.attachment.render_to_output_buffer(context, output)
end
# After the first condition unless works just like if
@blocks[1..-1].each do |block|
if block.evaluate(context)
result = Liquid::Utils.to_liquid_value(
block.evaluate(context)
)
if result
return block.attachment.render_to_output_buffer(context, output)
end
end
+2 -2
View File
@@ -5,7 +5,7 @@ module Liquid
attr_reader :line_number, :for_liquid_tag
def initialize(source, line_numbers = false, line_number: nil, for_liquid_tag: false)
@source = source
@source = source.to_s.to_str
@line_number = line_number || (line_numbers ? 1 : nil)
@for_liquid_tag = for_liquid_tag
@tokens = tokenize
@@ -24,7 +24,7 @@ module Liquid
private
def tokenize
return [] if @source.to_s.empty?
return [] if @source.empty?
return @source.split("\n") if @for_liquid_tag
+8
View File
@@ -81,5 +81,13 @@ module Liquid
rescue ::ArgumentError
nil
end
def self.to_liquid_value(obj)
# Enable "obj" to represent itself as a primitive value like integer, string, or boolean
return obj.to_liquid_value if obj.respond_to?(:to_liquid_value)
# Otherwise return the object itself
obj
end
end
end
+3
View File
@@ -40,6 +40,9 @@ module Liquid
@lookups.each_index do |i|
key = context.evaluate(@lookups[i])
# Cast "key" to its liquid value to enable it to act as a primitive value
key = Liquid::Utils.to_liquid_value(key)
# If object is a hash- or array-like object we look for the
# presence of the key and if its available we return it
if object.respond_to?(:[]) &&
+1 -1
View File
@@ -2,5 +2,5 @@
# frozen_string_literal: true
module Liquid
VERSION = "5.0.0"
VERSION = "5.1.0"
end
+9 -1
View File
@@ -3,11 +3,19 @@
require 'yaml'
module Database
DATABASE_FILE_PATH = "#{__dir__}/vision.database.yml"
# Load the standard vision toolkit database and re-arrage it to be simply exportable
# to liquid as assigns. All this is based on Shopify
def self.tables
@tables ||= begin
db = YAML.load_file("#{__dir__}/vision.database.yml")
db =
if YAML.respond_to?(:unsafe_load_file) # Only Psych 4+ can use unsafe_load_file
# unsafe_load_file is needed for YAML references
YAML.unsafe_load_file(DATABASE_FILE_PATH)
else
YAML.load_file(DATABASE_FILE_PATH)
end
# From vision source
db['products'].each do |product|
+55 -1
View File
@@ -145,6 +145,40 @@ class StandardFiltersTest < Minitest::Test
assert_equal('&lt;strong&gt;Hulk&lt;/strong&gt;', @filters.escape_once('&lt;strong&gt;Hulk</strong>'))
end
def test_base64_encode
assert_equal('b25lIHR3byB0aHJlZQ==', @filters.base64_encode('one two three'))
assert_equal('', @filters.base64_encode(nil))
end
def test_base64_decode
assert_equal('one two three', @filters.base64_decode('b25lIHR3byB0aHJlZQ=='))
exception = assert_raises(Liquid::ArgumentError) do
@filters.base64_decode("invalidbase64")
end
assert_equal('Liquid error: invalid base64 provided to base64_decode', exception.message)
end
def test_base64_url_safe_encode
assert_equal(
'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMTIzNDU2Nzg5MCAhQCMkJV4mKigpLT1fKy8_Ljo7W117fVx8',
@filters.base64_url_safe_encode('abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 !@#$%^&*()-=_+/?.:;[]{}\|')
)
assert_equal('', @filters.base64_url_safe_encode(nil))
end
def test_base64_url_safe_decode
assert_equal(
'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 !@#$%^&*()-=_+/?.:;[]{}\|',
@filters.base64_url_safe_decode('YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMTIzNDU2Nzg5MCAhQCMkJV4mKigpLT1fKy8_Ljo7W117fVx8')
)
exception = assert_raises(Liquid::ArgumentError) do
@filters.base64_url_safe_decode("invalidbase64")
end
assert_equal('Liquid error: invalid base64 provided to base64_url_safe_decode', exception.message)
end
def test_url_encode
assert_equal('foo%2B1%40example.com', @filters.url_encode('[email protected]'))
assert_equal('1', @filters.url_encode(1))
@@ -171,13 +205,17 @@ class StandardFiltersTest < Minitest::Test
assert_equal('one two three', @filters.truncatewords('one two three'))
assert_equal(
'Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221;...',
@filters.truncatewords('Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221; x 16&#8221; x 10.5&#8221; high) with cover.', 15)
@filters.truncatewords('Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221; x 16&#8221; x 10.5&#8221; high) with cover.', 15)
)
assert_equal("测试测试测试测试", @filters.truncatewords('测试测试测试测试', 5))
assert_equal('one two1', @filters.truncatewords("one two three", 2, 1))
assert_equal('one two three...', @filters.truncatewords("one two\tthree\nfour", 3))
assert_equal('one two...', @filters.truncatewords("one two three four", 2))
assert_equal('one...', @filters.truncatewords("one two three four", 0))
exception = assert_raises(Liquid::ArgumentError) do
@filters.truncatewords("one two three four", 1 << 31)
end
assert_equal("Liquid error: integer #{1 << 31} too big for truncatewords", exception.message)
end
def test_strip_html
@@ -690,6 +728,8 @@ class StandardFiltersTest < Minitest::Test
assert_equal("bar", @filters.default([], "bar"))
assert_equal("bar", @filters.default({}, "bar"))
assert_template_result('bar', "{{ false | default: 'bar' }}")
assert_template_result('bar', "{{ drop | default: 'bar' }}", 'drop' => BooleanDrop.new(false))
assert_template_result('Yay', "{{ drop | default: 'bar' }}", 'drop' => BooleanDrop.new(true))
end
def test_default_handle_false
@@ -700,6 +740,8 @@ class StandardFiltersTest < Minitest::Test
assert_equal("bar", @filters.default([], "bar", "allow_false" => true))
assert_equal("bar", @filters.default({}, "bar", "allow_false" => true))
assert_template_result('false', "{{ false | default: 'bar', allow_false: true }}")
assert_template_result('Nay', "{{ drop | default: 'bar', allow_false: true }}", 'drop' => BooleanDrop.new(false))
assert_template_result('Yay', "{{ drop | default: 'bar', allow_false: true }}", 'drop' => BooleanDrop.new(true))
end
def test_cannot_access_private_methods
@@ -728,6 +770,18 @@ class StandardFiltersTest < Minitest::Test
assert_equal(expectation, @filters.where(input, "ok"))
end
def test_where_string_keys
input = [
"alpha", "beta", "gamma", "delta"
]
expectation = [
"beta",
]
assert_equal(expectation, @filters.where(input, "be"))
end
def test_where_no_key_set
input = [
{ "handle" => "alpha", "ok" => true },
+25
View File
@@ -0,0 +1,25 @@
# frozen_string_literal: true
require 'test_helper'
class CommentTagTest < Minitest::Test
include Liquid
def test_single_line_comments_parse
assert_template_result('Before comment', <<~LIQUID)
Before comment
{%- comment -%}
Regular text comment
Liquid in comment: {% echo 'Hi from comment' %}
{%- endcomment -%}
LIQUID
end
def test_multi_line_comments_parse
assert_template_result('Before comment', <<~LIQUID)
Before comment
{%- comment -%} Regular text comment {%- endcomment -%}
{%- comment -%} Liquid in comment: {% echo 'Hi from comment' %} {%- endcomment -%}
LIQUID
end
end # CommentTagTest
+2 -2
View File
@@ -96,12 +96,12 @@ class IncludeTagTest < Minitest::Test
def test_include_tag_with_alias
assert_template_result("Product: Draft 151cm ",
"{% include 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% include 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_include_tag_for_alias
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% include 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% include 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_include_tag_with_default_name
@@ -1,59 +0,0 @@
# frozen_string_literal: true
require 'test_helper'
class InlineCommentTest < Minitest::Test
include Liquid
def test_tag_in_different_styles
assert_template_result('', '{% # This text gets ignored %}')
assert_template_result('', '{%# This text gets ignored #%}')
assert_template_result('', '{%# This text gets ignored %}')
assert_template_result('', '{%#- This text gets ignored -#%}')
end
def test_test_syntax_error
assert_template_result('fail', '{% #This doesnt work %}')
assert false
rescue
# ok good
end
def test_tag_ws_stripping
assert_template_result('', ' {%#- This text gets ignored -#%} ')
end
def test_comment_inline_tag
assert_template_result('ok', '{% echo "ok" # output something from a tag %}')
end
def test_comment_line_before_tag
assert_template_result('ok', '{% # this sort of comment also
echo "ok" %}')
end
def test_comment_inline_variable
assert_template_result('ok', '{{ "ok" # output something from a variable }}')
assert_template_result('ok', '{{ "OK" | downcase # output something from a variable }}')
end
def test_inside_liquid_tag
source = <<~LIQUID
{%- liquid
echo "before("
# This text gets ignored
echo ")after"
-%}
LIQUID
assert_template_result('before()after', source)
end
def test_multiline
assert_template_result('', '{% # this sort of comment also
# will just work, because it parses
# as a single call to the "#" tag %}')
end
end
+7 -7
View File
@@ -151,7 +151,7 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("Product: Draft 151cm ",
"{% render 'product' with products[0] %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% render 'product' with products[0] %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_render_tag_with_alias
@@ -161,7 +161,7 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("Product: Draft 151cm ",
"{% render 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% render 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_render_tag_for_alias
@@ -171,7 +171,7 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% render 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% render 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_render_tag_for
@@ -181,7 +181,7 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_render_tag_forloop
@@ -190,7 +190,7 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("Product: Draft 151cm first index:1 Product: Element 155cm last index:2 ",
"{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
"{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
end
def test_render_tag_for_drop
@@ -199,7 +199,7 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("123",
"{% render 'loop' for loop as value %}", "loop" => TestEnumerable.new)
"{% render 'loop' for loop as value %}", "loop" => TestEnumerable.new)
end
def test_render_tag_with_drop
@@ -208,6 +208,6 @@ class RenderTagTest < Minitest::Test
)
assert_template_result("TestEnumerable",
"{% render 'loop' with loop as value %}", "loop" => TestEnumerable.new)
"{% render 'loop' with loop as value %}", "loop" => TestEnumerable.new)
end
end
+14
View File
@@ -323,4 +323,18 @@ class TemplateTest < Minitest::Test
result = t.render('x' => 1, 'y' => 5)
assert_equal('12345', result)
end
def test_source_string_subclass
string_subclass = Class.new(String) do
# E.g. ActiveSupport::SafeBuffer does this, so don't just rely on to_s to return a String
def to_s
self
end
end
source = string_subclass.new("{% assign x = 2 -%} x= {{- x }}")
assert_instance_of(string_subclass, source)
output = Template.parse(source).render!
assert_equal("x=2", output)
assert_instance_of(String, output)
end
end
+31
View File
@@ -15,6 +15,33 @@ class VariableTest < Minitest::Test
assert_template_result('foobar', '{{ foo }}', 'foo' => ThingWithToLiquid.new)
end
def test_variable_lookup_calls_to_liquid_value
assert_template_result('1', '{{ foo }}', 'foo' => IntegerDrop.new('1'))
assert_template_result('2', '{{ list[foo] }}', 'foo' => IntegerDrop.new('1'), 'list' => [1, 2, 3])
assert_template_result('one', '{{ list[foo] }}', 'foo' => IntegerDrop.new('1'), 'list' => { 1 => 'one' })
assert_template_result('Yay', '{{ foo }}', 'foo' => BooleanDrop.new(true))
assert_template_result('YAY', '{{ foo | upcase }}', 'foo' => BooleanDrop.new(true))
end
def test_if_tag_calls_to_liquid_value
assert_template_result('one', '{% if foo == 1 %}one{% endif %}', 'foo' => IntegerDrop.new('1'))
assert_template_result('one', '{% if 0 < foo %}one{% endif %}', 'foo' => IntegerDrop.new('1'))
assert_template_result('one', '{% if foo > 0 %}one{% endif %}', 'foo' => IntegerDrop.new('1'))
assert_template_result('true', '{% if foo == true %}true{% endif %}', 'foo' => BooleanDrop.new(true))
assert_template_result('true', '{% if foo %}true{% endif %}', 'foo' => BooleanDrop.new(true))
assert_template_result('', '{% if foo %}true{% endif %}', 'foo' => BooleanDrop.new(false))
assert_template_result('', '{% if foo == true %}True{% endif %}', 'foo' => BooleanDrop.new(false))
end
def test_unless_tag_calls_to_liquid_value
assert_template_result('', '{% unless foo %}true{% endunless %}', 'foo' => BooleanDrop.new(true))
end
def test_case_tag_calls_to_liquid_value
assert_template_result('One', '{% case foo %}{% when 1 %}One{% endcase %}', 'foo' => IntegerDrop.new('1'))
end
def test_simple_with_whitespaces
template = Template.parse(%( {{ test }} ))
assert_equal(' worked ', template.render!('test' => 'worked'))
@@ -104,4 +131,8 @@ class VariableTest < Minitest::Test
def test_dynamic_find_var
assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
end
def test_raw_value_variable
assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
end
end
+38
View File
@@ -119,6 +119,44 @@ class ThingWithToLiquid
end
end
class IntegerDrop < Liquid::Drop
def initialize(value)
super()
@value = value.to_i
end
def ==(other)
@value == other
end
def to_s
@value.to_s
end
def to_liquid_value
@value
end
end
class BooleanDrop < Liquid::Drop
def initialize(value)
super()
@value = value
end
def ==(other)
@value == other
end
def to_liquid_value
@value
end
def to_s
@value ? "Yay" : "Nay"
end
end
class ErrorDrop < Liquid::Drop
def standard_error
raise Liquid::StandardError, 'standard error'
+14
View File
@@ -26,6 +26,13 @@ class ParseTreeVisitorTest < Minitest::Test
)
end
def test_echo
assert_equal(
["test"],
visit(%({% echo test %}))
)
end
def test_if_condition
assert_equal(
["test"],
@@ -152,6 +159,13 @@ class ParseTreeVisitorTest < Minitest::Test
)
end
def test_for_range
assert_equal(
["test"],
visit(%({% for x in (1..test) %}{% endfor %}))
)
end
def test_tablerow_in
assert_equal(
["test"],