Compare commits

...
Author SHA1 Message Date
Iain Campbell ec3ec41ce2 Update rubocop_todo 2022-06-01 13:14:10 -04:00
Andy WaiteandGitHub d4c24f3ce2 Merge pull request #1578 from Shopify/andyw8/drop-support-for-ruby2.5-and-2.6
Drop support for Ruby 2.5 and 2.6
2022-05-26 12:51:44 -04:00
Andy Waite 3bbb7aa7ba Reword Ruby breaking change notice 2022-05-19 10:10:44 -04:00
Andy Waite 102bac2e33 Regenerate .rubocop_todo.yml 2022-05-18 15:25:59 -04:00
Andy Waite e69f729f76 Use latest rubocop-shopify 2022-05-18 15:25:34 -04:00
Andy Waite 4ec0b85d80 Drop support for Ruby 2.5 and 2.6 2022-05-18 15:23:32 -04:00
Dylan Thacker-SmithandGitHub 05d768c6ab Merge pull request #1498 from Shopify/feature/new-comment-syntax
Add `#` inline comment tag.
2022-04-28 09:46:59 -04:00
Dylan Thacker-Smith 54414dfd83 Add changelog entry, making the next release a feature release 2022-04-28 09:43:08 -04:00
Dylan Thacker-Smith 23a8438fa6 Use liquid-c master branch again, it now has inline comment support 2022-04-28 09:39:16 -04:00
Dylan Thacker-Smith 21f3337dec Test a blank line in a comment tag 2022-04-28 09:38:44 -04:00
Charles-P. ClermontandDylan Thacker-Smith 1f0a0ad55c Add # inline comment tag.
This commit adds a new tag named `#` that behaves like a comment.

Therefore it behaves as you'd expect any tag would work. The difference
with the comment tag is that the comment is in the tag markup and that
there is no block delimiter.

What it looks like in practice:

```liquid
{%- # this is an inline comment -%}
{% # this too is an inline comment %}

{% liquid
  # required args:
  assign product = product

  # optional args:
  assign should_show_border = should_show_border | default: true
  assign should_show_cursor = should_show_cursor | default: true
%}

{% liquid
  # This is a very long comment that spans multiple lines.
  # It looks very similar to what it would look like if you wrote
  # ruby code instead of liquid. But it doesn't have all the clunk
  # of having an open tag and a close tag with so many characters.
%}
```

