mirror of
https://github.com/kemko/liquid.git
synced 2026-01-01 15:55:40 +03:00
Compare commits
17 Commits
fix-failin
...
liquid-pro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b06b71c34 | ||
|
|
78cd06fb92 | ||
|
|
ca6237cb33 | ||
|
|
b9597b548c | ||
|
|
806b2622da | ||
|
|
c34f7c9b2c | ||
|
|
604d899496 | ||
|
|
ddb45cd658 | ||
|
|
9876096cf4 | ||
|
|
8750b4b006 | ||
|
|
34083c96d5 | ||
|
|
9672ed5285 | ||
|
|
f3112fc038 | ||
|
|
d338ccb9a6 | ||
|
|
d67de1c9b2 | ||
|
|
b3097f143c | ||
|
|
7b309dc75d |
1027
.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml
Normal file
1027
.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml
Normal file
File diff suppressed because it is too large
Load Diff
122
.rubocop.yml
122
.rubocop.yml
@@ -1,6 +1,6 @@
|
||||
inherit_from:
|
||||
- https://shopify.github.io/ruby-style-guide/rubocop.yml
|
||||
- .rubocop_todo.yml
|
||||
- ./.rubocop_todo.yml
|
||||
|
||||
require: rubocop-performance
|
||||
|
||||
@@ -9,124 +9,8 @@ Performance:
|
||||
|
||||
AllCops:
|
||||
Exclude:
|
||||
- 'performance/shopify/*'
|
||||
- 'vendor/bundle/**/*'
|
||||
- 'pkg/**'
|
||||
|
||||
Metrics/BlockNesting:
|
||||
Max: 3
|
||||
|
||||
Metrics/ModuleLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/ClassLength:
|
||||
Enabled: false
|
||||
|
||||
Lint/AssignmentInCondition:
|
||||
Enabled: false
|
||||
|
||||
Lint/AmbiguousOperator:
|
||||
Enabled: false
|
||||
|
||||
Lint/AmbiguousRegexpLiteral:
|
||||
Enabled: false
|
||||
|
||||
Lint/ParenthesesAsGroupedExpression:
|
||||
Enabled: false
|
||||
|
||||
Lint/UnusedBlockArgument:
|
||||
Enabled: false
|
||||
|
||||
Layout/EndAlignment:
|
||||
EnforcedStyleAlignWith: variable
|
||||
|
||||
Lint/UnusedMethodArgument:
|
||||
Enabled: false
|
||||
|
||||
Style/SingleLineBlockParams:
|
||||
Enabled: false
|
||||
|
||||
Style/DoubleNegation:
|
||||
Enabled: false
|
||||
|
||||
Style/StringLiteralsInInterpolation:
|
||||
Enabled: false
|
||||
|
||||
Style/AndOr:
|
||||
Enabled: false
|
||||
|
||||
Style/SignalException:
|
||||
Enabled: false
|
||||
|
||||
Style/StringLiterals:
|
||||
Enabled: false
|
||||
|
||||
Style/BracesAroundHashParameters:
|
||||
Enabled: false
|
||||
|
||||
Style/NumericLiterals:
|
||||
Enabled: false
|
||||
|
||||
Layout/SpaceInsideArrayLiteralBrackets:
|
||||
Enabled: false
|
||||
|
||||
Layout/SpaceBeforeBlockBraces:
|
||||
Enabled: false
|
||||
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
|
||||
Style/TrailingCommaInArrayLiteral:
|
||||
Enabled: false
|
||||
|
||||
Style/TrailingCommaInHashLiteral:
|
||||
Enabled: false
|
||||
|
||||
Style/FormatString:
|
||||
Enabled: false
|
||||
|
||||
Layout/AlignParameters:
|
||||
EnforcedStyle: with_fixed_indentation
|
||||
|
||||
Layout/MultilineOperationIndentation:
|
||||
EnforcedStyle: indented
|
||||
|
||||
Style/IfUnlessModifier:
|
||||
Enabled: false
|
||||
|
||||
Style/RaiseArgs:
|
||||
Enabled: false
|
||||
|
||||
Style/PreferredHashMethods:
|
||||
Enabled: false
|
||||
|
||||
Style/RegexpLiteral:
|
||||
Enabled: false
|
||||
|
||||
Style/SymbolLiteral:
|
||||
Enabled: false
|
||||
|
||||
Naming/ConstantName:
|
||||
Enabled: false
|
||||
|
||||
Layout/CaseIndentation:
|
||||
Enabled: false
|
||||
|
||||
Style/ClassVars:
|
||||
Enabled: false
|
||||
|
||||
Style/PerlBackrefs:
|
||||
Enabled: false
|
||||
|
||||
Style/TrivialAccessors:
|
||||
AllowPredicates: true
|
||||
|
||||
Style/WordArray:
|
||||
Enabled: false
|
||||
|
||||
|
||||
Naming/MethodName:
|
||||
Exclude:
|
||||
- 'example/server/liquid_servlet.rb'
|
||||
- 'example/server/liquid_servlet.rb'
|
||||
@@ -1,34 +1,12 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2019-08-29 00:43:36 +1000 using RuboCop version 0.74.0.
|
||||
# on 2019-08-29 12:16:25 +1000 using RuboCop version 0.74.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: TreatCommentsAsGroupSeparators, Include.
|
||||
# Include: **/*.gemspec
|
||||
Gemspec/OrderedDependencies:
|
||||
Exclude:
|
||||
- 'liquid.gemspec'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: Include.
|
||||
# Include: **/*.gemspec,
|
||||
Gemspec/RequiredRubyVersion:
|
||||
Exclude:
|
||||
- 'liquid.gemspec'
|
||||
|
||||
# Offense count: 124
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
||||
# SupportedStyles: with_first_argument, with_fixed_indentation
|
||||
Layout/AlignArguments:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 7
|
||||
# Offense count: 13
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
||||
# SupportedHashRocketStyles: key, separator, table
|
||||
@@ -38,32 +16,17 @@ 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: 6
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Layout/ClosingHeredocIndentation:
|
||||
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
|
||||
Layout/ExtraSpacing:
|
||||
Exclude:
|
||||
- 'test/integration/tags/for_tag_test.rb'
|
||||
|
||||
# Offense count: 27
|
||||
# Cop supports --auto-correct.
|
||||
Layout/EmptyLineAfterGuardClause:
|
||||
Exclude:
|
||||
- 'lib/liquid/block.rb'
|
||||
- 'lib/liquid/block_body.rb'
|
||||
- 'lib/liquid/context.rb'
|
||||
- 'lib/liquid/drop.rb'
|
||||
- 'lib/liquid/lexer.rb'
|
||||
- 'lib/liquid/parser.rb'
|
||||
- 'lib/liquid/standardfilters.rb'
|
||||
- 'lib/liquid/strainer.rb'
|
||||
- 'lib/liquid/tags/for.rb'
|
||||
- 'lib/liquid/tags/if.rb'
|
||||
- 'lib/liquid/tags/include.rb'
|
||||
- 'lib/liquid/utils.rb'
|
||||
- 'lib/liquid/variable.rb'
|
||||
- 'lib/liquid/variable_lookup.rb'
|
||||
- 'performance/shopify/paginate.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
@@ -83,12 +46,61 @@ Layout/MultilineMethodCallBraceLayout:
|
||||
- 'test/integration/error_handling_test.rb'
|
||||
- 'test/unit/strainer_unit_test.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# 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
|
||||
# Cop supports --auto-correct.
|
||||
@@ -98,87 +110,133 @@ Lint/InheritException:
|
||||
Exclude:
|
||||
- 'lib/liquid/interrupts.rb'
|
||||
|
||||
# Offense count: 10
|
||||
# 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: 53
|
||||
Metrics/AbcSize:
|
||||
Max: 56
|
||||
|
||||
# Offense count: 12
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 13
|
||||
|
||||
# Offense count: 118
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/MethodLength:
|
||||
Max: 38
|
||||
|
||||
# Offense count: 9
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 11
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 95
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: PreferredName.
|
||||
Naming/RescuedExceptionsVariableName:
|
||||
Exclude:
|
||||
- 'lib/liquid/context.rb'
|
||||
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||
# URISchemes: http, https
|
||||
Metrics/LineLength:
|
||||
Max: 294
|
||||
|
||||
# Offense count: 20
|
||||
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
||||
# AllowedNames: io, id, to, by, on, in, at, ip, db
|
||||
Naming/UncommunicativeMethodParamName:
|
||||
# Offense count: 44
|
||||
Naming/ConstantName:
|
||||
Exclude:
|
||||
- 'example/server/example_servlet.rb'
|
||||
- 'lib/liquid/condition.rb'
|
||||
- 'lib/liquid/context.rb'
|
||||
- 'lib/liquid/standardfilters.rb'
|
||||
- 'lib/liquid.rb'
|
||||
- 'lib/liquid/block_body.rb'
|
||||
- 'lib/liquid/tags/assign.rb'
|
||||
- 'lib/liquid/tags/capture.rb'
|
||||
- 'lib/liquid/tags/case.rb'
|
||||
- 'lib/liquid/tags/cycle.rb'
|
||||
- 'lib/liquid/tags/for.rb'
|
||||
- 'lib/liquid/tags/if.rb'
|
||||
- 'lib/liquid/tags/include.rb'
|
||||
- 'lib/liquid/tags/raw.rb'
|
||||
- 'lib/liquid/tags/table_row.rb'
|
||||
- 'lib/liquid/variable.rb'
|
||||
- 'performance/shopify/comment_form.rb'
|
||||
- 'performance/shopify/paginate.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
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: inline, group
|
||||
Style/AccessModifierDeclarations:
|
||||
Style/ClassVars:
|
||||
Exclude:
|
||||
- 'lib/liquid/block_body.rb'
|
||||
- 'lib/liquid/tag.rb'
|
||||
- 'lib/liquid/tags/include.rb'
|
||||
- 'test/unit/strainer_unit_test.rb'
|
||||
- 'lib/liquid/condition.rb'
|
||||
- 'lib/liquid/strainer.rb'
|
||||
- 'lib/liquid/template.rb'
|
||||
|
||||
# Offense count: 10
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: prefer_alias, prefer_alias_method
|
||||
Style/Alias:
|
||||
Exclude:
|
||||
- 'lib/liquid/drop.rb'
|
||||
- 'lib/liquid/i18n.rb'
|
||||
- 'lib/liquid/profiler/hooks.rb'
|
||||
- 'lib/liquid/standardfilters.rb'
|
||||
- 'lib/liquid/tag.rb'
|
||||
- 'lib/liquid/tags/include.rb'
|
||||
- 'lib/liquid/variable.rb'
|
||||
|
||||
# Offense count: 22
|
||||
Style/CommentedKeyword:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
# 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.
|
||||
@@ -186,71 +244,50 @@ Style/EmptyCaseCondition:
|
||||
Exclude:
|
||||
- 'lib/liquid/lexer.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: compact, expanded
|
||||
Style/EmptyMethod:
|
||||
# SupportedStyles: each, for
|
||||
Style/For:
|
||||
Exclude:
|
||||
- 'lib/liquid/tag.rb'
|
||||
- 'lib/liquid/tags/comment.rb'
|
||||
- 'lib/liquid/tags/include.rb'
|
||||
- 'test/integration/tags/include_tag_test.rb'
|
||||
- 'test/unit/context_unit_test.rb'
|
||||
- 'performance/shopify/shop_filter.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 9
|
||||
# Cop supports --auto-correct.
|
||||
Style/Encoding:
|
||||
Exclude:
|
||||
- 'lib/liquid/version.rb'
|
||||
- 'liquid.gemspec'
|
||||
- 'test/integration/standard_filter_test.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Style/ExpandPathArguments:
|
||||
Exclude:
|
||||
- 'Rakefile'
|
||||
- 'liquid.gemspec'
|
||||
|
||||
# Offense count: 7
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: annotated, template, unannotated
|
||||
Style/FormatStringToken:
|
||||
# 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: 106
|
||||
# Offense count: 115
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: always, never
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
# Configuration parameters: MinBodyLength.
|
||||
Style/GuardClause:
|
||||
Exclude:
|
||||
- 'lib/liquid/condition.rb'
|
||||
- 'lib/liquid/lexer.rb'
|
||||
- 'lib/liquid/strainer.rb'
|
||||
- 'lib/liquid/tags/assign.rb'
|
||||
- 'lib/liquid/tags/capture.rb'
|
||||
- 'lib/liquid/tags/case.rb'
|
||||
- 'lib/liquid/tags/for.rb'
|
||||
- 'lib/liquid/tags/include.rb'
|
||||
- 'lib/liquid/tags/raw.rb'
|
||||
- 'lib/liquid/tags/table_row.rb'
|
||||
- 'lib/liquid/variable.rb'
|
||||
- 'test/unit/tokenizer_unit_test.rb'
|
||||
|
||||
# Offense count: 53
|
||||
# Offense count: 30
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: literals, strict
|
||||
Style/MutableConstant:
|
||||
Enabled: false
|
||||
# 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.
|
||||
@@ -260,29 +297,17 @@ Style/Next:
|
||||
Exclude:
|
||||
- 'lib/liquid/tags/for.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# Offense count: 52
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
|
||||
# SupportedStyles: predicate, comparison
|
||||
Style/NumericPredicate:
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'lib/liquid/context.rb'
|
||||
- 'lib/liquid/forloop_drop.rb'
|
||||
- 'lib/liquid/standardfilters.rb'
|
||||
- 'lib/liquid/tablerowloop_drop.rb'
|
||||
- 'test/integration/standard_filter_test.rb'
|
||||
- 'test/integration/template_test.rb'
|
||||
Style/PerlBackrefs:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
# Offense count: 33
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: PreferredDelimiters.
|
||||
Style/PercentLiteralDelimiters:
|
||||
Exclude:
|
||||
- 'lib/liquid/tags/if.rb'
|
||||
- 'liquid.gemspec'
|
||||
- 'test/integration/assign_test.rb'
|
||||
- 'test/integration/standard_filter_test.rb'
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: compact, exploded
|
||||
Style/RaiseArgs:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
@@ -290,6 +315,17 @@ 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.
|
||||
@@ -300,21 +336,31 @@ Style/SafeNavigation:
|
||||
- 'lib/liquid/strainer.rb'
|
||||
- 'lib/liquid/tokenizer.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# 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: 7
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: MinSize.
|
||||
# SupportedStyles: percent, brackets
|
||||
Style/SymbolArray:
|
||||
EnforcedStyle: brackets
|
||||
# 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.
|
||||
@@ -325,6 +371,33 @@ Style/TernaryParentheses:
|
||||
- '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:
|
||||
@@ -336,10 +409,3 @@ Style/UnneededPercentQ:
|
||||
Style/WhileUntilModifier:
|
||||
Exclude:
|
||||
- 'lib/liquid/tags/case.rb'
|
||||
|
||||
# Offense count: 665
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||
# URISchemes: http, https
|
||||
Metrics/LineLength:
|
||||
Max: 294
|
||||
|
||||
10
.travis.yml
10
.travis.yml
@@ -1,4 +1,5 @@
|
||||
language: ruby
|
||||
cache: bundler
|
||||
|
||||
rvm:
|
||||
- 2.4
|
||||
@@ -9,7 +10,6 @@ rvm:
|
||||
- jruby-head
|
||||
- truffleruby
|
||||
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- rvm: *latest_ruby
|
||||
@@ -20,9 +20,11 @@ matrix:
|
||||
- rvm: jruby-head
|
||||
- rvm: truffleruby
|
||||
|
||||
cache: bundler
|
||||
|
||||
script: bundle exec rake
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- gh-pages
|
||||
- /.*-stable/
|
||||
|
||||
notifications:
|
||||
disable: true
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -20,6 +20,6 @@ group :test do
|
||||
gem 'rubocop-performance', require: false
|
||||
|
||||
platform :mri, :truffleruby do
|
||||
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'liquid-tag'
|
||||
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'master'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,6 +74,7 @@ require 'liquid/condition'
|
||||
require 'liquid/utils'
|
||||
require 'liquid/tokenizer'
|
||||
require 'liquid/parse_context'
|
||||
require 'liquid/partial_cache'
|
||||
|
||||
# Load all the tags of the standard library
|
||||
#
|
||||
|
||||
@@ -12,17 +12,27 @@ module Liquid
|
||||
#
|
||||
# context['bob'] #=> nil class Context
|
||||
class Context
|
||||
attr_reader :scopes, :errors, :registers, :environments, :resource_limits
|
||||
attr_reader :scopes, :errors, :registers, :environments, :resource_limits, :static_registers, :static_environments
|
||||
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
||||
|
||||
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil)
|
||||
@environments = [environments].flatten
|
||||
@scopes = [(outer_scope || {})]
|
||||
@registers = registers
|
||||
@errors = []
|
||||
@partial = false
|
||||
@strict_variables = false
|
||||
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
|
||||
# rubocop:disable Metrics/ParameterLists
|
||||
def self.build(environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_registers: {}, static_environments: {})
|
||||
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_registers, static_environments)
|
||||
end
|
||||
|
||||
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_registers = {}, static_environments = {})
|
||||
@environments = [environments]
|
||||
@environments.flatten!
|
||||
|
||||
@static_environments = [static_environments].flat_map(&:freeze).freeze
|
||||
@scopes = [(outer_scope || {})]
|
||||
@registers = registers
|
||||
@static_registers = static_registers.freeze
|
||||
@errors = []
|
||||
@partial = false
|
||||
@strict_variables = false
|
||||
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
|
||||
@base_scope_depth = 0
|
||||
squash_instance_assigns_with_environments
|
||||
|
||||
@this_stack_used = false
|
||||
@@ -36,6 +46,7 @@ module Liquid
|
||||
@filters = []
|
||||
@global_filter = nil
|
||||
end
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
|
||||
def warnings
|
||||
@warnings ||= []
|
||||
@@ -89,7 +100,7 @@ module Liquid
|
||||
# Push new local scope on the stack. use <tt>Context#stack</tt> instead
|
||||
def push(new_scope = {})
|
||||
@scopes.unshift(new_scope)
|
||||
raise StackLevelError, "Nesting too deep".freeze if @scopes.length > Block::MAX_DEPTH
|
||||
check_overflow
|
||||
end
|
||||
|
||||
# Merge a hash of variables in the current local scope
|
||||
@@ -126,6 +137,25 @@ module Liquid
|
||||
@this_stack_used = old_stack_used
|
||||
end
|
||||
|
||||
# Creates a new context inheriting resource limits, filters, environment etc.,
|
||||
# but with an isolated scope.
|
||||
def new_isolated_subcontext
|
||||
check_overflow
|
||||
|
||||
Context.build(
|
||||
resource_limits: resource_limits,
|
||||
static_environments: static_environments,
|
||||
static_registers: static_registers
|
||||
).tap do |subcontext|
|
||||
subcontext.base_scope_depth = base_scope_depth + 1
|
||||
subcontext.exception_renderer = exception_renderer
|
||||
subcontext.filters = @filters
|
||||
subcontext.strainer = nil
|
||||
subcontext.errors = errors
|
||||
subcontext.warnings = warnings
|
||||
end
|
||||
end
|
||||
|
||||
def clear_instance_assigns
|
||||
@scopes[0] = {}
|
||||
end
|
||||
@@ -164,25 +194,13 @@ module Liquid
|
||||
# This was changed from find() to find_index() because this is a very hot
|
||||
# path and find_index() is optimized in MRI to reduce object allocation
|
||||
index = @scopes.find_index { |s| s.key?(key) }
|
||||
scope = @scopes[index] if index
|
||||
|
||||
variable = nil
|
||||
|
||||
if scope.nil?
|
||||
@environments.each do |e|
|
||||
variable = lookup_and_evaluate(e, key, raise_on_not_found: raise_on_not_found)
|
||||
# When lookup returned a value OR there is no value but the lookup also did not raise
|
||||
# then it is the value we are looking for.
|
||||
if !variable.nil? || @strict_variables && raise_on_not_found
|
||||
scope = e
|
||||
break
|
||||
end
|
||||
end
|
||||
variable = if index
|
||||
lookup_and_evaluate(@scopes[index], key, raise_on_not_found: raise_on_not_found)
|
||||
else
|
||||
try_variable_find_in_environments(key, raise_on_not_found: raise_on_not_found)
|
||||
end
|
||||
|
||||
scope ||= @environments.last || @scopes.last
|
||||
variable ||= lookup_and_evaluate(scope, key, raise_on_not_found: raise_on_not_found)
|
||||
|
||||
variable = variable.to_liquid
|
||||
variable.context = self if variable.respond_to?(:context=)
|
||||
|
||||
@@ -203,8 +221,38 @@ module Liquid
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :base_scope_depth, :warnings, :errors, :strainer, :filters
|
||||
|
||||
private
|
||||
|
||||
attr_reader :base_scope_depth
|
||||
|
||||
def try_variable_find_in_environments(key, raise_on_not_found:)
|
||||
@environments.each do |environment|
|
||||
found_variable = lookup_and_evaluate(environment, key, raise_on_not_found: raise_on_not_found)
|
||||
if !found_variable.nil? || @strict_variables && raise_on_not_found
|
||||
return found_variable
|
||||
end
|
||||
end
|
||||
@static_environments.each do |environment|
|
||||
found_variable = lookup_and_evaluate(environment, key, raise_on_not_found: raise_on_not_found)
|
||||
if !found_variable.nil? || @strict_variables && raise_on_not_found
|
||||
return found_variable
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def check_overflow
|
||||
raise StackLevelError, "Nesting too deep".freeze if overflow?
|
||||
end
|
||||
|
||||
def overflow?
|
||||
base_scope_depth + @scopes.length > Block::MAX_DEPTH
|
||||
end
|
||||
|
||||
def internal_error
|
||||
# raise and catch to set backtrace and cause on exception
|
||||
raise Liquid::InternalError, 'internal'
|
||||
|
||||
@@ -22,5 +22,6 @@
|
||||
tag_never_closed: "'%{block_name}' tag was never closed"
|
||||
meta_syntax_error: "Liquid syntax error: #{e.message}"
|
||||
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
|
||||
render: "Syntax error in tag 'render' - Template name must be a quoted string"
|
||||
argument:
|
||||
include: "Argument error in tag 'include' - Illegal template name"
|
||||
|
||||
18
lib/liquid/partial_cache.rb
Normal file
18
lib/liquid/partial_cache.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module Liquid
|
||||
class PartialCache
|
||||
def self.load(template_name, context:, parse_context:)
|
||||
cached_partials = (context.registers[:cached_partials] ||= {})
|
||||
cached = cached_partials[template_name]
|
||||
return cached if cached
|
||||
|
||||
file_system = (context.registers[:file_system] ||= Liquid::Template.file_system)
|
||||
source = file_system.read_template_file(template_name)
|
||||
parse_context.partial = true
|
||||
|
||||
partial = Liquid::Template.parse(source, parse_context)
|
||||
cached_partials[template_name] = partial
|
||||
ensure
|
||||
parse_context.partial = false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -44,7 +44,7 @@ module Liquid
|
||||
include Enumerable
|
||||
|
||||
class Timing
|
||||
attr_reader :code, :partial, :line_number, :children
|
||||
attr_reader :code, :partial, :line_number, :children, :total_time, :self_time
|
||||
|
||||
def initialize(node, partial)
|
||||
@code = node.respond_to?(:raw) ? node.raw : node
|
||||
@@ -63,6 +63,18 @@ module Liquid
|
||||
|
||||
def finish
|
||||
@end_time = Time.now
|
||||
@total_time = @end_time - @start_time
|
||||
if @children.size == 0
|
||||
@self_time = @total_time
|
||||
else
|
||||
total_children_time = 0
|
||||
|
||||
@children.each do |child|
|
||||
total_children_time += child.total_time
|
||||
end
|
||||
|
||||
@self_time = @total_time - total_children_time
|
||||
end
|
||||
end
|
||||
|
||||
def render_time
|
||||
|
||||
@@ -46,7 +46,12 @@ module Liquid
|
||||
template_name = context.evaluate(@template_name_expr)
|
||||
raise ArgumentError.new(options[:locale].t("errors.argument.include")) unless template_name
|
||||
|
||||
partial = load_cached_partial(template_name, context)
|
||||
partial = PartialCache.load(
|
||||
template_name,
|
||||
context: context,
|
||||
parse_context: parse_context
|
||||
)
|
||||
|
||||
context_variable_name = template_name.split('/'.freeze).last
|
||||
|
||||
variable = if @variable_name_expr
|
||||
@@ -83,35 +88,9 @@ module Liquid
|
||||
output
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
alias_method :parse_context, :options
|
||||
private :parse_context
|
||||
|
||||
def load_cached_partial(template_name, context)
|
||||
cached_partials = context.registers[:cached_partials] || {}
|
||||
|
||||
if cached = cached_partials[template_name]
|
||||
return cached
|
||||
end
|
||||
source = read_template_from_file_system(context)
|
||||
begin
|
||||
parse_context.partial = true
|
||||
partial = Liquid::Template.parse(source, parse_context)
|
||||
ensure
|
||||
parse_context.partial = false
|
||||
end
|
||||
cached_partials[template_name] = partial
|
||||
context.registers[:cached_partials] = cached_partials
|
||||
partial
|
||||
end
|
||||
|
||||
def read_template_from_file_system(context)
|
||||
file_system = context.registers[:file_system] || Liquid::Template.file_system
|
||||
|
||||
file_system.read_template_file(context.evaluate(@template_name_expr))
|
||||
end
|
||||
|
||||
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
||||
def children
|
||||
[
|
||||
|
||||
@@ -23,6 +23,7 @@ module Liquid
|
||||
def render_to_output_buffer(context, output)
|
||||
value = context.environments.first[@variable] ||= 0
|
||||
context.environments.first[@variable] = value + 1
|
||||
|
||||
output << value.to_s
|
||||
output
|
||||
end
|
||||
|
||||
54
lib/liquid/tags/render.rb
Normal file
54
lib/liquid/tags/render.rb
Normal file
@@ -0,0 +1,54 @@
|
||||
module Liquid
|
||||
class Render < Tag
|
||||
SYNTAX = /(#{QuotedString})#{QuotedFragment}*/o
|
||||
|
||||
attr_reader :template_name_expr, :attributes
|
||||
|
||||
def initialize(tag_name, markup, options)
|
||||
super
|
||||
|
||||
raise SyntaxError.new(options[:locale].t("errors.syntax.render".freeze)) unless markup =~ SYNTAX
|
||||
|
||||
template_name = $1
|
||||
|
||||
@template_name_expr = Expression.parse(template_name)
|
||||
|
||||
@attributes = {}
|
||||
markup.scan(TagAttributes) do |key, value|
|
||||
@attributes[key] = Expression.parse(value)
|
||||
end
|
||||
end
|
||||
|
||||
def render_to_output_buffer(context, output)
|
||||
# Though we evaluate this here we will only ever parse it as a string literal.
|
||||
template_name = context.evaluate(@template_name_expr)
|
||||
raise ArgumentError.new(options[:locale].t("errors.argument.include")) unless template_name
|
||||
|
||||
partial = PartialCache.load(
|
||||
template_name,
|
||||
context: context,
|
||||
parse_context: parse_context
|
||||
)
|
||||
|
||||
inner_context = context.new_isolated_subcontext
|
||||
inner_context.template_name = template_name
|
||||
inner_context.partial = true
|
||||
@attributes.each do |key, value|
|
||||
inner_context[key] = context.evaluate(value)
|
||||
end
|
||||
partial.render_to_output_buffer(inner_context, output)
|
||||
|
||||
output
|
||||
end
|
||||
|
||||
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
||||
def children
|
||||
[
|
||||
@node.template_name_expr,
|
||||
] + @node.attributes.values
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Template.register_tag('render'.freeze, Render)
|
||||
end
|
||||
149
test/integration/tags/render_tag_test.rb
Normal file
149
test/integration/tags/render_tag_test.rb
Normal file
@@ -0,0 +1,149 @@
|
||||
require 'test_helper'
|
||||
|
||||
class RenderTagTest < Minitest::Test
|
||||
include Liquid
|
||||
|
||||
def test_render_with_no_arguments
|
||||
Liquid::Template.file_system = StubFileSystem.new('source' => 'rendered content')
|
||||
assert_template_result 'rendered content', '{% render "source" %}'
|
||||
end
|
||||
|
||||
def test_render_tag_looks_for_file_system_in_registers_first
|
||||
file_system = StubFileSystem.new('pick_a_source' => 'from register file system')
|
||||
assert_equal 'from register file system',
|
||||
Template.parse('{% render "pick_a_source" %}').render!({}, registers: { file_system: file_system })
|
||||
end
|
||||
|
||||
def test_render_passes_named_arguments_into_inner_scope
|
||||
Liquid::Template.file_system = StubFileSystem.new('product' => '{{ inner_product.title }}')
|
||||
assert_template_result 'My Product', '{% render "product", inner_product: outer_product %}',
|
||||
'outer_product' => { 'title' => 'My Product' }
|
||||
end
|
||||
|
||||
def test_render_accepts_literals_as_arguments
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ price }}')
|
||||
assert_template_result '123', '{% render "snippet", price: 123 %}'
|
||||
end
|
||||
|
||||
def test_render_accepts_multiple_named_arguments
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ one }} {{ two }}')
|
||||
assert_template_result '1 2', '{% render "snippet", one: 1, two: 2 %}'
|
||||
end
|
||||
|
||||
def test_render_does_not_inherit_parent_scope_variables
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ outer_variable }}')
|
||||
assert_template_result '', '{% assign outer_variable = "should not be visible" %}{% render "snippet" %}'
|
||||
end
|
||||
|
||||
def test_render_does_not_inherit_variable_with_same_name_as_snippet
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ snippet }}')
|
||||
assert_template_result '', "{% assign snippet = 'should not be visible' %}{% render 'snippet' %}"
|
||||
end
|
||||
|
||||
def test_render_sets_the_correct_template_name_for_errors
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ unsafe }}')
|
||||
|
||||
with_taint_mode :error do
|
||||
template = Liquid::Template.parse('{% render "snippet", unsafe: unsafe %}')
|
||||
context = Context.new('unsafe' => (+'unsafe').tap(&:taint))
|
||||
template.render(context)
|
||||
|
||||
assert_equal [Liquid::TaintedError], template.errors.map(&:class)
|
||||
assert_equal 'snippet', template.errors.first.template_name
|
||||
end
|
||||
end
|
||||
|
||||
def test_render_sets_the_correct_template_name_for_warnings
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ unsafe }}')
|
||||
|
||||
with_taint_mode :warn do
|
||||
template = Liquid::Template.parse('{% render "snippet", unsafe: unsafe %}')
|
||||
context = Context.new('unsafe' => (+'unsafe').tap(&:taint))
|
||||
template.render(context)
|
||||
|
||||
assert_equal [Liquid::TaintedError], context.warnings.map(&:class)
|
||||
assert_equal 'snippet', context.warnings.first.template_name
|
||||
end
|
||||
end
|
||||
|
||||
def test_render_does_not_mutate_parent_scope
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{% assign inner = 1 %}')
|
||||
assert_template_result '', "{% render 'snippet' %}{{ inner }}"
|
||||
end
|
||||
|
||||
def test_nested_render_tag
|
||||
Liquid::Template.file_system = StubFileSystem.new(
|
||||
'one' => "one {% render 'two' %}",
|
||||
'two' => 'two'
|
||||
)
|
||||
assert_template_result 'one two', "{% render 'one' %}"
|
||||
end
|
||||
|
||||
def test_recursively_rendered_template_does_not_produce_endless_loop
|
||||
Liquid::Template.file_system = StubFileSystem.new('loop' => '{% render "loop" %}')
|
||||
|
||||
assert_raises Liquid::StackLevelError do
|
||||
Template.parse('{% render "loop" %}').render!
|
||||
end
|
||||
end
|
||||
|
||||
def test_includes_and_renders_count_towards_the_same_recursion_limit
|
||||
Liquid::Template.file_system = StubFileSystem.new(
|
||||
'loop_render' => '{% render "loop_include" %}',
|
||||
'loop_include' => '{% include "loop_render" %}'
|
||||
)
|
||||
|
||||
assert_raises Liquid::StackLevelError do
|
||||
Template.parse('{% render "loop_include" %}').render!
|
||||
end
|
||||
end
|
||||
|
||||
def test_dynamically_choosen_templates_are_not_allowed
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'should not be rendered')
|
||||
|
||||
assert_raises Liquid::SyntaxError do
|
||||
Liquid::Template.parse("{% assign name = 'snippet' %}{% render name %}")
|
||||
end
|
||||
end
|
||||
|
||||
def test_include_tag_caches_second_read_of_same_partial
|
||||
file_system = StubFileSystem.new('snippet' => 'echo')
|
||||
assert_equal 'echoecho',
|
||||
Template.parse('{% render "snippet" %}{% render "snippet" %}')
|
||||
.render!({}, registers: { file_system: file_system })
|
||||
assert_equal 1, file_system.file_read_count
|
||||
end
|
||||
|
||||
def test_render_tag_doesnt_cache_partials_across_renders
|
||||
file_system = StubFileSystem.new('snippet' => 'my message')
|
||||
|
||||
assert_equal 'my message',
|
||||
Template.parse('{% include "snippet" %}').render!({}, registers: { file_system: file_system })
|
||||
assert_equal 1, file_system.file_read_count
|
||||
|
||||
assert_equal 'my message',
|
||||
Template.parse('{% include "snippet" %}').render!({}, registers: { file_system: file_system })
|
||||
assert_equal 2, file_system.file_read_count
|
||||
end
|
||||
|
||||
def test_render_tag_within_if_statement
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'my message')
|
||||
assert_template_result 'my message', '{% if true %}{% render "snippet" %}{% endif %}'
|
||||
end
|
||||
|
||||
def test_break_through_render
|
||||
Liquid::Template.file_system = StubFileSystem.new('break' => '{% break %}')
|
||||
assert_template_result '1', '{% for i in (1..3) %}{{ i }}{% break %}{{ i }}{% endfor %}'
|
||||
assert_template_result '112233', '{% for i in (1..3) %}{{ i }}{% render "break" %}{{ i }}{% endfor %}'
|
||||
end
|
||||
|
||||
def test_increment_is_isolated_between_renders
|
||||
Liquid::Template.file_system = StubFileSystem.new('incr' => '{% increment %}')
|
||||
assert_template_result '010', '{% increment %}{% increment %}{% render "incr" %}'
|
||||
end
|
||||
|
||||
def test_decrement_is_isolated_between_renders
|
||||
Liquid::Template.file_system = StubFileSystem.new('decr' => '{% decrement %}')
|
||||
assert_template_result '-1-2-1', '{% decrement %}{% decrement %}{% render "decr" %}'
|
||||
end
|
||||
end
|
||||
@@ -121,3 +121,17 @@ class ErrorDrop < Liquid::Drop
|
||||
raise Exception, 'exception'
|
||||
end
|
||||
end
|
||||
|
||||
class StubFileSystem
|
||||
attr_reader :file_read_count
|
||||
|
||||
def initialize(values)
|
||||
@file_read_count = 0
|
||||
@values = values
|
||||
end
|
||||
|
||||
def read_template_file(template_path)
|
||||
@file_read_count += 1
|
||||
@values.fetch(template_path)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -468,11 +468,79 @@ class ContextUnitTest < Minitest::Test
|
||||
assert_equal 'hi filtered', context.apply_global_filter('hi')
|
||||
end
|
||||
|
||||
def test_static_environments_are_read_with_lower_priority_than_environments
|
||||
context = Context.build(
|
||||
static_environments: { 'shadowed' => 'static', 'unshadowed' => 'static' },
|
||||
environments: { 'shadowed' => 'dynamic' }
|
||||
)
|
||||
|
||||
assert_equal 'dynamic', context['shadowed']
|
||||
assert_equal 'static', context['unshadowed']
|
||||
end
|
||||
|
||||
def test_apply_global_filter_when_no_global_filter_exist
|
||||
context = Context.new
|
||||
assert_equal 'hi', context.apply_global_filter('hi')
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_does_not_inherit_variables
|
||||
super_context = Context.new
|
||||
super_context['my_variable'] = 'some value'
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
|
||||
assert_nil subcontext['my_variable']
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_inherits_static_environment
|
||||
super_context = Context.build(static_environments: { 'my_environment_value' => 'my value' })
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
|
||||
assert_equal 'my value', subcontext['my_environment_value']
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_inherits_resource_limits
|
||||
resource_limits = ResourceLimits.new({})
|
||||
super_context = Context.new({}, {}, {}, false, resource_limits)
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
assert_equal resource_limits, subcontext.resource_limits
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_inherits_exception_renderer
|
||||
super_context = Context.new
|
||||
super_context.exception_renderer = ->(_e) { 'my exception message' }
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
assert_equal 'my exception message', subcontext.handle_error(Liquid::Error.new)
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_does_not_inherit_non_static_registers
|
||||
registers = {
|
||||
my_register: :my_value
|
||||
}
|
||||
super_context = Context.new({}, {}, registers)
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
assert_nil subcontext.registers[:my_register]
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_inherits_static_registers
|
||||
super_context = Context.build(static_registers: { my_register: :my_value })
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
assert_equal :my_value, subcontext.static_registers[:my_register]
|
||||
end
|
||||
|
||||
def test_new_isolated_subcontext_inherits_filters
|
||||
my_filter = Module.new do
|
||||
def my_filter(*)
|
||||
'my filter result'
|
||||
end
|
||||
end
|
||||
|
||||
super_context = Context.new
|
||||
super_context.add_filters([my_filter])
|
||||
subcontext = super_context.new_isolated_subcontext
|
||||
template = Template.parse('{{ 123 | my_filter }}')
|
||||
assert_equal 'my filter result', template.render(subcontext)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_no_object_allocations
|
||||
|
||||
91
test/unit/partial_cache_unit_test.rb
Normal file
91
test/unit/partial_cache_unit_test.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
require 'test_helper'
|
||||
|
||||
class PartialCacheUnitTest < Minitest::Test
|
||||
def test_uses_the_file_system_register_if_present
|
||||
context = Liquid::Context.build(
|
||||
registers: {
|
||||
file_system: StubFileSystem.new('my_partial' => 'my partial body'),
|
||||
}
|
||||
)
|
||||
|
||||
partial = Liquid::PartialCache.load(
|
||||
'my_partial',
|
||||
context: context,
|
||||
parse_context: Liquid::ParseContext.new
|
||||
)
|
||||
|
||||
assert_equal 'my partial body', partial.render
|
||||
end
|
||||
|
||||
def test_reads_from_the_file_system_only_once_per_file
|
||||
file_system = StubFileSystem.new('my_partial' => 'some partial body')
|
||||
context = Liquid::Context.build(
|
||||
registers: { file_system: file_system }
|
||||
)
|
||||
|
||||
2.times do
|
||||
Liquid::PartialCache.load(
|
||||
'my_partial',
|
||||
context: context,
|
||||
parse_context: Liquid::ParseContext.new
|
||||
)
|
||||
end
|
||||
|
||||
assert_equal 1, file_system.file_read_count
|
||||
end
|
||||
|
||||
def test_cache_state_is_stored_per_context
|
||||
parse_context = Liquid::ParseContext.new
|
||||
shared_file_system = StubFileSystem.new(
|
||||
'my_partial' => 'my shared value'
|
||||
)
|
||||
context_one = Liquid::Context.build(
|
||||
registers: {
|
||||
file_system: shared_file_system,
|
||||
}
|
||||
)
|
||||
context_two = Liquid::Context.build(
|
||||
registers: {
|
||||
file_system: shared_file_system,
|
||||
}
|
||||
)
|
||||
|
||||
2.times do
|
||||
Liquid::PartialCache.load(
|
||||
'my_partial',
|
||||
context: context_one,
|
||||
parse_context: parse_context
|
||||
)
|
||||
end
|
||||
|
||||
Liquid::PartialCache.load(
|
||||
'my_partial',
|
||||
context: context_two,
|
||||
parse_context: parse_context
|
||||
)
|
||||
|
||||
assert_equal 2, shared_file_system.file_read_count
|
||||
end
|
||||
|
||||
def test_cache_is_not_broken_when_a_different_parse_context_is_used
|
||||
file_system = StubFileSystem.new('my_partial' => 'some partial body')
|
||||
context = Liquid::Context.build(
|
||||
registers: { file_system: file_system }
|
||||
)
|
||||
|
||||
Liquid::PartialCache.load(
|
||||
'my_partial',
|
||||
context: context,
|
||||
parse_context: Liquid::ParseContext.new(my_key: 'value one')
|
||||
)
|
||||
Liquid::PartialCache.load(
|
||||
'my_partial',
|
||||
context: context,
|
||||
parse_context: Liquid::ParseContext.new(my_key: 'value two')
|
||||
)
|
||||
|
||||
# Technically what we care about is that the file was parsed twice,
|
||||
# but measuring file reads is an OK proxy for this.
|
||||
assert_equal 1, file_system.file_read_count
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user