mirror of
https://github.com/kemko/liquid.git
synced 2026-01-02 00:05:42 +03:00
Compare commits
24 Commits
liquid-usa
...
sort-numer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bb533985e | ||
|
|
1c6a5d91fe | ||
|
|
1aa7d3d2ba | ||
|
|
0db9c56f34 | ||
|
|
f4d134cd5c | ||
|
|
b667bcb48b | ||
|
|
2c14e0b2ba | ||
|
|
ca207ed93f | ||
|
|
ef13343591 | ||
|
|
adb40c41b7 | ||
|
|
d8403af515 | ||
|
|
0d26f05bb8 | ||
|
|
1dcad34b06 | ||
|
|
9a42c8c8b2 | ||
|
|
1fcef2133f | ||
|
|
d7514b1305 | ||
|
|
c0ffee5919 | ||
|
|
724d02e9b3 | ||
|
|
a5b387cdd4 | ||
|
|
1f90a37b63 | ||
|
|
799da202df | ||
|
|
dafbb4ae90 | ||
|
|
2324564743 | ||
|
|
2f0a2c66f3 |
@@ -1,5 +1,5 @@
|
|||||||
inherit_from:
|
inherit_from:
|
||||||
- https://shopify.github.io/ruby-style-guide/rubocop.yml
|
- 'https://shopify.github.io/ruby-style-guide/rubocop.yml'
|
||||||
- .rubocop_todo.yml
|
- .rubocop_todo.yml
|
||||||
|
|
||||||
require: rubocop-performance
|
require: rubocop-performance
|
||||||
@@ -8,9 +8,10 @@ Performance:
|
|||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
|
TargetRubyVersion: 2.4
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'vendor/bundle/**/*'
|
- 'vendor/bundle/**/*'
|
||||||
|
|
||||||
Naming/MethodName:
|
Naming/MethodName:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'example/server/liquid_servlet.rb'
|
- 'example/server/liquid_servlet.rb'
|
||||||
|
|||||||
@@ -1,107 +1,11 @@
|
|||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `rubocop --auto-gen-config`
|
# `rubocop --auto-gen-config`
|
||||||
# on 2019-08-29 12:16:25 +1000 using RuboCop version 0.74.0.
|
# on 2019-09-11 06:34:25 +1000 using RuboCop version 0.74.0.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of RuboCop, may require this file to be generated again.
|
# versions of RuboCop, may require this file to be generated again.
|
||||||
|
|
||||||
# Offense count: 13
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
||||||
# SupportedHashRocketStyles: key, separator, table
|
|
||||||
# SupportedColonStyles: key, separator, table
|
|
||||||
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
||||||
Layout/AlignHash:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/condition.rb'
|
|
||||||
- 'lib/liquid/expression.rb'
|
|
||||||
- 'performance/shopify/comment_form.rb'
|
|
||||||
- 'performance/shopify/database.rb'
|
|
||||||
- 'performance/shopify/paginate.rb'
|
|
||||||
- 'test/unit/context_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 3
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
|
|
||||||
Layout/ExtraSpacing:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/paginate.rb'
|
|
||||||
|
|
||||||
# Offense count: 5
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: squiggly, active_support, powerpack, unindent
|
|
||||||
Layout/IndentHeredoc:
|
|
||||||
Exclude:
|
|
||||||
- 'test/integration/tags/for_tag_test.rb'
|
|
||||||
- 'test/integration/trim_mode_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 6
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: symmetrical, new_line, same_line
|
|
||||||
Layout/MultilineMethodCallBraceLayout:
|
|
||||||
Exclude:
|
|
||||||
- 'test/integration/error_handling_test.rb'
|
|
||||||
- 'test/unit/strainer_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 4
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowForAlignment.
|
|
||||||
Layout/SpaceAroundOperators:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/condition.rb'
|
|
||||||
- 'performance/shopify/paginate.rb'
|
|
||||||
|
|
||||||
# Offense count: 9
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
|
|
||||||
# SupportedStyles: space, no_space
|
|
||||||
# SupportedStylesForEmptyBraces: space, no_space
|
|
||||||
Layout/SpaceBeforeBlockBraces:
|
|
||||||
Exclude:
|
|
||||||
- 'example/server/server.rb'
|
|
||||||
- 'lib/liquid/variable.rb'
|
|
||||||
- 'test/integration/drop_test.rb'
|
|
||||||
- 'test/integration/standard_filter_test.rb'
|
|
||||||
- 'test/integration/tags/if_else_tag_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 19
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets.
|
|
||||||
# SupportedStyles: space, no_space, compact
|
|
||||||
# SupportedStylesForEmptyBrackets: space, no_space
|
|
||||||
Layout/SpaceInsideArrayLiteralBrackets:
|
|
||||||
Exclude:
|
|
||||||
- 'test/integration/drop_test.rb'
|
|
||||||
- 'test/integration/standard_filter_test.rb'
|
|
||||||
- 'test/integration/tags/for_tag_test.rb'
|
|
||||||
- 'test/integration/tags/include_tag_test.rb'
|
|
||||||
- 'test/integration/tags/standard_tag_test.rb'
|
|
||||||
- 'test/unit/context_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
Lint/AmbiguousOperator:
|
|
||||||
Exclude:
|
|
||||||
- 'test/unit/condition_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 16
|
|
||||||
# Configuration parameters: AllowSafeAssignment.
|
|
||||||
Lint/AssignmentInCondition:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/block_body.rb'
|
|
||||||
- 'lib/liquid/lexer.rb'
|
|
||||||
- 'lib/liquid/standardfilters.rb'
|
|
||||||
- 'lib/liquid/tags/for.rb'
|
|
||||||
- 'lib/liquid/tags/if.rb'
|
|
||||||
- 'lib/liquid/tags/include.rb'
|
|
||||||
- 'lib/liquid/tags/raw.rb'
|
|
||||||
- 'lib/liquid/variable.rb'
|
|
||||||
- 'performance/profile.rb'
|
|
||||||
- 'test/test_helper.rb'
|
|
||||||
- 'test/unit/tokenizer_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
# Offense count: 2
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
@@ -110,48 +14,7 @@ Lint/InheritException:
|
|||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/liquid/interrupts.rb'
|
- 'lib/liquid/interrupts.rb'
|
||||||
|
|
||||||
# Offense count: 10
|
# Offense count: 98
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
|
|
||||||
Lint/UnusedBlockArgument:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/condition.rb'
|
|
||||||
- 'lib/liquid/context.rb'
|
|
||||||
- 'lib/liquid/document.rb'
|
|
||||||
- 'lib/liquid/parse_context.rb'
|
|
||||||
- 'lib/liquid/template.rb'
|
|
||||||
- 'performance/shopify/json_filter.rb'
|
|
||||||
- 'test/integration/filter_test.rb'
|
|
||||||
- 'test/integration/render_profiling_test.rb'
|
|
||||||
- 'test/integration/variable_test.rb'
|
|
||||||
- 'test/unit/condition_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 12
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
|
|
||||||
Lint/UnusedMethodArgument:
|
|
||||||
Exclude:
|
|
||||||
- 'example/server/liquid_servlet.rb'
|
|
||||||
- 'test/integration/blank_test.rb'
|
|
||||||
- 'test/integration/error_handling_test.rb'
|
|
||||||
- 'test/integration/filter_test.rb'
|
|
||||||
- 'test/integration/output_test.rb'
|
|
||||||
- 'test/integration/standard_filter_test.rb'
|
|
||||||
- 'test/integration/tags/include_tag_test.rb'
|
|
||||||
- 'test/unit/strainer_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
Lint/UselessAssignment:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/database.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Configuration parameters: CheckForMethodsWithNoSideEffects.
|
|
||||||
Lint/Void:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/parse_context.rb'
|
|
||||||
|
|
||||||
# Offense count: 95
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||||
# URISchemes: http, https
|
# URISchemes: http, https
|
||||||
@@ -177,235 +40,9 @@ Naming/ConstantName:
|
|||||||
- 'performance/shopify/paginate.rb'
|
- 'performance/shopify/paginate.rb'
|
||||||
- 'test/integration/tags/include_tag_test.rb'
|
- 'test/integration/tags/include_tag_test.rb'
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Configuration parameters: .
|
|
||||||
# SupportedStyles: snake_case, camelCase
|
|
||||||
Naming/MethodName:
|
|
||||||
EnforcedStyle: snake_case
|
|
||||||
|
|
||||||
# Offense count: 3
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: always, conditionals
|
|
||||||
Style/AndOr:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/i18n.rb'
|
|
||||||
- 'lib/liquid/tags/table_row.rb'
|
|
||||||
- 'lib/liquid/tokenizer.rb'
|
|
||||||
|
|
||||||
# Offense count: 40
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: braces, no_braces, context_dependent
|
|
||||||
Style/BracesAroundHashParameters:
|
|
||||||
Exclude:
|
|
||||||
- 'test/integration/error_handling_test.rb'
|
|
||||||
- 'test/integration/filter_test.rb'
|
|
||||||
- 'test/integration/render_profiling_test.rb'
|
|
||||||
- 'test/integration/standard_filter_test.rb'
|
|
||||||
- 'test/integration/tags/echo_test.rb'
|
|
||||||
- 'test/integration/tags/increment_tag_test.rb'
|
|
||||||
- 'test/integration/tags/standard_tag_test.rb'
|
|
||||||
- 'test/integration/template_test.rb'
|
|
||||||
- 'test/unit/condition_unit_test.rb'
|
|
||||||
- 'test/unit/context_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 5
|
# Offense count: 5
|
||||||
Style/ClassVars:
|
Style/ClassVars:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/liquid/condition.rb'
|
- 'lib/liquid/condition.rb'
|
||||||
- 'lib/liquid/strainer.rb'
|
- 'lib/liquid/strainer.rb'
|
||||||
- 'lib/liquid/template.rb'
|
- 'lib/liquid/template.rb'
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
|
|
||||||
# SupportedStyles: assign_to_condition, assign_inside_condition
|
|
||||||
Style/ConditionalAssignment:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/errors.rb'
|
|
||||||
- 'performance/shopify/shop_filter.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Configuration parameters: AllowCoercion.
|
|
||||||
Style/DateTime:
|
|
||||||
Exclude:
|
|
||||||
- 'test/unit/context_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/EachWithObject:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/database.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/EmptyCaseCondition:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/lexer.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: each, for
|
|
||||||
Style/For:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/shop_filter.rb'
|
|
||||||
|
|
||||||
# Offense count: 9
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: format, sprintf, percent
|
|
||||||
Style/FormatString:
|
|
||||||
Exclude:
|
|
||||||
- 'example/server/example_servlet.rb'
|
|
||||||
- 'performance/shopify/money_filter.rb'
|
|
||||||
- 'performance/shopify/weight_filter.rb'
|
|
||||||
- 'test/integration/filter_test.rb'
|
|
||||||
- 'test/integration/hash_ordering_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 115
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: always, never
|
|
||||||
Style/FrozenStringLiteralComment:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 30
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: IgnoreMacros, IgnoredMethods, IncludedMacros, AllowParenthesesInMultilineCall, AllowParenthesesInChaining, AllowParenthesesInCamelCaseMethod, EnforcedStyle.
|
|
||||||
# SupportedStyles: require_parentheses, omit_parentheses
|
|
||||||
Style/MethodCallWithArgsParentheses:
|
|
||||||
Exclude:
|
|
||||||
- 'Gemfile'
|
|
||||||
- 'Rakefile'
|
|
||||||
- 'lib/liquid/block_body.rb'
|
|
||||||
- 'lib/liquid/parser.rb'
|
|
||||||
- 'lib/liquid/tags/for.rb'
|
|
||||||
- 'liquid.gemspec'
|
|
||||||
- 'performance/shopify/database.rb'
|
|
||||||
- 'performance/shopify/liquid.rb'
|
|
||||||
- 'test/test_helper.rb'
|
|
||||||
- 'test/unit/condition_unit_test.rb'
|
|
||||||
- 'test/unit/tags/if_tag_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, MinBodyLength.
|
|
||||||
# SupportedStyles: skip_modifier_ifs, always
|
|
||||||
Style/Next:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/tags/for.rb'
|
|
||||||
|
|
||||||
# Offense count: 52
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/PerlBackrefs:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 33
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: compact, exploded
|
|
||||||
Style/RaiseArgs:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/RedundantSelf:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/strainer.rb'
|
|
||||||
|
|
||||||
# Offense count: 5
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
|
|
||||||
# SupportedStyles: slashes, percent_r, mixed
|
|
||||||
Style/RegexpLiteral:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/file_system.rb'
|
|
||||||
- 'lib/liquid/standardfilters.rb'
|
|
||||||
- 'performance/shopify/shop_filter.rb'
|
|
||||||
- 'test/unit/condition_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 3
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, Whitelist.
|
|
||||||
# Whitelist: present?, blank?, presence, try, try!
|
|
||||||
Style/SafeNavigation:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/drop.rb'
|
|
||||||
- 'lib/liquid/strainer.rb'
|
|
||||||
- 'lib/liquid/tokenizer.rb'
|
|
||||||
|
|
||||||
# Offense count: 10
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowAsExpressionSeparator.
|
|
||||||
Style/Semicolon:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/database.rb'
|
|
||||||
- 'test/integration/error_handling_test.rb'
|
|
||||||
- 'test/integration/template_test.rb'
|
|
||||||
- 'test/unit/context_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: use_perl_names, use_english_names
|
|
||||||
Style/SpecialGlobalVars:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/liquid.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: single_quotes, double_quotes
|
|
||||||
Style/StringLiteralsInInterpolation:
|
|
||||||
Exclude:
|
|
||||||
- 'performance/shopify/tag_filter.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
|
||||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
|
||||||
Style/TernaryParentheses:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/context.rb'
|
|
||||||
- 'lib/liquid/utils.rb'
|
|
||||||
|
|
||||||
# Offense count: 21
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyleForMultiline.
|
|
||||||
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
|
||||||
Style/TrailingCommaInArrayLiteral:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/parse_tree_visitor.rb'
|
|
||||||
- 'lib/liquid/tags/include.rb'
|
|
||||||
- 'test/integration/parse_tree_visitor_test.rb'
|
|
||||||
- 'test/integration/standard_filter_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 9
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyleForMultiline.
|
|
||||||
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
|
||||||
Style/TrailingCommaInHashLiteral:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/condition.rb'
|
|
||||||
- 'lib/liquid/lexer.rb'
|
|
||||||
- 'lib/liquid/standardfilters.rb'
|
|
||||||
- 'performance/shopify/comment_form.rb'
|
|
||||||
- 'performance/shopify/database.rb'
|
|
||||||
- 'performance/shopify/paginate.rb'
|
|
||||||
- 'performance/theme_runner.rb'
|
|
||||||
- 'test/integration/output_test.rb'
|
|
||||||
- 'test/unit/context_unit_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/UnneededPercentQ:
|
|
||||||
Exclude:
|
|
||||||
- 'test/integration/error_handling_test.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/WhileUntilModifier:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/liquid/tags/case.rb'
|
|
||||||
@@ -7,8 +7,6 @@ rvm:
|
|||||||
- &latest_ruby 2.6
|
- &latest_ruby 2.6
|
||||||
- 2.7
|
- 2.7
|
||||||
- ruby-head
|
- ruby-head
|
||||||
- jruby-head
|
|
||||||
- truffleruby
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@@ -17,8 +15,6 @@ matrix:
|
|||||||
name: Profiling Memory Usage
|
name: Profiling Memory Usage
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- rvm: ruby-head
|
- rvm: ruby-head
|
||||||
- rvm: jruby-head
|
|
||||||
- rvm: truffleruby
|
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
|||||||
2
Gemfile
2
Gemfile
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
git_source(:github) do |repo_name|
|
git_source(:github) do |repo_name|
|
||||||
"https://github.com/#{repo_name}.git"
|
"https://github.com/#{repo_name}.git"
|
||||||
|
|||||||
16
Rakefile
16
Rakefile
@@ -1,18 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rake'
|
require 'rake'
|
||||||
require 'rake/testtask'
|
require 'rake/testtask'
|
||||||
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))
|
||||||
require "liquid/version"
|
require "liquid/version"
|
||||||
|
|
||||||
task default: [:test, :rubocop]
|
task(default: [:test, :rubocop])
|
||||||
|
|
||||||
desc 'run test suite with default parser'
|
desc('run test suite with default parser')
|
||||||
Rake::TestTask.new(:base_test) do |t|
|
Rake::TestTask.new(:base_test) do |t|
|
||||||
t.libs << '.' << 'lib' << 'test'
|
t.libs << '.' << 'lib' << 'test'
|
||||||
t.test_files = FileList['test/{integration,unit}/**/*_test.rb']
|
t.test_files = FileList['test/{integration,unit}/**/*_test.rb']
|
||||||
t.verbose = false
|
t.verbose = false
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'run test suite with warn error mode'
|
desc('run test suite with warn error mode')
|
||||||
task :warn_test do
|
task :warn_test do
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'warn'
|
ENV['LIQUID_PARSER_MODE'] = 'warn'
|
||||||
Rake::Task['base_test'].invoke
|
Rake::Task['base_test'].invoke
|
||||||
@@ -25,7 +27,7 @@ task :rubocop do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'runs test suite with both strict and lax parsers'
|
desc('runs test suite with both strict and lax parsers')
|
||||||
task :test do
|
task :test do
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'lax'
|
ENV['LIQUID_PARSER_MODE'] = 'lax'
|
||||||
Rake::Task['base_test'].invoke
|
Rake::Task['base_test'].invoke
|
||||||
@@ -47,7 +49,7 @@ task :test do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task gem: :build
|
task(gem: :build)
|
||||||
task :build do
|
task :build do
|
||||||
system "gem build liquid.gemspec"
|
system "gem build liquid.gemspec"
|
||||||
end
|
end
|
||||||
@@ -94,7 +96,7 @@ namespace :memory_profile do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Run example"
|
desc("Run example")
|
||||||
task :example do
|
task :example do
|
||||||
ruby "-w -d -Ilib example/server/server.rb"
|
ruby "-w -d -Ilib example/server/server.rb"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ProductsFilter
|
module ProductsFilter
|
||||||
def price(integer)
|
def price(integer)
|
||||||
sprintf("$%.2d USD", integer / 100.0)
|
format("$%.2d USD", integer / 100.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prettyprint(text)
|
def prettyprint(text)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class LiquidServlet < WEBrick::HTTPServlet::AbstractServlet
|
class LiquidServlet < WEBrick::HTTPServlet::AbstractServlet
|
||||||
def do_GET(req, res)
|
def do_GET(req, res)
|
||||||
handle(:get, req, res)
|
handle(:get, req, res)
|
||||||
@@ -9,12 +11,12 @@ class LiquidServlet < WEBrick::HTTPServlet::AbstractServlet
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def handle(type, req, res)
|
def handle(_type, req, res)
|
||||||
@request = req
|
@request = req
|
||||||
@response = res
|
@response = res
|
||||||
|
|
||||||
@request.path_info =~ /(\w+)\z/
|
@request.path_info =~ /(\w+)\z/
|
||||||
@action = $1 || 'index'
|
@action = Regexp.last_match(1) || 'index'
|
||||||
@assigns = send(@action) if respond_to?(@action)
|
@assigns = send(@action) if respond_to?(@action)
|
||||||
|
|
||||||
@response['Content-Type'] = "text/html"
|
@response['Content-Type'] = "text/html"
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'webrick'
|
require 'webrick'
|
||||||
require 'rexml/document'
|
require 'rexml/document'
|
||||||
|
|
||||||
@@ -8,5 +10,5 @@ require_relative 'example_servlet'
|
|||||||
# Setup webrick
|
# Setup webrick
|
||||||
server = WEBrick::HTTPServer.new(Port: ARGV[1] || 3000)
|
server = WEBrick::HTTPServer.new(Port: ARGV[1] || 3000)
|
||||||
server.mount('/', Servlet)
|
server.mount('/', Servlet)
|
||||||
trap("INT"){ server.shutdown }
|
trap("INT") { server.shutdown }
|
||||||
server.start
|
server.start
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Copyright (c) 2005 Tobias Luetke
|
# Copyright (c) 2005 Tobias Luetke
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -21,10 +23,10 @@
|
|||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
FilterSeparator = /\|/
|
FilterSeparator = /\|/
|
||||||
ArgumentSeparator = ','.freeze
|
ArgumentSeparator = ','
|
||||||
FilterArgumentSeparator = ':'.freeze
|
FilterArgumentSeparator = ':'
|
||||||
VariableAttributeSeparator = '.'.freeze
|
VariableAttributeSeparator = '.'
|
||||||
WhitespaceControl = '-'.freeze
|
WhitespaceControl = '-'
|
||||||
TagStart = /\{\%/
|
TagStart = /\{\%/
|
||||||
TagEnd = /\%\}/
|
TagEnd = /\%\}/
|
||||||
VariableSignature = /\(?[\w\-\.\[\]]\)?/
|
VariableSignature = /\(?[\w\-\.\[\]]\)?/
|
||||||
@@ -76,7 +78,10 @@ require 'liquid/tokenizer'
|
|||||||
require 'liquid/parse_context'
|
require 'liquid/parse_context'
|
||||||
require 'liquid/partial_cache'
|
require 'liquid/partial_cache'
|
||||||
require 'liquid/usage'
|
require 'liquid/usage'
|
||||||
|
require 'liquid/register'
|
||||||
|
require 'liquid/static_registers'
|
||||||
|
|
||||||
# Load all the tags of the standard library
|
# Load all the tags of the standard library
|
||||||
#
|
#
|
||||||
Dir["#{__dir__}/liquid/tags/*.rb"].each { |f| require f }
|
Dir["#{__dir__}/liquid/tags/*.rb"].each { |f| require f }
|
||||||
|
Dir["#{__dir__}/liquid/registers/*.rb"].each { |f| require f }
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Block < Tag
|
class Block < Tag
|
||||||
MAX_DEPTH = 100
|
MAX_DEPTH = 100
|
||||||
@@ -27,16 +29,16 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def unknown_tag(tag, _params, _tokens)
|
def unknown_tag(tag, _params, _tokens)
|
||||||
if tag == 'else'.freeze
|
if tag == 'else'
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.unexpected_else".freeze,
|
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_else",
|
||||||
block_name: block_name))
|
block_name: block_name)
|
||||||
elsif tag.start_with?('end'.freeze)
|
elsif tag.start_with?('end')
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.invalid_delimiter".freeze,
|
raise SyntaxError, parse_context.locale.t("errors.syntax.invalid_delimiter",
|
||||||
tag: tag,
|
tag: tag,
|
||||||
block_name: block_name,
|
block_name: block_name,
|
||||||
block_delimiter: block_delimiter))
|
block_delimiter: block_delimiter)
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.unknown_tag".freeze, tag: tag))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ module Liquid
|
|||||||
|
|
||||||
def parse_body(body, tokens)
|
def parse_body(body, tokens)
|
||||||
if parse_context.depth >= MAX_DEPTH
|
if parse_context.depth >= MAX_DEPTH
|
||||||
raise StackLevelError, "Nesting too deep".freeze
|
raise StackLevelError, "Nesting too deep"
|
||||||
end
|
end
|
||||||
parse_context.depth += 1
|
parse_context.depth += 1
|
||||||
begin
|
begin
|
||||||
@@ -61,7 +63,7 @@ module Liquid
|
|||||||
|
|
||||||
return false if end_tag_name == block_delimiter
|
return false if end_tag_name == block_delimiter
|
||||||
unless end_tag_name
|
unless end_tag_name
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_never_closed".freeze, block_name: block_name))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed", block_name: block_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# this tag is not registered with the system
|
# this tag is not registered with the system
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class BlockBody
|
class BlockBody
|
||||||
LiquidTagToken = /\A\s*(\w+)\s*(.*?)\z/o
|
LiquidTagToken = /\A\s*(\w+)\s*(.*?)\z/o
|
||||||
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
|
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
|
||||||
ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om
|
ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om
|
||||||
WhitespaceOrNothing = /\A\s*\z/
|
WhitespaceOrNothing = /\A\s*\z/
|
||||||
TAGSTART = "{%".freeze
|
TAGSTART = "{%"
|
||||||
VARSTART = "{{".freeze
|
VARSTART = "{{"
|
||||||
|
|
||||||
attr_reader :nodelist
|
attr_reader :nodelist
|
||||||
|
|
||||||
@@ -25,16 +27,16 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
private def parse_for_liquid_tag(tokenizer, parse_context)
|
private def parse_for_liquid_tag(tokenizer, parse_context)
|
||||||
while token = tokenizer.shift
|
while (token = tokenizer.shift)
|
||||||
unless token.empty? || token =~ WhitespaceOrNothing
|
unless token.empty? || token =~ WhitespaceOrNothing
|
||||||
unless token =~ LiquidTagToken
|
unless token =~ LiquidTagToken
|
||||||
# line isn't empty but didn't match tag syntax, yield and let the
|
# line isn't empty but didn't match tag syntax, yield and let the
|
||||||
# caller raise a syntax error
|
# caller raise a syntax error
|
||||||
return yield token, token
|
return yield token, token
|
||||||
end
|
end
|
||||||
tag_name = $1
|
tag_name = Regexp.last_match(1)
|
||||||
markup = $2
|
markup = Regexp.last_match(2)
|
||||||
unless tag = registered_tags[tag_name]
|
unless (tag = registered_tags[tag_name])
|
||||||
# end parsing if we reach an unknown tag and let the caller decide
|
# end parsing if we reach an unknown tag and let the caller decide
|
||||||
# determine how to proceed
|
# determine how to proceed
|
||||||
return yield tag_name, markup
|
return yield tag_name, markup
|
||||||
@@ -50,7 +52,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
private def parse_for_document(tokenizer, parse_context, &block)
|
private def parse_for_document(tokenizer, parse_context, &block)
|
||||||
while token = tokenizer.shift
|
while (token = tokenizer.shift)
|
||||||
next if token.empty?
|
next if token.empty?
|
||||||
case
|
case
|
||||||
when token.start_with?(TAGSTART)
|
when token.start_with?(TAGSTART)
|
||||||
@@ -58,21 +60,21 @@ module Liquid
|
|||||||
unless token =~ FullToken
|
unless token =~ FullToken
|
||||||
raise_missing_tag_terminator(token, parse_context)
|
raise_missing_tag_terminator(token, parse_context)
|
||||||
end
|
end
|
||||||
tag_name = $2
|
tag_name = Regexp.last_match(2)
|
||||||
markup = $4
|
markup = Regexp.last_match(4)
|
||||||
|
|
||||||
if parse_context.line_number
|
if parse_context.line_number
|
||||||
# newlines inside the tag should increase the line number,
|
# newlines inside the tag should increase the line number,
|
||||||
# particularly important for multiline {% liquid %} tags
|
# particularly important for multiline {% liquid %} tags
|
||||||
parse_context.line_number += $1.count("\n".freeze) + $3.count("\n".freeze)
|
parse_context.line_number += Regexp.last_match(1).count("\n") + Regexp.last_match(3).count("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
if tag_name == 'liquid'.freeze
|
if tag_name == 'liquid'
|
||||||
liquid_tag_tokenizer = Tokenizer.new(markup, line_number: parse_context.line_number, for_liquid_tag: true)
|
liquid_tag_tokenizer = Tokenizer.new(markup, line_number: parse_context.line_number, for_liquid_tag: true)
|
||||||
next parse_for_liquid_tag(liquid_tag_tokenizer, parse_context, &block)
|
next parse_for_liquid_tag(liquid_tag_tokenizer, parse_context, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
unless tag = registered_tags[tag_name]
|
unless (tag = registered_tags[tag_name])
|
||||||
# end parsing if we reach an unknown tag and let the caller decide
|
# end parsing if we reach an unknown tag and let the caller decide
|
||||||
# determine how to proceed
|
# determine how to proceed
|
||||||
return yield tag_name, markup
|
return yield tag_name, markup
|
||||||
@@ -101,7 +103,7 @@ module Liquid
|
|||||||
def whitespace_handler(token, parse_context)
|
def whitespace_handler(token, parse_context)
|
||||||
if token[2] == WhitespaceControl
|
if token[2] == WhitespaceControl
|
||||||
previous_token = @nodelist.last
|
previous_token = @nodelist.last
|
||||||
if previous_token.is_a? String
|
if previous_token.is_a?(String)
|
||||||
previous_token.rstrip!
|
previous_token.rstrip!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -113,14 +115,14 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
render_to_output_buffer(context, '')
|
render_to_output_buffer(context, +'')
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
context.resource_limits.render_score += @nodelist.length
|
context.resource_limits.render_score += @nodelist.length
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
while node = @nodelist[idx]
|
while (node = @nodelist[idx])
|
||||||
previous_output_size = output.bytesize
|
previous_output_size = output.bytesize
|
||||||
|
|
||||||
case node
|
case node
|
||||||
@@ -129,7 +131,7 @@ module Liquid
|
|||||||
when Variable
|
when Variable
|
||||||
render_node(context, output, node)
|
render_node(context, output, node)
|
||||||
when Block
|
when Block
|
||||||
render_node(context, node.blank? ? '' : output, node)
|
render_node(context, node.blank? ? +'' : output, node)
|
||||||
break if context.interrupt? # might have happened in a for-block
|
break if context.interrupt? # might have happened in a for-block
|
||||||
when Continue, Break
|
when Continue, Break
|
||||||
# If we get an Interrupt that means the block must stop processing. An
|
# If we get an Interrupt that means the block must stop processing. An
|
||||||
@@ -152,7 +154,13 @@ module Liquid
|
|||||||
private
|
private
|
||||||
|
|
||||||
def render_node(context, output, node)
|
def render_node(context, output, node)
|
||||||
node.render_to_output_buffer(context, output)
|
if node.disabled?(context)
|
||||||
|
output << node.disabled_error_message
|
||||||
|
return
|
||||||
|
end
|
||||||
|
disable_tags(context, node.disabled_tags) do
|
||||||
|
node.render_to_output_buffer(context, output)
|
||||||
|
end
|
||||||
rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e
|
rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e
|
||||||
context.handle_error(e, node.line_number)
|
context.handle_error(e, node.line_number)
|
||||||
rescue ::StandardError => e
|
rescue ::StandardError => e
|
||||||
@@ -160,10 +168,15 @@ module Liquid
|
|||||||
output << context.handle_error(e, line_number)
|
output << context.handle_error(e, line_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disable_tags(context, tags, &block)
|
||||||
|
return yield if tags.empty?
|
||||||
|
context.registers[:disabled_tags].disable(tags, &block)
|
||||||
|
end
|
||||||
|
|
||||||
def raise_if_resource_limits_reached(context, length)
|
def raise_if_resource_limits_reached(context, length)
|
||||||
context.resource_limits.render_length += length
|
context.resource_limits.render_length += length
|
||||||
return unless context.resource_limits.reached?
|
return unless context.resource_limits.reached?
|
||||||
raise MemoryError.new("Memory limits exceeded".freeze)
|
raise MemoryError, "Memory limits exceeded"
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_variable(token, parse_context)
|
def create_variable(token, parse_context)
|
||||||
@@ -175,11 +188,11 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def raise_missing_tag_terminator(token, parse_context)
|
def raise_missing_tag_terminator(token, parse_context)
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_termination".freeze, token: token, tag_end: TagEnd.inspect))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect)
|
||||||
end
|
end
|
||||||
|
|
||||||
def raise_missing_variable_terminator(token, parse_context)
|
def raise_missing_variable_terminator(token, parse_context)
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.variable_termination".freeze, token: token, tag_end: VariableEnd.inspect))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect)
|
||||||
end
|
end
|
||||||
|
|
||||||
def registered_tags
|
def registered_tags
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Container for liquid nodes which conveniently wraps decision making logic
|
# Container for liquid nodes which conveniently wraps decision making logic
|
||||||
#
|
#
|
||||||
@@ -8,21 +10,21 @@ module Liquid
|
|||||||
#
|
#
|
||||||
class Condition #:nodoc:
|
class Condition #:nodoc:
|
||||||
@@operators = {
|
@@operators = {
|
||||||
'=='.freeze => ->(cond, left, right) { cond.send(:equal_variables, left, right) },
|
'==' => ->(cond, left, right) { cond.send(:equal_variables, left, right) },
|
||||||
'!='.freeze => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
|
'!=' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
|
||||||
'<>'.freeze => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
|
'<>' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
|
||||||
'<'.freeze => :<,
|
'<' => :<,
|
||||||
'>'.freeze => :>,
|
'>' => :>,
|
||||||
'>='.freeze => :>=,
|
'>=' => :>=,
|
||||||
'<='.freeze => :<=,
|
'<=' => :<=,
|
||||||
'contains'.freeze => lambda do |cond, left, right|
|
'contains' => lambda do |_cond, left, right|
|
||||||
if left && right && left.respond_to?(:include?)
|
if left && right && left.respond_to?(:include?)
|
||||||
right = right.to_s if left.is_a?(String)
|
right = right.to_s if left.is_a?(String)
|
||||||
left.include?(right)
|
left.include?(right)
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
def self.operators
|
def self.operators
|
||||||
@@ -36,7 +38,7 @@ module Liquid
|
|||||||
@left = left
|
@left = left
|
||||||
@operator = operator
|
@operator = operator
|
||||||
@right = right
|
@right = right
|
||||||
@child_relation = nil
|
@child_relation = nil
|
||||||
@child_condition = nil
|
@child_condition = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
"#<Condition #{[@left, @operator, @right].compact.join(' '.freeze)}>"
|
"#<Condition #{[@left, @operator, @right].compact.join(' ')}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
@@ -116,7 +118,7 @@ module Liquid
|
|||||||
left = context.evaluate(left)
|
left = context.evaluate(left)
|
||||||
right = context.evaluate(right)
|
right = context.evaluate(right)
|
||||||
|
|
||||||
operation = self.class.operators[op] || raise(Liquid::ArgumentError.new("Unknown operator #{op}"))
|
operation = self.class.operators[op] || raise(Liquid::ArgumentError, "Unknown operator #{op}")
|
||||||
|
|
||||||
if operation.respond_to?(:call)
|
if operation.respond_to?(:call)
|
||||||
operation.call(self, left, right)
|
operation.call(self, left, right)
|
||||||
@@ -124,7 +126,7 @@ module Liquid
|
|||||||
begin
|
begin
|
||||||
left.send(operation, right)
|
left.send(operation, right)
|
||||||
rescue ::ArgumentError => e
|
rescue ::ArgumentError => e
|
||||||
raise Liquid::ArgumentError.new(e.message)
|
raise Liquid::ArgumentError, e.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Context keeps the variable stack and resolves variables, as well as keywords
|
# Context keeps the variable stack and resolves variables, as well as keywords
|
||||||
#
|
#
|
||||||
@@ -16,18 +18,17 @@ module Liquid
|
|||||||
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
||||||
|
|
||||||
# rubocop:disable Metrics/ParameterLists
|
# rubocop:disable Metrics/ParameterLists
|
||||||
def self.build(environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_registers: {}, static_environments: {})
|
def self.build(environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {})
|
||||||
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_registers, static_environments)
|
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_environments)
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_registers = {}, static_environments = {})
|
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {})
|
||||||
@environments = [environments]
|
@environments = [environments]
|
||||||
@environments.flatten!
|
@environments.flatten!
|
||||||
|
|
||||||
@static_environments = [static_environments].flat_map(&:freeze).freeze
|
@static_environments = [static_environments].flat_map(&:freeze).freeze
|
||||||
@scopes = [(outer_scope || {})]
|
@scopes = [(outer_scope || {})]
|
||||||
@registers = registers
|
@registers = registers
|
||||||
@static_registers = static_registers.freeze
|
|
||||||
@errors = []
|
@errors = []
|
||||||
@partial = false
|
@partial = false
|
||||||
@strict_variables = false
|
@strict_variables = false
|
||||||
@@ -35,11 +36,9 @@ module Liquid
|
|||||||
@base_scope_depth = 0
|
@base_scope_depth = 0
|
||||||
squash_instance_assigns_with_environments
|
squash_instance_assigns_with_environments
|
||||||
|
|
||||||
@this_stack_used = false
|
|
||||||
|
|
||||||
self.exception_renderer = Template.default_exception_renderer
|
self.exception_renderer = Template.default_exception_renderer
|
||||||
if rethrow_errors
|
if rethrow_errors
|
||||||
self.exception_renderer = ->(e) { raise }
|
self.exception_renderer = ->(_e) { raise }
|
||||||
end
|
end
|
||||||
|
|
||||||
@interrupts = []
|
@interrupts = []
|
||||||
@@ -122,19 +121,11 @@ module Liquid
|
|||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# context['var] #=> nil
|
# context['var] #=> nil
|
||||||
def stack(new_scope = nil)
|
def stack(new_scope = {})
|
||||||
old_stack_used = @this_stack_used
|
push(new_scope)
|
||||||
if new_scope
|
|
||||||
push(new_scope)
|
|
||||||
@this_stack_used = true
|
|
||||||
else
|
|
||||||
@this_stack_used = false
|
|
||||||
end
|
|
||||||
|
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
pop if @this_stack_used
|
pop
|
||||||
@this_stack_used = old_stack_used
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates a new context inheriting resource limits, filters, environment etc.,
|
# Creates a new context inheriting resource limits, filters, environment etc.,
|
||||||
@@ -145,7 +136,7 @@ module Liquid
|
|||||||
Context.build(
|
Context.build(
|
||||||
resource_limits: resource_limits,
|
resource_limits: resource_limits,
|
||||||
static_environments: static_environments,
|
static_environments: static_environments,
|
||||||
static_registers: static_registers
|
registers: StaticRegisters.new(registers)
|
||||||
).tap do |subcontext|
|
).tap do |subcontext|
|
||||||
subcontext.base_scope_depth = base_scope_depth + 1
|
subcontext.base_scope_depth = base_scope_depth + 1
|
||||||
subcontext.exception_renderer = exception_renderer
|
subcontext.exception_renderer = exception_renderer
|
||||||
@@ -162,10 +153,6 @@ module Liquid
|
|||||||
|
|
||||||
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
|
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
|
||||||
def []=(key, value)
|
def []=(key, value)
|
||||||
unless @this_stack_used
|
|
||||||
@this_stack_used = true
|
|
||||||
push({})
|
|
||||||
end
|
|
||||||
@scopes[0][key] = value
|
@scopes[0][key] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -215,7 +202,7 @@ module Liquid
|
|||||||
value = obj[key]
|
value = obj[key]
|
||||||
|
|
||||||
if value.is_a?(Proc) && obj.respond_to?(:[]=)
|
if value.is_a?(Proc) && obj.respond_to?(:[]=)
|
||||||
obj[key] = (value.arity == 0) ? value.call : value.call(self)
|
obj[key] = value.arity == 0 ? value.call : value.call(self)
|
||||||
else
|
else
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
@@ -246,7 +233,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_overflow
|
def check_overflow
|
||||||
raise StackLevelError, "Nesting too deep".freeze if overflow?
|
raise StackLevelError, "Nesting too deep" if overflow?
|
||||||
end
|
end
|
||||||
|
|
||||||
def overflow?
|
def overflow?
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Document < BlockBody
|
class Document < BlockBody
|
||||||
def self.parse(tokens, parse_context)
|
def self.parse(tokens, parse_context)
|
||||||
@@ -7,7 +9,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse(tokens, parse_context)
|
def parse(tokens, parse_context)
|
||||||
super do |end_tag_name, end_tag_params|
|
super do |end_tag_name, _end_tag_params|
|
||||||
unknown_tag(end_tag_name, parse_context) if end_tag_name
|
unknown_tag(end_tag_name, parse_context) if end_tag_name
|
||||||
end
|
end
|
||||||
rescue SyntaxError => e
|
rescue SyntaxError => e
|
||||||
@@ -17,10 +19,10 @@ module Liquid
|
|||||||
|
|
||||||
def unknown_tag(tag, parse_context)
|
def unknown_tag(tag, parse_context)
|
||||||
case tag
|
case tag
|
||||||
when 'else'.freeze, 'end'.freeze
|
when 'else', 'end'
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.unexpected_outer_tag".freeze, tag: tag))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_outer_tag", tag: tag)
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.unknown_tag".freeze, tag: tag))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'set'
|
require 'set'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
@@ -25,7 +27,7 @@ module Liquid
|
|||||||
|
|
||||||
# Catch all for the method
|
# Catch all for the method
|
||||||
def liquid_method_missing(method)
|
def liquid_method_missing(method)
|
||||||
return nil unless @context && @context.strict_variables
|
return nil unless @context&.strict_variables
|
||||||
raise Liquid::UndefinedDropMethod, "undefined method #{method}"
|
raise Liquid::UndefinedDropMethod, "undefined method #{method}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ module Liquid
|
|||||||
|
|
||||||
if include?(Enumerable)
|
if include?(Enumerable)
|
||||||
blacklist += Enumerable.public_instance_methods
|
blacklist += Enumerable.public_instance_methods
|
||||||
blacklist -= [:sort, :count, :first, :min, :max, :include?]
|
blacklist -= [:sort, :count, :first, :min, :max]
|
||||||
end
|
end
|
||||||
|
|
||||||
whitelist = [:to_liquid] + (public_instance_methods - blacklist)
|
whitelist = [:to_liquid] + (public_instance_methods - blacklist)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Error < ::StandardError
|
class Error < ::StandardError
|
||||||
attr_accessor :line_number
|
attr_accessor :line_number
|
||||||
@@ -5,7 +7,7 @@ module Liquid
|
|||||||
attr_accessor :markup_context
|
attr_accessor :markup_context
|
||||||
|
|
||||||
def to_s(with_prefix = true)
|
def to_s(with_prefix = true)
|
||||||
str = ""
|
str = +""
|
||||||
str << message_prefix if with_prefix
|
str << message_prefix if with_prefix
|
||||||
str << super()
|
str << super()
|
||||||
|
|
||||||
@@ -20,11 +22,11 @@ module Liquid
|
|||||||
private
|
private
|
||||||
|
|
||||||
def message_prefix
|
def message_prefix
|
||||||
str = ""
|
str = +""
|
||||||
if is_a?(SyntaxError)
|
str << if is_a?(SyntaxError)
|
||||||
str << "Liquid syntax error"
|
"Liquid syntax error"
|
||||||
else
|
else
|
||||||
str << "Liquid error"
|
"Liquid error"
|
||||||
end
|
end
|
||||||
|
|
||||||
if line_number
|
if line_number
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Expression
|
class Expression
|
||||||
class MethodLiteral
|
class MethodLiteral
|
||||||
@@ -14,11 +16,11 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
LITERALS = {
|
LITERALS = {
|
||||||
nil => nil, 'nil'.freeze => nil, 'null'.freeze => nil, ''.freeze => nil,
|
nil => nil, 'nil' => nil, 'null' => nil, '' => nil,
|
||||||
'true'.freeze => true,
|
'true' => true,
|
||||||
'false'.freeze => false,
|
'false' => false,
|
||||||
'blank'.freeze => MethodLiteral.new(:blank?, '').freeze,
|
'blank' => MethodLiteral.new(:blank?, '').freeze,
|
||||||
'empty'.freeze => MethodLiteral.new(:empty?, '').freeze
|
'empty' => MethodLiteral.new(:empty?, '').freeze
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
SINGLE_QUOTED_STRING = /\A'(.*)'\z/m
|
SINGLE_QUOTED_STRING = /\A'(.*)'\z/m
|
||||||
@@ -33,13 +35,13 @@ module Liquid
|
|||||||
else
|
else
|
||||||
case markup
|
case markup
|
||||||
when SINGLE_QUOTED_STRING, DOUBLE_QUOTED_STRING
|
when SINGLE_QUOTED_STRING, DOUBLE_QUOTED_STRING
|
||||||
$1
|
Regexp.last_match(1)
|
||||||
when INTEGERS_REGEX
|
when INTEGERS_REGEX
|
||||||
$1.to_i
|
Regexp.last_match(1).to_i
|
||||||
when RANGES_REGEX
|
when RANGES_REGEX
|
||||||
RangeLookup.parse($1, $2)
|
RangeLookup.parse(Regexp.last_match(1), Regexp.last_match(2))
|
||||||
when FLOATS_REGEX
|
when FLOATS_REGEX
|
||||||
$1.to_f
|
Regexp.last_match(1).to_f
|
||||||
else
|
else
|
||||||
VariableLookup.parse(markup)
|
VariableLookup.parse(markup)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'time'
|
require 'time'
|
||||||
require 'date'
|
require 'date'
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# A Liquid file system is a way to let your templates retrieve other templates for use with the include tag.
|
# A Liquid file system is a way to let your templates retrieve other templates for use with the include tag.
|
||||||
#
|
#
|
||||||
@@ -44,7 +46,7 @@ module Liquid
|
|||||||
class LocalFileSystem
|
class LocalFileSystem
|
||||||
attr_accessor :root
|
attr_accessor :root
|
||||||
|
|
||||||
def initialize(root, pattern = "_%s.liquid".freeze)
|
def initialize(root, pattern = "_%s.liquid")
|
||||||
@root = root
|
@root = root
|
||||||
@pattern = pattern
|
@pattern = pattern
|
||||||
end
|
end
|
||||||
@@ -57,9 +59,9 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def full_path(template_path)
|
def full_path(template_path)
|
||||||
raise FileSystemError, "Illegal template name '#{template_path}'" unless template_path =~ /\A[^.\/][a-zA-Z0-9_\/]+\z/
|
raise FileSystemError, "Illegal template name '#{template_path}'" unless %r{\A[^./][a-zA-Z0-9_/]+\z}.match?(template_path)
|
||||||
|
|
||||||
full_path = if template_path.include?('/'.freeze)
|
full_path = if template_path.include?('/')
|
||||||
File.join(root, File.dirname(template_path), @pattern % File.basename(template_path))
|
File.join(root, File.dirname(template_path), @pattern % File.basename(template_path))
|
||||||
else
|
else
|
||||||
File.join(root, @pattern % template_path)
|
File.join(root, @pattern % template_path)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class ForloopDrop < Drop
|
class ForloopDrop < Drop
|
||||||
def initialize(name, length, parentloop)
|
def initialize(name, length, parentloop)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
@@ -26,13 +28,13 @@ module Liquid
|
|||||||
def interpolate(name, vars)
|
def interpolate(name, vars)
|
||||||
name.gsub(/%\{(\w+)\}/) do
|
name.gsub(/%\{(\w+)\}/) do
|
||||||
# raise TranslationError, "Undefined key #{$1} for interpolation in translation #{name}" unless vars[$1.to_sym]
|
# raise TranslationError, "Undefined key #{$1} for interpolation in translation #{name}" unless vars[$1.to_sym]
|
||||||
(vars[$1.to_sym]).to_s
|
(vars[Regexp.last_match(1).to_sym]).to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def deep_fetch_translation(name)
|
def deep_fetch_translation(name)
|
||||||
name.split('.'.freeze).reduce(locale) do |level, cur|
|
name.split('.').reduce(locale) do |level, cur|
|
||||||
level[cur] or raise TranslationError, "Translation for #{name} does not exist in locale #{path}"
|
level[cur] || raise(TranslationError, "Translation for #{name} does not exist in locale #{path}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# An interrupt is any command that breaks processing of a block (ex: a for loop).
|
# An interrupt is any command that breaks processing of a block (ex: a for loop).
|
||||||
class Interrupt
|
class Interrupt
|
||||||
attr_reader :message
|
attr_reader :message
|
||||||
|
|
||||||
def initialize(message = nil)
|
def initialize(message = nil)
|
||||||
@message = message || "interrupt".freeze
|
@message = message || "interrupt"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "strscan"
|
require "strscan"
|
||||||
module Liquid
|
module Liquid
|
||||||
class Lexer
|
class Lexer
|
||||||
SPECIALS = {
|
SPECIALS = {
|
||||||
'|'.freeze => :pipe,
|
'|' => :pipe,
|
||||||
'.'.freeze => :dot,
|
'.' => :dot,
|
||||||
':'.freeze => :colon,
|
':' => :colon,
|
||||||
','.freeze => :comma,
|
',' => :comma,
|
||||||
'['.freeze => :open_square,
|
'[' => :open_square,
|
||||||
']'.freeze => :close_square,
|
']' => :close_square,
|
||||||
'('.freeze => :open_round,
|
'(' => :open_round,
|
||||||
')'.freeze => :close_round,
|
')' => :close_round,
|
||||||
'?'.freeze => :question,
|
'?' => :question,
|
||||||
'-'.freeze => :dash
|
'-' => :dash,
|
||||||
}.freeze
|
}.freeze
|
||||||
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
|
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
|
||||||
SINGLE_STRING_LITERAL = /'[^\']*'/
|
SINGLE_STRING_LITERAL = /'[^\']*'/
|
||||||
@@ -31,16 +33,21 @@ module Liquid
|
|||||||
until @ss.eos?
|
until @ss.eos?
|
||||||
@ss.skip(WHITESPACE_OR_NOTHING)
|
@ss.skip(WHITESPACE_OR_NOTHING)
|
||||||
break if @ss.eos?
|
break if @ss.eos?
|
||||||
tok = case
|
tok = if (t = @ss.scan(COMPARISON_OPERATOR))
|
||||||
when t = @ss.scan(COMPARISON_OPERATOR) then [:comparison, t]
|
[:comparison, t]
|
||||||
when t = @ss.scan(SINGLE_STRING_LITERAL) then [:string, t]
|
elsif (t = @ss.scan(SINGLE_STRING_LITERAL))
|
||||||
when t = @ss.scan(DOUBLE_STRING_LITERAL) then [:string, t]
|
[:string, t]
|
||||||
when t = @ss.scan(NUMBER_LITERAL) then [:number, t]
|
elsif (t = @ss.scan(DOUBLE_STRING_LITERAL))
|
||||||
when t = @ss.scan(IDENTIFIER) then [:id, t]
|
[:string, t]
|
||||||
when t = @ss.scan(DOTDOT) then [:dotdot, t]
|
elsif (t = @ss.scan(NUMBER_LITERAL))
|
||||||
|
[:number, t]
|
||||||
|
elsif (t = @ss.scan(IDENTIFIER))
|
||||||
|
[:id, t]
|
||||||
|
elsif (t = @ss.scan(DOTDOT))
|
||||||
|
[:dotdot, t]
|
||||||
else
|
else
|
||||||
c = @ss.getch
|
c = @ss.getch
|
||||||
if s = SPECIALS[c]
|
if (s = SPECIALS[c])
|
||||||
[s, c]
|
[s, c]
|
||||||
else
|
else
|
||||||
raise SyntaxError, "Unexpected character #{c}"
|
raise SyntaxError, "Unexpected character #{c}"
|
||||||
|
|||||||
@@ -25,3 +25,5 @@
|
|||||||
render: "Syntax error in tag 'render' - Template name must be a quoted string"
|
render: "Syntax error in tag 'render' - Template name must be a quoted string"
|
||||||
argument:
|
argument:
|
||||||
include: "Argument error in tag 'include' - Illegal template name"
|
include: "Argument error in tag 'include' - Illegal template name"
|
||||||
|
disabled:
|
||||||
|
tag: "usage is not allowed in this context"
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class ParseContext
|
class ParseContext
|
||||||
attr_accessor :locale, :line_number, :trim_whitespace, :depth
|
attr_accessor :locale, :line_number, :trim_whitespace, :depth
|
||||||
@@ -19,7 +21,6 @@ module Liquid
|
|||||||
@partial = value
|
@partial = value
|
||||||
@options = value ? partial_options : @template_options
|
@options = value ? partial_options : @template_options
|
||||||
@error_mode = @options[:error_mode] || Template.error_mode
|
@error_mode = @options[:error_mode] || Template.error_mode
|
||||||
value
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def partial_options
|
def partial_options
|
||||||
@@ -28,7 +29,7 @@ module Liquid
|
|||||||
if dont_pass == true
|
if dont_pass == true
|
||||||
{ locale: locale }
|
{ locale: locale }
|
||||||
elsif dont_pass.is_a?(Array)
|
elsif dont_pass.is_a?(Array)
|
||||||
@template_options.reject { |k, v| dont_pass.include?(k) }
|
@template_options.reject { |k, _v| dont_pass.include?(k) }
|
||||||
else
|
else
|
||||||
@template_options
|
@template_options
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ module Liquid
|
|||||||
item, new_context = @callbacks[node.class].call(node, context)
|
item, new_context = @callbacks[node.class].call(node, context)
|
||||||
[
|
[
|
||||||
item,
|
item,
|
||||||
ParseTreeVisitor.for(node, @callbacks).visit(new_context || context)
|
ParseTreeVisitor.for(node, @callbacks).visit(new_context || context),
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Parser
|
class Parser
|
||||||
def initialize(input)
|
def initialize(input)
|
||||||
@@ -51,7 +53,7 @@ module Liquid
|
|||||||
token = @tokens[@p]
|
token = @tokens[@p]
|
||||||
if token[0] == :id
|
if token[0] == :id
|
||||||
variable_signature
|
variable_signature
|
||||||
elsif SINGLE_TOKEN_EXPRESSION_TYPES.include? token[0]
|
elsif SINGLE_TOKEN_EXPRESSION_TYPES.include?(token[0])
|
||||||
consume
|
consume
|
||||||
elsif token.first == :open_round
|
elsif token.first == :open_round
|
||||||
consume
|
consume
|
||||||
@@ -66,10 +68,10 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def argument
|
def argument
|
||||||
str = ""
|
str = +""
|
||||||
# might be a keyword argument (identifier: expression)
|
# might be a keyword argument (identifier: expression)
|
||||||
if look(:id) && look(:colon, 1)
|
if look(:id) && look(:colon, 1)
|
||||||
str << consume << consume << ' '.freeze
|
str << consume << consume << ' '
|
||||||
end
|
end
|
||||||
|
|
||||||
str << expression
|
str << expression
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
module ParserSwitching
|
module ParserSwitching
|
||||||
def parse_with_selected_parser(markup)
|
def parse_with_selected_parser(markup)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class PartialCache
|
class PartialCache
|
||||||
def self.load(template_name, context:, parse_context:)
|
def self.load(template_name, context:, parse_context:)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'liquid/profiler/hooks'
|
require 'liquid/profiler/hooks'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class BlockBody
|
class BlockBody
|
||||||
def render_node_with_profiling(context, output, node)
|
def render_node_with_profiling(context, output, node)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class RangeLookup
|
class RangeLookup
|
||||||
def self.parse(start_markup, end_markup)
|
def self.parse(start_markup, end_markup)
|
||||||
|
|||||||
6
lib/liquid/register.rb
Normal file
6
lib/liquid/register.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Liquid
|
||||||
|
class Register
|
||||||
|
end
|
||||||
|
end
|
||||||
32
lib/liquid/registers/disabled_tags.rb
Normal file
32
lib/liquid/registers/disabled_tags.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Liquid
|
||||||
|
class DisabledTags < Register
|
||||||
|
def initialize
|
||||||
|
@disabled_tags = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def disabled?(tag)
|
||||||
|
@disabled_tags.key?(tag) && @disabled_tags[tag] > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable(tags)
|
||||||
|
tags.each(&method(:increment))
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
tags.each(&method(:decrement))
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def increment(tag)
|
||||||
|
@disabled_tags[tag] ||= 0
|
||||||
|
@disabled_tags[tag] += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def decrement(tag)
|
||||||
|
@disabled_tags[tag] -= 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Template.add_register(:disabled_tags, DisabledTags.new)
|
||||||
|
end
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class ResourceLimits
|
class ResourceLimits
|
||||||
attr_accessor :render_length, :render_score, :assign_score,
|
attr_accessor :render_length, :render_score, :assign_score,
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'cgi'
|
require 'cgi'
|
||||||
require 'bigdecimal'
|
require 'bigdecimal'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
module StandardFilters
|
module StandardFilters
|
||||||
HTML_ESCAPE = {
|
HTML_ESCAPE = {
|
||||||
'&'.freeze => '&'.freeze,
|
'&' => '&',
|
||||||
'>'.freeze => '>'.freeze,
|
'>' => '>',
|
||||||
'<'.freeze => '<'.freeze,
|
'<' => '<',
|
||||||
'"'.freeze => '"'.freeze,
|
'"' => '"',
|
||||||
"'".freeze => '''.freeze
|
"'" => ''',
|
||||||
}.freeze
|
}.freeze
|
||||||
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
|
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
|
||||||
STRIP_HTML_BLOCKS = Regexp.union(
|
STRIP_HTML_BLOCKS = Regexp.union(
|
||||||
/<script.*?<\/script>/m,
|
%r{<script.*?</script>}m,
|
||||||
/<!--.*?-->/m,
|
/<!--.*?-->/m,
|
||||||
/<style.*?<\/style>/m
|
%r{<style.*?</style>}m
|
||||||
)
|
)
|
||||||
STRIP_HTML_TAGS = /<.*?>/m
|
STRIP_HTML_TAGS = /<.*?>/m
|
||||||
|
|
||||||
@@ -72,7 +74,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Truncate a string down to x characters
|
# Truncate a string down to x characters
|
||||||
def truncate(input, length = 50, truncate_string = "...".freeze)
|
def truncate(input, length = 50, truncate_string = "...")
|
||||||
return if input.nil?
|
return if input.nil?
|
||||||
input_str = input.to_s
|
input_str = input.to_s
|
||||||
length = Utils.to_integer(length)
|
length = Utils.to_integer(length)
|
||||||
@@ -82,13 +84,13 @@ module Liquid
|
|||||||
input_str.length > length ? input_str[0...l].concat(truncate_string_str) : input_str
|
input_str.length > length ? input_str[0...l].concat(truncate_string_str) : input_str
|
||||||
end
|
end
|
||||||
|
|
||||||
def truncatewords(input, words = 15, truncate_string = "...".freeze)
|
def truncatewords(input, words = 15, truncate_string = "...")
|
||||||
return if input.nil?
|
return if input.nil?
|
||||||
wordlist = input.to_s.split
|
wordlist = input.to_s.split
|
||||||
words = Utils.to_integer(words)
|
words = Utils.to_integer(words)
|
||||||
l = words - 1
|
l = words - 1
|
||||||
l = 0 if l < 0
|
l = 0 if l < 0
|
||||||
wordlist.length > l ? wordlist[0..l].join(" ".freeze).concat(truncate_string.to_s) : input
|
wordlist.length > l ? wordlist[0..l].join(" ").concat(truncate_string.to_s) : input
|
||||||
end
|
end
|
||||||
|
|
||||||
# Split input string into an array of substrings separated by given pattern.
|
# Split input string into an array of substrings separated by given pattern.
|
||||||
@@ -113,7 +115,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def strip_html(input)
|
def strip_html(input)
|
||||||
empty = ''.freeze
|
empty = ''
|
||||||
result = input.to_s.gsub(STRIP_HTML_BLOCKS, empty)
|
result = input.to_s.gsub(STRIP_HTML_BLOCKS, empty)
|
||||||
result.gsub!(STRIP_HTML_TAGS, empty)
|
result.gsub!(STRIP_HTML_TAGS, empty)
|
||||||
result
|
result
|
||||||
@@ -121,11 +123,11 @@ module Liquid
|
|||||||
|
|
||||||
# Remove all newlines from the string
|
# Remove all newlines from the string
|
||||||
def strip_newlines(input)
|
def strip_newlines(input)
|
||||||
input.to_s.gsub(/\r?\n/, ''.freeze)
|
input.to_s.gsub(/\r?\n/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Join elements of the array with certain character between them
|
# Join elements of the array with certain character between them
|
||||||
def join(input, glue = ' '.freeze)
|
def join(input, glue = ' ')
|
||||||
InputIterator.new(input).join(glue)
|
InputIterator.new(input).join(glue)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -191,6 +193,23 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sort elements of an array in numeric order
|
||||||
|
# provide optional property with which to sort an array of hashes or drops
|
||||||
|
def sort_numeric(input, property = nil)
|
||||||
|
ary = InputIterator.new(input)
|
||||||
|
if property.nil?
|
||||||
|
ary.sort do |a, b|
|
||||||
|
Utils.to_number(a) <=> Utils.to_number(b)
|
||||||
|
end
|
||||||
|
elsif ary.empty? # The next two cases assume a non-empty array.
|
||||||
|
[]
|
||||||
|
elsif ary.first.respond_to?(:[]) && !ary.first[property].nil?
|
||||||
|
ary.sort do |a, b|
|
||||||
|
Utils.to_number(a[property]) <=> Utils.to_number(b[property])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Remove duplicate elements from an array
|
# Remove duplicate elements from an array
|
||||||
# provide optional property with which to determine uniqueness
|
# provide optional property with which to determine uniqueness
|
||||||
def uniq(input, property = nil)
|
def uniq(input, property = nil)
|
||||||
@@ -220,7 +239,7 @@ module Liquid
|
|||||||
InputIterator.new(input).map do |e|
|
InputIterator.new(input).map do |e|
|
||||||
e = e.call if e.is_a?(Proc)
|
e = e.call if e.is_a?(Proc)
|
||||||
|
|
||||||
if property == "to_liquid".freeze
|
if property == "to_liquid"
|
||||||
e
|
e
|
||||||
elsif e.respond_to?(:[])
|
elsif e.respond_to?(:[])
|
||||||
r = e[property]
|
r = e[property]
|
||||||
@@ -250,23 +269,23 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Replace occurrences of a string with another
|
# Replace occurrences of a string with another
|
||||||
def replace(input, string, replacement = ''.freeze)
|
def replace(input, string, replacement = '')
|
||||||
input.to_s.gsub(string.to_s, replacement.to_s)
|
input.to_s.gsub(string.to_s, replacement.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Replace the first occurrences of a string with another
|
# Replace the first occurrences of a string with another
|
||||||
def replace_first(input, string, replacement = ''.freeze)
|
def replace_first(input, string, replacement = '')
|
||||||
input.to_s.sub(string.to_s, replacement.to_s)
|
input.to_s.sub(string.to_s, replacement.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
# remove a substring
|
# remove a substring
|
||||||
def remove(input, string)
|
def remove(input, string)
|
||||||
input.to_s.gsub(string.to_s, ''.freeze)
|
input.to_s.gsub(string.to_s, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
# remove the first occurrences of a substring
|
# remove the first occurrences of a substring
|
||||||
def remove_first(input, string)
|
def remove_first(input, string)
|
||||||
input.to_s.sub(string.to_s, ''.freeze)
|
input.to_s.sub(string.to_s, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
# add one string to another
|
# add one string to another
|
||||||
@@ -276,7 +295,7 @@ module Liquid
|
|||||||
|
|
||||||
def concat(input, array)
|
def concat(input, array)
|
||||||
unless array.respond_to?(:to_ary)
|
unless array.respond_to?(:to_ary)
|
||||||
raise ArgumentError.new("concat filter requires an array argument")
|
raise ArgumentError, "concat filter requires an array argument"
|
||||||
end
|
end
|
||||||
InputIterator.new(input).concat(array)
|
InputIterator.new(input).concat(array)
|
||||||
end
|
end
|
||||||
@@ -288,7 +307,7 @@ module Liquid
|
|||||||
|
|
||||||
# Add <br /> tags in front of all newlines in input string
|
# Add <br /> tags in front of all newlines in input string
|
||||||
def newline_to_br(input)
|
def newline_to_br(input)
|
||||||
input.to_s.gsub(/\n/, "<br />\n".freeze)
|
input.to_s.gsub(/\n/, "<br />\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reformat a date using Ruby's core Time#strftime( string ) -> string
|
# Reformat a date using Ruby's core Time#strftime( string ) -> string
|
||||||
@@ -325,7 +344,7 @@ module Liquid
|
|||||||
def date(input, format)
|
def date(input, format)
|
||||||
return input if format.to_s.empty?
|
return input if format.to_s.empty?
|
||||||
|
|
||||||
return input unless date = Utils.to_date(input)
|
return input unless (date = Utils.to_date(input))
|
||||||
|
|
||||||
date.strftime(format.to_s)
|
date.strftime(format.to_s)
|
||||||
end
|
end
|
||||||
@@ -419,7 +438,7 @@ module Liquid
|
|||||||
result.is_a?(BigDecimal) ? result.to_f : result
|
result.is_a?(BigDecimal) ? result.to_f : result
|
||||||
end
|
end
|
||||||
|
|
||||||
def default(input, default_value = ''.freeze)
|
def default(input, default_value = '')
|
||||||
if !input || input.respond_to?(:empty?) && input.empty?
|
if !input || input.respond_to?(:empty?) && input.empty?
|
||||||
Usage.increment("default_filter_received_false_value") if input == false # See https://github.com/Shopify/liquid/issues/1127
|
Usage.increment("default_filter_received_false_value") if input == false # See https://github.com/Shopify/liquid/issues/1127
|
||||||
default_value
|
default_value
|
||||||
@@ -431,7 +450,7 @@ module Liquid
|
|||||||
private
|
private
|
||||||
|
|
||||||
def raise_property_error(property)
|
def raise_property_error(property)
|
||||||
raise Liquid::ArgumentError.new("cannot select the property '#{property}'")
|
raise Liquid::ArgumentError, "cannot select the property '#{property}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
def apply_operation(input, operand, operation)
|
def apply_operation(input, operand, operation)
|
||||||
|
|||||||
36
lib/liquid/static_registers.rb
Normal file
36
lib/liquid/static_registers.rb
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Liquid
|
||||||
|
class StaticRegisters
|
||||||
|
attr_reader :static, :registers
|
||||||
|
|
||||||
|
def initialize(registers = {})
|
||||||
|
@static = registers.is_a?(StaticRegisters) ? registers.static : registers
|
||||||
|
@registers = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def []=(key, value)
|
||||||
|
@registers[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def [](key)
|
||||||
|
if @registers.key?(key)
|
||||||
|
@registers[key]
|
||||||
|
else
|
||||||
|
@static[key]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(key)
|
||||||
|
@registers.delete(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch(key, default = nil)
|
||||||
|
key?(key) ? self[key] : default
|
||||||
|
end
|
||||||
|
|
||||||
|
def key?(key)
|
||||||
|
@registers.key?(key) || @static.key?(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'set'
|
require 'set'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
@@ -27,7 +29,7 @@ module Liquid
|
|||||||
|
|
||||||
def self.add_filter(filter)
|
def self.add_filter(filter)
|
||||||
raise ArgumentError, "Expected module but got: #{filter.class}" unless filter.is_a?(Module)
|
raise ArgumentError, "Expected module but got: #{filter.class}" unless filter.is_a?(Module)
|
||||||
unless self.include?(filter)
|
unless include?(filter)
|
||||||
invokable_non_public_methods = (filter.private_instance_methods + filter.protected_instance_methods).select { |m| invokable?(m) }
|
invokable_non_public_methods = (filter.private_instance_methods + filter.protected_instance_methods).select { |m| invokable?(m) }
|
||||||
if invokable_non_public_methods.any?
|
if invokable_non_public_methods.any?
|
||||||
raise MethodOverrideError, "Filter overrides registered public methods as non public: #{invokable_non_public_methods.join(', ')}"
|
raise MethodOverrideError, "Filter overrides registered public methods as non public: #{invokable_non_public_methods.join(', ')}"
|
||||||
@@ -54,7 +56,7 @@ module Liquid
|
|||||||
def invoke(method, *args)
|
def invoke(method, *args)
|
||||||
if self.class.invokable?(method)
|
if self.class.invokable?(method)
|
||||||
send(method, *args)
|
send(method, *args)
|
||||||
elsif @context && @context.strict_filters
|
elsif @context&.strict_filters
|
||||||
raise Liquid::UndefinedFilter, "undefined filter #{method}"
|
raise Liquid::UndefinedFilter, "undefined filter #{method}"
|
||||||
else
|
else
|
||||||
args.first
|
args.first
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class TablerowloopDrop < Drop
|
class TablerowloopDrop < Drop
|
||||||
def initialize(length, cols)
|
def initialize(length, cols)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Tag
|
class Tag
|
||||||
attr_reader :nodelist, :tag_name, :line_number, :parse_context
|
attr_reader :nodelist, :tag_name, :line_number, :parse_context
|
||||||
@@ -11,7 +13,15 @@ module Liquid
|
|||||||
tag
|
tag
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disable_tags(*tags)
|
||||||
|
disabled_tags.push(*tags)
|
||||||
|
end
|
||||||
|
|
||||||
private :new
|
private :new
|
||||||
|
|
||||||
|
def disabled_tags
|
||||||
|
@disabled_tags ||= []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(tag_name, markup, parse_context)
|
def initialize(tag_name, markup, parse_context)
|
||||||
@@ -33,7 +43,15 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render(_context)
|
def render(_context)
|
||||||
''.freeze
|
''
|
||||||
|
end
|
||||||
|
|
||||||
|
def disabled?(context)
|
||||||
|
context.registers[:disabled_tags].disabled?(tag_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def disabled_error_message
|
||||||
|
"#{tag_name} #{options[:locale].t('errors.disabled.tag')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# For backwards compatibility with custom tags. In a future release, the semantics
|
# For backwards compatibility with custom tags. In a future release, the semantics
|
||||||
@@ -47,5 +65,9 @@ module Liquid
|
|||||||
def blank?
|
def blank?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disabled_tags
|
||||||
|
self.class.disabled_tags
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Assign sets a variable in your template.
|
# Assign sets a variable in your template.
|
||||||
#
|
#
|
||||||
@@ -11,7 +13,7 @@ module Liquid
|
|||||||
Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/om
|
Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/om
|
||||||
|
|
||||||
def self.syntax_error_translation_key
|
def self.syntax_error_translation_key
|
||||||
"errors.syntax.assign".freeze
|
"errors.syntax.assign"
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :to, :from
|
attr_reader :to, :from
|
||||||
@@ -19,10 +21,10 @@ module Liquid
|
|||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
super
|
super
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@to = $1
|
@to = Regexp.last_match(1)
|
||||||
@from = Variable.new($2, options)
|
@from = Variable.new(Regexp.last_match(2), options)
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t(self.class.syntax_error_translation_key))
|
raise SyntaxError, options[:locale].t(self.class.syntax_error_translation_key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -59,5 +61,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('assign'.freeze, Assign)
|
Template.register_tag('assign', Assign)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Break tag to be used to break out of a for loop.
|
# Break tag to be used to break out of a for loop.
|
||||||
#
|
#
|
||||||
@@ -14,5 +16,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('break'.freeze, Break)
|
Template.register_tag('break', Break)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Capture stores the result of a block into a variable without rendering it inplace.
|
# Capture stores the result of a block into a variable without rendering it inplace.
|
||||||
#
|
#
|
||||||
@@ -16,9 +18,9 @@ module Liquid
|
|||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
super
|
super
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@to = $1
|
@to = Regexp.last_match(1)
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.capture"))
|
raise SyntaxError, options[:locale].t("errors.syntax.capture")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -35,5 +37,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('capture'.freeze, Capture)
|
Template.register_tag('capture', Capture)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Case < Block
|
class Case < Block
|
||||||
Syntax = /(#{QuotedFragment})/o
|
Syntax = /(#{QuotedFragment})/o
|
||||||
@@ -10,17 +12,15 @@ module Liquid
|
|||||||
@blocks = []
|
@blocks = []
|
||||||
|
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@left = Expression.parse($1)
|
@left = Expression.parse(Regexp.last_match(1))
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.case".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.case")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse(tokens)
|
def parse(tokens)
|
||||||
body = BlockBody.new
|
body = BlockBody.new
|
||||||
while parse_body(body, tokens)
|
body = @blocks.last.attachment while parse_body(body, tokens)
|
||||||
body = @blocks.last.attachment
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def nodelist
|
def nodelist
|
||||||
@@ -29,9 +29,9 @@ module Liquid
|
|||||||
|
|
||||||
def unknown_tag(tag, markup, tokens)
|
def unknown_tag(tag, markup, tokens)
|
||||||
case tag
|
case tag
|
||||||
when 'when'.freeze
|
when 'when'
|
||||||
record_when_condition(markup)
|
record_when_condition(markup)
|
||||||
when 'else'.freeze
|
when 'else'
|
||||||
record_else_condition(markup)
|
record_else_condition(markup)
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
@@ -39,16 +39,14 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
context.stack do
|
execute_else_block = true
|
||||||
execute_else_block = true
|
|
||||||
|
|
||||||
@blocks.each do |block|
|
@blocks.each do |block|
|
||||||
if block.else?
|
if block.else?
|
||||||
block.attachment.render_to_output_buffer(context, output) if execute_else_block
|
block.attachment.render_to_output_buffer(context, output) if execute_else_block
|
||||||
elsif block.evaluate(context)
|
elsif block.evaluate(context)
|
||||||
execute_else_block = false
|
execute_else_block = false
|
||||||
block.attachment.render_to_output_buffer(context, output)
|
block.attachment.render_to_output_buffer(context, output)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -62,12 +60,12 @@ module Liquid
|
|||||||
|
|
||||||
while markup
|
while markup
|
||||||
unless markup =~ WhenSyntax
|
unless markup =~ WhenSyntax
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.case_invalid_when".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_when")
|
||||||
end
|
end
|
||||||
|
|
||||||
markup = $2
|
markup = Regexp.last_match(2)
|
||||||
|
|
||||||
block = Condition.new(@left, '=='.freeze, Expression.parse($1))
|
block = Condition.new(@left, '==', Expression.parse(Regexp.last_match(1)))
|
||||||
block.attach(body)
|
block.attach(body)
|
||||||
@blocks << block
|
@blocks << block
|
||||||
end
|
end
|
||||||
@@ -75,7 +73,7 @@ module Liquid
|
|||||||
|
|
||||||
def record_else_condition(markup)
|
def record_else_condition(markup)
|
||||||
unless markup.strip.empty?
|
unless markup.strip.empty?
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.case_invalid_else".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_else")
|
||||||
end
|
end
|
||||||
|
|
||||||
block = ElseCondition.new
|
block = ElseCondition.new
|
||||||
@@ -90,5 +88,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('case'.freeze, Case)
|
Template.register_tag('case', Case)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Comment < Block
|
class Comment < Block
|
||||||
def render_to_output_buffer(_context, output)
|
def render_to_output_buffer(_context, output)
|
||||||
@@ -12,5 +14,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('comment'.freeze, Comment)
|
Template.register_tag('comment', Comment)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Continue tag to be used to break out of a for loop.
|
# Continue tag to be used to break out of a for loop.
|
||||||
#
|
#
|
||||||
@@ -14,5 +16,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('continue'.freeze, Continue)
|
Template.register_tag('continue', Continue)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
|
# Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
|
||||||
#
|
#
|
||||||
@@ -21,38 +23,36 @@ module Liquid
|
|||||||
super
|
super
|
||||||
case markup
|
case markup
|
||||||
when NamedSyntax
|
when NamedSyntax
|
||||||
@variables = variables_from_string($2)
|
@variables = variables_from_string(Regexp.last_match(2))
|
||||||
@name = Expression.parse($1)
|
@name = Expression.parse(Regexp.last_match(1))
|
||||||
when SimpleSyntax
|
when SimpleSyntax
|
||||||
@variables = variables_from_string(markup)
|
@variables = variables_from_string(markup)
|
||||||
@name = @variables.to_s
|
@name = @variables.to_s
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.cycle".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.cycle")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
context.registers[:cycle] ||= {}
|
context.registers[:cycle] ||= {}
|
||||||
|
|
||||||
context.stack do
|
key = context.evaluate(@name)
|
||||||
key = context.evaluate(@name)
|
iteration = context.registers[:cycle][key].to_i
|
||||||
iteration = context.registers[:cycle][key].to_i
|
|
||||||
|
|
||||||
val = context.evaluate(@variables[iteration])
|
val = context.evaluate(@variables[iteration])
|
||||||
|
|
||||||
if val.is_a?(Array)
|
if val.is_a?(Array)
|
||||||
val = val.join
|
val = val.join
|
||||||
elsif !val.is_a?(String)
|
elsif !val.is_a?(String)
|
||||||
val = val.to_s
|
val = val.to_s
|
||||||
end
|
|
||||||
|
|
||||||
output << val
|
|
||||||
|
|
||||||
iteration += 1
|
|
||||||
iteration = 0 if iteration >= @variables.size
|
|
||||||
context.registers[:cycle][key] = iteration
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
output << val
|
||||||
|
|
||||||
|
iteration += 1
|
||||||
|
iteration = 0 if iteration >= @variables.size
|
||||||
|
context.registers[:cycle][key] = iteration
|
||||||
|
|
||||||
output
|
output
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ module Liquid
|
|||||||
def variables_from_string(markup)
|
def variables_from_string(markup)
|
||||||
markup.split(',').collect do |var|
|
markup.split(',').collect do |var|
|
||||||
var =~ /\s*(#{QuotedFragment})\s*/o
|
var =~ /\s*(#{QuotedFragment})\s*/o
|
||||||
$1 ? Expression.parse($1) : nil
|
Regexp.last_match(1) ? Expression.parse(Regexp.last_match(1)) : nil
|
||||||
end.compact
|
end.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# decrement is used in a place where one needs to insert a counter
|
# decrement is used in a place where one needs to insert a counter
|
||||||
# into a template, and needs the counter to survive across
|
# into a template, and needs the counter to survive across
|
||||||
@@ -32,5 +34,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('decrement'.freeze, Decrement)
|
Template.register_tag('decrement', Decrement)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Echo outputs an expression
|
# Echo outputs an expression
|
||||||
#
|
#
|
||||||
@@ -16,9 +18,9 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
@variable.render_to_output_buffer(context, '')
|
@variable.render_to_output_buffer(context, +'')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('echo'.freeze, Echo)
|
Template.register_tag('echo', Echo)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# "For" iterates over an array or collection.
|
# "For" iterates over an array or collection.
|
||||||
# Several useful variables are available to you within the loop.
|
# Several useful variables are available to you within the loop.
|
||||||
@@ -66,7 +68,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def unknown_tag(tag, markup, tokens)
|
def unknown_tag(tag, markup, tokens)
|
||||||
return super unless tag == 'else'.freeze
|
return super unless tag == 'else'
|
||||||
@else_block = BlockBody.new
|
@else_block = BlockBody.new
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -86,31 +88,31 @@ module Liquid
|
|||||||
|
|
||||||
def lax_parse(markup)
|
def lax_parse(markup)
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@variable_name = $1
|
@variable_name = Regexp.last_match(1)
|
||||||
collection_name = $2
|
collection_name = Regexp.last_match(2)
|
||||||
@reversed = !!$3
|
@reversed = !!Regexp.last_match(3)
|
||||||
@name = "#{@variable_name}-#{collection_name}"
|
@name = "#{@variable_name}-#{collection_name}"
|
||||||
@collection_name = Expression.parse(collection_name)
|
@collection_name = Expression.parse(collection_name)
|
||||||
markup.scan(TagAttributes) do |key, value|
|
markup.scan(TagAttributes) do |key, value|
|
||||||
set_attribute(key, value)
|
set_attribute(key, value)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.for".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.for")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
def strict_parse(markup)
|
||||||
p = Parser.new(markup)
|
p = Parser.new(markup)
|
||||||
@variable_name = p.consume(:id)
|
@variable_name = p.consume(:id)
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_in".freeze)) unless p.id?('in'.freeze)
|
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
|
||||||
collection_name = p.expression
|
collection_name = p.expression
|
||||||
@name = "#{@variable_name}-#{collection_name}"
|
@name = "#{@variable_name}-#{collection_name}"
|
||||||
@collection_name = Expression.parse(collection_name)
|
@collection_name = Expression.parse(collection_name)
|
||||||
@reversed = p.id?('reversed'.freeze)
|
@reversed = p.id?('reversed')
|
||||||
|
|
||||||
while p.look(:id) && p.look(:colon, 1)
|
while p.look(:id) && p.look(:colon, 1)
|
||||||
unless attribute = p.id?('limit'.freeze) || p.id?('offset'.freeze)
|
unless (attribute = p.id?('limit') || p.id?('offset'))
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_attribute".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_attribute")
|
||||||
end
|
end
|
||||||
p.consume
|
p.consume
|
||||||
set_attribute(attribute, p.expression)
|
set_attribute(attribute, p.expression)
|
||||||
@@ -162,7 +164,7 @@ module Liquid
|
|||||||
for_stack.push(loop_vars)
|
for_stack.push(loop_vars)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
context['forloop'.freeze] = loop_vars
|
context['forloop'] = loop_vars
|
||||||
|
|
||||||
segment.each do |item|
|
segment.each do |item|
|
||||||
context[@variable_name] = item
|
context[@variable_name] = item
|
||||||
@@ -170,11 +172,10 @@ module Liquid
|
|||||||
loop_vars.send(:increment!)
|
loop_vars.send(:increment!)
|
||||||
|
|
||||||
# Handle any interrupts if they exist.
|
# Handle any interrupts if they exist.
|
||||||
if context.interrupt?
|
next unless context.interrupt?
|
||||||
interrupt = context.pop_interrupt
|
interrupt = context.pop_interrupt
|
||||||
break if interrupt.is_a? BreakInterrupt
|
break if interrupt.is_a?(BreakInterrupt)
|
||||||
next if interrupt.is_a? ContinueInterrupt
|
next if interrupt.is_a?(ContinueInterrupt)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
for_stack.pop
|
for_stack.pop
|
||||||
@@ -186,13 +187,13 @@ module Liquid
|
|||||||
|
|
||||||
def set_attribute(key, expr)
|
def set_attribute(key, expr)
|
||||||
case key
|
case key
|
||||||
when 'offset'.freeze
|
when 'offset'
|
||||||
@from = if expr == 'continue'.freeze
|
@from = if expr == 'continue'
|
||||||
:continue
|
:continue
|
||||||
else
|
else
|
||||||
Expression.parse(expr)
|
Expression.parse(expr)
|
||||||
end
|
end
|
||||||
when 'limit'.freeze
|
when 'limit'
|
||||||
@limit = Expression.parse(expr)
|
@limit = Expression.parse(expr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -212,5 +213,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('for'.freeze, For)
|
Template.register_tag('for', For)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# If is the conditional block
|
# If is the conditional block
|
||||||
#
|
#
|
||||||
@@ -19,7 +21,7 @@ module Liquid
|
|||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
super
|
super
|
||||||
@blocks = []
|
@blocks = []
|
||||||
push_block('if'.freeze, markup)
|
push_block('if', markup)
|
||||||
end
|
end
|
||||||
|
|
||||||
def nodelist
|
def nodelist
|
||||||
@@ -32,7 +34,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def unknown_tag(tag, markup, tokens)
|
def unknown_tag(tag, markup, tokens)
|
||||||
if ['elsif'.freeze, 'else'.freeze].include?(tag)
|
if ['elsif', 'else'].include?(tag)
|
||||||
push_block(tag, markup)
|
push_block(tag, markup)
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
@@ -40,11 +42,9 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
context.stack do
|
@blocks.each do |block|
|
||||||
@blocks.each do |block|
|
if block.evaluate(context)
|
||||||
if block.evaluate(context)
|
return block.attachment.render_to_output_buffer(context, output)
|
||||||
return block.attachment.render_to_output_buffer(context, output)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ module Liquid
|
|||||||
private
|
private
|
||||||
|
|
||||||
def push_block(tag, markup)
|
def push_block(tag, markup)
|
||||||
block = if tag == 'else'.freeze
|
block = if tag == 'else'
|
||||||
ElseCondition.new
|
ElseCondition.new
|
||||||
else
|
else
|
||||||
parse_with_selected_parser(markup)
|
parse_with_selected_parser(markup)
|
||||||
@@ -66,17 +66,17 @@ module Liquid
|
|||||||
|
|
||||||
def lax_parse(markup)
|
def lax_parse(markup)
|
||||||
expressions = markup.scan(ExpressionsAndOperators)
|
expressions = markup.scan(ExpressionsAndOperators)
|
||||||
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless expressions.pop =~ Syntax
|
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop =~ Syntax
|
||||||
|
|
||||||
condition = Condition.new(Expression.parse($1), $2, Expression.parse($3))
|
condition = Condition.new(Expression.parse(Regexp.last_match(1)), Regexp.last_match(2), Expression.parse(Regexp.last_match(3)))
|
||||||
|
|
||||||
until expressions.empty?
|
until expressions.empty?
|
||||||
operator = expressions.pop.to_s.strip
|
operator = expressions.pop.to_s.strip
|
||||||
|
|
||||||
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless expressions.pop.to_s =~ Syntax
|
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop.to_s =~ Syntax
|
||||||
|
|
||||||
new_condition = Condition.new(Expression.parse($1), $2, Expression.parse($3))
|
new_condition = Condition.new(Expression.parse(Regexp.last_match(1)), Regexp.last_match(2), Expression.parse(Regexp.last_match(3)))
|
||||||
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless BOOLEAN_OPERATORS.include?(operator)
|
raise SyntaxError, options[:locale].t("errors.syntax.if") unless BOOLEAN_OPERATORS.include?(operator)
|
||||||
new_condition.send(operator, condition)
|
new_condition.send(operator, condition)
|
||||||
condition = new_condition
|
condition = new_condition
|
||||||
end
|
end
|
||||||
@@ -94,7 +94,7 @@ module Liquid
|
|||||||
def parse_binary_comparisons(p)
|
def parse_binary_comparisons(p)
|
||||||
condition = parse_comparison(p)
|
condition = parse_comparison(p)
|
||||||
first_condition = condition
|
first_condition = condition
|
||||||
while op = (p.id?('and'.freeze) || p.id?('or'.freeze))
|
while (op = (p.id?('and') || p.id?('or')))
|
||||||
child_condition = parse_comparison(p)
|
child_condition = parse_comparison(p)
|
||||||
condition.send(op, child_condition)
|
condition.send(op, child_condition)
|
||||||
condition = child_condition
|
condition = child_condition
|
||||||
@@ -104,7 +104,7 @@ module Liquid
|
|||||||
|
|
||||||
def parse_comparison(p)
|
def parse_comparison(p)
|
||||||
a = Expression.parse(p.expression)
|
a = Expression.parse(p.expression)
|
||||||
if op = p.consume?(:comparison)
|
if (op = p.consume?(:comparison))
|
||||||
b = Expression.parse(p.expression)
|
b = Expression.parse(p.expression)
|
||||||
Condition.new(a, op, b)
|
Condition.new(a, op, b)
|
||||||
else
|
else
|
||||||
@@ -119,5 +119,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('if'.freeze, If)
|
Template.register_tag('if', If)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Ifchanged < Block
|
class Ifchanged < Block
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
context.stack do
|
block_output = +''
|
||||||
block_output = ''
|
super(context, block_output)
|
||||||
super(context, block_output)
|
|
||||||
|
|
||||||
if block_output != context.registers[:ifchanged]
|
if block_output != context.registers[:ifchanged]
|
||||||
context.registers[:ifchanged] = block_output
|
context.registers[:ifchanged] = block_output
|
||||||
output << block_output
|
output << block_output
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
output
|
output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('ifchanged'.freeze, Ifchanged)
|
Template.register_tag('ifchanged', Ifchanged)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Include allows templates to relate with other templates
|
# Include allows templates to relate with other templates
|
||||||
#
|
#
|
||||||
@@ -23,8 +25,8 @@ module Liquid
|
|||||||
|
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
|
|
||||||
template_name = $1
|
template_name = Regexp.last_match(1)
|
||||||
variable_name = $3
|
variable_name = Regexp.last_match(3)
|
||||||
|
|
||||||
@variable_name_expr = variable_name ? Expression.parse(variable_name) : nil
|
@variable_name_expr = variable_name ? Expression.parse(variable_name) : nil
|
||||||
@template_name_expr = Expression.parse(template_name)
|
@template_name_expr = Expression.parse(template_name)
|
||||||
@@ -35,7 +37,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.include".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.include")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ module Liquid
|
|||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
template_name = context.evaluate(@template_name_expr)
|
template_name = context.evaluate(@template_name_expr)
|
||||||
raise ArgumentError.new(options[:locale].t("errors.argument.include")) unless template_name
|
raise ArgumentError, options[:locale].t("errors.argument.include") unless template_name
|
||||||
|
|
||||||
partial = PartialCache.load(
|
partial = PartialCache.load(
|
||||||
template_name,
|
template_name,
|
||||||
@@ -52,7 +54,7 @@ module Liquid
|
|||||||
parse_context: parse_context
|
parse_context: parse_context
|
||||||
)
|
)
|
||||||
|
|
||||||
context_variable_name = template_name.split('/'.freeze).last
|
context_variable_name = template_name.split('/').last
|
||||||
|
|
||||||
variable = if @variable_name_expr
|
variable = if @variable_name_expr
|
||||||
context.evaluate(@variable_name_expr)
|
context.evaluate(@variable_name_expr)
|
||||||
@@ -95,11 +97,11 @@ module Liquid
|
|||||||
def children
|
def children
|
||||||
[
|
[
|
||||||
@node.template_name_expr,
|
@node.template_name_expr,
|
||||||
@node.variable_name_expr
|
@node.variable_name_expr,
|
||||||
] + @node.attributes.values
|
] + @node.attributes.values
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('include'.freeze, Include)
|
Template.register_tag('include', Include)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# increment is used in a place where one needs to insert a counter
|
# increment is used in a place where one needs to insert a counter
|
||||||
# into a template, and needs the counter to survive across
|
# into a template, and needs the counter to survive across
|
||||||
@@ -29,5 +31,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('increment'.freeze, Increment)
|
Template.register_tag('increment', Increment)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Raw < Block
|
class Raw < Block
|
||||||
Syntax = /\A\s*\z/
|
Syntax = /\A\s*\z/
|
||||||
@@ -10,16 +12,16 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse(tokens)
|
def parse(tokens)
|
||||||
@body = ''
|
@body = +''
|
||||||
while token = tokens.shift
|
while (token = tokens.shift)
|
||||||
if token =~ FullTokenPossiblyInvalid
|
if token =~ FullTokenPossiblyInvalid
|
||||||
@body << $1 if $1 != "".freeze
|
@body << Regexp.last_match(1) if Regexp.last_match(1) != ""
|
||||||
return if block_delimiter == $2
|
return if block_delimiter == Regexp.last_match(2)
|
||||||
end
|
end
|
||||||
@body << token unless token.empty?
|
@body << token unless token.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_never_closed".freeze, block_name: block_name))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed", block_name: block_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(_context, output)
|
def render_to_output_buffer(_context, output)
|
||||||
@@ -38,11 +40,11 @@ module Liquid
|
|||||||
protected
|
protected
|
||||||
|
|
||||||
def ensure_valid_markup(tag_name, markup, parse_context)
|
def ensure_valid_markup(tag_name, markup, parse_context)
|
||||||
unless markup =~ Syntax
|
unless Syntax.match?(markup)
|
||||||
raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_unexpected_args".freeze, tag: tag_name))
|
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_unexpected_args", tag: tag_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('raw'.freeze, Raw)
|
Template.register_tag('raw', Raw)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Render < Tag
|
class Render < Tag
|
||||||
SYNTAX = /(#{QuotedString})#{QuotedFragment}*/o
|
SYNTAX = /(#{QuotedString})#{QuotedFragment}*/o
|
||||||
|
|
||||||
|
disable_tags "include"
|
||||||
|
|
||||||
attr_reader :template_name_expr, :attributes
|
attr_reader :template_name_expr, :attributes
|
||||||
|
|
||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
super
|
super
|
||||||
|
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.render".freeze)) unless markup =~ SYNTAX
|
raise SyntaxError, options[:locale].t("errors.syntax.render") unless markup =~ SYNTAX
|
||||||
|
|
||||||
template_name = $1
|
template_name = Regexp.last_match(1)
|
||||||
|
|
||||||
@template_name_expr = Expression.parse(template_name)
|
@template_name_expr = Expression.parse(template_name)
|
||||||
|
|
||||||
@@ -20,9 +24,13 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
|
render_tag(context, output)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_tag(context, output)
|
||||||
# Though we evaluate this here we will only ever parse it as a string literal.
|
# Though we evaluate this here we will only ever parse it as a string literal.
|
||||||
template_name = context.evaluate(@template_name_expr)
|
template_name = context.evaluate(@template_name_expr)
|
||||||
raise ArgumentError.new(options[:locale].t("errors.argument.include")) unless template_name
|
raise ArgumentError, options[:locale].t("errors.argument.include") unless template_name
|
||||||
|
|
||||||
partial = PartialCache.load(
|
partial = PartialCache.load(
|
||||||
template_name,
|
template_name,
|
||||||
@@ -50,5 +58,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('render'.freeze, Render)
|
Template.register_tag('render', Render)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class TableRow < Block
|
class TableRow < Block
|
||||||
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
|
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
|
||||||
@@ -7,33 +9,33 @@ module Liquid
|
|||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
super
|
super
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@variable_name = $1
|
@variable_name = Regexp.last_match(1)
|
||||||
@collection_name = Expression.parse($2)
|
@collection_name = Expression.parse(Regexp.last_match(2))
|
||||||
@attributes = {}
|
@attributes = {}
|
||||||
markup.scan(TagAttributes) do |key, value|
|
markup.scan(TagAttributes) do |key, value|
|
||||||
@attributes[key] = Expression.parse(value)
|
@attributes[key] = Expression.parse(value)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.table_row".freeze))
|
raise SyntaxError, options[:locale].t("errors.syntax.table_row")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
collection = context.evaluate(@collection_name) or return ''.freeze
|
(collection = context.evaluate(@collection_name)) || (return '')
|
||||||
|
|
||||||
from = @attributes.key?('offset'.freeze) ? context.evaluate(@attributes['offset'.freeze]).to_i : 0
|
from = @attributes.key?('offset') ? context.evaluate(@attributes['offset']).to_i : 0
|
||||||
to = @attributes.key?('limit'.freeze) ? from + context.evaluate(@attributes['limit'.freeze]).to_i : nil
|
to = @attributes.key?('limit') ? from + context.evaluate(@attributes['limit']).to_i : nil
|
||||||
|
|
||||||
collection = Utils.slice_collection(collection, from, to)
|
collection = Utils.slice_collection(collection, from, to)
|
||||||
|
|
||||||
length = collection.length
|
length = collection.length
|
||||||
|
|
||||||
cols = context.evaluate(@attributes['cols'.freeze]).to_i
|
cols = context.evaluate(@attributes['cols']).to_i
|
||||||
|
|
||||||
output << "<tr class=\"row1\">\n"
|
output << "<tr class=\"row1\">\n"
|
||||||
context.stack do
|
context.stack do
|
||||||
tablerowloop = Liquid::TablerowloopDrop.new(length, cols)
|
tablerowloop = Liquid::TablerowloopDrop.new(length, cols)
|
||||||
context['tablerowloop'.freeze] = tablerowloop
|
context['tablerowloop'] = tablerowloop
|
||||||
|
|
||||||
collection.each do |item|
|
collection.each do |item|
|
||||||
context[@variable_name] = item
|
context[@variable_name] = item
|
||||||
@@ -61,5 +63,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('tablerow'.freeze, TableRow)
|
Template.register_tag('tablerow', TableRow)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative 'if'
|
require_relative 'if'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
@@ -7,18 +9,16 @@ module Liquid
|
|||||||
#
|
#
|
||||||
class Unless < If
|
class Unless < If
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
context.stack do
|
# First condition is interpreted backwards ( if not )
|
||||||
# First condition is interpreted backwards ( if not )
|
first_block = @blocks.first
|
||||||
first_block = @blocks.first
|
unless first_block.evaluate(context)
|
||||||
unless first_block.evaluate(context)
|
return first_block.attachment.render_to_output_buffer(context, output)
|
||||||
return first_block.attachment.render_to_output_buffer(context, output)
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# After the first condition unless works just like if
|
# After the first condition unless works just like if
|
||||||
@blocks[1..-1].each do |block|
|
@blocks[1..-1].each do |block|
|
||||||
if block.evaluate(context)
|
if block.evaluate(context)
|
||||||
return block.attachment.render_to_output_buffer(context, output)
|
return block.attachment.render_to_output_buffer(context, output)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -26,5 +26,5 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Template.register_tag('unless'.freeze, Unless)
|
Template.register_tag('unless', Unless)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Templates are central to liquid.
|
# Templates are central to liquid.
|
||||||
# Interpretating templates is a two step process. First you compile the
|
# Interpretating templates is a two step process. First you compile the
|
||||||
@@ -90,6 +92,14 @@ module Liquid
|
|||||||
@tags ||= TagRegistry.new
|
@tags ||= TagRegistry.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_register(name, klass)
|
||||||
|
registers[name.to_sym] = klass
|
||||||
|
end
|
||||||
|
|
||||||
|
def registers
|
||||||
|
@registers ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
def error_mode
|
def error_mode
|
||||||
@error_mode ||= :lax
|
@error_mode ||= :lax
|
||||||
end
|
end
|
||||||
@@ -165,14 +175,14 @@ module Liquid
|
|||||||
# filters and tags and might be useful to integrate liquid more with its host application
|
# filters and tags and might be useful to integrate liquid more with its host application
|
||||||
#
|
#
|
||||||
def render(*args)
|
def render(*args)
|
||||||
return ''.freeze if @root.nil?
|
return '' if @root.nil?
|
||||||
|
|
||||||
context = case args.first
|
context = case args.first
|
||||||
when Liquid::Context
|
when Liquid::Context
|
||||||
c = args.shift
|
c = args.shift
|
||||||
|
|
||||||
if @rethrow_errors
|
if @rethrow_errors
|
||||||
c.exception_renderer = ->(e) { raise }
|
c.exception_renderer = ->(_e) { raise }
|
||||||
end
|
end
|
||||||
|
|
||||||
c
|
c
|
||||||
@@ -189,18 +199,26 @@ module Liquid
|
|||||||
|
|
||||||
output = nil
|
output = nil
|
||||||
|
|
||||||
|
context_register = context.registers.is_a?(StaticRegisters) ? context.registers.static : context.registers
|
||||||
|
|
||||||
case args.last
|
case args.last
|
||||||
when Hash
|
when Hash
|
||||||
options = args.pop
|
options = args.pop
|
||||||
output = options[:output] if options[:output]
|
output = options[:output] if options[:output]
|
||||||
|
|
||||||
registers.merge!(options[:registers]) if options[:registers].is_a?(Hash)
|
options[:registers]&.each do |key, register|
|
||||||
|
context_register[key] = register
|
||||||
|
end
|
||||||
|
|
||||||
apply_options_to_context(context, options)
|
apply_options_to_context(context, options)
|
||||||
when Module, Array
|
when Module, Array
|
||||||
context.add_filters(args.pop)
|
context.add_filters(args.pop)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Template.registers.each do |key, register|
|
||||||
|
context_register[key] = register
|
||||||
|
end
|
||||||
|
|
||||||
# Retrying a render resets resource usage
|
# Retrying a render resets resource usage
|
||||||
context.resource_limits.reset
|
context.resource_limits.reset
|
||||||
|
|
||||||
@@ -208,7 +226,7 @@ module Liquid
|
|||||||
# render the nodelist.
|
# render the nodelist.
|
||||||
# for performance reasons we get an array back here. join will make a string out of it.
|
# for performance reasons we get an array back here. join will make a string out of it.
|
||||||
with_profiling(context) do
|
with_profiling(context) do
|
||||||
@root.render_to_output_buffer(context, output || '')
|
@root.render_to_output_buffer(context, output || +'')
|
||||||
end
|
end
|
||||||
rescue Liquid::MemoryError => e
|
rescue Liquid::MemoryError => e
|
||||||
context.handle_error(e)
|
context.handle_error(e)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class Tokenizer
|
class Tokenizer
|
||||||
attr_reader :line_number, :for_liquid_tag
|
attr_reader :line_number, :for_liquid_tag
|
||||||
@@ -10,7 +12,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def shift
|
def shift
|
||||||
token = @tokens.shift or return
|
(token = @tokens.shift) || return
|
||||||
|
|
||||||
if @line_number
|
if @line_number
|
||||||
@line_number += @for_liquid_tag ? 1 : token.count("\n")
|
@line_number += @for_liquid_tag ? 1 : token.count("\n")
|
||||||
@@ -29,7 +31,7 @@ module Liquid
|
|||||||
tokens = @source.split(TemplateParser)
|
tokens = @source.split(TemplateParser)
|
||||||
|
|
||||||
# removes the rogue empty element at the beginning of the array
|
# removes the rogue empty element at the beginning of the array
|
||||||
tokens.shift if tokens[0] && tokens[0].empty?
|
tokens.shift if tokens[0]&.empty?
|
||||||
|
|
||||||
tokens
|
tokens
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
module Usage
|
module Usage
|
||||||
def self.increment(name)
|
def self.increment(name)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
module Utils
|
module Utils
|
||||||
def self.slice_collection(collection, from, to)
|
def self.slice_collection(collection, from, to)
|
||||||
@@ -50,7 +52,7 @@ module Liquid
|
|||||||
when Numeric
|
when Numeric
|
||||||
obj
|
obj
|
||||||
when String
|
when String
|
||||||
(obj.strip =~ /\A-?\d+\.\d+\z/) ? BigDecimal(obj) : obj.to_i
|
/\A-?\d+\.\d+\z/.match?(obj.strip) ? BigDecimal(obj) : obj.to_i
|
||||||
else
|
else
|
||||||
if obj.respond_to?(:to_number)
|
if obj.respond_to?(:to_number)
|
||||||
obj.to_number
|
obj.to_number
|
||||||
@@ -69,7 +71,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
case obj
|
case obj
|
||||||
when 'now'.freeze, 'today'.freeze
|
when 'now', 'today'
|
||||||
Time.now
|
Time.now
|
||||||
when /\A\d+\z/, Integer
|
when /\A\d+\z/, Integer
|
||||||
Time.at(obj.to_i)
|
Time.at(obj.to_i)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
# Holds variables. Variables are only loaded "just in time"
|
# Holds variables. Variables are only loaded "just in time"
|
||||||
# and are not evaluated as part of the render stage
|
# and are not evaluated as part of the render stage
|
||||||
@@ -43,11 +45,11 @@ module Liquid
|
|||||||
@filters = []
|
@filters = []
|
||||||
return unless markup =~ MarkupWithQuotedFragment
|
return unless markup =~ MarkupWithQuotedFragment
|
||||||
|
|
||||||
name_markup = $1
|
name_markup = Regexp.last_match(1)
|
||||||
filter_markup = $2
|
filter_markup = Regexp.last_match(2)
|
||||||
@name = Expression.parse(name_markup)
|
@name = Expression.parse(name_markup)
|
||||||
if filter_markup =~ FilterMarkupRegex
|
if filter_markup =~ FilterMarkupRegex
|
||||||
filters = $1.scan(FilterParser)
|
filters = Regexp.last_match(1).scan(FilterParser)
|
||||||
filters.each do |f|
|
filters.each do |f|
|
||||||
next unless f =~ /\w+/
|
next unless f =~ /\w+/
|
||||||
filtername = Regexp.last_match(0)
|
filtername = Regexp.last_match(0)
|
||||||
@@ -102,13 +104,21 @@ module Liquid
|
|||||||
output
|
output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disabled?(_context)
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def disabled_tags
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def parse_filter_expressions(filter_name, unparsed_args)
|
def parse_filter_expressions(filter_name, unparsed_args)
|
||||||
filter_args = []
|
filter_args = []
|
||||||
keyword_args = nil
|
keyword_args = nil
|
||||||
unparsed_args.each do |a|
|
unparsed_args.each do |a|
|
||||||
if matches = a.match(JustTagAttributes)
|
if (matches = a.match(JustTagAttributes))
|
||||||
keyword_args ||= {}
|
keyword_args ||= {}
|
||||||
keyword_args[matches[1]] = Expression.parse(matches[2])
|
keyword_args[matches[1]] = Expression.parse(matches[2])
|
||||||
else
|
else
|
||||||
@@ -121,7 +131,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_filter_expressions(context, filter_args, filter_kwargs)
|
def evaluate_filter_expressions(context, filter_args, filter_kwargs)
|
||||||
parsed_args = filter_args.map{ |expr| context.evaluate(expr) }
|
parsed_args = filter_args.map { |expr| context.evaluate(expr) }
|
||||||
if filter_kwargs
|
if filter_kwargs
|
||||||
parsed_kwargs = {}
|
parsed_kwargs = {}
|
||||||
filter_kwargs.each do |key, expr|
|
filter_kwargs.each do |key, expr|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
class VariableLookup
|
class VariableLookup
|
||||||
SQUARE_BRACKETED = /\A\[(.*)\]\z/m
|
SQUARE_BRACKETED = /\A\[(.*)\]\z/m
|
||||||
COMMAND_METHODS = ['size'.freeze, 'first'.freeze, 'last'.freeze].freeze
|
COMMAND_METHODS = ['size', 'first', 'last'].freeze
|
||||||
|
|
||||||
attr_reader :name, :lookups
|
attr_reader :name, :lookups
|
||||||
|
|
||||||
@@ -14,7 +16,7 @@ module Liquid
|
|||||||
|
|
||||||
name = lookups.shift
|
name = lookups.shift
|
||||||
if name =~ SQUARE_BRACKETED
|
if name =~ SQUARE_BRACKETED
|
||||||
name = Expression.parse($1)
|
name = Expression.parse(Regexp.last_match(1))
|
||||||
end
|
end
|
||||||
@name = name
|
@name = name
|
||||||
|
|
||||||
@@ -24,7 +26,7 @@ module Liquid
|
|||||||
@lookups.each_index do |i|
|
@lookups.each_index do |i|
|
||||||
lookup = lookups[i]
|
lookup = lookups[i]
|
||||||
if lookup =~ SQUARE_BRACKETED
|
if lookup =~ SQUARE_BRACKETED
|
||||||
lookups[i] = Expression.parse($1)
|
lookups[i] = Expression.parse(Regexp.last_match(1))
|
||||||
elsif COMMAND_METHODS.include?(lookup)
|
elsif COMMAND_METHODS.include?(lookup)
|
||||||
@command_flags |= 1 << i
|
@command_flags |= 1 << i
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
VERSION = "4.0.3".freeze
|
VERSION = "4.0.3"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
lib = File.expand_path('../lib/', __FILE__)
|
lib = File.expand_path('../lib/', __FILE__)
|
||||||
$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
|
||||||
require "liquid/version"
|
require "liquid/version"
|
||||||
|
|
||||||
@@ -26,6 +27,6 @@ Gem::Specification.new do |s|
|
|||||||
|
|
||||||
s.require_path = "lib"
|
s.require_path = "lib"
|
||||||
|
|
||||||
s.add_development_dependency 'rake', '~> 11.3'
|
s.add_development_dependency('rake', '~> 11.3')
|
||||||
s.add_development_dependency 'minitest'
|
s.add_development_dependency('minitest')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'benchmark/ips'
|
require 'benchmark/ips'
|
||||||
require_relative 'theme_runner'
|
require_relative 'theme_runner'
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'stackprof'
|
require 'stackprof'
|
||||||
require_relative 'theme_runner'
|
require_relative 'theme_runner'
|
||||||
|
|
||||||
@@ -13,7 +15,7 @@ profiler.run
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if profile_type == :cpu && graph_filename = ENV['GRAPH_FILENAME']
|
if profile_type == :cpu && (graph_filename = ENV['GRAPH_FILENAME'])
|
||||||
File.open(graph_filename, 'w') do |f|
|
File.open(graph_filename, 'w') do |f|
|
||||||
StackProf::Report.new(results).print_graphviz(nil, f)
|
StackProf::Report.new(results).print_graphviz(nil, f)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CommentForm < Liquid::Block
|
class CommentForm < Liquid::Block
|
||||||
Syntax = /(#{Liquid::VariableSignature}+)/
|
Syntax = /(#{Liquid::VariableSignature}+)/
|
||||||
|
|
||||||
@@ -5,10 +7,10 @@ class CommentForm < Liquid::Block
|
|||||||
super
|
super
|
||||||
|
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@variable_name = $1
|
@variable_name = Regexp.last_match(1)
|
||||||
@attributes = {}
|
@attributes = {}
|
||||||
else
|
else
|
||||||
raise SyntaxError.new("Syntax Error in 'comment_form' - Valid syntax: comment_form [article]")
|
raise SyntaxError, "Syntax Error in 'comment_form' - Valid syntax: comment_form [article]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -20,8 +22,8 @@ class CommentForm < Liquid::Block
|
|||||||
'posted_successfully?' => context.registers[:posted_successfully],
|
'posted_successfully?' => context.registers[:posted_successfully],
|
||||||
'errors' => context['comment.errors'],
|
'errors' => context['comment.errors'],
|
||||||
'author' => context['comment.author'],
|
'author' => context['comment.author'],
|
||||||
'email' => context['comment.email'],
|
'email' => context['comment.email'],
|
||||||
'body' => context['comment.body']
|
'body' => context['comment.body'],
|
||||||
}
|
}
|
||||||
|
|
||||||
output << wrap_in_form(article, render_all(@nodelist, context, output))
|
output << wrap_in_form(article, render_all(@nodelist, context, output))
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
|
|
||||||
module Database
|
module Database
|
||||||
@@ -16,9 +18,10 @@ module Database
|
|||||||
end
|
end
|
||||||
|
|
||||||
# key the tables by handles, as this is how liquid expects it.
|
# key the tables by handles, as this is how liquid expects it.
|
||||||
db = db.inject({}) do |assigns, (key, values)|
|
db = db.each_with_object({}) do |(key, values), assigns|
|
||||||
assigns[key] = values.inject({}) { |h, v| h[v['handle']] = v; h; }
|
assigns[key] = values.each_with_object({}) do |v, h|
|
||||||
assigns
|
h[v['handle']] = v
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Some standard direct accessors so that the specialized templates
|
# Some standard direct accessors so that the specialized templates
|
||||||
@@ -29,9 +32,9 @@ module Database
|
|||||||
db['article'] = db['blog']['articles'].first
|
db['article'] = db['blog']['articles'].first
|
||||||
|
|
||||||
db['cart'] = {
|
db['cart'] = {
|
||||||
'total_price' => db['line_items'].values.inject(0) { |sum, item| sum += item['line_price'] * item['quantity'] },
|
'total_price' => db['line_items'].values.inject(0) { |sum, item| sum + item['line_price'] * item['quantity'] },
|
||||||
'item_count' => db['line_items'].values.inject(0) { |sum, item| sum += item['quantity'] },
|
'item_count' => db['line_items'].values.inject(0) { |sum, item| sum + item['quantity'] },
|
||||||
'items' => db['line_items'].values
|
'items' => db['line_items'].values,
|
||||||
}
|
}
|
||||||
|
|
||||||
db
|
db
|
||||||
@@ -40,6 +43,6 @@ module Database
|
|||||||
end
|
end
|
||||||
|
|
||||||
if __FILE__ == $PROGRAM_NAME
|
if __FILE__ == $PROGRAM_NAME
|
||||||
p Database.tables['collections']['frontpage'].keys
|
p(Database.tables['collections']['frontpage'].keys)
|
||||||
# p Database.tables['blog']['articles']
|
# p Database.tables['blog']['articles']
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'json'
|
require 'json'
|
||||||
|
|
||||||
module JsonFilter
|
module JsonFilter
|
||||||
def json(object)
|
def json(object)
|
||||||
JSON.dump(object.reject { |k, v| k == "collections" })
|
JSON.dump(object.reject { |k, _v| k == "collections" })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
$:.unshift __dir__ + '/../../lib'
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift(__dir__ + '/../../lib')
|
||||||
require_relative '../../lib/liquid'
|
require_relative '../../lib/liquid'
|
||||||
|
|
||||||
require_relative 'comment_form'
|
require_relative 'comment_form'
|
||||||
@@ -9,11 +11,11 @@ require_relative 'shop_filter'
|
|||||||
require_relative 'tag_filter'
|
require_relative 'tag_filter'
|
||||||
require_relative 'weight_filter'
|
require_relative 'weight_filter'
|
||||||
|
|
||||||
Liquid::Template.register_tag 'paginate', Paginate
|
Liquid::Template.register_tag('paginate', Paginate)
|
||||||
Liquid::Template.register_tag 'form', CommentForm
|
Liquid::Template.register_tag('form', CommentForm)
|
||||||
|
|
||||||
Liquid::Template.register_filter JsonFilter
|
Liquid::Template.register_filter(JsonFilter)
|
||||||
Liquid::Template.register_filter MoneyFilter
|
Liquid::Template.register_filter(MoneyFilter)
|
||||||
Liquid::Template.register_filter WeightFilter
|
Liquid::Template.register_filter(WeightFilter)
|
||||||
Liquid::Template.register_filter ShopFilter
|
Liquid::Template.register_filter(ShopFilter)
|
||||||
Liquid::Template.register_filter TagFilter
|
Liquid::Template.register_filter(TagFilter)
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module MoneyFilter
|
module MoneyFilter
|
||||||
def money_with_currency(money)
|
def money_with_currency(money)
|
||||||
return '' if money.nil?
|
return '' if money.nil?
|
||||||
sprintf("$ %.2f USD", money / 100.0)
|
format("$ %.2f USD", money / 100.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
def money(money)
|
def money(money)
|
||||||
return '' if money.nil?
|
return '' if money.nil?
|
||||||
sprintf("$ %.2f", money / 100.0)
|
format("$ %.2f", money / 100.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Paginate < Liquid::Block
|
class Paginate < Liquid::Block
|
||||||
Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/
|
Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/
|
||||||
|
|
||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
super
|
super
|
||||||
|
|
||||||
if markup =~ Syntax
|
if markup =~ Syntax
|
||||||
@collection_name = $1
|
@collection_name = Regexp.last_match(1)
|
||||||
@page_size = if $2
|
@page_size = if Regexp.last_match(2)
|
||||||
$3.to_i
|
Regexp.last_match(3).to_i
|
||||||
else
|
else
|
||||||
20
|
20
|
||||||
end
|
end
|
||||||
@@ -17,7 +19,7 @@ class Paginate < Liquid::Block
|
|||||||
@attributes[key] = value
|
@attributes[key] = value
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise SyntaxError.new("Syntax Error in tag 'paginate' - Valid syntax: paginate [collection] by number")
|
raise SyntaxError, "Syntax Error in tag 'paginate' - Valid syntax: paginate [collection] by number"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -25,19 +27,19 @@ class Paginate < Liquid::Block
|
|||||||
@context = context
|
@context = context
|
||||||
|
|
||||||
context.stack do
|
context.stack do
|
||||||
current_page = context['current_page'].to_i
|
current_page = context['current_page'].to_i
|
||||||
|
|
||||||
pagination = {
|
pagination = {
|
||||||
'page_size' => @page_size,
|
'page_size' => @page_size,
|
||||||
'current_page' => 5,
|
'current_page' => 5,
|
||||||
'current_offset' => @page_size * 5
|
'current_offset' => @page_size * 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
context['paginate'] = pagination
|
context['paginate'] = pagination
|
||||||
|
|
||||||
collection_size = context[@collection_name].size
|
collection_size = context[@collection_name].size
|
||||||
|
|
||||||
raise ArgumentError.new("Cannot paginate array '#{@collection_name}'. Not found.") if collection_size.nil?
|
raise ArgumentError, "Cannot paginate array '#{@collection_name}'. Not found." if collection_size.nil?
|
||||||
|
|
||||||
page_count = (collection_size.to_f / @page_size.to_f).to_f.ceil + 1
|
page_count = (collection_size.to_f / @page_size.to_f).to_f.ceil + 1
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ShopFilter
|
module ShopFilter
|
||||||
def asset_url(input)
|
def asset_url(input)
|
||||||
"/files/1/[shop_id]/[shop_id]/assets/#{input}"
|
"/files/1/[shop_id]/[shop_id]/assets/#{input}"
|
||||||
@@ -52,7 +54,7 @@ module ShopFilter
|
|||||||
end
|
end
|
||||||
|
|
||||||
def product_img_url(url, style = 'small')
|
def product_img_url(url, style = 'small')
|
||||||
unless url =~ /\Aproducts\/([\w\-\_]+)\.(\w{2,4})/
|
unless url =~ %r{\Aproducts/([\w\-\_]+)\.(\w{2,4})}
|
||||||
raise ArgumentError, 'filter "size" can only be called on product images'
|
raise ArgumentError, 'filter "size" can only be called on product images'
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ module ShopFilter
|
|||||||
when 'original'
|
when 'original'
|
||||||
return '/files/shops/random_number/' + url
|
return '/files/shops/random_number/' + url
|
||||||
when 'grande', 'large', 'medium', 'compact', 'small', 'thumb', 'icon'
|
when 'grande', 'large', 'medium', 'compact', 'small', 'thumb', 'icon'
|
||||||
"/files/shops/random_number/products/#{$1}_#{style}.#{$2}"
|
"/files/shops/random_number/products/#{Regexp.last_match(1)}_#{style}.#{Regexp.last_match(2)}"
|
||||||
else
|
else
|
||||||
raise ArgumentError, 'valid parameters for filter "size" are: original, grande, large, medium, compact, small, thumb and icon '
|
raise ArgumentError, 'valid parameters for filter "size" are: original, grande, large, medium, compact, small, thumb and icon '
|
||||||
end
|
end
|
||||||
@@ -70,16 +72,14 @@ module ShopFilter
|
|||||||
html = []
|
html = []
|
||||||
html << %(<span class="prev">#{link_to(paginate['previous']['title'], paginate['previous']['url'])}</span>) if paginate['previous']
|
html << %(<span class="prev">#{link_to(paginate['previous']['title'], paginate['previous']['url'])}</span>) if paginate['previous']
|
||||||
|
|
||||||
for part in paginate['parts']
|
paginate['parts'].each do |part|
|
||||||
|
html << if part['is_link']
|
||||||
if part['is_link']
|
%(<span class="page">#{link_to(part['title'], part['url'])}</span>)
|
||||||
html << %(<span class="page">#{link_to(part['title'], part['url'])}</span>)
|
|
||||||
elsif part['title'].to_i == paginate['current_page'].to_i
|
elsif part['title'].to_i == paginate['current_page'].to_i
|
||||||
html << %(<span class="page current">#{part['title']}</span>)
|
%(<span class="page current">#{part['title']}</span>)
|
||||||
else
|
else
|
||||||
html << %(<span class="deco">#{part['title']}</span>)
|
%(<span class="deco">#{part['title']}</span>)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
html << %(<span class="next">#{link_to(paginate['next']['title'], paginate['next']['url'])}</span>) if paginate['next']
|
html << %(<span class="next">#{link_to(paginate['next']['title'], paginate['next']['url'])}</span>) if paginate['next']
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module TagFilter
|
module TagFilter
|
||||||
def link_to_tag(label, tag)
|
def link_to_tag(label, tag)
|
||||||
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tag}\">#{label}</a>"
|
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tag}\">#{label}</a>"
|
||||||
@@ -13,11 +15,11 @@ module TagFilter
|
|||||||
|
|
||||||
def link_to_add_tag(label, tag)
|
def link_to_add_tag(label, tag)
|
||||||
tags = (@context['current_tags'] + [tag]).uniq
|
tags = (@context['current_tags'] + [tag]).uniq
|
||||||
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tags.join("+")}\">#{label}</a>"
|
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tags.join('+')}\">#{label}</a>"
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_remove_tag(label, tag)
|
def link_to_remove_tag(label, tag)
|
||||||
tags = (@context['current_tags'] - [tag]).uniq
|
tags = (@context['current_tags'] - [tag]).uniq
|
||||||
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tags.join("+")}\">#{label}</a>"
|
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tags.join('+')}\">#{label}</a>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module WeightFilter
|
module WeightFilter
|
||||||
def weight(grams)
|
def weight(grams)
|
||||||
sprintf("%.2f", grams / 1000)
|
format("%.2f", grams / 1000)
|
||||||
end
|
end
|
||||||
|
|
||||||
def weight_with_unit(grams)
|
def weight_with_unit(grams)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# This profiler run simulates Shopify.
|
# This profiler run simulates Shopify.
|
||||||
# We are looking in the tests directory for liquid files and render them within the designated layout file.
|
# 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.
|
# We will also export a substantial database to liquid which the templates can render values of.
|
||||||
@@ -31,7 +33,7 @@ class ThemeRunner
|
|||||||
{
|
{
|
||||||
liquid: File.read(test),
|
liquid: File.read(test),
|
||||||
layout: (File.file?(theme_path) ? File.read(theme_path) : nil),
|
layout: (File.file?(theme_path) ? File.read(theme_path) : nil),
|
||||||
template_name: test
|
template_name: test,
|
||||||
}
|
}
|
||||||
end.compact
|
end.compact
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class AssignTest < Minitest::Test
|
class AssignTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class FoobarTag < Liquid::Tag
|
class FoobarTag < Liquid::Tag
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(_context, output)
|
||||||
output << ' '
|
output << ' '
|
||||||
output
|
output
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class BlockTest < Minitest::Test
|
class BlockTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class CaptureTest < Minitest::Test
|
class CaptureTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class ContextTest < Minitest::Test
|
class ContextTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class DocumentTest < Minitest::Test
|
class DocumentTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class ContextDrop < Liquid::Drop
|
class ContextDrop < Liquid::Drop
|
||||||
@@ -31,7 +33,7 @@ class ProductDrop < Liquid::Drop
|
|||||||
|
|
||||||
class CatchallDrop < Liquid::Drop
|
class CatchallDrop < Liquid::Drop
|
||||||
def liquid_method_missing(method)
|
def liquid_method_missing(method)
|
||||||
'catchall_method: ' << method.to_s
|
"catchall_method: #{method}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ class ProductDrop < Liquid::Drop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def user_input
|
def user_input
|
||||||
"foo".taint
|
(+"foo").taint
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
@@ -201,9 +203,9 @@ class DropsTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_scope_though_proc
|
def test_scope_though_proc
|
||||||
assert_equal '1', Liquid::Template.parse('{{ s }}').render!('context' => ContextDrop.new, 's' => proc{ |c| c['context.scopes'] })
|
assert_equal '1', Liquid::Template.parse('{{ s }}').render!('context' => ContextDrop.new, 's' => proc { |c| c['context.scopes'] })
|
||||||
assert_equal '2', Liquid::Template.parse('{%for i in dummy%}{{ s }}{%endfor%}').render!('context' => ContextDrop.new, 's' => proc{ |c| c['context.scopes'] }, 'dummy' => [1])
|
assert_equal '2', Liquid::Template.parse('{%for i in dummy%}{{ s }}{%endfor%}').render!('context' => ContextDrop.new, 's' => proc { |c| c['context.scopes'] }, 'dummy' => [1])
|
||||||
assert_equal '3', Liquid::Template.parse('{%for i in dummy%}{%for i in dummy%}{{ s }}{%endfor%}{%endfor%}').render!('context' => ContextDrop.new, 's' => proc{ |c| c['context.scopes'] }, 'dummy' => [1])
|
assert_equal '3', Liquid::Template.parse('{%for i in dummy%}{%for i in dummy%}{{ s }}{%endfor%}{%endfor%}').render!('context' => ContextDrop.new, 's' => proc { |c| c['context.scopes'] }, 'dummy' => [1])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_scope_with_assigns
|
def test_scope_with_assigns
|
||||||
@@ -241,7 +243,7 @@ class DropsTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_some_enumerable_methods_still_get_invoked
|
def test_some_enumerable_methods_still_get_invoked
|
||||||
[ :count, :max ].each do |method|
|
[:count, :max].each do |method|
|
||||||
assert_equal "3", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => RealEnumerableDrop.new)
|
assert_equal "3", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => RealEnumerableDrop.new)
|
||||||
assert_equal "3", Liquid::Template.parse("{{collection[\"#{method}\"]}}").render!('collection' => RealEnumerableDrop.new)
|
assert_equal "3", Liquid::Template.parse("{{collection[\"#{method}\"]}}").render!('collection' => RealEnumerableDrop.new)
|
||||||
assert_equal "3", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => EnumerableDrop.new)
|
assert_equal "3", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => EnumerableDrop.new)
|
||||||
@@ -250,7 +252,7 @@ class DropsTest < Minitest::Test
|
|||||||
|
|
||||||
assert_equal "yes", Liquid::Template.parse("{% if collection contains 3 %}yes{% endif %}").render!('collection' => RealEnumerableDrop.new)
|
assert_equal "yes", Liquid::Template.parse("{% if collection contains 3 %}yes{% endif %}").render!('collection' => RealEnumerableDrop.new)
|
||||||
|
|
||||||
[ :min, :first ].each do |method|
|
[:min, :first].each do |method|
|
||||||
assert_equal "1", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => RealEnumerableDrop.new)
|
assert_equal "1", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => RealEnumerableDrop.new)
|
||||||
assert_equal "1", Liquid::Template.parse("{{collection[\"#{method}\"]}}").render!('collection' => RealEnumerableDrop.new)
|
assert_equal "1", Liquid::Template.parse("{{collection[\"#{method}\"]}}").render!('collection' => RealEnumerableDrop.new)
|
||||||
assert_equal "1", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => EnumerableDrop.new)
|
assert_equal "1", Liquid::Template.parse("{{collection.#{method}}}").render!('collection' => EnumerableDrop.new)
|
||||||
@@ -270,4 +272,11 @@ class DropsTest < Minitest::Test
|
|||||||
assert_equal 'ProductDrop', Liquid::Template.parse("{{ product }}").render!('product' => ProductDrop.new)
|
assert_equal 'ProductDrop', Liquid::Template.parse("{{ product }}").render!('product' => ProductDrop.new)
|
||||||
assert_equal 'EnumerableDrop', Liquid::Template.parse('{{ collection }}').render!('collection' => EnumerableDrop.new)
|
assert_equal 'EnumerableDrop', Liquid::Template.parse('{{ collection }}').render!('collection' => EnumerableDrop.new)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_invokable_methods
|
||||||
|
assert_equal %w(to_liquid catchall user_input context texts).to_set, ProductDrop.invokable_methods
|
||||||
|
assert_equal %w(to_liquid scopes_as_array loop_pos scopes).to_set, ContextDrop.invokable_methods
|
||||||
|
assert_equal %w(to_liquid size max min first count).to_set, EnumerableDrop.invokable_methods
|
||||||
|
assert_equal %w(to_liquid max min sort count first).to_set, RealEnumerableDrop.invokable_methods
|
||||||
|
end
|
||||||
end # DropsTest
|
end # DropsTest
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class ErrorHandlingTest < Minitest::Test
|
class ErrorHandlingTest < Minitest::Test
|
||||||
@@ -83,15 +85,14 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
|
|
||||||
def test_with_line_numbers_adds_numbers_to_parser_errors
|
def test_with_line_numbers_adds_numbers_to_parser_errors
|
||||||
err = assert_raises(SyntaxError) do
|
err = assert_raises(SyntaxError) do
|
||||||
Liquid::Template.parse(%q(
|
Liquid::Template.parse('
|
||||||
foobar
|
foobar
|
||||||
|
|
||||||
{% "cat" | foobar %}
|
{% "cat" | foobar %}
|
||||||
|
|
||||||
bla
|
bla
|
||||||
),
|
',
|
||||||
line_numbers: true
|
line_numbers: true)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_match(/Liquid syntax error \(line 4\)/, err.message)
|
assert_match(/Liquid syntax error \(line 4\)/, err.message)
|
||||||
@@ -99,15 +100,14 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
|
|
||||||
def test_with_line_numbers_adds_numbers_to_parser_errors_with_whitespace_trim
|
def test_with_line_numbers_adds_numbers_to_parser_errors_with_whitespace_trim
|
||||||
err = assert_raises(SyntaxError) do
|
err = assert_raises(SyntaxError) do
|
||||||
Liquid::Template.parse(%q(
|
Liquid::Template.parse('
|
||||||
foobar
|
foobar
|
||||||
|
|
||||||
{%- "cat" | foobar -%}
|
{%- "cat" | foobar -%}
|
||||||
|
|
||||||
bla
|
bla
|
||||||
),
|
',
|
||||||
line_numbers: true
|
line_numbers: true)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_match(/Liquid syntax error \(line 4\)/, err.message)
|
assert_match(/Liquid syntax error \(line 4\)/, err.message)
|
||||||
@@ -122,8 +122,7 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
bla
|
bla
|
||||||
',
|
',
|
||||||
error_mode: :warn,
|
error_mode: :warn,
|
||||||
line_numbers: true
|
line_numbers: true)
|
||||||
)
|
|
||||||
|
|
||||||
assert_equal ['Liquid syntax error (line 4): Unexpected character = in "1 =! 2"'],
|
assert_equal ['Liquid syntax error (line 4): Unexpected character = in "1 =! 2"'],
|
||||||
template.warnings.map(&:message)
|
template.warnings.map(&:message)
|
||||||
@@ -139,8 +138,7 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
bla
|
bla
|
||||||
',
|
',
|
||||||
error_mode: :strict,
|
error_mode: :strict,
|
||||||
line_numbers: true
|
line_numbers: true)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal 'Liquid syntax error (line 4): Unexpected character = in "1 =! 2"', err.message
|
assert_equal 'Liquid syntax error (line 4): Unexpected character = in "1 =! 2"', err.message
|
||||||
@@ -157,8 +155,7 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
|
|
||||||
bla
|
bla
|
||||||
',
|
',
|
||||||
line_numbers: true
|
line_numbers: true)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "Liquid syntax error (line 5): Unknown tag 'foo'", err.message
|
assert_equal "Liquid syntax error (line 5): Unknown tag 'foo'", err.message
|
||||||
@@ -205,7 +202,7 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
def test_default_exception_renderer_with_internal_error
|
def test_default_exception_renderer_with_internal_error
|
||||||
template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}', line_numbers: true)
|
template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}', line_numbers: true)
|
||||||
|
|
||||||
output = template.render({ 'errors' => ErrorDrop.new })
|
output = template.render('errors' => ErrorDrop.new)
|
||||||
|
|
||||||
assert_equal 'This is a runtime error: Liquid error (line 1): internal', output
|
assert_equal 'This is a runtime error: Liquid error (line 1): internal', output
|
||||||
assert_equal [Liquid::InternalError], template.errors.map(&:class)
|
assert_equal [Liquid::InternalError], template.errors.map(&:class)
|
||||||
@@ -214,10 +211,13 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
def test_setting_default_exception_renderer
|
def test_setting_default_exception_renderer
|
||||||
old_exception_renderer = Liquid::Template.default_exception_renderer
|
old_exception_renderer = Liquid::Template.default_exception_renderer
|
||||||
exceptions = []
|
exceptions = []
|
||||||
Liquid::Template.default_exception_renderer = ->(e) { exceptions << e; '' }
|
Liquid::Template.default_exception_renderer = ->(e) {
|
||||||
|
exceptions << e
|
||||||
|
''
|
||||||
|
}
|
||||||
template = Liquid::Template.parse('This is a runtime error: {{ errors.argument_error }}')
|
template = Liquid::Template.parse('This is a runtime error: {{ errors.argument_error }}')
|
||||||
|
|
||||||
output = template.render({ 'errors' => ErrorDrop.new })
|
output = template.render('errors' => ErrorDrop.new)
|
||||||
|
|
||||||
assert_equal 'This is a runtime error: ', output
|
assert_equal 'This is a runtime error: ', output
|
||||||
assert_equal [Liquid::ArgumentError], template.errors.map(&:class)
|
assert_equal [Liquid::ArgumentError], template.errors.map(&:class)
|
||||||
@@ -228,7 +228,10 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
def test_exception_renderer_exposing_non_liquid_error
|
def test_exception_renderer_exposing_non_liquid_error
|
||||||
template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}', line_numbers: true)
|
template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}', line_numbers: true)
|
||||||
exceptions = []
|
exceptions = []
|
||||||
handler = ->(e) { exceptions << e; e.cause }
|
handler = ->(e) {
|
||||||
|
exceptions << e
|
||||||
|
e.cause
|
||||||
|
}
|
||||||
|
|
||||||
output = template.render({ 'errors' => ErrorDrop.new }, exception_renderer: handler)
|
output = template.render({ 'errors' => ErrorDrop.new }, exception_renderer: handler)
|
||||||
|
|
||||||
@@ -239,7 +242,7 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
class TestFileSystem
|
class TestFileSystem
|
||||||
def read_template_file(template_path)
|
def read_template_file(_template_path)
|
||||||
"{{ errors.argument_error }}"
|
"{{ errors.argument_error }}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
module MoneyFilter
|
module MoneyFilter
|
||||||
def money(input)
|
def money(input)
|
||||||
sprintf(' %d$ ', input)
|
format(' %d$ ', input)
|
||||||
end
|
end
|
||||||
|
|
||||||
def money_with_underscore(input)
|
def money_with_underscore(input)
|
||||||
sprintf(' %d$ ', input)
|
format(' %d$ ', input)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module CanadianMoneyFilter
|
module CanadianMoneyFilter
|
||||||
def money(input)
|
def money(input)
|
||||||
sprintf(' %d$ CAD ', input)
|
format(' %d$ CAD ', input)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module SubstituteFilter
|
module SubstituteFilter
|
||||||
def substitute(input, params = {})
|
def substitute(input, params = {})
|
||||||
input.gsub(/%\{(\w+)\}/) { |match| params[$1] }
|
input.gsub(/%\{(\w+)\}/) { |_match| params[Regexp.last_match(1)] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ class FiltersTest < Minitest::Test
|
|||||||
include Liquid
|
include Liquid
|
||||||
|
|
||||||
module OverrideObjectMethodFilter
|
module OverrideObjectMethodFilter
|
||||||
def tap(input)
|
def tap(_input)
|
||||||
"tap overridden"
|
"tap overridden"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -149,7 +151,7 @@ class FiltersTest < Minitest::Test
|
|||||||
assert_equal "tap overridden", Template.parse("{{var | tap}}").render!({ 'var' => 1000 }, filters: [OverrideObjectMethodFilter])
|
assert_equal "tap overridden", Template.parse("{{var | tap}}").render!({ 'var' => 1000 }, filters: [OverrideObjectMethodFilter])
|
||||||
|
|
||||||
# tap still treated as a non-existent filter
|
# tap still treated as a non-existent filter
|
||||||
assert_equal "1000", Template.parse("{{var | tap}}").render!({ 'var' => 1000 })
|
assert_equal "1000", Template.parse("{{var | tap}}").render!('var' => 1000)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class HashOrderingTest < Minitest::Test
|
class HashOrderingTest < Minitest::Test
|
||||||
module MoneyFilter
|
module MoneyFilter
|
||||||
def money(input)
|
def money(input)
|
||||||
sprintf(' %d$ ', input)
|
format(' %d$ ', input)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module CanadianMoneyFilter
|
module CanadianMoneyFilter
|
||||||
def money(input)
|
def money(input)
|
||||||
sprintf(' %d$ CAD ', input)
|
format(' %d$ CAD ', input)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
module FunnyFilter
|
module FunnyFilter
|
||||||
def make_funny(input)
|
def make_funny(_input)
|
||||||
'LOL'
|
'LOL'
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ class OutputTest < Minitest::Test
|
|||||||
def setup
|
def setup
|
||||||
@assigns = {
|
@assigns = {
|
||||||
'best_cars' => 'bmw',
|
'best_cars' => 'bmw',
|
||||||
'car' => { 'bmw' => 'good', 'gm' => 'bad' }
|
'car' => { 'bmw' => 'good', 'gm' => 'bad' },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ class ParseTreeVisitorTest < Minitest::Test
|
|||||||
[[nil, [
|
[[nil, [
|
||||||
[nil, [[nil, [["other", []]]]]],
|
[nil, [[nil, [["other", []]]]]],
|
||||||
["test", []],
|
["test", []],
|
||||||
["xs", []]
|
["xs", []],
|
||||||
]]],
|
]]],
|
||||||
traversal(%({% for x in xs offset: test %}{{ other }}{% endfor %})).visit
|
traversal(%({% for x in xs offset: test %}{{ other }}{% endfor %})).visit
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class ParsingQuirksTest < Minitest::Test
|
class ParsingQuirksTest < Minitest::Test
|
||||||
|
|||||||
27
test/integration/registers/disabled_tags_test.rb
Normal file
27
test/integration/registers/disabled_tags_test.rb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class DisabledTagsTest < Minitest::Test
|
||||||
|
include Liquid
|
||||||
|
|
||||||
|
class DisableRaw < Block
|
||||||
|
disable_tags "raw"
|
||||||
|
end
|
||||||
|
|
||||||
|
class DisableRawEcho < Block
|
||||||
|
disable_tags "raw", "echo"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disables_raw
|
||||||
|
with_custom_tag('disable', DisableRaw) do
|
||||||
|
assert_template_result 'raw usage is not allowed in this contextfoo', '{% disable %}{% raw %}Foobar{% endraw %}{% echo "foo" %}{% enddisable %}'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disables_echo_and_raw
|
||||||
|
with_custom_tag('disable', DisableRawEcho) do
|
||||||
|
assert_template_result 'raw usage is not allowed in this contextecho usage is not allowed in this context', '{% disable %}{% raw %}Foobar{% endraw %}{% echo "foo" %}{% enddisable %}'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class RenderProfilingTest < Minitest::Test
|
class RenderProfilingTest < Minitest::Test
|
||||||
@@ -128,7 +130,7 @@ class RenderProfilingTest < Minitest::Test
|
|||||||
t.render!
|
t.render!
|
||||||
|
|
||||||
timing_count = 0
|
timing_count = 0
|
||||||
t.profiler.each do |timing|
|
t.profiler.each do |_timing|
|
||||||
timing_count += 1
|
timing_count += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -145,7 +147,7 @@ class RenderProfilingTest < Minitest::Test
|
|||||||
|
|
||||||
def test_profiling_marks_children_of_for_blocks
|
def test_profiling_marks_children_of_for_blocks
|
||||||
t = Template.parse("{% for item in collection %} {{ item }} {% endfor %}", profile: true)
|
t = Template.parse("{% for item in collection %} {{ item }} {% endfor %}", profile: true)
|
||||||
t.render!({ "collection" => ["one", "two"] })
|
t.render!("collection" => ["one", "two"])
|
||||||
|
|
||||||
assert_equal 1, t.profiler.length
|
assert_equal 1, t.profiler.length
|
||||||
# Will profile each invocation of the for block
|
# Will profile each invocation of the for block
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
module SecurityFilter
|
module SecurityFilter
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ class TestThing
|
|||||||
"woot: #{@foo}"
|
"woot: #{@foo}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](whatever)
|
def [](_whatever)
|
||||||
to_s
|
to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ class TestEnumerable < Liquid::Drop
|
|||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
def each(&block)
|
def each(&block)
|
||||||
[ { "foo" => 1, "bar" => 2 }, { "foo" => 2, "bar" => 1 }, { "foo" => 3, "bar" => 3 } ].each(&block)
|
[{ "foo" => 1, "bar" => 2 }, { "foo" => 2, "bar" => 1 }, { "foo" => 3, "bar" => 3 }].each(&block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -197,6 +198,12 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
assert_equal [{ "a" => 1 }, { "a" => 2 }, { "a" => 3 }, { "a" => 4 }], @filters.sort([{ "a" => 4 }, { "a" => 3 }, { "a" => 1 }, { "a" => 2 }], "a")
|
assert_equal [{ "a" => 1 }, { "a" => 2 }, { "a" => 3 }, { "a" => 4 }], @filters.sort([{ "a" => 4 }, { "a" => 3 }, { "a" => 1 }, { "a" => 2 }], "a")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_sort_numeric
|
||||||
|
assert_equal ['1', '2', '3', '10'], @filters.sort_numeric(['10', '3', '2', '1'])
|
||||||
|
assert_equal [{ "a" => '1' }, { "a" => '2' }, { "a" => '3' }, { "a" => '10' }],
|
||||||
|
@filters.sort_numeric([{ "a" => '10' }, { "a" => '3' }, { "a" => '1' }, { "a" => '2' }], "a")
|
||||||
|
end
|
||||||
|
|
||||||
def test_sort_with_nils
|
def test_sort_with_nils
|
||||||
assert_equal [1, 2, 3, 4, nil], @filters.sort([nil, 4, 3, 2, 1])
|
assert_equal [1, 2, 3, 4, nil], @filters.sort([nil, 4, 3, 2, 1])
|
||||||
assert_equal [{ "a" => 1 }, { "a" => 2 }, { "a" => 3 }, { "a" => 4 }, {}], @filters.sort([{ "a" => 4 }, { "a" => 3 }, {}, { "a" => 1 }, { "a" => 2 }], "a")
|
assert_equal [{ "a" => 1 }, { "a" => 2 }, { "a" => 3 }, { "a" => 4 }, {}], @filters.sort([{ "a" => 4 }, { "a" => 3 }, {}, { "a" => 1 }, { "a" => 2 }], "a")
|
||||||
@@ -208,14 +215,14 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "handle" => "beta" },
|
{ "handle" => "beta" },
|
||||||
{ "price" => 1, "handle" => "gamma" },
|
{ "price" => 1, "handle" => "gamma" },
|
||||||
{ "handle" => "delta" },
|
{ "handle" => "delta" },
|
||||||
{ "price" => 2, "handle" => "epsilon" }
|
{ "price" => 2, "handle" => "epsilon" },
|
||||||
]
|
]
|
||||||
expectation = [
|
expectation = [
|
||||||
{ "price" => 1, "handle" => "gamma" },
|
{ "price" => 1, "handle" => "gamma" },
|
||||||
{ "price" => 2, "handle" => "epsilon" },
|
{ "price" => 2, "handle" => "epsilon" },
|
||||||
{ "price" => 4, "handle" => "alpha" },
|
{ "price" => 4, "handle" => "alpha" },
|
||||||
{ "handle" => "delta" },
|
{ "handle" => "delta" },
|
||||||
{ "handle" => "beta" }
|
{ "handle" => "beta" },
|
||||||
]
|
]
|
||||||
assert_equal expectation, @filters.sort(input, "price")
|
assert_equal expectation, @filters.sort(input, "price")
|
||||||
end
|
end
|
||||||
@@ -236,14 +243,14 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "handle" => "beta" },
|
{ "handle" => "beta" },
|
||||||
{ "price" => "1", "handle" => "gamma" },
|
{ "price" => "1", "handle" => "gamma" },
|
||||||
{ "handle" => "delta" },
|
{ "handle" => "delta" },
|
||||||
{ "price" => 2, "handle" => "epsilon" }
|
{ "price" => 2, "handle" => "epsilon" },
|
||||||
]
|
]
|
||||||
expectation = [
|
expectation = [
|
||||||
{ "price" => "1", "handle" => "gamma" },
|
{ "price" => "1", "handle" => "gamma" },
|
||||||
{ "price" => 2, "handle" => "epsilon" },
|
{ "price" => 2, "handle" => "epsilon" },
|
||||||
{ "price" => "4", "handle" => "alpha" },
|
{ "price" => "4", "handle" => "alpha" },
|
||||||
{ "handle" => "delta" },
|
{ "handle" => "delta" },
|
||||||
{ "handle" => "beta" }
|
{ "handle" => "beta" },
|
||||||
]
|
]
|
||||||
assert_equal expectation, @filters.sort_natural(input, "price")
|
assert_equal expectation, @filters.sort_natural(input, "price")
|
||||||
end
|
end
|
||||||
@@ -256,7 +263,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "fake" => "t" },
|
{ "fake" => "t" },
|
||||||
{ "key" => "a" },
|
{ "key" => "a" },
|
||||||
{ "key" => "b" },
|
{ "key" => "b" },
|
||||||
{ "key" => "c" }
|
{ "key" => "c" },
|
||||||
]
|
]
|
||||||
expectation = [
|
expectation = [
|
||||||
{ "key" => "a" },
|
{ "key" => "a" },
|
||||||
@@ -265,7 +272,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "key" => "X" },
|
{ "key" => "X" },
|
||||||
{ "key" => "Y" },
|
{ "key" => "Y" },
|
||||||
{ "key" => "Z" },
|
{ "key" => "Z" },
|
||||||
{ "fake" => "t" }
|
{ "fake" => "t" },
|
||||||
]
|
]
|
||||||
assert_equal expectation, @filters.sort_natural(input, "key")
|
assert_equal expectation, @filters.sort_natural(input, "key")
|
||||||
assert_equal ["a", "b", "c", "X", "Y", "Z"], @filters.sort_natural(["X", "Y", "Z", "a", "b", "c"])
|
assert_equal ["a", "b", "c", "X", "Y", "Z"], @filters.sort_natural(["X", "Y", "Z", "a", "b", "c"])
|
||||||
@@ -279,7 +286,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
foo = [
|
foo = [
|
||||||
[1],
|
[1],
|
||||||
[2],
|
[2],
|
||||||
[3]
|
[3],
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_raises Liquid::ArgumentError do
|
assert_raises Liquid::ArgumentError do
|
||||||
@@ -291,11 +298,15 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
assert_equal [], @filters.sort_natural([], "a")
|
assert_equal [], @filters.sort_natural([], "a")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_sort_numeric_empty_array
|
||||||
|
assert_equal [], @filters.sort_numeric([], "a")
|
||||||
|
end
|
||||||
|
|
||||||
def test_sort_natural_invalid_property
|
def test_sort_natural_invalid_property
|
||||||
foo = [
|
foo = [
|
||||||
[1],
|
[1],
|
||||||
[2],
|
[2],
|
||||||
[3]
|
[3],
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_raises Liquid::ArgumentError do
|
assert_raises Liquid::ArgumentError do
|
||||||
@@ -304,7 +315,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_legacy_sort_hash
|
def test_legacy_sort_hash
|
||||||
assert_equal [{ a: 1, b: 2 }], @filters.sort({ a: 1, b: 2 })
|
assert_equal [{ a: 1, b: 2 }], @filters.sort(a: 1, b: 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_numerical_vs_lexicographical_sort
|
def test_numerical_vs_lexicographical_sort
|
||||||
@@ -330,7 +341,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
foo = [
|
foo = [
|
||||||
[1],
|
[1],
|
||||||
[2],
|
[2],
|
||||||
[3]
|
[3],
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_raises Liquid::ArgumentError do
|
assert_raises Liquid::ArgumentError do
|
||||||
@@ -346,7 +357,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
foo = [
|
foo = [
|
||||||
[1],
|
[1],
|
||||||
[2],
|
[2],
|
||||||
[3]
|
[3],
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_raises Liquid::ArgumentError do
|
assert_raises Liquid::ArgumentError do
|
||||||
@@ -380,7 +391,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
|
|
||||||
def test_map_on_hashes
|
def test_map_on_hashes
|
||||||
assert_template_result "4217", '{{ thing | map: "foo" | map: "bar" }}',
|
assert_template_result "4217", '{{ thing | map: "foo" | map: "bar" }}',
|
||||||
"thing" => { "foo" => [ { "bar" => 42 }, { "bar" => 17 } ] }
|
"thing" => { "foo" => [{ "bar" => 42 }, { "bar" => 17 }] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_legacy_map_on_hashes_with_dynamic_key
|
def test_legacy_map_on_hashes_with_dynamic_key
|
||||||
@@ -397,7 +408,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
|
|
||||||
def test_map_over_proc
|
def test_map_over_proc
|
||||||
drop = TestDrop.new
|
drop = TestDrop.new
|
||||||
p = proc{ drop }
|
p = proc { drop }
|
||||||
templ = '{{ procs | map: "test" }}'
|
templ = '{{ procs | map: "test" }}'
|
||||||
assert_template_result "testfoo", templ, "procs" => [p]
|
assert_template_result "testfoo", templ, "procs" => [p]
|
||||||
end
|
end
|
||||||
@@ -405,10 +416,10 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
def test_map_over_drops_returning_procs
|
def test_map_over_drops_returning_procs
|
||||||
drops = [
|
drops = [
|
||||||
{
|
{
|
||||||
"proc" => ->{ "foo" },
|
"proc" => -> { "foo" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"proc" => ->{ "bar" },
|
"proc" => -> { "bar" },
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
templ = '{{ drops | map: "proc" }}'
|
templ = '{{ drops | map: "proc" }}'
|
||||||
@@ -423,7 +434,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
foo = [
|
foo = [
|
||||||
[1],
|
[1],
|
||||||
[2],
|
[2],
|
||||||
[3]
|
[3],
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_raises Liquid::ArgumentError do
|
assert_raises Liquid::ArgumentError do
|
||||||
@@ -435,7 +446,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
foo = [
|
foo = [
|
||||||
[1],
|
[1],
|
||||||
[2],
|
[2],
|
||||||
[3]
|
[3],
|
||||||
]
|
]
|
||||||
assert_raises Liquid::ArgumentError do
|
assert_raises Liquid::ArgumentError do
|
||||||
@filters.map(foo, nil)
|
@filters.map(foo, nil)
|
||||||
@@ -697,12 +708,12 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "handle" => "alpha", "ok" => true },
|
{ "handle" => "alpha", "ok" => true },
|
||||||
{ "handle" => "beta", "ok" => false },
|
{ "handle" => "beta", "ok" => false },
|
||||||
{ "handle" => "gamma", "ok" => false },
|
{ "handle" => "gamma", "ok" => false },
|
||||||
{ "handle" => "delta", "ok" => true }
|
{ "handle" => "delta", "ok" => true },
|
||||||
]
|
]
|
||||||
|
|
||||||
expectation = [
|
expectation = [
|
||||||
{ "handle" => "alpha", "ok" => true },
|
{ "handle" => "alpha", "ok" => true },
|
||||||
{ "handle" => "delta", "ok" => true }
|
{ "handle" => "delta", "ok" => true },
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_equal expectation, @filters.where(input, "ok", true)
|
assert_equal expectation, @filters.where(input, "ok", true)
|
||||||
@@ -714,12 +725,12 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "handle" => "alpha", "ok" => true },
|
{ "handle" => "alpha", "ok" => true },
|
||||||
{ "handle" => "beta" },
|
{ "handle" => "beta" },
|
||||||
{ "handle" => "gamma" },
|
{ "handle" => "gamma" },
|
||||||
{ "handle" => "delta", "ok" => true }
|
{ "handle" => "delta", "ok" => true },
|
||||||
]
|
]
|
||||||
|
|
||||||
expectation = [
|
expectation = [
|
||||||
{ "handle" => "alpha", "ok" => true },
|
{ "handle" => "alpha", "ok" => true },
|
||||||
{ "handle" => "delta", "ok" => true }
|
{ "handle" => "delta", "ok" => true },
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_equal expectation, @filters.where(input, "ok", true)
|
assert_equal expectation, @filters.where(input, "ok", true)
|
||||||
@@ -740,7 +751,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
input = [
|
input = [
|
||||||
{ "message" => "Bonjour!", "language" => "French" },
|
{ "message" => "Bonjour!", "language" => "French" },
|
||||||
{ "message" => "Hello!", "language" => "English" },
|
{ "message" => "Hello!", "language" => "English" },
|
||||||
{ "message" => "Hallo!", "language" => "German" }
|
{ "message" => "Hallo!", "language" => "German" },
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_equal [{ "message" => "Bonjour!", "language" => "French" }], @filters.where(input, "language", "French")
|
assert_equal [{ "message" => "Bonjour!", "language" => "French" }], @filters.where(input, "language", "French")
|
||||||
@@ -758,7 +769,7 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
{ "foo" => false },
|
{ "foo" => false },
|
||||||
{ "foo" => true },
|
{ "foo" => true },
|
||||||
{ "foo" => "for sure" },
|
{ "foo" => "for sure" },
|
||||||
{ "bar" => true }
|
{ "bar" => true },
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_equal [{ "foo" => true }, { "foo" => "for sure" }], @filters.where(input, "foo")
|
assert_equal [{ "foo" => true }, { "foo" => "for sure" }], @filters.where(input, "foo")
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class BreakTagTest < Minitest::Test
|
class BreakTagTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class ContinueTagTest < Minitest::Test
|
class ContinueTagTest < Minitest::Test
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class EchoTest < Minitest::Test
|
class EchoTest < Minitest::Test
|
||||||
include Liquid
|
include Liquid
|
||||||
|
|
||||||
def test_echo_outputs_its_input
|
def test_echo_outputs_its_input
|
||||||
assert_template_result('BAR', <<~LIQUID, { 'variable-name' => 'bar' })
|
assert_template_result('BAR', <<~LIQUID, 'variable-name' => 'bar')
|
||||||
{%- echo variable-name | upcase -%}
|
{%- echo variable-name | upcase -%}
|
||||||
LIQUID
|
LIQUID
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class ThingWithValue < Liquid::Drop
|
class ThingWithValue < Liquid::Drop
|
||||||
@@ -23,16 +25,16 @@ class ForTagTest < Minitest::Test
|
|||||||
yo
|
yo
|
||||||
|
|
||||||
HERE
|
HERE
|
||||||
template = <<HERE
|
template = <<~HERE
|
||||||
{%for item in array%}
|
{%for item in array%}
|
||||||
yo
|
yo
|
||||||
{%endfor%}
|
{%endfor%}
|
||||||
HERE
|
HERE
|
||||||
assert_template_result(expected, template, 'array' => [1, 2, 3])
|
assert_template_result(expected, template, 'array' => [1, 2, 3])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_for_reversed
|
def test_for_reversed
|
||||||
assigns = { 'array' => [ 1, 2, 3] }
|
assigns = { 'array' => [1, 2, 3] }
|
||||||
assert_template_result('321', '{%for item in array reversed %}{{item}}{%endfor%}', assigns)
|
assert_template_result('321', '{%for item in array reversed %}{{item}}{%endfor%}', assigns)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class IfElseTagTest < Minitest::Test
|
class IfElseTagTest < Minitest::Test
|
||||||
@@ -132,7 +134,7 @@ class IfElseTagTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_syntax_error_no_variable
|
def test_syntax_error_no_variable
|
||||||
assert_raises(SyntaxError){ assert_template_result('', '{% if jerry == 1 %}') }
|
assert_raises(SyntaxError) { assert_template_result('', '{% if jerry == 1 %}') }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_syntax_error_no_expression
|
def test_syntax_error_no_expression
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user