Co-authored-by: Dylan Thacker-Smith <[email protected]>
2022-04-28 09:38:44 -04:00
Dylan Thacker-SmithandGitHub 36dce29776 Avoid evaluating the template name in the render tag (#1568) 2022-04-21 16:10:42 -04:00
Dylan Thacker-SmithandGitHub 8b68630a11 Merge pull request #1474 from Shopify/clarify-warn-error-mode-doc
Clarify that the error_mode: :warn parse option is only for strict errors
2022-04-21 12:25:36 -04:00
Chris AtLeeandGitHub 8882338aa1 Merge pull request #1553 from Shopify/catlee/shared_partial_cache
Ensure that partial caches are shared with subcontexts
2022-04-08 10:09:49 -04:00
Chris AtLeeandDylan Thacker-Smith 6c2c621712 Ensure that partial caches are shared with subcontexts
Make Context use StaticRegisters by default. This makes it easier to
ensure that all subcontexts share the same static registers.

Co-authored-by: Dylan Thacker-Smith <[email protected]>
2022-04-08 10:05:58 -04:00
Dylan Thacker-SmithandGitHub 1cae1e497f Merge pull request #1560 from ghousemohamed/fix-typo
Fix typo: syntetic -> synthetic
2022-04-05 20:15:09 -04:00
Dylan Thacker-SmithandGitHub ed7dae50aa Merge pull request #1562 from ghousemohamed/bump-actions-checkout-to-v3
Bump actions/checkout to v3
2022-04-05 19:46:41 -04:00
Ghouse Mohamed 7e99432bd1 Bumped actions/checkout to v3 2022-04-04 03:57:24 +05:30
Ghouse Mohamed 6c187b8470 Fix typo: syntetic -> synthetic 2022-03-27 23:18:01 +05:30
Dylan Thacker-SmithandGitHub 6e07f73f68 History.md: Remove non-fix from fixes section of recent release. (#1556) 2022-03-23 11:59:50 -04:00
Marc-André CournoyerandGitHub f64af57b7b Merge pull request #1540 from Watson1978/remove-redundant-regexp
Remove redundant regexp
2022-03-22 14:52:49 -04:00
Marc-André CournoyerandGitHub c60c3c7802 Merge pull request #1554 from Shopify/bump-5.3.0
Update changelog & bump version for 5.3.0 release
2022-03-22 13:30:28 -04:00
Marc-André Cournoyer 11625b1bc9 Update release date 2022-03-22 13:24:02 -04:00
Marc-André Cournoyer ec6fb4d5fa Update changelog & bump version for 5.3.0 release 2022-03-17 15:39:04 -04:00
Watson fad58ef436 Use String#match? instead of String#=~ to reduce allocation for backreferecne
## Test code
```ruby
require 'benchmark/ips'

WhitespaceOrNothing = /\A\s*\z/
token = " " * 20
token =~ WhitespaceOrNothing

Benchmark.ips do |x|
  x.report("=~") {
    token =~ WhitespaceOrNothing
  }
  x.report("match?") {
    token.match?(WhitespaceOrNothing)
  }

  x.compare!
end
```

## Result
```
Warming up --------------------------------------
                  =~   271.356k i/100ms
              match?   579.655k i/100ms
Calculating -------------------------------------
                  =~      2.717M (± 0.4%) i/s -     13.839M in   5.092947s
              match?      5.695M (± 1.6%) i/s -     28.983M in   5.090640s

Comparison:
              match?:  5694747.3 i/s
                  =~:  2717370.9 i/s - 2.10x  (± 0.00) slower
```
2022-03-16 12:44:27 +09:00
Watson 22568080b1 Revert "Use strip & empty? to detect Whitespaces"
This reverts commit dd7ed00ec4.
2022-03-16 12:33:45 +09:00
Watson dd7ed00ec4 Use strip & empty? to detect Whitespaces
## Test code
```ruby
require 'benchmark/ips'

WhitespaceOrNothing = /\A\s*\z/
token = " " * 20

Benchmark.ips do |x|
  x.report("WhitespaceOrNothing") {
    token =~ WhitespaceOrNothing
  }
  x.report("strip & empty?") {
    token.strip.empty?
  }

  x.compare!
end
```

## Result
```
Warming up --------------------------------------
 WhitespaceOrNothing   266.391k i/100ms
      strip & empty?     1.044M i/100ms
Calculating -------------------------------------
 WhitespaceOrNothing      2.705M (± 0.4%) i/s -     13.586M in   5.023453s
      strip & empty?     10.400M (± 1.1%) i/s -     52.182M in   5.017990s

Comparison:
      strip & empty?: 10400286.2 i/s
 WhitespaceOrNothing:  2704552.3 i/s - 3.85x  (± 0.00) slower
```
2022-03-12 19:24:56 +09:00
Watson 1667c1180e Use start_with? and end_with? to detect SQUARE_BRAKET
## Test code
```ruby
require 'benchmark/ips'

SQUARE_BRACKETED = /\A\[(.*)\]\z/m
markup = "[product.catchall]"

Benchmark.ips do |x|
  x.report("SQUARE_BRACKETED") {
    if markup =~ SQUARE_BRACKETED
      Regexp.last_match(1)
    end
  }
  x.report("start/end_with?") {
    if markup&.start_with?('[') && markup&.end_with?(']')
      markup[1..-2]
    end
  }

  x.compare!
end
```

## Result
```
Warming up --------------------------------------
    SQUARE_BRACKETED   261.300k i/100ms
     start/end_with?   548.813k i/100ms
Calculating -------------------------------------
    SQUARE_BRACKETED      2.632M (± 0.6%) i/s -     13.326M in   5.064085s
     start/end_with?      5.471M (± 0.5%) i/s -     27.441M in   5.015770s

Comparison:
     start/end_with?:  5470994.1 i/s
    SQUARE_BRACKETED:  2631642.3 i/s - 2.08x  (± 0.00) slower
```
2022-03-12 18:14:16 +09:00
Dylan Thacker-Smith 0e14d539a3 README: Use newer hash syntax for the error_mode parse option 2021-09-16 10:16:36 -04:00
Dylan Thacker-Smith db106ae058 Clarify that the error_mode: :warn parse option is only for strict errors 2021-09-16 10:13:57 -04:00
22 changed files with 347 additions and 53 deletions
+3 -3
View File
@@ -6,12 +6,12 @@ jobs:
strategy:
matrix:
entry:
- { ruby: 2.5, allowed-failure: false } # minimum supported
- { ruby: 2.7, allowed-failure: false } # minimum supported
- { ruby: 3.1, allowed-failure: false } # latest
- { ruby: ruby-head, allowed-failure: true }
name: test (${{ matrix.entry.ruby }})
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.entry.ruby }}
@@ -26,7 +26,7 @@ jobs:
memory_profile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
+1 -1
View File
@@ -10,7 +10,7 @@ Performance:
Enabled: true
AllCops:
TargetRubyVersion: 2.5
TargetRubyVersion: 2.7
NewCops: disable
Exclude:
- 'vendor/bundle/**/*'
+145 -14
View File
@@ -1,27 +1,82 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2020-12-11 18:53:41 UTC using RuboCop version 1.6.1.
# on 2022-06-01 17:13:35 UTC using RuboCop version 1.30.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: runtime_error, standard_error
Lint/InheritException:
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Include.
# Include: **/*.gemspec
Gemspec/DeprecatedAttributeAssignment:
Exclude:
- 'lib/liquid/interrupts.rb'
- 'liquid.gemspec'
# Offense count: 113
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 260
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
# Include: **/*.gemspec
Gemspec/OrderedDependencies:
Exclude:
- 'liquid.gemspec'
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
Layout/ClosingHeredocIndentation:
Exclude:
- 'test/integration/tags/for_tag_test.rb'
# Offense count: 34
# This cop supports safe autocorrection (--autocorrect).
Layout/EmptyLineAfterGuardClause:
Exclude:
- 'lib/liquid/block.rb'
- 'lib/liquid/block_body.rb'
- 'lib/liquid/context.rb'
- 'lib/liquid/drop.rb'
- 'lib/liquid/lexer.rb'
- 'lib/liquid/parser.rb'
- 'lib/liquid/profiler/hooks.rb'
- 'lib/liquid/standardfilters.rb'
- 'lib/liquid/tags/for.rb'
- 'lib/liquid/tags/if.rb'
- 'lib/liquid/utils.rb'
- 'lib/liquid/variable.rb'
- 'lib/liquid/variable_lookup.rb'
- 'performance/shopify/money_filter.rb'
- 'performance/shopify/paginate.rb'
# Offense count: 8
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowAliasSyntax, AllowedMethods.
# AllowedMethods: alias_method, public, protected, private
Layout/EmptyLinesAroundAttributeAccessor:
Exclude:
- 'lib/liquid/template.rb'
- 'test/integration/filter_test.rb'
- 'test/integration/tags/include_tag_test.rb'
- 'test/unit/strainer_template_unit_test.rb'
# Offense count: 17
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented
Layout/LineEndStringConcatenationIndentation:
Exclude:
- 'test/integration/tags/for_tag_test.rb'
- 'test/integration/tags/increment_tag_test.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented
Layout/MultilineOperationIndentation:
Exclude:
- 'lib/liquid/expression.rb'
# Offense count: 9
Lint/MissingSuper:
Exclude:
- 'lib/liquid/forloop_drop.rb'
@@ -33,7 +88,7 @@ Lint/MissingSuper:
- 'test/integration/tags/for_tag_test.rb'
- 'test/integration/tags/table_row_test.rb'
# Offense count: 43
# Offense count: 44
Naming/ConstantName:
Exclude:
- 'lib/liquid.rb'
@@ -51,7 +106,83 @@ Naming/ConstantName:
- 'performance/shopify/paginate.rb'
- 'test/integration/tags/include_tag_test.rb'
# Offense count: 9
# Configuration parameters: CheckIdentifiers, CheckConstants, CheckVariables, CheckStrings, CheckSymbols, CheckComments, CheckFilepaths, FlaggedTerms.
Naming/InclusiveLanguage:
Exclude:
- 'lib/liquid/drop.rb'
- 'lib/liquid/parse_context.rb'
- 'test/integration/drop_test.rb'
- 'test/integration/tags/if_else_tag_test.rb'
# Offense count: 2
Style/ClassVars:
Exclude:
- 'lib/liquid/condition.rb'
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
Style/ExplicitBlockArgument:
Exclude:
- 'test/integration/context_test.rb'
- 'test/integration/tag/disableable_test.rb'
- 'test/integration/tags/for_tag_test.rb'
# Offense count: 2982
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiterals:
Enabled: false
# Offense count: 20
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Exclude:
- 'lib/liquid/condition.rb'
- 'lib/liquid/strainer_template.rb'
- 'lib/liquid/tag/disableable.rb'
- 'performance/shopify/shop_filter.rb'
- 'performance/shopify/tag_filter.rb'
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
Style/TrailingCommaInArrayLiteral:
Exclude:
- 'example/server/example_servlet.rb'
- 'lib/liquid/condition.rb'
- 'test/integration/context_test.rb'
- 'test/integration/standard_filter_test.rb'
- 'test/unit/parse_tree_visitor_test.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
Style/TrailingCommaInHashLiteral:
Exclude:
- 'lib/liquid/expression.rb'
# Offense count: 19
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, MinSize, WordRegex.
# SupportedStyles: percent, brackets
Style/WordArray:
Exclude:
- 'lib/liquid/tags/if.rb'
- 'liquid.gemspec'
- 'test/integration/assign_test.rb'
- 'test/integration/context_test.rb'
- 'test/integration/drop_test.rb'
- 'test/integration/standard_filter_test.rb'
# Offense count: 117
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 260
+1 -2
View File
@@ -18,8 +18,7 @@ group :benchmark, :test do
end
group :test do
gem 'rubocop', '~> 1.4', require: false
gem 'rubocop-shopify', '~> 1.0.7', require: false
gem 'rubocop-shopify', '~> 2.6', require: false
gem 'rubocop-performance', require: false
platform :mri, :truffleruby do
+17 -1
View File
@@ -1,9 +1,25 @@
# Liquid Change Log
## 5.3.0 (unreleased)
## 5.4.0 (unreleased)
### Breaking Changes
* Drop support for end-of-life Ruby versions (2.5 and 2.6) (#1578) [Andy Waite]
### Features
* Allow `#` to be used as an inline comment tag (#1498) [CP Clermont]
### Fixes
* `PartialCache` now shares snippet cache with subcontexts by default (#1553) [Chris AtLee]
* Hash registers no longer leak into subcontexts as static registers (#1564) [Chris AtLee]
### Changed
* Liquid::Context#registers now always returns a Liquid::StaticRegisters object, though supports the most used Hash functions for compatibility (#1553)
## 5.3.0 2022-03-22
### Fixes
* StandardFilter: Fix missing @context on iterations (#1525) [Thierry Joyal]
* Fix warning about block and default value in `static_registers.rb` (#1531) [Peter Zhu]
### Deprecation
* Condition#evaluate to require mandatory context argument in Liquid 6.0.0 (#1527) [Thierry Joyal]
+2 -2
View File
@@ -63,13 +63,13 @@ when templates are invalid. You can enable this new parser like this:
```ruby
Liquid::Template.error_mode = :strict # Raises a SyntaxError when invalid syntax is used
Liquid::Template.error_mode = :warn # Adds errors to template.errors but continues as normal
Liquid::Template.error_mode = :warn # Adds strict errors to template.errors but continues as normal
Liquid::Template.error_mode = :lax # The default mode, accepts almost anything.
```
If you want to set the error mode only on specific templates you can pass `:error_mode` as an option to `parse`:
```ruby
Liquid::Template.parse(source, :error_mode => :strict)
Liquid::Template.parse(source, error_mode: :strict)
```
This is useful for doing things like enabling strict mode only in the theme editor.
+1
View File
@@ -29,6 +29,7 @@ module Liquid
WhitespaceControl = '-'
TagStart = /\{\%/
TagEnd = /\%\}/
TagName = /#|\w+/
VariableSignature = /\(?[\w\-\.\[\]]\)?/
VariableSegment = /[\w\-]/
VariableStart = /\{\{/
+4 -4
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*(#{TagName})\s*(.*?)\z/o
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(#{TagName})(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om
WhitespaceOrNothing = /\A\s*\z/
TAGSTART = "{%"
@@ -37,7 +37,7 @@ module Liquid
private def parse_for_liquid_tag(tokenizer, parse_context)
while (token = tokenizer.shift)
unless token.empty? || token =~ WhitespaceOrNothing
unless token.empty? || token.match?(WhitespaceOrNothing)
unless token =~ LiquidTagToken
# line isn't empty but didn't match tag syntax, yield and let the
# caller raise a syntax error
@@ -150,7 +150,7 @@ module Liquid
end
parse_context.trim_whitespace = false
@nodelist << token
@blank &&= !!(token =~ WhitespaceOrNothing)
@blank &&= token.match?(WhitespaceOrNothing)
end
parse_context.line_number = tokenizer.line_number
end
+5 -1
View File
@@ -28,7 +28,7 @@ module Liquid
@static_environments = [static_environments].flat_map(&:freeze).freeze
@scopes = [(outer_scope || {})]
@registers = registers
@registers = registers.is_a?(StaticRegisters) ? registers : StaticRegisters.new(registers)
@errors = []
@partial = false
@strict_variables = false
@@ -39,6 +39,10 @@ module Liquid
@global_filter = nil
@disabled_tags = {}
@registers.static[:cached_partials] ||= {}
@registers.static[:file_system] ||= Liquid::Template.file_system
@registers.static[:template_factory] ||= Liquid::TemplateFactory.new
self.exception_renderer = Template.default_exception_renderer
if rethrow_errors
self.exception_renderer = Liquid::RAISE_EXCEPTION_LAMBDA
+6 -5
View File
@@ -13,15 +13,16 @@
for_invalid_attribute: "Invalid attribute in for loop. Valid attributes are limit and offset"
if: "Syntax Error in tag 'if' - Valid syntax: if [expression]"
include: "Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]"
unknown_tag: "Unknown tag '%{tag}'"
inline_comment_invalid: "Syntax error in tag '#' - Each line of comments must be prefixed by the '#' character"
invalid_delimiter: "'%{tag}' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
render: "Syntax error in tag 'render' - Template name must be a quoted string"
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
tag_never_closed: "'%{block_name}' tag was never closed"
tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}"
unexpected_else: "%{block_name} tag does not expect 'else' tag"
unexpected_outer_tag: "Unexpected outer '%{tag}' tag"
tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}"
unknown_tag: "Unknown tag '%{tag}'"
variable_termination: "Variable '%{token}' was not properly terminated with regexp: %{tag_end}"
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"
argument:
include: "Argument error in tag 'include' - Illegal template name"
disabled:
+3 -3
View File
@@ -3,16 +3,16 @@
module Liquid
class PartialCache
def self.load(template_name, context:, parse_context:)
cached_partials = (context.registers[:cached_partials] ||= {})
cached_partials = context.registers[:cached_partials]
cached = cached_partials[template_name]
return cached if cached
file_system = (context.registers[:file_system] ||= Liquid::Template.file_system)
file_system = context.registers[:file_system]
source = file_system.read_template_file(template_name)
parse_context.partial = true
template_factory = (context.registers[:template_factory] ||= Liquid::TemplateFactory.new)
template_factory = context.registers[:template_factory]
template = template_factory.for(template_name)
partial = template.parse(source, parse_context)
+30
View File
@@ -0,0 +1,30 @@
# 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 and prevent the introduction
# of inline comments from being backward incompatible change.
#
# As such, we're forcing users to put a # symbol on every line otherwise this
# tag will throw an error.
if markup.match?(/\n\s*[^#\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
+3 -3
View File
@@ -34,9 +34,9 @@ module Liquid
end
def render_tag(context, output)
# Though we evaluate this here we will only ever parse it as a string literal.
template_name = context.evaluate(@template_name_expr)
raise ArgumentError, options[:locale].t("errors.argument.include") unless template_name
# The expression should be a String literal, which parses to a String object
template_name = @template_name_expr
raise ::ArgumentError unless template_name.is_a?(String)
partial = PartialCache.load(
template_name,
+2 -3
View File
@@ -167,15 +167,14 @@ module Liquid
output = nil
context_register = context.registers.is_a?(StaticRegisters) ? context.registers.static : context.registers
case args.last
when Hash
options = args.pop
output = options[:output] if options[:output]
static_registers = context.registers.static
options[:registers]&.each do |key, register|
context_register[key] = register
static_registers[key] = register
end
apply_options_to_context(context, options)
+5 -6
View File
@@ -2,8 +2,7 @@
module Liquid
class VariableLookup
SQUARE_BRACKETED = /\A\[(.*)\]\z/m
COMMAND_METHODS = ['size', 'first', 'last'].freeze
COMMAND_METHODS = ['size', 'first', 'last'].freeze
attr_reader :name, :lookups
@@ -15,8 +14,8 @@ module Liquid
lookups = markup.scan(VariableParser)
name = lookups.shift
if name =~ SQUARE_BRACKETED
name = Expression.parse(Regexp.last_match(1))
if name&.start_with?('[') && name&.end_with?(']')
name = Expression.parse(name[1..-2])
end
@name = name
@@ -25,8 +24,8 @@ module Liquid
@lookups.each_index do |i|
lookup = lookups[i]
if lookup =~ SQUARE_BRACKETED
lookups[i] = Expression.parse(Regexp.last_match(1))
if lookup&.start_with?('[') && lookup&.end_with?(']')
lookups[i] = Expression.parse(lookup[1..-2])
elsif COMMAND_METHODS.include?(lookup)
@command_flags |= 1 << i
end
+1 -1
View File
@@ -2,5 +2,5 @@
# frozen_string_literal: true
module Liquid
VERSION = "5.3.0.alpha"
VERSION = "5.4.0.alpha"
end
+1 -1
View File
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.license = "MIT"
# s.description = "A secure, non-evaling end user template engine with aesthetic markup."
s.required_ruby_version = ">= 2.5.0"
s.required_ruby_version = ">= 2.7.0"
s.required_rubygems_version = ">= 1.3.7"
s.metadata['allowed_push_host'] = 'https://rubygems.org'
+1 -1
View File
@@ -3,7 +3,7 @@
# This profiler run simulates Shopify.
# We are looking in the tests directory for liquid files and render them within the designated layout file.
# We will also export a substantial database to liquid which the templates can render values of.
# All this is to make the benchmark as non syntetic as possible. All templates and tests are lifted from
# All this is to make the benchmark as non synthetic as possible. All templates and tests are lifted from
# direct real-world usage and the profiler measures code that looks very similar to the way it looks in
# Shopify which is likely the biggest user of liquid in the world which something to the tune of several
# million Template#render calls a day.
+14
View File
@@ -618,6 +618,20 @@ class ContextTest < Minitest::Test
end
end
def test_context_always_uses_static_registers
registers = {
my_register: :my_value,
}
c = Context.new({}, {}, registers)
assert_instance_of(StaticRegisters, c.registers)
assert_equal(:my_value, c.registers[:my_register])
r = StaticRegisters.new(registers)
c = Context.new({}, {}, r)
assert_instance_of(StaticRegisters, c.registers)
assert_equal(:my_value, c.registers[:my_register])
end
private
def assert_no_object_allocations
+2 -2
View File
@@ -32,7 +32,7 @@ class TestDrop < Liquid::Drop
attr_reader :value
def registers
@context.registers
{ @value => @context.registers[@value] }
end
end
@@ -440,7 +440,7 @@ class StandardFiltersTest < Minitest::Test
end
def test_map_calls_context=
model = TestModel.new(value: "test")
model = TestModel.new(value: :test)
template = Template.parse('{{ foo | map: "registers" }}')
template.registers[:test] = 1234
@@ -0,0 +1,69 @@
# frozen_string_literal: true
require 'test_helper'
class InlineCommentTest < Minitest::Test
include Liquid
def test_inline_comment_returns_nothing
assert_template_result('', '{%- # this is an inline comment -%}')
assert_template_result('', '{%-# this is an inline comment -%}')
assert_template_result('', '{% # this is an inline comment %}')
assert_template_result('', '{%# this is an inline comment %}')
end
def test_inline_comment_does_not_require_a_space_after_the_pound_sign
assert_template_result('', '{%#this is an inline comment%}')
end
def test_liquid_inline_comment_returns_nothing
assert_template_result('Hey there, how are you doing today?', <<~LIQUID)
{%- liquid
# This is how you'd write a block comment in a liquid tag.
# It looks a lot like what you'd have in ruby.
# You can use it as inline documentation in your
# liquid blocks to explain why you're doing something.
echo "Hey there, "
# It won't affect the output.
echo "how are you doing today?"
-%}
LIQUID
end
def test_inline_comment_can_be_written_on_multiple_lines
assert_template_result('', <<~LIQUID)
{%-
# That kind of block comment is also allowed.
# It would only be a stylistic difference.
# Much like JavaScript's /* */ comments and their
# leading * on new lines.
-%}
LIQUID
end
def test_inline_comment_multiple_pound_signs
assert_template_result('', <<~LIQUID)
{%- liquid
######################################
# We support comments like this too. #
######################################
-%}
LIQUID
end
def test_inline_comments_require_the_pound_sign_on_every_new_line
assert_match_syntax_error("Each line of comments must be prefixed by the '#' character", <<~LIQUID)
{%-
# some comment
echo 'hello world'
-%}
LIQUID
end
def test_inline_comment_does_not_support_nested_tags
assert_template_result(' -%}', "{%- # {% echo 'hello world' %} -%}")
end
end
+31
View File
@@ -125,4 +125,35 @@ class PartialCacheUnitTest < Minitest::Test
assert_equal('my partial body', partial.render)
assert_equal(1, template_factory.count)
end
def test_cache_state_is_shared_for_subcontexts
parse_context = Liquid::ParseContext.new
shared_file_system = StubFileSystem.new(
'my_partial' => 'my shared value'
)
context = Liquid::Context.build(
registers: Liquid::StaticRegisters.new(
file_system: shared_file_system,
)
)
subcontext = context.new_isolated_subcontext
assert_equal(subcontext.registers[:cached_partials].object_id, context.registers[:cached_partials].object_id)
2.times do
Liquid::PartialCache.load(
'my_partial',
context: context,
parse_context: parse_context
)
Liquid::PartialCache.load(
'my_partial',
context: subcontext,
parse_context: parse_context
)
end
assert_equal(1, shared_file_system.file_read_count)
end
end