diff --git a/.rubocop.yml b/.rubocop.yml index 6b9aa9fe..1c0f8324 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ inherit_from: - - https://shopify.github.io/ruby-style-guide/rubocop.yml + - 'https://shopify.github.io/ruby-style-guide/rubocop.yml' - .rubocop_todo.yml require: rubocop-performance @@ -8,9 +8,10 @@ Performance: Enabled: true AllCops: + TargetRubyVersion: 2.4 Exclude: - 'vendor/bundle/**/*' - + Naming/MethodName: Exclude: - - 'example/server/liquid_servlet.rb' \ No newline at end of file + - 'example/server/liquid_servlet.rb' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 22330ae6..34a2e244 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,107 +1,11 @@ # This configuration was generated by # `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 # 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: 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 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. @@ -110,48 +14,7 @@ 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: 95 +# Offense count: 98 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https @@ -177,235 +40,9 @@ Naming/ConstantName: - '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 Style/ClassVars: Exclude: - 'lib/liquid/condition.rb' - 'lib/liquid/strainer.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' + - 'lib/liquid/template.rb' \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b6a7db0d..f9c8c7fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,6 @@ rvm: - &latest_ruby 2.6 - 2.7 - ruby-head - - jruby-head - - truffleruby matrix: include: @@ -17,8 +15,6 @@ matrix: name: Profiling Memory Usage allow_failures: - rvm: ruby-head - - rvm: jruby-head - - rvm: truffleruby branches: only: diff --git a/Gemfile b/Gemfile index d77a7387..f5209346 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source 'https://rubygems.org' git_source(:github) do |repo_name| "https://github.com/#{repo_name}.git" @@ -20,6 +22,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 diff --git a/README.md b/README.md index 77e9ff43..6802a717 100644 --- a/README.md +++ b/README.md @@ -106,3 +106,9 @@ template = Liquid::Template.parse("{{x}} {{y}}") template.render!({ 'x' => 1}, { strict_variables: true }) #=> Liquid::UndefinedVariable: Liquid error: undefined variable y ``` + +### Usage tracking + +To help track usages of a feature or code path in production, we have released opt-in usage tracking. To enable this, we provide an empty `Liquid:: Usage.increment` method which you can customize to your needs. The feature is well suited to https://github.com/Shopify/statsd-instrument. However, the choice of implementation is up to you. + +Once you have enabled usage tracking, we recommend reporting any events through Github Issues that your system may be logging. It is highly likely this event has been added to consider deprecating or improving code specific to this event, so please raise any concerns. \ No newline at end of file diff --git a/Rakefile b/Rakefile index f7186eb7..66ae0fae 100755 --- a/Rakefile +++ b/Rakefile @@ -1,18 +1,20 @@ +# frozen_string_literal: true + require 'rake' require 'rake/testtask' -$LOAD_PATH.unshift File.expand_path("../lib", __FILE__) +$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__)) 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| t.libs << '.' << 'lib' << 'test' t.test_files = FileList['test/{integration,unit}/**/*_test.rb'] t.verbose = false end -desc 'run test suite with warn error mode' +desc('run test suite with warn error mode') task :warn_test do ENV['LIQUID_PARSER_MODE'] = 'warn' Rake::Task['base_test'].invoke @@ -25,7 +27,7 @@ task :rubocop do 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 ENV['LIQUID_PARSER_MODE'] = 'lax' Rake::Task['base_test'].invoke @@ -47,7 +49,7 @@ task :test do end end -task gem: :build +task(gem: :build) task :build do system "gem build liquid.gemspec" end @@ -94,7 +96,7 @@ namespace :memory_profile do end end -desc "Run example" +desc("Run example") task :example do ruby "-w -d -Ilib example/server/server.rb" end diff --git a/example/server/example_servlet.rb b/example/server/example_servlet.rb index dbc7a4b7..b09e3bb7 100644 --- a/example/server/example_servlet.rb +++ b/example/server/example_servlet.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module ProductsFilter def price(integer) - sprintf("$%.2d USD", integer / 100.0) + format("$%.2d USD", integer / 100.0) end def prettyprint(text) diff --git a/example/server/liquid_servlet.rb b/example/server/liquid_servlet.rb index b2bf515f..55e21d21 100644 --- a/example/server/liquid_servlet.rb +++ b/example/server/liquid_servlet.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class LiquidServlet < WEBrick::HTTPServlet::AbstractServlet def do_GET(req, res) handle(:get, req, res) @@ -9,12 +11,12 @@ class LiquidServlet < WEBrick::HTTPServlet::AbstractServlet private - def handle(type, req, res) + def handle(_type, req, res) @request = req @response = res @request.path_info =~ /(\w+)\z/ - @action = $1 || 'index' + @action = Regexp.last_match(1) || 'index' @assigns = send(@action) if respond_to?(@action) @response['Content-Type'] = "text/html" diff --git a/example/server/server.rb b/example/server/server.rb index 703b361c..bb7a4bc9 100644 --- a/example/server/server.rb +++ b/example/server/server.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'webrick' require 'rexml/document' @@ -8,5 +10,5 @@ require_relative 'example_servlet' # Setup webrick server = WEBrick::HTTPServer.new(Port: ARGV[1] || 3000) server.mount('/', Servlet) -trap("INT"){ server.shutdown } +trap("INT") { server.shutdown } server.start diff --git a/lib/liquid.rb b/lib/liquid.rb index 0e198bb4..cfaccee5 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Copyright (c) 2005 Tobias Luetke # # Permission is hereby granted, free of charge, to any person obtaining @@ -21,10 +23,10 @@ module Liquid FilterSeparator = /\|/ - ArgumentSeparator = ','.freeze - FilterArgumentSeparator = ':'.freeze - VariableAttributeSeparator = '.'.freeze - WhitespaceControl = '-'.freeze + ArgumentSeparator = ',' + FilterArgumentSeparator = ':' + VariableAttributeSeparator = '.' + WhitespaceControl = '-' TagStart = /\{\%/ TagEnd = /\%\}/ VariableSignature = /\(?[\w\-\.\[\]]\)?/ @@ -75,7 +77,11 @@ require 'liquid/utils' require 'liquid/tokenizer' require 'liquid/parse_context' require 'liquid/partial_cache' +require 'liquid/usage' +require 'liquid/register' +require 'liquid/static_registers' # Load all the tags of the standard library # Dir["#{__dir__}/liquid/tags/*.rb"].each { |f| require f } +Dir["#{__dir__}/liquid/registers/*.rb"].each { |f| require f } diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index 549a3a36..f6698442 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Block < Tag MAX_DEPTH = 100 @@ -27,16 +29,16 @@ module Liquid end def unknown_tag(tag, _params, _tokens) - if tag == 'else'.freeze - raise SyntaxError.new(parse_context.locale.t("errors.syntax.unexpected_else".freeze, - block_name: block_name)) - elsif tag.start_with?('end'.freeze) - raise SyntaxError.new(parse_context.locale.t("errors.syntax.invalid_delimiter".freeze, + if tag == 'else' + raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_else", + block_name: block_name) + elsif tag.start_with?('end') + raise SyntaxError, parse_context.locale.t("errors.syntax.invalid_delimiter", tag: tag, block_name: block_name, - block_delimiter: block_delimiter)) + block_delimiter: block_delimiter) 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 @@ -52,7 +54,7 @@ module Liquid def parse_body(body, tokens) if parse_context.depth >= MAX_DEPTH - raise StackLevelError, "Nesting too deep".freeze + raise StackLevelError, "Nesting too deep" end parse_context.depth += 1 begin @@ -61,7 +63,7 @@ module Liquid return false if end_tag_name == block_delimiter 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 # this tag is not registered with the system diff --git a/lib/liquid/block_body.rb b/lib/liquid/block_body.rb index 27b4eef0..45be8b8a 100644 --- a/lib/liquid/block_body.rb +++ b/lib/liquid/block_body.rb @@ -1,11 +1,13 @@ +# frozen_string_literal: true + module Liquid class BlockBody LiquidTagToken = /\A\s*(\w+)\s*(.*?)\z/o FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om WhitespaceOrNothing = /\A\s*\z/ - TAGSTART = "{%".freeze - VARSTART = "{{".freeze + TAGSTART = "{%" + VARSTART = "{{" attr_reader :nodelist @@ -25,16 +27,16 @@ module Liquid end private def parse_for_liquid_tag(tokenizer, parse_context) - while token = tokenizer.shift + while (token = tokenizer.shift) unless token.empty? || token =~ WhitespaceOrNothing unless token =~ LiquidTagToken # line isn't empty but didn't match tag syntax, yield and let the # caller raise a syntax error return yield token, token end - tag_name = $1 - markup = $2 - unless tag = registered_tags[tag_name] + tag_name = Regexp.last_match(1) + markup = Regexp.last_match(2) + unless (tag = registered_tags[tag_name]) # end parsing if we reach an unknown tag and let the caller decide # determine how to proceed return yield tag_name, markup @@ -50,7 +52,7 @@ module Liquid end private def parse_for_document(tokenizer, parse_context, &block) - while token = tokenizer.shift + while (token = tokenizer.shift) next if token.empty? case when token.start_with?(TAGSTART) @@ -58,21 +60,21 @@ module Liquid unless token =~ FullToken raise_missing_tag_terminator(token, parse_context) end - tag_name = $2 - markup = $4 + tag_name = Regexp.last_match(2) + markup = Regexp.last_match(4) if parse_context.line_number # newlines inside the tag should increase the line number, # 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 - 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) next parse_for_liquid_tag(liquid_tag_tokenizer, parse_context, &block) 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 # determine how to proceed return yield tag_name, markup @@ -101,7 +103,7 @@ module Liquid def whitespace_handler(token, parse_context) if token[2] == WhitespaceControl previous_token = @nodelist.last - if previous_token.is_a? String + if previous_token.is_a?(String) previous_token.rstrip! end end @@ -113,14 +115,14 @@ module Liquid end def render(context) - render_to_output_buffer(context, '') + render_to_output_buffer(context, +'') end def render_to_output_buffer(context, output) context.resource_limits.render_score += @nodelist.length idx = 0 - while node = @nodelist[idx] + while (node = @nodelist[idx]) previous_output_size = output.bytesize case node @@ -129,7 +131,7 @@ module Liquid when Variable render_node(context, output, node) 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 when Continue, Break # If we get an Interrupt that means the block must stop processing. An @@ -152,7 +154,13 @@ module Liquid private 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 context.handle_error(e, node.line_number) rescue ::StandardError => e @@ -160,10 +168,15 @@ module Liquid output << context.handle_error(e, line_number) 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) context.resource_limits.render_length += length return unless context.resource_limits.reached? - raise MemoryError.new("Memory limits exceeded".freeze) + raise MemoryError, "Memory limits exceeded" end def create_variable(token, parse_context) @@ -175,11 +188,11 @@ module Liquid end 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 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 def registered_tags diff --git a/lib/liquid/condition.rb b/lib/liquid/condition.rb index 3b51682e..93ec68b7 100644 --- a/lib/liquid/condition.rb +++ b/lib/liquid/condition.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Container for liquid nodes which conveniently wraps decision making logic # @@ -8,21 +10,21 @@ module Liquid # class Condition #:nodoc: @@operators = { - '=='.freeze => ->(cond, left, right) { cond.send(:equal_variables, left, right) }, - '!='.freeze => ->(cond, left, right) { !cond.send(:equal_variables, left, right) }, - '<>'.freeze => ->(cond, left, right) { !cond.send(:equal_variables, left, right) }, - '<'.freeze => :<, - '>'.freeze => :>, - '>='.freeze => :>=, - '<='.freeze => :<=, - 'contains'.freeze => lambda do |cond, left, right| + '==' => ->(cond, left, right) { cond.send(:equal_variables, left, right) }, + '!=' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) }, + '<>' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) }, + '<' => :<, + '>' => :>, + '>=' => :>=, + '<=' => :<=, + 'contains' => lambda do |_cond, left, right| if left && right && left.respond_to?(:include?) right = right.to_s if left.is_a?(String) left.include?(right) else false end - end + end, } def self.operators @@ -36,7 +38,7 @@ module Liquid @left = left @operator = operator @right = right - @child_relation = nil + @child_relation = nil @child_condition = nil end @@ -78,7 +80,7 @@ module Liquid end def inspect - "#" + "#" end protected @@ -116,7 +118,7 @@ module Liquid left = context.evaluate(left) 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) operation.call(self, left, right) @@ -124,7 +126,7 @@ module Liquid begin left.send(operation, right) rescue ::ArgumentError => e - raise Liquid::ArgumentError.new(e.message) + raise Liquid::ArgumentError, e.message end end end diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index 90e6b789..88e46713 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # 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 # 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) + 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_environments) 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.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 @@ -35,11 +36,9 @@ module Liquid @base_scope_depth = 0 squash_instance_assigns_with_environments - @this_stack_used = false - self.exception_renderer = Template.default_exception_renderer if rethrow_errors - self.exception_renderer = ->(e) { raise } + self.exception_renderer = ->(_e) { raise } end @interrupts = [] @@ -122,19 +121,11 @@ module Liquid # end # # context['var] #=> nil - def stack(new_scope = nil) - old_stack_used = @this_stack_used - if new_scope - push(new_scope) - @this_stack_used = true - else - @this_stack_used = false - end - + def stack(new_scope = {}) + push(new_scope) yield ensure - pop if @this_stack_used - @this_stack_used = old_stack_used + pop end # Creates a new context inheriting resource limits, filters, environment etc., @@ -145,7 +136,7 @@ module Liquid Context.build( resource_limits: resource_limits, static_environments: static_environments, - static_registers: static_registers + registers: StaticRegisters.new(registers) ).tap do |subcontext| subcontext.base_scope_depth = base_scope_depth + 1 subcontext.exception_renderer = exception_renderer @@ -162,10 +153,6 @@ module Liquid # Only allow String, Numeric, Hash, Array, Proc, Boolean or Liquid::Drop def []=(key, value) - unless @this_stack_used - @this_stack_used = true - push({}) - end @scopes[0][key] = value end @@ -215,7 +202,7 @@ module Liquid value = obj[key] 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 value end @@ -246,7 +233,7 @@ module Liquid end def check_overflow - raise StackLevelError, "Nesting too deep".freeze if overflow? + raise StackLevelError, "Nesting too deep" if overflow? end def overflow? diff --git a/lib/liquid/document.rb b/lib/liquid/document.rb index d035dd46..e160886d 100644 --- a/lib/liquid/document.rb +++ b/lib/liquid/document.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Document < BlockBody def self.parse(tokens, parse_context) @@ -7,7 +9,7 @@ module Liquid end 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 end rescue SyntaxError => e @@ -17,10 +19,10 @@ module Liquid def unknown_tag(tag, parse_context) case tag - when 'else'.freeze, 'end'.freeze - raise SyntaxError.new(parse_context.locale.t("errors.syntax.unexpected_outer_tag".freeze, tag: tag)) + when 'else', 'end' + raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_outer_tag", tag: tag) 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 diff --git a/lib/liquid/drop.rb b/lib/liquid/drop.rb index 6b5aa993..d4d8950f 100644 --- a/lib/liquid/drop.rb +++ b/lib/liquid/drop.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'set' module Liquid @@ -25,7 +27,7 @@ module Liquid # Catch all for the 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}" end @@ -67,7 +69,7 @@ module Liquid if include?(Enumerable) blacklist += Enumerable.public_instance_methods - blacklist -= [:sort, :count, :first, :min, :max, :include?] + blacklist -= [:sort, :count, :first, :min, :max] end whitelist = [:to_liquid] + (public_instance_methods - blacklist) diff --git a/lib/liquid/errors.rb b/lib/liquid/errors.rb index defa5ea9..eda0bd2a 100644 --- a/lib/liquid/errors.rb +++ b/lib/liquid/errors.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Error < ::StandardError attr_accessor :line_number @@ -5,7 +7,7 @@ module Liquid attr_accessor :markup_context def to_s(with_prefix = true) - str = "" + str = +"" str << message_prefix if with_prefix str << super() @@ -20,11 +22,11 @@ module Liquid private def message_prefix - str = "" - if is_a?(SyntaxError) - str << "Liquid syntax error" + str = +"" + str << if is_a?(SyntaxError) + "Liquid syntax error" else - str << "Liquid error" + "Liquid error" end if line_number diff --git a/lib/liquid/expression.rb b/lib/liquid/expression.rb index 98be6db6..9670906b 100644 --- a/lib/liquid/expression.rb +++ b/lib/liquid/expression.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Expression class MethodLiteral @@ -14,11 +16,11 @@ module Liquid end LITERALS = { - nil => nil, 'nil'.freeze => nil, 'null'.freeze => nil, ''.freeze => nil, - 'true'.freeze => true, - 'false'.freeze => false, - 'blank'.freeze => MethodLiteral.new(:blank?, '').freeze, - 'empty'.freeze => MethodLiteral.new(:empty?, '').freeze + nil => nil, 'nil' => nil, 'null' => nil, '' => nil, + 'true' => true, + 'false' => false, + 'blank' => MethodLiteral.new(:blank?, '').freeze, + 'empty' => MethodLiteral.new(:empty?, '').freeze }.freeze SINGLE_QUOTED_STRING = /\A'(.*)'\z/m @@ -33,13 +35,13 @@ module Liquid else case markup when SINGLE_QUOTED_STRING, DOUBLE_QUOTED_STRING - $1 + Regexp.last_match(1) when INTEGERS_REGEX - $1.to_i + Regexp.last_match(1).to_i when RANGES_REGEX - RangeLookup.parse($1, $2) + RangeLookup.parse(Regexp.last_match(1), Regexp.last_match(2)) when FLOATS_REGEX - $1.to_f + Regexp.last_match(1).to_f else VariableLookup.parse(markup) end diff --git a/lib/liquid/extensions.rb b/lib/liquid/extensions.rb index 09078193..d1854983 100644 --- a/lib/liquid/extensions.rb +++ b/lib/liquid/extensions.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'time' require 'date' diff --git a/lib/liquid/file_system.rb b/lib/liquid/file_system.rb index 13f1f460..27ab6325 100644 --- a/lib/liquid/file_system.rb +++ b/lib/liquid/file_system.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # 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 attr_accessor :root - def initialize(root, pattern = "_%s.liquid".freeze) + def initialize(root, pattern = "_%s.liquid") @root = root @pattern = pattern end @@ -57,9 +59,9 @@ module Liquid end 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)) else File.join(root, @pattern % template_path) diff --git a/lib/liquid/forloop_drop.rb b/lib/liquid/forloop_drop.rb index 81b2d1a2..0ffa2559 100644 --- a/lib/liquid/forloop_drop.rb +++ b/lib/liquid/forloop_drop.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class ForloopDrop < Drop def initialize(name, length, parentloop) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index 2671507e..4a2885e8 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'yaml' module Liquid @@ -26,13 +28,13 @@ module Liquid def interpolate(name, vars) name.gsub(/%\{(\w+)\}/) do # 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 def deep_fetch_translation(name) - name.split('.'.freeze).reduce(locale) do |level, cur| - level[cur] or raise TranslationError, "Translation for #{name} does not exist in locale #{path}" + name.split('.').reduce(locale) do |level, cur| + level[cur] || raise(TranslationError, "Translation for #{name} does not exist in locale #{path}") end end end diff --git a/lib/liquid/interrupts.rb b/lib/liquid/interrupts.rb index 41359d78..28355b84 100644 --- a/lib/liquid/interrupts.rb +++ b/lib/liquid/interrupts.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + module Liquid # An interrupt is any command that breaks processing of a block (ex: a for loop). class Interrupt attr_reader :message def initialize(message = nil) - @message = message || "interrupt".freeze + @message = message || "interrupt" end end diff --git a/lib/liquid/lexer.rb b/lib/liquid/lexer.rb index f290744d..a251c3e5 100644 --- a/lib/liquid/lexer.rb +++ b/lib/liquid/lexer.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + require "strscan" module Liquid class Lexer SPECIALS = { - '|'.freeze => :pipe, - '.'.freeze => :dot, - ':'.freeze => :colon, - ','.freeze => :comma, - '['.freeze => :open_square, - ']'.freeze => :close_square, - '('.freeze => :open_round, - ')'.freeze => :close_round, - '?'.freeze => :question, - '-'.freeze => :dash + '|' => :pipe, + '.' => :dot, + ':' => :colon, + ',' => :comma, + '[' => :open_square, + ']' => :close_square, + '(' => :open_round, + ')' => :close_round, + '?' => :question, + '-' => :dash, }.freeze IDENTIFIER = /[a-zA-Z_][\w-]*\??/ SINGLE_STRING_LITERAL = /'[^\']*'/ @@ -31,16 +33,21 @@ module Liquid until @ss.eos? @ss.skip(WHITESPACE_OR_NOTHING) break if @ss.eos? - tok = case - when t = @ss.scan(COMPARISON_OPERATOR) then [:comparison, t] - when t = @ss.scan(SINGLE_STRING_LITERAL) then [:string, t] - when t = @ss.scan(DOUBLE_STRING_LITERAL) then [:string, t] - when t = @ss.scan(NUMBER_LITERAL) then [:number, t] - when t = @ss.scan(IDENTIFIER) then [:id, t] - when t = @ss.scan(DOTDOT) then [:dotdot, t] + tok = if (t = @ss.scan(COMPARISON_OPERATOR)) + [:comparison, t] + elsif (t = @ss.scan(SINGLE_STRING_LITERAL)) + [:string, t] + elsif (t = @ss.scan(DOUBLE_STRING_LITERAL)) + [:string, t] + elsif (t = @ss.scan(NUMBER_LITERAL)) + [:number, t] + elsif (t = @ss.scan(IDENTIFIER)) + [:id, t] + elsif (t = @ss.scan(DOTDOT)) + [:dotdot, t] else c = @ss.getch - if s = SPECIALS[c] + if (s = SPECIALS[c]) [s, c] else raise SyntaxError, "Unexpected character #{c}" diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml index c0a9aff7..a26320bc 100644 --- a/lib/liquid/locales/en.yml +++ b/lib/liquid/locales/en.yml @@ -25,3 +25,5 @@ render: "Syntax error in tag 'render' - Template name must be a quoted string" argument: include: "Argument error in tag 'include' - Illegal template name" + disabled: + tag: "usage is not allowed in this context" diff --git a/lib/liquid/parse_context.rb b/lib/liquid/parse_context.rb index abcdaeba..4afdbe59 100644 --- a/lib/liquid/parse_context.rb +++ b/lib/liquid/parse_context.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class ParseContext attr_accessor :locale, :line_number, :trim_whitespace, :depth @@ -19,7 +21,6 @@ module Liquid @partial = value @options = value ? partial_options : @template_options @error_mode = @options[:error_mode] || Template.error_mode - value end def partial_options @@ -28,7 +29,7 @@ module Liquid if dont_pass == true { locale: locale } 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 @template_options end diff --git a/lib/liquid/parse_tree_visitor.rb b/lib/liquid/parse_tree_visitor.rb index 74f5563a..d50943f3 100644 --- a/lib/liquid/parse_tree_visitor.rb +++ b/lib/liquid/parse_tree_visitor.rb @@ -28,7 +28,7 @@ module Liquid item, new_context = @callbacks[node.class].call(node, context) [ item, - ParseTreeVisitor.for(node, @callbacks).visit(new_context || context) + ParseTreeVisitor.for(node, @callbacks).visit(new_context || context), ] end end diff --git a/lib/liquid/parser.rb b/lib/liquid/parser.rb index 16df6e93..6b9e8374 100644 --- a/lib/liquid/parser.rb +++ b/lib/liquid/parser.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Parser def initialize(input) @@ -51,7 +53,7 @@ module Liquid token = @tokens[@p] if token[0] == :id variable_signature - elsif SINGLE_TOKEN_EXPRESSION_TYPES.include? token[0] + elsif SINGLE_TOKEN_EXPRESSION_TYPES.include?(token[0]) consume elsif token.first == :open_round consume @@ -66,10 +68,10 @@ module Liquid end def argument - str = "" + str = +"" # might be a keyword argument (identifier: expression) if look(:id) && look(:colon, 1) - str << consume << consume << ' '.freeze + str << consume << consume << ' ' end str << expression diff --git a/lib/liquid/parser_switching.rb b/lib/liquid/parser_switching.rb index 3aa664ab..402b0566 100644 --- a/lib/liquid/parser_switching.rb +++ b/lib/liquid/parser_switching.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid module ParserSwitching def parse_with_selected_parser(markup) diff --git a/lib/liquid/partial_cache.rb b/lib/liquid/partial_cache.rb index d0b88457..43c2e39b 100644 --- a/lib/liquid/partial_cache.rb +++ b/lib/liquid/partial_cache.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class PartialCache def self.load(template_name, context:, parse_context:) diff --git a/lib/liquid/profiler.rb b/lib/liquid/profiler.rb index dc9db60a..dc3f1db6 100644 --- a/lib/liquid/profiler.rb +++ b/lib/liquid/profiler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'liquid/profiler/hooks' module Liquid diff --git a/lib/liquid/profiler/hooks.rb b/lib/liquid/profiler/hooks.rb index cda166b7..e7086533 100644 --- a/lib/liquid/profiler/hooks.rb +++ b/lib/liquid/profiler/hooks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class BlockBody def render_node_with_profiling(context, output, node) diff --git a/lib/liquid/range_lookup.rb b/lib/liquid/range_lookup.rb index 93bb420c..8e4d7652 100644 --- a/lib/liquid/range_lookup.rb +++ b/lib/liquid/range_lookup.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class RangeLookup def self.parse(start_markup, end_markup) diff --git a/lib/liquid/register.rb b/lib/liquid/register.rb new file mode 100644 index 00000000..92d02266 --- /dev/null +++ b/lib/liquid/register.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Liquid + class Register + end +end diff --git a/lib/liquid/registers/disabled_tags.rb b/lib/liquid/registers/disabled_tags.rb new file mode 100644 index 00000000..b1cd3bda --- /dev/null +++ b/lib/liquid/registers/disabled_tags.rb @@ -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 diff --git a/lib/liquid/resource_limits.rb b/lib/liquid/resource_limits.rb index 08b359ba..5b7e8e46 100644 --- a/lib/liquid/resource_limits.rb +++ b/lib/liquid/resource_limits.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class ResourceLimits attr_accessor :render_length, :render_score, :assign_score, diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index 3f53f509..482afd48 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -1,20 +1,22 @@ +# frozen_string_literal: true + require 'cgi' require 'bigdecimal' module Liquid module StandardFilters HTML_ESCAPE = { - '&'.freeze => '&'.freeze, - '>'.freeze => '>'.freeze, - '<'.freeze => '<'.freeze, - '"'.freeze => '"'.freeze, - "'".freeze => '''.freeze + '&' => '&', + '>' => '>', + '<' => '<', + '"' => '"', + "'" => ''', }.freeze HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/ STRIP_HTML_BLOCKS = Regexp.union( - //m, + %r{}m, //m, - //m + %r{}m ) STRIP_HTML_TAGS = /<.*?>/m @@ -72,7 +74,7 @@ module Liquid end # 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? input_str = input.to_s 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 end - def truncatewords(input, words = 15, truncate_string = "...".freeze) + def truncatewords(input, words = 15, truncate_string = "...") return if input.nil? wordlist = input.to_s.split words = Utils.to_integer(words) l = words - 1 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 # Split input string into an array of substrings separated by given pattern. @@ -113,7 +115,7 @@ module Liquid end def strip_html(input) - empty = ''.freeze + empty = '' result = input.to_s.gsub(STRIP_HTML_BLOCKS, empty) result.gsub!(STRIP_HTML_TAGS, empty) result @@ -121,11 +123,11 @@ module Liquid # Remove all newlines from the string def strip_newlines(input) - input.to_s.gsub(/\r?\n/, ''.freeze) + input.to_s.gsub(/\r?\n/, '') end # Join elements of the array with certain character between them - def join(input, glue = ' '.freeze) + def join(input, glue = ' ') InputIterator.new(input).join(glue) end @@ -220,7 +222,7 @@ module Liquid InputIterator.new(input).map do |e| e = e.call if e.is_a?(Proc) - if property == "to_liquid".freeze + if property == "to_liquid" e elsif e.respond_to?(:[]) r = e[property] @@ -250,23 +252,23 @@ module Liquid end # 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) end # 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) end # remove a substring def remove(input, string) - input.to_s.gsub(string.to_s, ''.freeze) + input.to_s.gsub(string.to_s, '') end # remove the first occurrences of a substring def remove_first(input, string) - input.to_s.sub(string.to_s, ''.freeze) + input.to_s.sub(string.to_s, '') end # add one string to another @@ -276,7 +278,7 @@ module Liquid def concat(input, array) unless array.respond_to?(:to_ary) - raise ArgumentError.new("concat filter requires an array argument") + raise ArgumentError, "concat filter requires an array argument" end InputIterator.new(input).concat(array) end @@ -288,7 +290,7 @@ module Liquid # Add
tags in front of all newlines in input string def newline_to_br(input) - input.to_s.gsub(/\n/, "
\n".freeze) + input.to_s.gsub(/\n/, "
\n") end # Reformat a date using Ruby's core Time#strftime( string ) -> string @@ -325,7 +327,7 @@ module Liquid def date(input, format) 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) end @@ -430,7 +432,7 @@ module Liquid private def raise_property_error(property) - raise Liquid::ArgumentError.new("cannot select the property '#{property}'") + raise Liquid::ArgumentError, "cannot select the property '#{property}'" end def apply_operation(input, operand, operation) diff --git a/lib/liquid/static_registers.rb b/lib/liquid/static_registers.rb new file mode 100644 index 00000000..06c52ab0 --- /dev/null +++ b/lib/liquid/static_registers.rb @@ -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 diff --git a/lib/liquid/strainer.rb b/lib/liquid/strainer.rb index 76d56d23..3f3417e3 100644 --- a/lib/liquid/strainer.rb +++ b/lib/liquid/strainer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'set' module Liquid @@ -27,7 +29,7 @@ module Liquid def self.add_filter(filter) 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) } if invokable_non_public_methods.any? 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) if self.class.invokable?(method) send(method, *args) - elsif @context && @context.strict_filters + elsif @context&.strict_filters raise Liquid::UndefinedFilter, "undefined filter #{method}" else args.first diff --git a/lib/liquid/tablerowloop_drop.rb b/lib/liquid/tablerowloop_drop.rb index cda4a1ed..0d00b6f1 100644 --- a/lib/liquid/tablerowloop_drop.rb +++ b/lib/liquid/tablerowloop_drop.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class TablerowloopDrop < Drop def initialize(length, cols) diff --git a/lib/liquid/tag.rb b/lib/liquid/tag.rb index 13b7e4bb..ffd22868 100644 --- a/lib/liquid/tag.rb +++ b/lib/liquid/tag.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Tag attr_reader :nodelist, :tag_name, :line_number, :parse_context @@ -11,7 +13,15 @@ module Liquid tag end + def disable_tags(*tags) + disabled_tags.push(*tags) + end + private :new + + def disabled_tags + @disabled_tags ||= [] + end end def initialize(tag_name, markup, parse_context) @@ -33,7 +43,15 @@ module Liquid end 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 # For backwards compatibility with custom tags. In a future release, the semantics @@ -47,5 +65,9 @@ module Liquid def blank? false end + + def disabled_tags + self.class.disabled_tags + end end end diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 50a95536..aaad14cf 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Assign sets a variable in your template. # @@ -11,7 +13,7 @@ module Liquid Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/om def self.syntax_error_translation_key - "errors.syntax.assign".freeze + "errors.syntax.assign" end attr_reader :to, :from @@ -19,10 +21,10 @@ module Liquid def initialize(tag_name, markup, options) super if markup =~ Syntax - @to = $1 - @from = Variable.new($2, options) + @to = Regexp.last_match(1) + @from = Variable.new(Regexp.last_match(2), options) 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 @@ -59,5 +61,5 @@ module Liquid end end - Template.register_tag('assign'.freeze, Assign) + Template.register_tag('assign', Assign) end diff --git a/lib/liquid/tags/break.rb b/lib/liquid/tags/break.rb index 6fe0969b..80f46278 100644 --- a/lib/liquid/tags/break.rb +++ b/lib/liquid/tags/break.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Break tag to be used to break out of a for loop. # @@ -14,5 +16,5 @@ module Liquid end end - Template.register_tag('break'.freeze, Break) + Template.register_tag('break', Break) end diff --git a/lib/liquid/tags/capture.rb b/lib/liquid/tags/capture.rb index d717b769..1cace9c1 100644 --- a/lib/liquid/tags/capture.rb +++ b/lib/liquid/tags/capture.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # 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) super if markup =~ Syntax - @to = $1 + @to = Regexp.last_match(1) else - raise SyntaxError.new(options[:locale].t("errors.syntax.capture")) + raise SyntaxError, options[:locale].t("errors.syntax.capture") end end @@ -35,5 +37,5 @@ module Liquid end end - Template.register_tag('capture'.freeze, Capture) + Template.register_tag('capture', Capture) end diff --git a/lib/liquid/tags/case.rb b/lib/liquid/tags/case.rb index 92b2ed0d..30484c6d 100644 --- a/lib/liquid/tags/case.rb +++ b/lib/liquid/tags/case.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Case < Block Syntax = /(#{QuotedFragment})/o @@ -10,17 +12,15 @@ module Liquid @blocks = [] if markup =~ Syntax - @left = Expression.parse($1) + @left = Expression.parse(Regexp.last_match(1)) else - raise SyntaxError.new(options[:locale].t("errors.syntax.case".freeze)) + raise SyntaxError, options[:locale].t("errors.syntax.case") end end def parse(tokens) body = BlockBody.new - while parse_body(body, tokens) - body = @blocks.last.attachment - end + body = @blocks.last.attachment while parse_body(body, tokens) end def nodelist @@ -29,9 +29,9 @@ module Liquid def unknown_tag(tag, markup, tokens) case tag - when 'when'.freeze + when 'when' record_when_condition(markup) - when 'else'.freeze + when 'else' record_else_condition(markup) else super @@ -39,16 +39,14 @@ module Liquid end def render_to_output_buffer(context, output) - context.stack do - execute_else_block = true + execute_else_block = true - @blocks.each do |block| - if block.else? - block.attachment.render_to_output_buffer(context, output) if execute_else_block - elsif block.evaluate(context) - execute_else_block = false - block.attachment.render_to_output_buffer(context, output) - end + @blocks.each do |block| + if block.else? + block.attachment.render_to_output_buffer(context, output) if execute_else_block + elsif block.evaluate(context) + execute_else_block = false + block.attachment.render_to_output_buffer(context, output) end end @@ -62,12 +60,12 @@ module Liquid while markup 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 - 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) @blocks << block end @@ -75,7 +73,7 @@ module Liquid def record_else_condition(markup) 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 block = ElseCondition.new @@ -90,5 +88,5 @@ module Liquid end end - Template.register_tag('case'.freeze, Case) + Template.register_tag('case', Case) end diff --git a/lib/liquid/tags/comment.rb b/lib/liquid/tags/comment.rb index cad3931e..a5460f99 100644 --- a/lib/liquid/tags/comment.rb +++ b/lib/liquid/tags/comment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Comment < Block def render_to_output_buffer(_context, output) @@ -12,5 +14,5 @@ module Liquid end end - Template.register_tag('comment'.freeze, Comment) + Template.register_tag('comment', Comment) end diff --git a/lib/liquid/tags/continue.rb b/lib/liquid/tags/continue.rb index 9c81ec2c..fb1f371e 100644 --- a/lib/liquid/tags/continue.rb +++ b/lib/liquid/tags/continue.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Continue tag to be used to break out of a for loop. # @@ -14,5 +16,5 @@ module Liquid end end - Template.register_tag('continue'.freeze, Continue) + Template.register_tag('continue', Continue) end diff --git a/lib/liquid/tags/cycle.rb b/lib/liquid/tags/cycle.rb index e42244d4..b203c785 100644 --- a/lib/liquid/tags/cycle.rb +++ b/lib/liquid/tags/cycle.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Cycle is usually used within a loop to alternate between values, like colors or DOM classes. # @@ -21,38 +23,36 @@ module Liquid super case markup when NamedSyntax - @variables = variables_from_string($2) - @name = Expression.parse($1) + @variables = variables_from_string(Regexp.last_match(2)) + @name = Expression.parse(Regexp.last_match(1)) when SimpleSyntax @variables = variables_from_string(markup) @name = @variables.to_s else - raise SyntaxError.new(options[:locale].t("errors.syntax.cycle".freeze)) + raise SyntaxError, options[:locale].t("errors.syntax.cycle") end end def render_to_output_buffer(context, output) context.registers[:cycle] ||= {} - context.stack do - key = context.evaluate(@name) - iteration = context.registers[:cycle][key].to_i + key = context.evaluate(@name) + iteration = context.registers[:cycle][key].to_i - val = context.evaluate(@variables[iteration]) + val = context.evaluate(@variables[iteration]) - if val.is_a?(Array) - val = val.join - elsif !val.is_a?(String) - val = val.to_s - end - - output << val - - iteration += 1 - iteration = 0 if iteration >= @variables.size - context.registers[:cycle][key] = iteration + if val.is_a?(Array) + val = val.join + elsif !val.is_a?(String) + val = val.to_s end + output << val + + iteration += 1 + iteration = 0 if iteration >= @variables.size + context.registers[:cycle][key] = iteration + output end @@ -61,7 +61,7 @@ module Liquid def variables_from_string(markup) markup.split(',').collect do |var| var =~ /\s*(#{QuotedFragment})\s*/o - $1 ? Expression.parse($1) : nil + Regexp.last_match(1) ? Expression.parse(Regexp.last_match(1)) : nil end.compact end diff --git a/lib/liquid/tags/decrement.rb b/lib/liquid/tags/decrement.rb index 08ddd4d6..d761a0c3 100644 --- a/lib/liquid/tags/decrement.rb +++ b/lib/liquid/tags/decrement.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # decrement is used in a place where one needs to insert a counter # into a template, and needs the counter to survive across @@ -32,5 +34,5 @@ module Liquid end end - Template.register_tag('decrement'.freeze, Decrement) + Template.register_tag('decrement', Decrement) end diff --git a/lib/liquid/tags/echo.rb b/lib/liquid/tags/echo.rb index d3d30e3b..1f789376 100644 --- a/lib/liquid/tags/echo.rb +++ b/lib/liquid/tags/echo.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Echo outputs an expression # @@ -16,9 +18,9 @@ module Liquid end def render(context) - @variable.render_to_output_buffer(context, '') + @variable.render_to_output_buffer(context, +'') end end - Template.register_tag('echo'.freeze, Echo) + Template.register_tag('echo', Echo) end diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index 71c2f910..5c7b5601 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # "For" iterates over an array or collection. # Several useful variables are available to you within the loop. @@ -66,7 +68,7 @@ module Liquid end def unknown_tag(tag, markup, tokens) - return super unless tag == 'else'.freeze + return super unless tag == 'else' @else_block = BlockBody.new end @@ -86,31 +88,31 @@ module Liquid def lax_parse(markup) if markup =~ Syntax - @variable_name = $1 - collection_name = $2 - @reversed = !!$3 + @variable_name = Regexp.last_match(1) + collection_name = Regexp.last_match(2) + @reversed = !!Regexp.last_match(3) @name = "#{@variable_name}-#{collection_name}" @collection_name = Expression.parse(collection_name) markup.scan(TagAttributes) do |key, value| set_attribute(key, value) end else - raise SyntaxError.new(options[:locale].t("errors.syntax.for".freeze)) + raise SyntaxError, options[:locale].t("errors.syntax.for") end end def strict_parse(markup) p = Parser.new(markup) @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 @name = "#{@variable_name}-#{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) - unless attribute = p.id?('limit'.freeze) || p.id?('offset'.freeze) - raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_attribute".freeze)) + unless (attribute = p.id?('limit') || p.id?('offset')) + raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_attribute") end p.consume set_attribute(attribute, p.expression) @@ -162,7 +164,7 @@ module Liquid for_stack.push(loop_vars) begin - context['forloop'.freeze] = loop_vars + context['forloop'] = loop_vars segment.each do |item| context[@variable_name] = item @@ -170,11 +172,10 @@ module Liquid loop_vars.send(:increment!) # Handle any interrupts if they exist. - if context.interrupt? - interrupt = context.pop_interrupt - break if interrupt.is_a? BreakInterrupt - next if interrupt.is_a? ContinueInterrupt - end + next unless context.interrupt? + interrupt = context.pop_interrupt + break if interrupt.is_a?(BreakInterrupt) + next if interrupt.is_a?(ContinueInterrupt) end ensure for_stack.pop @@ -186,13 +187,13 @@ module Liquid def set_attribute(key, expr) case key - when 'offset'.freeze - @from = if expr == 'continue'.freeze + when 'offset' + @from = if expr == 'continue' :continue else Expression.parse(expr) end - when 'limit'.freeze + when 'limit' @limit = Expression.parse(expr) end end @@ -212,5 +213,5 @@ module Liquid end end - Template.register_tag('for'.freeze, For) + Template.register_tag('for', For) end diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index 25534a98..b68e309a 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # If is the conditional block # @@ -19,7 +21,7 @@ module Liquid def initialize(tag_name, markup, options) super @blocks = [] - push_block('if'.freeze, markup) + push_block('if', markup) end def nodelist @@ -32,7 +34,7 @@ module Liquid end def unknown_tag(tag, markup, tokens) - if ['elsif'.freeze, 'else'.freeze].include?(tag) + if ['elsif', 'else'].include?(tag) push_block(tag, markup) else super @@ -40,11 +42,9 @@ module Liquid end def render_to_output_buffer(context, output) - context.stack do - @blocks.each do |block| - if block.evaluate(context) - return block.attachment.render_to_output_buffer(context, output) - end + @blocks.each do |block| + if block.evaluate(context) + return block.attachment.render_to_output_buffer(context, output) end end @@ -54,7 +54,7 @@ module Liquid private def push_block(tag, markup) - block = if tag == 'else'.freeze + block = if tag == 'else' ElseCondition.new else parse_with_selected_parser(markup) @@ -66,17 +66,17 @@ module Liquid def lax_parse(markup) 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? 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)) - raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless BOOLEAN_OPERATORS.include?(operator) + new_condition = Condition.new(Expression.parse(Regexp.last_match(1)), Regexp.last_match(2), Expression.parse(Regexp.last_match(3))) + raise SyntaxError, options[:locale].t("errors.syntax.if") unless BOOLEAN_OPERATORS.include?(operator) new_condition.send(operator, condition) condition = new_condition end @@ -94,7 +94,7 @@ module Liquid def parse_binary_comparisons(p) condition = parse_comparison(p) 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) condition.send(op, child_condition) condition = child_condition @@ -104,7 +104,7 @@ module Liquid def parse_comparison(p) a = Expression.parse(p.expression) - if op = p.consume?(:comparison) + if (op = p.consume?(:comparison)) b = Expression.parse(p.expression) Condition.new(a, op, b) else @@ -119,5 +119,5 @@ module Liquid end end - Template.register_tag('if'.freeze, If) + Template.register_tag('if', If) end diff --git a/lib/liquid/tags/ifchanged.rb b/lib/liquid/tags/ifchanged.rb index e3040cec..dd3be532 100644 --- a/lib/liquid/tags/ifchanged.rb +++ b/lib/liquid/tags/ifchanged.rb @@ -1,19 +1,19 @@ +# frozen_string_literal: true + module Liquid class Ifchanged < Block def render_to_output_buffer(context, output) - context.stack do - block_output = '' - super(context, block_output) + block_output = +'' + super(context, block_output) - if block_output != context.registers[:ifchanged] - context.registers[:ifchanged] = block_output - output << block_output - end + if block_output != context.registers[:ifchanged] + context.registers[:ifchanged] = block_output + output << block_output end output end end - Template.register_tag('ifchanged'.freeze, Ifchanged) + Template.register_tag('ifchanged', Ifchanged) end diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb index fd86ee4b..bbcfb1cc 100644 --- a/lib/liquid/tags/include.rb +++ b/lib/liquid/tags/include.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Include allows templates to relate with other templates # @@ -23,8 +25,8 @@ module Liquid if markup =~ Syntax - template_name = $1 - variable_name = $3 + template_name = Regexp.last_match(1) + variable_name = Regexp.last_match(3) @variable_name_expr = variable_name ? Expression.parse(variable_name) : nil @template_name_expr = Expression.parse(template_name) @@ -35,7 +37,7 @@ module Liquid end else - raise SyntaxError.new(options[:locale].t("errors.syntax.include".freeze)) + raise SyntaxError, options[:locale].t("errors.syntax.include") end end @@ -44,7 +46,7 @@ module Liquid def render_to_output_buffer(context, output) 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( template_name, @@ -52,7 +54,7 @@ module Liquid parse_context: parse_context ) - context_variable_name = template_name.split('/'.freeze).last + context_variable_name = template_name.split('/').last variable = if @variable_name_expr context.evaluate(@variable_name_expr) @@ -95,11 +97,11 @@ module Liquid def children [ @node.template_name_expr, - @node.variable_name_expr + @node.variable_name_expr, ] + @node.attributes.values end end end - Template.register_tag('include'.freeze, Include) + Template.register_tag('include', Include) end diff --git a/lib/liquid/tags/increment.rb b/lib/liquid/tags/increment.rb index 95875aa6..241b316b 100644 --- a/lib/liquid/tags/increment.rb +++ b/lib/liquid/tags/increment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # increment is used in a place where one needs to insert a counter # into a template, and needs the counter to survive across @@ -29,5 +31,5 @@ module Liquid end end - Template.register_tag('increment'.freeze, Increment) + Template.register_tag('increment', Increment) end diff --git a/lib/liquid/tags/raw.rb b/lib/liquid/tags/raw.rb index 4fa75d99..e4a78a81 100644 --- a/lib/liquid/tags/raw.rb +++ b/lib/liquid/tags/raw.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Raw < Block Syntax = /\A\s*\z/ @@ -10,16 +12,16 @@ module Liquid end def parse(tokens) - @body = '' - while token = tokens.shift + @body = +'' + while (token = tokens.shift) if token =~ FullTokenPossiblyInvalid - @body << $1 if $1 != "".freeze - return if block_delimiter == $2 + @body << Regexp.last_match(1) if Regexp.last_match(1) != "" + return if block_delimiter == Regexp.last_match(2) end @body << token unless token.empty? 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 def render_to_output_buffer(_context, output) @@ -38,11 +40,11 @@ module Liquid protected def ensure_valid_markup(tag_name, markup, parse_context) - unless markup =~ Syntax - raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_unexpected_args".freeze, tag: tag_name)) + unless Syntax.match?(markup) + raise SyntaxError, parse_context.locale.t("errors.syntax.tag_unexpected_args", tag: tag_name) end end end - Template.register_tag('raw'.freeze, Raw) + Template.register_tag('raw', Raw) end diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb index 2e5310b4..1403b584 100644 --- a/lib/liquid/tags/render.rb +++ b/lib/liquid/tags/render.rb @@ -1,15 +1,19 @@ +# frozen_string_literal: true + module Liquid class Render < Tag - Syntax = /(#{QuotedString})#{QuotedFragment}*/o + SYNTAX = /(#{QuotedString})#{QuotedFragment}*/o + + disable_tags "include" 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 + 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) @@ -20,9 +24,13 @@ module Liquid end 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. 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( template_name, @@ -50,5 +58,5 @@ module Liquid end end - Template.register_tag('render'.freeze, Render) + Template.register_tag('render', Render) end diff --git a/lib/liquid/tags/table_row.rb b/lib/liquid/tags/table_row.rb index 95321020..7c59bd32 100644 --- a/lib/liquid/tags/table_row.rb +++ b/lib/liquid/tags/table_row.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class TableRow < Block Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o @@ -7,33 +9,33 @@ module Liquid def initialize(tag_name, markup, options) super if markup =~ Syntax - @variable_name = $1 - @collection_name = Expression.parse($2) + @variable_name = Regexp.last_match(1) + @collection_name = Expression.parse(Regexp.last_match(2)) @attributes = {} markup.scan(TagAttributes) do |key, value| @attributes[key] = Expression.parse(value) end else - raise SyntaxError.new(options[:locale].t("errors.syntax.table_row".freeze)) + raise SyntaxError, options[:locale].t("errors.syntax.table_row") end end 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 - to = @attributes.key?('limit'.freeze) ? from + context.evaluate(@attributes['limit'.freeze]).to_i : nil + from = @attributes.key?('offset') ? context.evaluate(@attributes['offset']).to_i : 0 + to = @attributes.key?('limit') ? from + context.evaluate(@attributes['limit']).to_i : nil collection = Utils.slice_collection(collection, from, to) length = collection.length - cols = context.evaluate(@attributes['cols'.freeze]).to_i + cols = context.evaluate(@attributes['cols']).to_i output << "\n" context.stack do tablerowloop = Liquid::TablerowloopDrop.new(length, cols) - context['tablerowloop'.freeze] = tablerowloop + context['tablerowloop'] = tablerowloop collection.each do |item| context[@variable_name] = item @@ -61,5 +63,5 @@ module Liquid end end - Template.register_tag('tablerow'.freeze, TableRow) + Template.register_tag('tablerow', TableRow) end diff --git a/lib/liquid/tags/unless.rb b/lib/liquid/tags/unless.rb index 18856c3b..f67f57a9 100644 --- a/lib/liquid/tags/unless.rb +++ b/lib/liquid/tags/unless.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative 'if' module Liquid @@ -7,18 +9,16 @@ module Liquid # class Unless < If def render_to_output_buffer(context, output) - context.stack do - # First condition is interpreted backwards ( if not ) - first_block = @blocks.first - unless first_block.evaluate(context) - return first_block.attachment.render_to_output_buffer(context, output) - end + # First condition is interpreted backwards ( if not ) + first_block = @blocks.first + unless first_block.evaluate(context) + return first_block.attachment.render_to_output_buffer(context, output) + end - # After the first condition unless works just like if - @blocks[1..-1].each do |block| - if block.evaluate(context) - return block.attachment.render_to_output_buffer(context, output) - end + # After the first condition unless works just like if + @blocks[1..-1].each do |block| + if block.evaluate(context) + return block.attachment.render_to_output_buffer(context, output) end end @@ -26,5 +26,5 @@ module Liquid end end - Template.register_tag('unless'.freeze, Unless) + Template.register_tag('unless', Unless) end diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 91e30fbc..e23df246 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Templates are central to liquid. # Interpretating templates is a two step process. First you compile the @@ -90,6 +92,14 @@ module Liquid @tags ||= TagRegistry.new end + def add_register(name, klass) + registers[name.to_sym] = klass + end + + def registers + @registers ||= {} + end + def error_mode @error_mode ||= :lax end @@ -165,14 +175,14 @@ module Liquid # filters and tags and might be useful to integrate liquid more with its host application # def render(*args) - return ''.freeze if @root.nil? + return '' if @root.nil? context = case args.first when Liquid::Context c = args.shift if @rethrow_errors - c.exception_renderer = ->(e) { raise } + c.exception_renderer = ->(_e) { raise } end c @@ -189,18 +199,26 @@ module Liquid output = nil + context_register = context.registers.is_a?(StaticRegisters) ? context.registers.static : context.registers + case args.last when Hash options = args.pop output = options[:output] if options[:output] - 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) when Module, Array context.add_filters(args.pop) end + Template.registers.each do |key, register| + context_register[key] = register + end + # Retrying a render resets resource usage context.resource_limits.reset @@ -208,7 +226,7 @@ module Liquid # render the nodelist. # for performance reasons we get an array back here. join will make a string out of it. with_profiling(context) do - @root.render_to_output_buffer(context, output || '') + @root.render_to_output_buffer(context, output || +'') end rescue Liquid::MemoryError => e context.handle_error(e) diff --git a/lib/liquid/tokenizer.rb b/lib/liquid/tokenizer.rb index d3fd6766..a89c7899 100644 --- a/lib/liquid/tokenizer.rb +++ b/lib/liquid/tokenizer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid class Tokenizer attr_reader :line_number, :for_liquid_tag @@ -10,7 +12,7 @@ module Liquid end def shift - token = @tokens.shift or return + (token = @tokens.shift) || return if @line_number @line_number += @for_liquid_tag ? 1 : token.count("\n") @@ -29,7 +31,7 @@ module Liquid tokens = @source.split(TemplateParser) # 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 end diff --git a/lib/liquid/usage.rb b/lib/liquid/usage.rb new file mode 100644 index 00000000..141eccb9 --- /dev/null +++ b/lib/liquid/usage.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Liquid + module Usage + def self.increment(name) + end + end +end diff --git a/lib/liquid/utils.rb b/lib/liquid/utils.rb index 516ac0cf..709fb002 100644 --- a/lib/liquid/utils.rb +++ b/lib/liquid/utils.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid module Utils def self.slice_collection(collection, from, to) @@ -50,7 +52,7 @@ module Liquid when Numeric obj 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 if obj.respond_to?(:to_number) obj.to_number @@ -69,7 +71,7 @@ module Liquid end case obj - when 'now'.freeze, 'today'.freeze + when 'now', 'today' Time.now when /\A\d+\z/, Integer Time.at(obj.to_i) diff --git a/lib/liquid/variable.rb b/lib/liquid/variable.rb index cbf99864..5b686e2d 100644 --- a/lib/liquid/variable.rb +++ b/lib/liquid/variable.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Liquid # Holds variables. Variables are only loaded "just in time" # and are not evaluated as part of the render stage @@ -43,11 +45,11 @@ module Liquid @filters = [] return unless markup =~ MarkupWithQuotedFragment - name_markup = $1 - filter_markup = $2 + name_markup = Regexp.last_match(1) + filter_markup = Regexp.last_match(2) @name = Expression.parse(name_markup) if filter_markup =~ FilterMarkupRegex - filters = $1.scan(FilterParser) + filters = Regexp.last_match(1).scan(FilterParser) filters.each do |f| next unless f =~ /\w+/ filtername = Regexp.last_match(0) @@ -102,13 +104,21 @@ module Liquid output end + def disabled?(_context) + false + end + + def disabled_tags + [] + end + private def parse_filter_expressions(filter_name, unparsed_args) filter_args = [] keyword_args = nil unparsed_args.each do |a| - if matches = a.match(JustTagAttributes) + if (matches = a.match(JustTagAttributes)) keyword_args ||= {} keyword_args[matches[1]] = Expression.parse(matches[2]) else @@ -121,7 +131,7 @@ module Liquid end 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 parsed_kwargs = {} filter_kwargs.each do |key, expr| diff --git a/lib/liquid/variable_lookup.rb b/lib/liquid/variable_lookup.rb index 62f4877c..112373d5 100644 --- a/lib/liquid/variable_lookup.rb +++ b/lib/liquid/variable_lookup.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + module Liquid class VariableLookup SQUARE_BRACKETED = /\A\[(.*)\]\z/m - COMMAND_METHODS = ['size'.freeze, 'first'.freeze, 'last'.freeze].freeze + COMMAND_METHODS = ['size', 'first', 'last'].freeze attr_reader :name, :lookups @@ -14,7 +16,7 @@ module Liquid name = lookups.shift if name =~ SQUARE_BRACKETED - name = Expression.parse($1) + name = Expression.parse(Regexp.last_match(1)) end @name = name @@ -24,7 +26,7 @@ module Liquid @lookups.each_index do |i| lookup = lookups[i] if lookup =~ SQUARE_BRACKETED - lookups[i] = Expression.parse($1) + lookups[i] = Expression.parse(Regexp.last_match(1)) elsif COMMAND_METHODS.include?(lookup) @command_flags |= 1 << i end diff --git a/lib/liquid/version.rb b/lib/liquid/version.rb index da01c476..9af29732 100644 --- a/lib/liquid/version.rb +++ b/lib/liquid/version.rb @@ -1,5 +1,6 @@ # encoding: utf-8 +# frozen_string_literal: true module Liquid - VERSION = "4.0.3".freeze + VERSION = "4.0.3" end diff --git a/liquid.gemspec b/liquid.gemspec index 89df19a0..54a11fb9 100644 --- a/liquid.gemspec +++ b/liquid.gemspec @@ -1,7 +1,8 @@ # encoding: utf-8 +# frozen_string_literal: true 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" @@ -26,6 +27,6 @@ Gem::Specification.new do |s| s.require_path = "lib" - s.add_development_dependency 'rake', '~> 11.3' - s.add_development_dependency 'minitest' + s.add_development_dependency('rake', '~> 11.3') + s.add_development_dependency('minitest') end diff --git a/performance/benchmark.rb b/performance/benchmark.rb index 68c568c1..4d28b9ac 100644 --- a/performance/benchmark.rb +++ b/performance/benchmark.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'benchmark/ips' require_relative 'theme_runner' diff --git a/performance/profile.rb b/performance/profile.rb index c6fb1932..70740778 100644 --- a/performance/profile.rb +++ b/performance/profile.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'stackprof' require_relative 'theme_runner' @@ -13,7 +15,7 @@ profiler.run 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| StackProf::Report.new(results).print_graphviz(nil, f) end diff --git a/performance/shopify/comment_form.rb b/performance/shopify/comment_form.rb index 7b5bd53b..7648e1a4 100644 --- a/performance/shopify/comment_form.rb +++ b/performance/shopify/comment_form.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CommentForm < Liquid::Block Syntax = /(#{Liquid::VariableSignature}+)/ @@ -5,10 +7,10 @@ class CommentForm < Liquid::Block super if markup =~ Syntax - @variable_name = $1 + @variable_name = Regexp.last_match(1) @attributes = {} 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 @@ -20,8 +22,8 @@ class CommentForm < Liquid::Block 'posted_successfully?' => context.registers[:posted_successfully], 'errors' => context['comment.errors'], 'author' => context['comment.author'], - 'email' => context['comment.email'], - 'body' => context['comment.body'] + 'email' => context['comment.email'], + 'body' => context['comment.body'], } output << wrap_in_form(article, render_all(@nodelist, context, output)) diff --git a/performance/shopify/database.rb b/performance/shopify/database.rb index 2b5bca49..2db6d300 100644 --- a/performance/shopify/database.rb +++ b/performance/shopify/database.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'yaml' module Database @@ -16,9 +18,10 @@ module Database end # key the tables by handles, as this is how liquid expects it. - db = db.inject({}) do |assigns, (key, values)| - assigns[key] = values.inject({}) { |h, v| h[v['handle']] = v; h; } - assigns + db = db.each_with_object({}) do |(key, values), assigns| + assigns[key] = values.each_with_object({}) do |v, h| + h[v['handle']] = v + end end # Some standard direct accessors so that the specialized templates @@ -29,9 +32,9 @@ module Database db['article'] = db['blog']['articles'].first db['cart'] = { - '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'] }, - 'items' => db['line_items'].values + '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'] }, + 'items' => db['line_items'].values, } db @@ -40,6 +43,6 @@ module Database end if __FILE__ == $PROGRAM_NAME - p Database.tables['collections']['frontpage'].keys + p(Database.tables['collections']['frontpage'].keys) # p Database.tables['blog']['articles'] end diff --git a/performance/shopify/json_filter.rb b/performance/shopify/json_filter.rb index 8fbb5b66..c7c25d8a 100644 --- a/performance/shopify/json_filter.rb +++ b/performance/shopify/json_filter.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + require 'json' module JsonFilter def json(object) - JSON.dump(object.reject { |k, v| k == "collections" }) + JSON.dump(object.reject { |k, _v| k == "collections" }) end end diff --git a/performance/shopify/liquid.rb b/performance/shopify/liquid.rb index 7716debc..40444c3c 100644 --- a/performance/shopify/liquid.rb +++ b/performance/shopify/liquid.rb @@ -1,4 +1,6 @@ -$:.unshift __dir__ + '/../../lib' +# frozen_string_literal: true + +$LOAD_PATH.unshift(__dir__ + '/../../lib') require_relative '../../lib/liquid' require_relative 'comment_form' @@ -9,11 +11,11 @@ require_relative 'shop_filter' require_relative 'tag_filter' require_relative 'weight_filter' -Liquid::Template.register_tag 'paginate', Paginate -Liquid::Template.register_tag 'form', CommentForm +Liquid::Template.register_tag('paginate', Paginate) +Liquid::Template.register_tag('form', CommentForm) -Liquid::Template.register_filter JsonFilter -Liquid::Template.register_filter MoneyFilter -Liquid::Template.register_filter WeightFilter -Liquid::Template.register_filter ShopFilter -Liquid::Template.register_filter TagFilter +Liquid::Template.register_filter(JsonFilter) +Liquid::Template.register_filter(MoneyFilter) +Liquid::Template.register_filter(WeightFilter) +Liquid::Template.register_filter(ShopFilter) +Liquid::Template.register_filter(TagFilter) diff --git a/performance/shopify/money_filter.rb b/performance/shopify/money_filter.rb index 8dad7890..b0135e3e 100644 --- a/performance/shopify/money_filter.rb +++ b/performance/shopify/money_filter.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + module MoneyFilter def money_with_currency(money) return '' if money.nil? - sprintf("$ %.2f USD", money / 100.0) + format("$ %.2f USD", money / 100.0) end def money(money) return '' if money.nil? - sprintf("$ %.2f", money / 100.0) + format("$ %.2f", money / 100.0) end private diff --git a/performance/shopify/paginate.rb b/performance/shopify/paginate.rb index 0abd11ff..f7238238 100644 --- a/performance/shopify/paginate.rb +++ b/performance/shopify/paginate.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + class Paginate < Liquid::Block - Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/ + Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/ def initialize(tag_name, markup, options) super if markup =~ Syntax - @collection_name = $1 - @page_size = if $2 - $3.to_i + @collection_name = Regexp.last_match(1) + @page_size = if Regexp.last_match(2) + Regexp.last_match(3).to_i else 20 end @@ -17,7 +19,7 @@ class Paginate < Liquid::Block @attributes[key] = value end 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 @@ -25,19 +27,19 @@ class Paginate < Liquid::Block @context = context context.stack do - current_page = context['current_page'].to_i + current_page = context['current_page'].to_i pagination = { - 'page_size' => @page_size, - 'current_page' => 5, - 'current_offset' => @page_size * 5 + 'page_size' => @page_size, + 'current_page' => 5, + 'current_offset' => @page_size * 5, } 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 diff --git a/performance/shopify/shop_filter.rb b/performance/shopify/shop_filter.rb index 89c9083b..9f0cdc2f 100644 --- a/performance/shopify/shop_filter.rb +++ b/performance/shopify/shop_filter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ShopFilter def asset_url(input) "/files/1/[shop_id]/[shop_id]/assets/#{input}" @@ -52,7 +54,7 @@ module ShopFilter end 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' end @@ -60,7 +62,7 @@ module ShopFilter when 'original' return '/files/shops/random_number/' + url 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 raise ArgumentError, 'valid parameters for filter "size" are: original, grande, large, medium, compact, small, thumb and icon ' end @@ -70,16 +72,14 @@ module ShopFilter html = [] html << %(#{link_to(paginate['previous']['title'], paginate['previous']['url'])}) if paginate['previous'] - for part in paginate['parts'] - - if part['is_link'] - html << %(#{link_to(part['title'], part['url'])}) + paginate['parts'].each do |part| + html << if part['is_link'] + %(#{link_to(part['title'], part['url'])}) elsif part['title'].to_i == paginate['current_page'].to_i - html << %(#{part['title']}) + %(#{part['title']}) else - html << %(#{part['title']}) + %(#{part['title']}) end - end html << %(#{link_to(paginate['next']['title'], paginate['next']['url'])}) if paginate['next'] diff --git a/performance/shopify/tag_filter.rb b/performance/shopify/tag_filter.rb index ab5aef62..58f066be 100644 --- a/performance/shopify/tag_filter.rb +++ b/performance/shopify/tag_filter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module TagFilter def link_to_tag(label, tag) "#{label}" @@ -13,11 +15,11 @@ module TagFilter def link_to_add_tag(label, tag) tags = (@context['current_tags'] + [tag]).uniq - "#{label}" + "#{label}" end def link_to_remove_tag(label, tag) tags = (@context['current_tags'] - [tag]).uniq - "#{label}" + "#{label}" end end diff --git a/performance/shopify/weight_filter.rb b/performance/shopify/weight_filter.rb index a0a15fca..6ba95f37 100644 --- a/performance/shopify/weight_filter.rb +++ b/performance/shopify/weight_filter.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module WeightFilter def weight(grams) - sprintf("%.2f", grams / 1000) + format("%.2f", grams / 1000) end def weight_with_unit(grams) diff --git a/performance/theme_runner.rb b/performance/theme_runner.rb index 9f6a1fc4..5ad01c55 100644 --- a/performance/theme_runner.rb +++ b/performance/theme_runner.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This profiler run simulates Shopify. # We are looking in the tests directory for liquid files and render them within the designated layout file. # We will also export a substantial database to liquid which the templates can render values of. @@ -31,7 +33,7 @@ class ThemeRunner { liquid: File.read(test), layout: (File.file?(theme_path) ? File.read(theme_path) : nil), - template_name: test + template_name: test, } end.compact diff --git a/test/integration/assign_test.rb b/test/integration/assign_test.rb index 55022899..ffcb8a3f 100644 --- a/test/integration/assign_test.rb +++ b/test/integration/assign_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class AssignTest < Minitest::Test diff --git a/test/integration/blank_test.rb b/test/integration/blank_test.rb index 2b46ad71..f92490b2 100644 --- a/test/integration/blank_test.rb +++ b/test/integration/blank_test.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + require 'test_helper' class FoobarTag < Liquid::Tag - def render_to_output_buffer(context, output) + def render_to_output_buffer(_context, output) output << ' ' output end diff --git a/test/integration/block_test.rb b/test/integration/block_test.rb index 08245301..5603b53f 100644 --- a/test/integration/block_test.rb +++ b/test/integration/block_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class BlockTest < Minitest::Test diff --git a/test/integration/capture_test.rb b/test/integration/capture_test.rb index 8d965b35..f28e1b1b 100644 --- a/test/integration/capture_test.rb +++ b/test/integration/capture_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class CaptureTest < Minitest::Test diff --git a/test/integration/context_test.rb b/test/integration/context_test.rb index 2d109bb7..cd6d7a88 100644 --- a/test/integration/context_test.rb +++ b/test/integration/context_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ContextTest < Minitest::Test diff --git a/test/integration/document_test.rb b/test/integration/document_test.rb index bcc4a21c..375ccfa7 100644 --- a/test/integration/document_test.rb +++ b/test/integration/document_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class DocumentTest < Minitest::Test diff --git a/test/integration/drop_test.rb b/test/integration/drop_test.rb index 2de4a5a1..3fe61750 100644 --- a/test/integration/drop_test.rb +++ b/test/integration/drop_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ContextDrop < Liquid::Drop @@ -31,7 +33,7 @@ class ProductDrop < Liquid::Drop class CatchallDrop < Liquid::Drop def liquid_method_missing(method) - 'catchall_method: ' << method.to_s + "catchall_method: #{method}" end end @@ -48,7 +50,7 @@ class ProductDrop < Liquid::Drop end def user_input - "foo".taint + (+"foo").taint end protected @@ -201,9 +203,9 @@ class DropsTest < Minitest::Test end def test_scope_though_proc - 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 '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 '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 '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 def test_scope_with_assigns @@ -241,7 +243,7 @@ class DropsTest < Minitest::Test end 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' => 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) - [ :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' => EnumerableDrop.new) @@ -270,4 +272,11 @@ class DropsTest < Minitest::Test assert_equal 'ProductDrop', Liquid::Template.parse("{{ product }}").render!('product' => ProductDrop.new) assert_equal 'EnumerableDrop', Liquid::Template.parse('{{ collection }}').render!('collection' => EnumerableDrop.new) 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 diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index b2d186cf..7abaec04 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ErrorHandlingTest < Minitest::Test @@ -83,15 +85,14 @@ class ErrorHandlingTest < Minitest::Test def test_with_line_numbers_adds_numbers_to_parser_errors err = assert_raises(SyntaxError) do - Liquid::Template.parse(%q( + Liquid::Template.parse(' foobar {% "cat" | foobar %} bla - ), - line_numbers: true - ) + ', + line_numbers: true) end 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 err = assert_raises(SyntaxError) do - Liquid::Template.parse(%q( + Liquid::Template.parse(' foobar {%- "cat" | foobar -%} bla - ), - line_numbers: true - ) + ', + line_numbers: true) end assert_match(/Liquid syntax error \(line 4\)/, err.message) @@ -122,8 +122,7 @@ class ErrorHandlingTest < Minitest::Test bla ', error_mode: :warn, - line_numbers: true - ) + line_numbers: true) assert_equal ['Liquid syntax error (line 4): Unexpected character = in "1 =! 2"'], template.warnings.map(&:message) @@ -139,8 +138,7 @@ class ErrorHandlingTest < Minitest::Test bla ', error_mode: :strict, - line_numbers: true - ) + line_numbers: true) end assert_equal 'Liquid syntax error (line 4): Unexpected character = in "1 =! 2"', err.message @@ -157,8 +155,7 @@ class ErrorHandlingTest < Minitest::Test bla ', - line_numbers: true - ) + line_numbers: true) end 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 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 [Liquid::InternalError], template.errors.map(&:class) @@ -214,10 +211,13 @@ class ErrorHandlingTest < Minitest::Test def test_setting_default_exception_renderer old_exception_renderer = Liquid::Template.default_exception_renderer 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 }}') - output = template.render({ 'errors' => ErrorDrop.new }) + output = template.render('errors' => ErrorDrop.new) assert_equal 'This is a runtime error: ', output assert_equal [Liquid::ArgumentError], template.errors.map(&:class) @@ -228,7 +228,10 @@ class ErrorHandlingTest < Minitest::Test def test_exception_renderer_exposing_non_liquid_error template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}', line_numbers: true) exceptions = [] - handler = ->(e) { exceptions << e; e.cause } + handler = ->(e) { + exceptions << e + e.cause + } output = template.render({ 'errors' => ErrorDrop.new }, exception_renderer: handler) @@ -239,7 +242,7 @@ class ErrorHandlingTest < Minitest::Test end class TestFileSystem - def read_template_file(template_path) + def read_template_file(_template_path) "{{ errors.argument_error }}" end end diff --git a/test/integration/filter_test.rb b/test/integration/filter_test.rb index d3c880e8..270477e6 100644 --- a/test/integration/filter_test.rb +++ b/test/integration/filter_test.rb @@ -1,24 +1,26 @@ +# frozen_string_literal: true + require 'test_helper' module MoneyFilter def money(input) - sprintf(' %d$ ', input) + format(' %d$ ', input) end def money_with_underscore(input) - sprintf(' %d$ ', input) + format(' %d$ ', input) end end module CanadianMoneyFilter def money(input) - sprintf(' %d$ CAD ', input) + format(' %d$ CAD ', input) end end module SubstituteFilter def substitute(input, params = {}) - input.gsub(/%\{(\w+)\}/) { |match| params[$1] } + input.gsub(/%\{(\w+)\}/) { |_match| params[Regexp.last_match(1)] } end end @@ -26,7 +28,7 @@ class FiltersTest < Minitest::Test include Liquid module OverrideObjectMethodFilter - def tap(input) + def tap(_input) "tap overridden" end end @@ -149,7 +151,7 @@ class FiltersTest < Minitest::Test assert_equal "tap overridden", Template.parse("{{var | tap}}").render!({ 'var' => 1000 }, filters: [OverrideObjectMethodFilter]) # 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 diff --git a/test/integration/hash_ordering_test.rb b/test/integration/hash_ordering_test.rb index dfc1c29f..27d0b9b9 100644 --- a/test/integration/hash_ordering_test.rb +++ b/test/integration/hash_ordering_test.rb @@ -1,15 +1,17 @@ +# frozen_string_literal: true + require 'test_helper' class HashOrderingTest < Minitest::Test module MoneyFilter def money(input) - sprintf(' %d$ ', input) + format(' %d$ ', input) end end module CanadianMoneyFilter def money(input) - sprintf(' %d$ CAD ', input) + format(' %d$ CAD ', input) end end diff --git a/test/integration/output_test.rb b/test/integration/output_test.rb index b4cf9d70..687cad87 100644 --- a/test/integration/output_test.rb +++ b/test/integration/output_test.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + require 'test_helper' module FunnyFilter - def make_funny(input) + def make_funny(_input) 'LOL' end @@ -32,7 +34,7 @@ class OutputTest < Minitest::Test def setup @assigns = { 'best_cars' => 'bmw', - 'car' => { 'bmw' => 'good', 'gm' => 'bad' } + 'car' => { 'bmw' => 'good', 'gm' => 'bad' }, } end diff --git a/test/integration/parse_tree_visitor_test.rb b/test/integration/parse_tree_visitor_test.rb index 6ad6a2d0..d1af123d 100644 --- a/test/integration/parse_tree_visitor_test.rb +++ b/test/integration/parse_tree_visitor_test.rb @@ -227,7 +227,7 @@ class ParseTreeVisitorTest < Minitest::Test [[nil, [ [nil, [[nil, [["other", []]]]]], ["test", []], - ["xs", []] + ["xs", []], ]]], traversal(%({% for x in xs offset: test %}{{ other }}{% endfor %})).visit ) diff --git a/test/integration/parsing_quirks_test.rb b/test/integration/parsing_quirks_test.rb index 29cb6d6d..c210b486 100644 --- a/test/integration/parsing_quirks_test.rb +++ b/test/integration/parsing_quirks_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ParsingQuirksTest < Minitest::Test diff --git a/test/integration/registers/disabled_tags_test.rb b/test/integration/registers/disabled_tags_test.rb new file mode 100644 index 00000000..1fb24589 --- /dev/null +++ b/test/integration/registers/disabled_tags_test.rb @@ -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 diff --git a/test/integration/render_profiling_test.rb b/test/integration/render_profiling_test.rb index d0111e77..753b2be2 100644 --- a/test/integration/render_profiling_test.rb +++ b/test/integration/render_profiling_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class RenderProfilingTest < Minitest::Test @@ -128,7 +130,7 @@ class RenderProfilingTest < Minitest::Test t.render! timing_count = 0 - t.profiler.each do |timing| + t.profiler.each do |_timing| timing_count += 1 end @@ -145,7 +147,7 @@ class RenderProfilingTest < Minitest::Test def test_profiling_marks_children_of_for_blocks 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 # Will profile each invocation of the for block diff --git a/test/integration/security_test.rb b/test/integration/security_test.rb index f603ff08..28e9d392 100644 --- a/test/integration/security_test.rb +++ b/test/integration/security_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' module SecurityFilter diff --git a/test/integration/standard_filter_test.rb b/test/integration/standard_filter_test.rb index 2e111ebe..7cd3e315 100644 --- a/test/integration/standard_filter_test.rb +++ b/test/integration/standard_filter_test.rb @@ -1,4 +1,5 @@ # encoding: utf-8 +# frozen_string_literal: true require 'test_helper' @@ -17,7 +18,7 @@ class TestThing "woot: #{@foo}" end - def [](whatever) + def [](_whatever) to_s end @@ -37,7 +38,7 @@ class TestEnumerable < Liquid::Drop include Enumerable 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 @@ -208,14 +209,14 @@ class StandardFiltersTest < Minitest::Test { "handle" => "beta" }, { "price" => 1, "handle" => "gamma" }, { "handle" => "delta" }, - { "price" => 2, "handle" => "epsilon" } + { "price" => 2, "handle" => "epsilon" }, ] expectation = [ { "price" => 1, "handle" => "gamma" }, { "price" => 2, "handle" => "epsilon" }, { "price" => 4, "handle" => "alpha" }, { "handle" => "delta" }, - { "handle" => "beta" } + { "handle" => "beta" }, ] assert_equal expectation, @filters.sort(input, "price") end @@ -236,14 +237,14 @@ class StandardFiltersTest < Minitest::Test { "handle" => "beta" }, { "price" => "1", "handle" => "gamma" }, { "handle" => "delta" }, - { "price" => 2, "handle" => "epsilon" } + { "price" => 2, "handle" => "epsilon" }, ] expectation = [ { "price" => "1", "handle" => "gamma" }, { "price" => 2, "handle" => "epsilon" }, { "price" => "4", "handle" => "alpha" }, { "handle" => "delta" }, - { "handle" => "beta" } + { "handle" => "beta" }, ] assert_equal expectation, @filters.sort_natural(input, "price") end @@ -256,7 +257,7 @@ class StandardFiltersTest < Minitest::Test { "fake" => "t" }, { "key" => "a" }, { "key" => "b" }, - { "key" => "c" } + { "key" => "c" }, ] expectation = [ { "key" => "a" }, @@ -265,7 +266,7 @@ class StandardFiltersTest < Minitest::Test { "key" => "X" }, { "key" => "Y" }, { "key" => "Z" }, - { "fake" => "t" } + { "fake" => "t" }, ] 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"]) @@ -279,7 +280,7 @@ class StandardFiltersTest < Minitest::Test foo = [ [1], [2], - [3] + [3], ] assert_raises Liquid::ArgumentError do @@ -295,7 +296,7 @@ class StandardFiltersTest < Minitest::Test foo = [ [1], [2], - [3] + [3], ] assert_raises Liquid::ArgumentError do @@ -304,7 +305,7 @@ class StandardFiltersTest < Minitest::Test end 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 def test_numerical_vs_lexicographical_sort @@ -330,7 +331,7 @@ class StandardFiltersTest < Minitest::Test foo = [ [1], [2], - [3] + [3], ] assert_raises Liquid::ArgumentError do @@ -346,7 +347,7 @@ class StandardFiltersTest < Minitest::Test foo = [ [1], [2], - [3] + [3], ] assert_raises Liquid::ArgumentError do @@ -380,7 +381,7 @@ class StandardFiltersTest < Minitest::Test def test_map_on_hashes assert_template_result "4217", '{{ thing | map: "foo" | map: "bar" }}', - "thing" => { "foo" => [ { "bar" => 42 }, { "bar" => 17 } ] } + "thing" => { "foo" => [{ "bar" => 42 }, { "bar" => 17 }] } end def test_legacy_map_on_hashes_with_dynamic_key @@ -397,7 +398,7 @@ class StandardFiltersTest < Minitest::Test def test_map_over_proc drop = TestDrop.new - p = proc{ drop } + p = proc { drop } templ = '{{ procs | map: "test" }}' assert_template_result "testfoo", templ, "procs" => [p] end @@ -405,10 +406,10 @@ class StandardFiltersTest < Minitest::Test def test_map_over_drops_returning_procs drops = [ { - "proc" => ->{ "foo" }, + "proc" => -> { "foo" }, }, { - "proc" => ->{ "bar" }, + "proc" => -> { "bar" }, }, ] templ = '{{ drops | map: "proc" }}' @@ -423,7 +424,7 @@ class StandardFiltersTest < Minitest::Test foo = [ [1], [2], - [3] + [3], ] assert_raises Liquid::ArgumentError do @@ -435,7 +436,7 @@ class StandardFiltersTest < Minitest::Test foo = [ [1], [2], - [3] + [3], ] assert_raises Liquid::ArgumentError do @filters.map(foo, nil) @@ -706,12 +707,12 @@ class StandardFiltersTest < Minitest::Test { "handle" => "alpha", "ok" => true }, { "handle" => "beta", "ok" => false }, { "handle" => "gamma", "ok" => false }, - { "handle" => "delta", "ok" => true } + { "handle" => "delta", "ok" => true }, ] expectation = [ { "handle" => "alpha", "ok" => true }, - { "handle" => "delta", "ok" => true } + { "handle" => "delta", "ok" => true }, ] assert_equal expectation, @filters.where(input, "ok", true) @@ -723,12 +724,12 @@ class StandardFiltersTest < Minitest::Test { "handle" => "alpha", "ok" => true }, { "handle" => "beta" }, { "handle" => "gamma" }, - { "handle" => "delta", "ok" => true } + { "handle" => "delta", "ok" => true }, ] expectation = [ { "handle" => "alpha", "ok" => true }, - { "handle" => "delta", "ok" => true } + { "handle" => "delta", "ok" => true }, ] assert_equal expectation, @filters.where(input, "ok", true) @@ -749,7 +750,7 @@ class StandardFiltersTest < Minitest::Test input = [ { "message" => "Bonjour!", "language" => "French" }, { "message" => "Hello!", "language" => "English" }, - { "message" => "Hallo!", "language" => "German" } + { "message" => "Hallo!", "language" => "German" }, ] assert_equal [{ "message" => "Bonjour!", "language" => "French" }], @filters.where(input, "language", "French") @@ -767,7 +768,7 @@ class StandardFiltersTest < Minitest::Test { "foo" => false }, { "foo" => true }, { "foo" => "for sure" }, - { "bar" => true } + { "bar" => true }, ] assert_equal [{ "foo" => true }, { "foo" => "for sure" }], @filters.where(input, "foo") diff --git a/test/integration/tags/break_tag_test.rb b/test/integration/tags/break_tag_test.rb index 0fbde837..c3a46791 100644 --- a/test/integration/tags/break_tag_test.rb +++ b/test/integration/tags/break_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class BreakTagTest < Minitest::Test diff --git a/test/integration/tags/continue_tag_test.rb b/test/integration/tags/continue_tag_test.rb index ce4c158b..00cca17c 100644 --- a/test/integration/tags/continue_tag_test.rb +++ b/test/integration/tags/continue_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ContinueTagTest < Minitest::Test diff --git a/test/integration/tags/echo_test.rb b/test/integration/tags/echo_test.rb index ed5b821d..c64932e3 100644 --- a/test/integration/tags/echo_test.rb +++ b/test/integration/tags/echo_test.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require 'test_helper' class EchoTest < Minitest::Test include Liquid 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 -%} LIQUID end diff --git a/test/integration/tags/for_tag_test.rb b/test/integration/tags/for_tag_test.rb index 9980e258..667efac0 100644 --- a/test/integration/tags/for_tag_test.rb +++ b/test/integration/tags/for_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ThingWithValue < Liquid::Drop @@ -23,16 +25,16 @@ class ForTagTest < Minitest::Test yo HERE - template = < [1, 2, 3]) end 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) end diff --git a/test/integration/tags/if_else_tag_test.rb b/test/integration/tags/if_else_tag_test.rb index 45a5d3ac..d54b2fb8 100644 --- a/test/integration/tags/if_else_tag_test.rb +++ b/test/integration/tags/if_else_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class IfElseTagTest < Minitest::Test @@ -132,7 +134,7 @@ class IfElseTagTest < Minitest::Test end 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 def test_syntax_error_no_expression diff --git a/test/integration/tags/include_tag_test.rb b/test/integration/tags/include_tag_test.rb index 14bb8c3a..45410a7a 100644 --- a/test/integration/tags/include_tag_test.rb +++ b/test/integration/tags/include_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class TestFileSystem @@ -40,14 +42,14 @@ class TestFileSystem end class OtherFileSystem - def read_template_file(template_path) + def read_template_file(_template_path) 'from OtherFileSystem' end end class CountingFileSystem attr_reader :count - def read_template_file(template_path) + def read_template_file(_template_path) @count ||= 0 @count += 1 'from CountingFileSystem' @@ -59,14 +61,14 @@ class CustomInclude < Liquid::Tag def initialize(tag_name, markup, tokens) markup =~ Syntax - @template_name = $1 + @template_name = Regexp.last_match(1) super end def parse(tokens) end - def render_to_output_buffer(context, output) + def render_to_output_buffer(_context, output) output << @template_name[1..-2] output end @@ -86,7 +88,7 @@ class IncludeTagTest < Minitest::Test def test_include_tag_with assert_template_result "Product: Draft 151cm ", - "{% include 'product' with products[0] %}", "products" => [ { 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' } ] + "{% include 'product' with products[0] %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] end def test_include_tag_with_default_name @@ -96,7 +98,7 @@ class IncludeTagTest < Minitest::Test def test_include_tag_for assert_template_result "Product: Draft 151cm Product: Element 155cm ", - "{% include 'product' for products %}", "products" => [ { 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' } ] + "{% include 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] end def test_include_tag_with_local_variables @@ -134,7 +136,7 @@ class IncludeTagTest < Minitest::Test def test_recursively_included_template_does_not_produce_endless_loop infinite_file_system = Class.new do - def read_template_file(template_path) + def read_template_file(_template_path) "-{% include 'loop' %}" end end diff --git a/test/integration/tags/increment_tag_test.rb b/test/integration/tags/increment_tag_test.rb index 97c51ac5..d561a1b5 100644 --- a/test/integration/tags/increment_tag_test.rb +++ b/test/integration/tags/increment_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class IncrementTagTest < Minitest::Test @@ -13,11 +15,11 @@ class IncrementTagTest < Minitest::Test end def test_dec - assert_template_result('9', '{%decrement port %}', { 'port' => 10 }) + assert_template_result('9', '{%decrement port %}', 'port' => 10) assert_template_result('-1 -2', '{%decrement port %} {%decrement port%}', {}) assert_template_result('1 5 2 2 5', '{%increment port %} {%increment starboard%} ' \ '{%increment port %} {%decrement port%} ' \ - '{%decrement starboard %}', { 'port' => 1, 'starboard' => 5 }) + '{%decrement starboard %}', 'port' => 1, 'starboard' => 5) end end diff --git a/test/integration/tags/liquid_tag_test.rb b/test/integration/tags/liquid_tag_test.rb index 628eb85e..b5f6b492 100644 --- a/test/integration/tags/liquid_tag_test.rb +++ b/test/integration/tags/liquid_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class LiquidTagTest < Minitest::Test diff --git a/test/integration/tags/raw_tag_test.rb b/test/integration/tags/raw_tag_test.rb index 634d052d..461e5bfc 100644 --- a/test/integration/tags/raw_tag_test.rb +++ b/test/integration/tags/raw_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class RawTagTest < Minitest::Test diff --git a/test/integration/tags/render_tag_test.rb b/test/integration/tags/render_tag_test.rb index a31d0182..87373a28 100644 --- a/test/integration/tags/render_tag_test.rb +++ b/test/integration/tags/render_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class RenderTagTest < Minitest::Test @@ -87,14 +89,12 @@ class RenderTagTest < Minitest::Test end end - def test_includes_and_renders_count_towards_the_same_recursion_limit + def test_sub_contexts_count_towards_the_same_recursion_limit Liquid::Template.file_system = StubFileSystem.new( - 'loop_render' => '{% render "loop_include" %}', - 'loop_include' => '{% include "loop_render" %}' + 'loop_render' => '{% render "loop_render" %}', ) - - assert_raises Liquid::StackLevelError do - Template.parse('{% render "loop_include" %}').render! + assert_raises Liquid::StackLevelError do + Template.parse('{% render "loop_render" %}').render! end end @@ -110,7 +110,7 @@ class RenderTagTest < Minitest::Test file_system = StubFileSystem.new('snippet' => 'echo') assert_equal 'echoecho', Template.parse('{% render "snippet" %}{% render "snippet" %}') - .render!({}, registers: { file_system: file_system }) + .render!({}, registers: { file_system: file_system }) assert_equal 1, file_system.file_read_count end @@ -146,4 +146,23 @@ class RenderTagTest < Minitest::Test Liquid::Template.file_system = StubFileSystem.new('decr' => '{% decrement %}') assert_template_result '-1-2-1', '{% decrement %}{% decrement %}{% render "decr" %}' end + + def test_includes_will_not_render_inside_render_tag + Liquid::Template.file_system = StubFileSystem.new( + 'foo' => 'bar', + 'test_include' => '{% include "foo" %}' + ) + + assert_template_result 'include usage is not allowed in this context', '{% render "test_include" %}' + end + + def test_includes_will_not_render_inside_nested_sibling_tags + Liquid::Template.file_system = StubFileSystem.new( + 'foo' => 'bar', + 'nested_render_with_sibling_include' => '{% render "test_include" %}{% include "foo" %}', + 'test_include' => '{% include "foo" %}' + ) + + assert_template_result 'include usage is not allowed in this contextinclude usage is not allowed in this context', '{% render "nested_render_with_sibling_include" %}' + end end diff --git a/test/integration/tags/standard_tag_test.rb b/test/integration/tags/standard_tag_test.rb index 4b4703a6..7939cd36 100644 --- a/test/integration/tags/standard_tag_test.rb +++ b/test/integration/tags/standard_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class StandardTagTest < Minitest::Test @@ -69,7 +71,7 @@ class StandardTagTest < Minitest::Test assert_raises(SyntaxError) do assert_template_result('content foo content foo ', '{{ var2 }}{% capture %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}', - { 'var' => 'content' }) + 'var' => 'content') end end @@ -183,32 +185,32 @@ class StandardTagTest < Minitest::Test def test_case_when_or code = '{% case condition %}{% when 1 or 2 or 3 %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}' - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 1 }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 2 }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 3 }) - assert_template_result(' its 4 ', code, { 'condition' => 4 }) - assert_template_result('', code, { 'condition' => 5 }) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 1) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 2) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 3) + assert_template_result(' its 4 ', code, 'condition' => 4) + assert_template_result('', code, 'condition' => 5) code = '{% case condition %}{% when 1 or "string" or null %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}' - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 1 }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 'string' }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => nil }) - assert_template_result('', code, { 'condition' => 'something else' }) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 1) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 'string') + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => nil) + assert_template_result('', code, 'condition' => 'something else') end def test_case_when_comma code = '{% case condition %}{% when 1, 2, 3 %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}' - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 1 }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 2 }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 3 }) - assert_template_result(' its 4 ', code, { 'condition' => 4 }) - assert_template_result('', code, { 'condition' => 5 }) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 1) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 2) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 3) + assert_template_result(' its 4 ', code, 'condition' => 4) + assert_template_result('', code, 'condition' => 5) code = '{% case condition %}{% when 1, "string", null %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}' - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 1 }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => 'string' }) - assert_template_result(' its 1 or 2 or 3 ', code, { 'condition' => nil }) - assert_template_result('', code, { 'condition' => 'something else' }) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 1) + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => 'string') + assert_template_result(' its 1 or 2 or 3 ', code, 'condition' => nil) + assert_template_result('', code, 'condition' => 'something else') end def test_assign @@ -283,10 +285,10 @@ class StandardTagTest < Minitest::Test end def test_ifchanged - assigns = { 'array' => [ 1, 1, 2, 2, 3, 3] } + assigns = { 'array' => [1, 1, 2, 2, 3, 3] } assert_template_result('123', '{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}', assigns) - assigns = { 'array' => [ 1, 1, 1, 1] } + assigns = { 'array' => [1, 1, 1, 1] } assert_template_result('1', '{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}', assigns) end diff --git a/test/integration/tags/statements_test.rb b/test/integration/tags/statements_test.rb index eeff166f..0d024d0f 100644 --- a/test/integration/tags/statements_test.rb +++ b/test/integration/tags/statements_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class StatementsTest < Minitest::Test diff --git a/test/integration/tags/table_row_test.rb b/test/integration/tags/table_row_test.rb index d7bc14cf..71df4f38 100644 --- a/test/integration/tags/table_row_test.rb +++ b/test/integration/tags/table_row_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class TableRowTest < Minitest::Test diff --git a/test/integration/tags/unless_else_tag_test.rb b/test/integration/tags/unless_else_tag_test.rb index c414a715..469d1c0b 100644 --- a/test/integration/tags/unless_else_tag_test.rb +++ b/test/integration/tags/unless_else_tag_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class UnlessElseTagTest < Minitest::Test diff --git a/test/integration/template_test.rb b/test/integration/template_test.rb index 0dc0ae5f..48549f55 100644 --- a/test/integration/template_test.rb +++ b/test/integration/template_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' require 'timeout' @@ -79,7 +81,10 @@ class TemplateTest < Minitest::Test def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders t = Template.new - t.assigns['number'] = -> { @global ||= 0; @global += 1 } + t.assigns['number'] = -> { + @global ||= 0 + @global += 1 + } assert_equal '1', t.parse("{{number}}").render! assert_equal '1', t.parse("{{number}}").render! assert_equal '1', t.render! @@ -88,7 +93,10 @@ class TemplateTest < Minitest::Test def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders t = Template.new - assigns = { 'number' => -> { @global ||= 0; @global += 1 } } + assigns = { 'number' => -> { + @global ||= 0 + @global += 1 + } } assert_equal '1', t.parse("{{number}}").render!(assigns) assert_equal '1', t.parse("{{number}}").render!(assigns) assert_equal '1', t.render!(assigns) @@ -224,7 +232,7 @@ class TemplateTest < Minitest::Test end def test_render_bang_force_rethrow_errors_on_passed_context - context = Context.new({ 'drop' => ErroneousDrop.new }) + context = Context.new('drop' => ErroneousDrop.new) t = Template.new.parse('{{ drop.bad_method }}') e = assert_raises RuntimeError do @@ -235,7 +243,10 @@ class TemplateTest < Minitest::Test def test_exception_renderer_that_returns_string exception = nil - handler = ->(e) { exception = e; '' } + handler = ->(e) { + exception = e + '' + } output = Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: handler) @@ -246,7 +257,10 @@ class TemplateTest < Minitest::Test def test_exception_renderer_that_raises exception = nil assert_raises(Liquid::ZeroDivisionError) do - Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) { exception = e; raise }) + Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) { + exception = e + raise + }) end assert exception.is_a?(Liquid::ZeroDivisionError) end @@ -267,7 +281,7 @@ class TemplateTest < Minitest::Test def test_undefined_variables t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}") - result = t.render({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, { strict_variables: true }) + result = t.render({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true) assert_equal '33 32 ', result assert_equal 3, t.errors.count @@ -292,14 +306,14 @@ class TemplateTest < Minitest::Test t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}") assert_raises UndefinedVariable do - t.render!({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, { strict_variables: true }) + t.render!({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true) end end def test_undefined_drop_methods d = DropWithUndefinedMethod.new t = Template.new.parse('{{ foo }} {{ woot }}') - result = t.render(d, { strict_variables: true }) + result = t.render(d, strict_variables: true) assert_equal 'foo ', result assert_equal 1, t.errors.count @@ -311,7 +325,7 @@ class TemplateTest < Minitest::Test t = Template.new.parse('{{ foo }} {{ woot }}') assert_raises UndefinedDropMethod do - t.render!(d, { strict_variables: true }) + t.render!(d, strict_variables: true) end end @@ -322,7 +336,7 @@ class TemplateTest < Minitest::Test "-#{v}-" end end - result = t.render({ 'a' => 123, 'x' => 'foo' }, { filters: [filters], strict_filters: true }) + result = t.render({ 'a' => 123, 'x' => 'foo' }, filters: [filters], strict_filters: true) assert_equal '123 ', result assert_equal 1, t.errors.count @@ -334,17 +348,17 @@ class TemplateTest < Minitest::Test t = Template.parse("{{x | somefilter1 | upcase | somefilter2}}") assert_raises UndefinedFilter do - t.render!({ 'x' => 'foo' }, { strict_filters: true }) + t.render!({ 'x' => 'foo' }, strict_filters: true) end end def test_using_range_literal_works_as_expected t = Template.parse("{% assign foo = (x..y) %}{{ foo }}") - result = t.render({ 'x' => 1, 'y' => 5 }) + result = t.render('x' => 1, 'y' => 5) assert_equal '1..5', result t = Template.parse("{% assign nums = (x..y) %}{% for num in nums %}{{ num }}{% endfor %}") - result = t.render({ 'x' => 1, 'y' => 5 }) + result = t.render('x' => 1, 'y' => 5) assert_equal '12345', result end end diff --git a/test/integration/trim_mode_test.rb b/test/integration/trim_mode_test.rb index 52248cff..438f86b5 100644 --- a/test/integration/trim_mode_test.rb +++ b/test/integration/trim_mode_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class TrimModeTest < Minitest::Test @@ -76,14 +78,14 @@ class TrimModeTest < Minitest::Test

END_TEMPLATE - expected = <<-END_EXPECTED -
-

-#{whitespace} - yes -#{whitespace} -

-
+ expected = <<~END_EXPECTED +
+

+ #{whitespace} + yes + #{whitespace} +

+
END_EXPECTED assert_template_result(expected, text) @@ -96,12 +98,12 @@ class TrimModeTest < Minitest::Test

END_TEMPLATE - expected = <<-END_EXPECTED -
-

-#{whitespace} -

-
+ expected = <<~END_EXPECTED +
+

+ #{whitespace} +

+
END_EXPECTED assert_template_result(expected, text) end @@ -337,12 +339,12 @@ class TrimModeTest < Minitest::Test

END_TEMPLATE - expected = <<-END_EXPECTED -
-

-#{whitespace} -

-
+ expected = <<~END_EXPECTED +
+

+ #{whitespace} +

+
END_EXPECTED assert_template_result(expected, text) end @@ -513,16 +515,16 @@ class TrimModeTest < Minitest::Test {% endraw %} END_TEMPLATE - expected = <<-END_EXPECTED -
-#{whitespace} - {%- if true -%} -

- {{- 'John' -}} -

- {%- endif -%} -#{whitespace} -
+ expected = <<~END_EXPECTED +
+ #{whitespace} + {%- if true -%} +

+ {{- 'John' -}} +

+ {%- endif -%} + #{whitespace} +
END_EXPECTED assert_template_result(expected, text) end diff --git a/test/integration/variable_test.rb b/test/integration/variable_test.rb index abd6e70c..94ed1eca 100644 --- a/test/integration/variable_test.rb +++ b/test/integration/variable_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class VariableTest < Minitest::Test @@ -76,7 +78,7 @@ class VariableTest < Minitest::Test def test_hash_with_default_proc template = Template.parse(%(Hello {{ test }})) - assigns = Hash.new { |h, k| raise "Unknown variable '#{k}'" } + assigns = Hash.new { |_h, k| raise "Unknown variable '#{k}'" } assigns['test'] = 'Tobi' assert_equal 'Hello Tobi', template.render!(assigns) assigns.delete('test') diff --git a/test/test_helper.rb b/test/test_helper.rb index 27a24342..9606ef8f 100755 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true ENV["MT_NO_EXPECTATIONS"] = "1" require 'minitest/autorun' @@ -8,7 +9,7 @@ require 'liquid.rb' require 'liquid/profiler' mode = :strict -if env_mode = ENV['LIQUID_PARSER_MODE'] +if (env_mode = ENV['LIQUID_PARSER_MODE']) puts "-- #{env_mode.upcase} ERROR MODE" mode = env_mode.to_sym end @@ -41,7 +42,7 @@ module Minitest end def assert_template_result_matches(expected, template, assigns = {}, message = nil) - return assert_template_result(expected, template, assigns, message) unless expected.is_a? Regexp + return assert_template_result(expected, template, assigns, message) unless expected.is_a?(Regexp) assert_match expected, Template.parse(template, line_numbers: true).render!(assigns), message end diff --git a/test/unit/block_unit_test.rb b/test/unit/block_unit_test.rb index 9f7b94f8..fa06a877 100644 --- a/test/unit/block_unit_test.rb +++ b/test/unit/block_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class BlockUnitTest < Minitest::Test @@ -61,7 +63,7 @@ class BlockUnitTest < Minitest::Test assert_equal 'hello', template.render - buf = '' + buf = +'' output = template.render({}, output: buf) assert_equal 'hello', output assert_equal 'hello', buf @@ -79,7 +81,7 @@ class BlockUnitTest < Minitest::Test assert_equal 'foohellobar', template.render - buf = '' + buf = +'' output = template.render({}, output: buf) assert_equal 'foohellobar', output assert_equal 'foohellobar', buf diff --git a/test/unit/condition_unit_test.rb b/test/unit/condition_unit_test.rb index b3b90e88..8d4e02f9 100644 --- a/test/unit/condition_unit_test.rb +++ b/test/unit/condition_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ConditionUnitTest < Minitest::Test @@ -24,9 +26,9 @@ class ConditionUnitTest < Minitest::Test assert_evaluates_true 1, '<=', 1 # negative numbers assert_evaluates_true 1, '>', -1 - assert_evaluates_true -1, '<', 1 + assert_evaluates_true(-1, '<', 1) assert_evaluates_true 1.0, '>', -1.0 - assert_evaluates_true -1.0, '<', 1.0 + assert_evaluates_true(-1.0, '<', 1.0) end def test_default_operators_evalute_false @@ -68,7 +70,7 @@ class ConditionUnitTest < Minitest::Test assert_nil Condition.new({}, '>', 2).evaluate assert_nil Condition.new(2, '>', {}).evaluate assert_equal false, Condition.new({}, '==', 2).evaluate - assert_equal true, Condition.new({ 'a' => 1 }, '==', { 'a' => 1 }).evaluate + assert_equal true, Condition.new({ 'a' => 1 }, '==', 'a' => 1).evaluate assert_equal true, Condition.new({ 'a' => 2 }, 'contains', 'a').evaluate end @@ -107,11 +109,11 @@ class ConditionUnitTest < Minitest::Test assert_equal false, condition.evaluate - condition.or Condition.new(2, '==', 1) + condition.or(Condition.new(2, '==', 1)) assert_equal false, condition.evaluate - condition.or Condition.new(1, '==', 1) + condition.or(Condition.new(1, '==', 1)) assert_equal true, condition.evaluate end @@ -121,22 +123,22 @@ class ConditionUnitTest < Minitest::Test assert_equal true, condition.evaluate - condition.and Condition.new(2, '==', 2) + condition.and(Condition.new(2, '==', 2)) assert_equal true, condition.evaluate - condition.and Condition.new(2, '==', 1) + condition.and(Condition.new(2, '==', 1)) assert_equal false, condition.evaluate end def test_should_allow_custom_proc_operator - Condition.operators['starts_with'] = proc { |cond, left, right| left =~ %r{^#{right}} } + Condition.operators['starts_with'] = proc { |_cond, left, right| left =~ /^#{right}/ } assert_evaluates_true 'bob', 'starts_with', 'b' assert_evaluates_false 'bob', 'starts_with', 'o' ensure - Condition.operators.delete 'starts_with' + Condition.operators.delete('starts_with') end def test_left_or_right_may_contain_operators diff --git a/test/unit/context_unit_test.rb b/test/unit/context_unit_test.rb index 9252eb52..3b460d7a 100644 --- a/test/unit/context_unit_test.rb +++ b/test/unit/context_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class HundredCentes @@ -83,7 +85,7 @@ class ContextUnitTest < Minitest::Test @context['date'] = Date.today assert_equal Date.today, @context['date'] - now = DateTime.now + now = Time.now @context['datetime'] = now assert_equal now, @context['datetime'] @@ -206,9 +208,9 @@ class ContextUnitTest < Minitest::Test end def test_merge - @context.merge({ "test" => "test" }) + @context.merge("test" => "test") assert_equal 'test', @context['test'] - @context.merge({ "test" => "newvalue", "foo" => "bar" }) + @context.merge("test" => "newvalue", "foo" => "bar") assert_equal 'newvalue', @context['test'] assert_equal 'bar', @context['foo'] end @@ -235,10 +237,10 @@ class ContextUnitTest < Minitest::Test def test_hash_to_array_transition @context['colors'] = { - 'Blue' => ['003366', '336699', '6699CC', '99CCFF'], - 'Green' => ['003300', '336633', '669966', '99CC99'], - 'Yellow' => ['CC9900', 'FFCC00', 'FFFF99', 'FFFFCC'], - 'Red' => ['660000', '993333', 'CC6666', 'FF9999'] + 'Blue' => ['003366', '336699', '6699CC', '99CCFF'], + 'Green' => ['003300', '336633', '669966', '99CC99'], + 'Yellow' => ['CC9900', 'FFCC00', 'FFFF99', 'FFFFCC'], + 'Red' => ['660000', '993333', 'CC6666', 'FF9999'], } assert_equal '003366', @context['colors.Blue[0]'] @@ -263,7 +265,7 @@ class ContextUnitTest < Minitest::Test def test_access_hashes_with_hash_notation @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] } - @context['product'] = { 'variants' => [ { 'title' => 'draft151cm' }, { 'title' => 'element151cm' } ] } + @context['product'] = { 'variants' => [{ 'title' => 'draft151cm' }, { 'title' => 'element151cm' }] } assert_equal 5, @context['products["count"]'] assert_equal 'deepsnow', @context['products["tags"][0]'] @@ -301,7 +303,7 @@ class ContextUnitTest < Minitest::Test end def test_first_can_appear_in_middle_of_callchain - @context['product'] = { 'variants' => [ { 'title' => 'draft151cm' }, { 'title' => 'element151cm' } ] } + @context['product'] = { 'variants' => [{ 'title' => 'draft151cm' }, { 'title' => 'element151cm' }] } assert_equal 'draft151cm', @context['product.variants[0].title'] assert_equal 'element151cm', @context['product.variants[1].title'] @@ -403,7 +405,11 @@ class ContextUnitTest < Minitest::Test end def test_lambda_is_called_once - @context['callcount'] = proc { @global ||= 0; @global += 1; @global.to_s } + @context['callcount'] = proc { + @global ||= 0 + @global += 1 + @global.to_s + } assert_equal '1', @context['callcount'] assert_equal '1', @context['callcount'] @@ -413,7 +419,11 @@ class ContextUnitTest < Minitest::Test end def test_nested_lambda_is_called_once - @context['callcount'] = { "lambda" => proc { @global ||= 0; @global += 1; @global.to_s } } + @context['callcount'] = { "lambda" => proc { + @global ||= 0 + @global += 1 + @global.to_s + } } assert_equal '1', @context['callcount.lambda'] assert_equal '1', @context['callcount.lambda'] @@ -423,7 +433,11 @@ class ContextUnitTest < Minitest::Test end def test_lambda_in_array_is_called_once - @context['callcount'] = [1, 2, proc { @global ||= 0; @global += 1; @global.to_s }, 4, 5] + @context['callcount'] = [1, 2, proc { + @global ||= 0 + @global += 1 + @global.to_s + }, 4, 5] assert_equal '1', @context['callcount[2]'] assert_equal '1', @context['callcount[2]'] @@ -453,7 +467,7 @@ class ContextUnitTest < Minitest::Test end def test_context_initialization_with_a_proc_in_environment - contx = Context.new([test: ->(c) { c['poutine'] }], { test: :foo }) + contx = Context.new([test: ->(c) { c['poutine'] }], test: :foo) assert contx assert_nil contx['poutine'] @@ -514,17 +528,25 @@ class ContextUnitTest < Minitest::Test def test_new_isolated_subcontext_does_not_inherit_non_static_registers registers = { - my_register: :my_value + my_register: :my_value, } - super_context = Context.new({}, {}, registers) + super_context = Context.new({}, {}, StaticRegisters.new(registers)) + super_context.registers[:my_register] = :my_alt_value subcontext = super_context.new_isolated_subcontext - assert_nil subcontext.registers[:my_register] + assert_equal :my_value, subcontext.registers[:my_register] end def test_new_isolated_subcontext_inherits_static_registers - super_context = Context.build(static_registers: { my_register: :my_value }) + super_context = Context.build(registers: { my_register: :my_value }) subcontext = super_context.new_isolated_subcontext - assert_equal :my_value, subcontext.static_registers[:my_register] + assert_equal :my_value, subcontext.registers[:my_register] + end + + def test_new_isolated_subcontext_registers_do_not_pollute_context + super_context = Context.build(registers: { my_register: :my_value }) + subcontext = super_context.new_isolated_subcontext + subcontext.registers[:my_register] = :my_alt_value + assert_equal :my_value, super_context.registers[:my_register] end def test_new_isolated_subcontext_inherits_filters diff --git a/test/unit/file_system_unit_test.rb b/test/unit/file_system_unit_test.rb index 2c7250ba..c76a7edd 100644 --- a/test/unit/file_system_unit_test.rb +++ b/test/unit/file_system_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class FileSystemUnitTest < Minitest::Test diff --git a/test/unit/i18n_unit_test.rb b/test/unit/i18n_unit_test.rb index b57500e3..338787e3 100644 --- a/test/unit/i18n_unit_test.rb +++ b/test/unit/i18n_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class I18nUnitTest < Minitest::Test diff --git a/test/unit/lexer_unit_test.rb b/test/unit/lexer_unit_test.rb index 5adcf2bd..7a2a4a56 100644 --- a/test/unit/lexer_unit_test.rb +++ b/test/unit/lexer_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class LexerUnitTest < Minitest::Test diff --git a/test/unit/parser_unit_test.rb b/test/unit/parser_unit_test.rb index 9f23337a..7456bf30 100644 --- a/test/unit/parser_unit_test.rb +++ b/test/unit/parser_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ParserUnitTest < Minitest::Test diff --git a/test/unit/partial_cache_unit_test.rb b/test/unit/partial_cache_unit_test.rb index 29f11449..dd431853 100644 --- a/test/unit/partial_cache_unit_test.rb +++ b/test/unit/partial_cache_unit_test.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + 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') + file_system: StubFileSystem.new('my_partial' => 'my partial body'), } ) @@ -41,12 +43,12 @@ class PartialCacheUnitTest < Minitest::Test ) context_one = Liquid::Context.build( registers: { - file_system: shared_file_system + file_system: shared_file_system, } ) context_two = Liquid::Context.build( registers: { - file_system: shared_file_system + file_system: shared_file_system, } ) diff --git a/test/unit/regexp_unit_test.rb b/test/unit/regexp_unit_test.rb index 0821229f..666bc664 100644 --- a/test/unit/regexp_unit_test.rb +++ b/test/unit/regexp_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class RegexpUnitTest < Minitest::Test diff --git a/test/unit/registers/disabled_tags_unit_test.rb b/test/unit/registers/disabled_tags_unit_test.rb new file mode 100644 index 00000000..90ac0166 --- /dev/null +++ b/test/unit/registers/disabled_tags_unit_test.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'test_helper' + +class DisabledTagsUnitTest < Minitest::Test + include Liquid + + def test_disables_tag_specified + register = DisabledTags.new + register.disable(%w(foo bar)) do + assert_equal true, register.disabled?("foo") + assert_equal true, register.disabled?("bar") + assert_equal false, register.disabled?("unknown") + end + end + + def test_disables_nested_tags + register = DisabledTags.new + register.disable(["foo"]) do + register.disable(["foo"]) do + assert_equal true, register.disabled?("foo") + assert_equal false, register.disabled?("bar") + end + register.disable(["bar"]) do + assert_equal true, register.disabled?("foo") + assert_equal true, register.disabled?("bar") + register.disable(["foo"]) do + assert_equal true, register.disabled?("foo") + assert_equal true, register.disabled?("bar") + end + end + assert_equal true, register.disabled?("foo") + assert_equal false, register.disabled?("bar") + end + end +end diff --git a/test/unit/static_registers_unit_test.rb b/test/unit/static_registers_unit_test.rb new file mode 100644 index 00000000..125440f2 --- /dev/null +++ b/test/unit/static_registers_unit_test.rb @@ -0,0 +1,248 @@ +# frozen_string_literal: true + +require 'test_helper' + +class StaticRegistersUnitTest < Minitest::Test + include Liquid + + def set + static_register = StaticRegisters.new + static_register[nil] = true + static_register[1] = :one + static_register[:one] = "one" + static_register["two"] = "three" + static_register["two"] = 3 + static_register[false] = nil + + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, static_register.registers) + + static_register + end + + def test_get + static_register = set + + assert_equal true, static_register[nil] + assert_equal :one, static_register[1] + assert_equal "one", static_register[:one] + assert_equal 3, static_register["two"] + assert_nil static_register[false] + assert_nil static_register["unknown"] + end + + def test_delete + static_register = set + + assert_equal true, static_register.delete(nil) + assert_equal :one, static_register.delete(1) + assert_equal "one", static_register.delete(:one) + assert_equal 3, static_register.delete("two") + assert_nil static_register.delete(false) + assert_nil static_register.delete("unknown") + + assert_equal({}, static_register.registers) + end + + def test_fetch + static_register = set + + assert_equal true, static_register.fetch(nil) + assert_equal :one, static_register.fetch(1) + assert_equal "one", static_register.fetch(:one) + assert_equal 3, static_register.fetch("two") + assert_nil static_register.fetch(false) + assert_nil static_register.fetch("unknown") + end + + def test_fetch_default + static_register = StaticRegisters.new + + assert_equal true, static_register.fetch(nil, true) + assert_equal :one, static_register.fetch(1, :one) + assert_equal "one", static_register.fetch(:one, "one") + assert_equal 3, static_register.fetch("two", 3) + assert_nil static_register.fetch(false, nil) + end + + def test_key + static_register = set + + assert_equal true, static_register.key?(nil) + assert_equal true, static_register.key?(1) + assert_equal true, static_register.key?(:one) + assert_equal true, static_register.key?("two") + assert_equal true, static_register.key?(false) + assert_equal false, static_register.key?("unknown") + assert_equal false, static_register.key?(true) + end + + def set_with_static + static_register = StaticRegisters.new(nil => true, 1 => :one, :one => "one", "two" => 3, false => nil) + static_register[nil] = false + static_register["two"] = 4 + static_register[true] = "foo" + + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, static_register.static) + assert_equal({ nil => false, "two" => 4, true => "foo" }, static_register.registers) + + static_register + end + + def test_get_with_static + static_register = set_with_static + + assert_equal false, static_register[nil] + assert_equal :one, static_register[1] + assert_equal "one", static_register[:one] + assert_equal 4, static_register["two"] + assert_equal "foo", static_register[true] + assert_nil static_register[false] + end + + def test_delete_with_static + static_register = set_with_static + + assert_equal false, static_register.delete(nil) + assert_equal 4, static_register.delete("two") + assert_equal "foo", static_register.delete(true) + assert_nil static_register.delete("unknown") + assert_nil static_register.delete(:one) + + assert_equal({}, static_register.registers) + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, static_register.static) + end + + def test_fetch_with_static + static_register = set_with_static + + assert_equal false, static_register.fetch(nil) + assert_equal :one, static_register.fetch(1) + assert_equal "one", static_register.fetch(:one) + assert_equal 4, static_register.fetch("two") + assert_equal "foo", static_register.fetch(true) + assert_nil static_register.fetch(false) + end + + def test_key_with_static + static_register = set_with_static + + assert_equal true, static_register.key?(nil) + assert_equal true, static_register.key?(1) + assert_equal true, static_register.key?(:one) + assert_equal true, static_register.key?("two") + assert_equal true, static_register.key?(false) + assert_equal false, static_register.key?("unknown") + assert_equal true, static_register.key?(true) + end + + def test_static_register_can_be_frozen + static_register = set_with_static + + static = static_register.static.freeze + + assert_raises(RuntimeError) do + static["two"] = "foo" + end + + assert_raises(RuntimeError) do + static["unknown"] = "foo" + end + + assert_raises(RuntimeError) do + static.delete("two") + end + end + + def test_new_static_retains_static + static_register = StaticRegisters.new(nil => true, 1 => :one, :one => "one", "two" => 3, false => nil) + static_register["one"] = 1 + static_register["two"] = 2 + static_register["three"] = 3 + + new_register = StaticRegisters.new(static_register) + assert_equal({}, new_register.registers) + + new_register["one"] = 4 + new_register["two"] = 5 + new_register["three"] = 6 + + newest_register = StaticRegisters.new(new_register) + assert_equal({}, newest_register.registers) + + newest_register["one"] = 7 + newest_register["two"] = 8 + newest_register["three"] = 9 + + assert_equal({ "one" => 1, "two" => 2, "three" => 3 }, static_register.registers) + assert_equal({ "one" => 4, "two" => 5, "three" => 6 }, new_register.registers) + assert_equal({ "one" => 7, "two" => 8, "three" => 9 }, newest_register.registers) + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, static_register.static) + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, new_register.static) + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, newest_register.static) + end + + def test_multiple_instances_are_unique + static_register = StaticRegisters.new(nil => true, 1 => :one, :one => "one", "two" => 3, false => nil) + static_register["one"] = 1 + static_register["two"] = 2 + static_register["three"] = 3 + + new_register = StaticRegisters.new(foo: :bar) + assert_equal({}, new_register.registers) + + new_register["one"] = 4 + new_register["two"] = 5 + new_register["three"] = 6 + + newest_register = StaticRegisters.new(bar: :foo) + assert_equal({}, newest_register.registers) + + newest_register["one"] = 7 + newest_register["two"] = 8 + newest_register["three"] = 9 + + assert_equal({ "one" => 1, "two" => 2, "three" => 3 }, static_register.registers) + assert_equal({ "one" => 4, "two" => 5, "three" => 6 }, new_register.registers) + assert_equal({ "one" => 7, "two" => 8, "three" => 9 }, newest_register.registers) + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, static_register.static) + assert_equal({ foo: :bar }, new_register.static) + assert_equal({ bar: :foo }, newest_register.static) + end + + def test_can_update_static_directly_and_updates_all_instances + static_register = StaticRegisters.new(nil => true, 1 => :one, :one => "one", "two" => 3, false => nil) + static_register["one"] = 1 + static_register["two"] = 2 + static_register["three"] = 3 + + new_register = StaticRegisters.new(static_register) + assert_equal({}, new_register.registers) + + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil }, static_register.static) + + new_register["one"] = 4 + new_register["two"] = 5 + new_register["three"] = 6 + new_register.static["four"] = 10 + + newest_register = StaticRegisters.new(new_register) + assert_equal({}, newest_register.registers) + + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil, "four" => 10 }, new_register.static) + + newest_register["one"] = 7 + newest_register["two"] = 8 + newest_register["three"] = 9 + new_register.static["four"] = 5 + new_register.static["five"] = 15 + + assert_equal({ "one" => 1, "two" => 2, "three" => 3 }, static_register.registers) + assert_equal({ "one" => 4, "two" => 5, "three" => 6 }, new_register.registers) + assert_equal({ "one" => 7, "two" => 8, "three" => 9 }, newest_register.registers) + + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil, "four" => 5, "five" => 15 }, newest_register.static) + + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil, "four" => 5, "five" => 15 }, static_register.static) + assert_equal({ nil => true, 1 => :one, :one => "one", "two" => 3, false => nil, "four" => 5, "five" => 15 }, new_register.static) + end +end diff --git a/test/unit/strainer_unit_test.rb b/test/unit/strainer_unit_test.rb index 5ce21004..2fb9ad44 100644 --- a/test/unit/strainer_unit_test.rb +++ b/test/unit/strainer_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class StrainerUnitTest < Minitest::Test @@ -36,7 +38,8 @@ class StrainerUnitTest < Minitest::Test rescue Liquid::ArgumentError => e assert_match( /\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/, - e.message) + e.message + ) assert_equal e.backtrace[0].split(':')[0], __FILE__ end end @@ -135,7 +138,7 @@ class StrainerUnitTest < Minitest::Test end module LateAddedFilter - def late_added_filter(input) + def late_added_filter(_input) "filtered" end end @@ -150,7 +153,7 @@ class StrainerUnitTest < Minitest::Test mod = Module.new do class << self attr_accessor :include_count - def included(mod) + def included(_mod) self.include_count += 1 end end diff --git a/test/unit/tag_unit_test.rb b/test/unit/tag_unit_test.rb index a3fb40e3..c9543e92 100644 --- a/test/unit/tag_unit_test.rb +++ b/test/unit/tag_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class TagUnitTest < Minitest::Test @@ -31,7 +33,7 @@ class TagUnitTest < Minitest::Test assert_equal 'hello', template.render - buf = '' + buf = +'' output = template.render({}, output: buf) assert_equal 'hello', output assert_equal 'hello', buf @@ -49,7 +51,7 @@ class TagUnitTest < Minitest::Test assert_equal 'foohellobar', template.render - buf = '' + buf = +'' output = template.render({}, output: buf) assert_equal 'foohellobar', output assert_equal 'foohellobar', buf diff --git a/test/unit/tags/case_tag_unit_test.rb b/test/unit/tags/case_tag_unit_test.rb index 71103081..0f3a61f7 100644 --- a/test/unit/tags/case_tag_unit_test.rb +++ b/test/unit/tags/case_tag_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class CaseTagUnitTest < Minitest::Test diff --git a/test/unit/tags/for_tag_unit_test.rb b/test/unit/tags/for_tag_unit_test.rb index b8fc5206..e6306c3a 100644 --- a/test/unit/tags/for_tag_unit_test.rb +++ b/test/unit/tags/for_tag_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class ForTagUnitTest < Minitest::Test diff --git a/test/unit/tags/if_tag_unit_test.rb b/test/unit/tags/if_tag_unit_test.rb index 7ecfc409..32243b73 100644 --- a/test/unit/tags/if_tag_unit_test.rb +++ b/test/unit/tags/if_tag_unit_test.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require 'test_helper' class IfTagUnitTest < Minitest::Test def test_if_nodelist template = Liquid::Template.parse('{% if true %}IF{% else %}ELSE{% endif %}') - assert_equal ['IF', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten + assert_equal(['IF', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten) end end diff --git a/test/unit/template_unit_test.rb b/test/unit/template_unit_test.rb index 6328be53..bc02896d 100644 --- a/test/unit/template_unit_test.rb +++ b/test/unit/template_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class TemplateUnitTest < Minitest::Test diff --git a/test/unit/tokenizer_unit_test.rb b/test/unit/tokenizer_unit_test.rb index de84c1fb..44342d6c 100644 --- a/test/unit/tokenizer_unit_test.rb +++ b/test/unit/tokenizer_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class TokenizerTest < Minitest::Test @@ -33,7 +35,7 @@ class TokenizerTest < Minitest::Test def tokenize(source) tokenizer = Liquid::Tokenizer.new(source) tokens = [] - while t = tokenizer.shift + while (t = tokenizer.shift) tokens << t end tokens diff --git a/test/unit/variable_unit_test.rb b/test/unit/variable_unit_test.rb index 5a21ace8..da1d4ea3 100644 --- a/test/unit/variable_unit_test.rb +++ b/test/unit/variable_unit_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class VariableUnitTest < Minitest::Test