Compare commits

..

4 Commits

Author SHA1 Message Date
Mike Angell
10f7ed4b9c Tidy instance variables 2019-09-17 02:33:02 +10:00
Mike Angell
3bf8470a49 Avoid deep flatten 2019-09-17 02:30:20 +10:00
Mike Angell
740241a997 Enable Instance Assigns to survive many renders 2019-09-17 01:59:55 +10:00
Mike Angell
29dfe2aea4 Prevent needing to squash instance assigns
Instead of needing to squash instance assigns, we instead just put them at the bottom of the enviornment stack.

This simplifies the code base and gains extra performance by not needing to loop over scopes and environments.
2019-09-16 21:42:51 +10:00
130 changed files with 292 additions and 979 deletions

View File

@@ -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,10 +8,9 @@ Performance:
Enabled: true
AllCops:
TargetRubyVersion: 2.4
Exclude:
- 'vendor/bundle/**/*'
Naming/MethodName:
Exclude:
- 'example/server/liquid_servlet.rb'
- 'example/server/liquid_servlet.rb'

View File

@@ -6,6 +6,26 @@
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 2
Lint/AmbiguousOperator:
Exclude:
- 'test/unit/condition_unit_test.rb'
# Offense count: 21
# 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/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.
@@ -14,6 +34,17 @@ Lint/InheritException:
Exclude:
- 'lib/liquid/interrupts.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: 98
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
@@ -45,4 +76,26 @@ Style/ClassVars:
Exclude:
- 'lib/liquid/condition.rb'
- 'lib/liquid/strainer.rb'
- 'lib/liquid/template.rb'
- 'lib/liquid/template.rb'
# Offense count: 1
# Configuration parameters: AllowCoercion.
Style/DateTime:
Exclude:
- 'test/unit/context_unit_test.rb'
# Offense count: 119
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, never
Style/FrozenStringLiteralComment:
Enabled: false
# Offense count: 9
# Cop supports --auto-correct.
# Configuration parameters: AllowAsExpressionSeparator.
Style/Semicolon:
Exclude:
- 'test/integration/error_handling_test.rb'
- 'test/integration/template_test.rb'
- 'test/unit/context_unit_test.rb'

View File

@@ -7,6 +7,8 @@ rvm:
- &latest_ruby 2.6
- 2.7
- ruby-head
- jruby-head
- truffleruby
matrix:
include:
@@ -15,6 +17,8 @@ matrix:
name: Profiling Memory Usage
allow_failures:
- rvm: ruby-head
- rvm: jruby-head
- rvm: truffleruby
branches:
only:

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
source 'https://rubygems.org'
git_source(:github) do |repo_name|
"https://github.com/#{repo_name}.git"

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'rake'
require 'rake/testtask'
$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module ProductsFilter
def price(integer)
format("$%.2d USD", integer / 100.0)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
class LiquidServlet < WEBrick::HTTPServlet::AbstractServlet
def do_GET(req, res)
handle(:get, req, res)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'webrick'
require 'rexml/document'

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
# Copyright (c) 2005 Tobias Luetke
#
# Permission is hereby granted, free of charge, to any person obtaining
@@ -23,10 +21,10 @@
module Liquid
FilterSeparator = /\|/
ArgumentSeparator = ','
FilterArgumentSeparator = ':'
VariableAttributeSeparator = '.'
WhitespaceControl = '-'
ArgumentSeparator = ','.freeze
FilterArgumentSeparator = ':'.freeze
VariableAttributeSeparator = '.'.freeze
WhitespaceControl = '-'.freeze
TagStart = /\{\%/
TagEnd = /\%\}/
VariableSignature = /\(?[\w\-\.\[\]]\)?/
@@ -78,10 +76,7 @@ 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 }

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Block < Tag
MAX_DEPTH = 100
@@ -29,16 +27,16 @@ module Liquid
end
def unknown_tag(tag, _params, _tokens)
if tag == 'else'
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_else",
if tag == 'else'.freeze
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_else".freeze,
block_name: block_name)
elsif tag.start_with?('end')
raise SyntaxError, parse_context.locale.t("errors.syntax.invalid_delimiter",
elsif tag.start_with?('end'.freeze)
raise SyntaxError, parse_context.locale.t("errors.syntax.invalid_delimiter".freeze,
tag: tag,
block_name: block_name,
block_delimiter: block_delimiter)
else
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag".freeze, tag: tag)
end
end
@@ -54,7 +52,7 @@ module Liquid
def parse_body(body, tokens)
if parse_context.depth >= MAX_DEPTH
raise StackLevelError, "Nesting too deep"
raise StackLevelError, "Nesting too deep".freeze
end
parse_context.depth += 1
begin
@@ -63,7 +61,7 @@ module Liquid
return false if end_tag_name == block_delimiter
unless end_tag_name
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed", block_name: block_name)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed".freeze, block_name: block_name)
end
# this tag is not registered with the system

View File

@@ -1,13 +1,11 @@
# 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 = "{%"
VARSTART = "{{"
TAGSTART = "{%".freeze
VARSTART = "{{".freeze
attr_reader :nodelist
@@ -27,7 +25,7 @@ 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
@@ -36,7 +34,7 @@ module Liquid
end
tag_name = Regexp.last_match(1)
markup = Regexp.last_match(2)
unless (tag = registered_tags[tag_name])
unless tag = registered_tags[tag_name]
# end parsing if we reach an unknown tag and let the caller decide
# determine how to proceed
return yield tag_name, markup
@@ -52,7 +50,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)
@@ -66,15 +64,15 @@ module Liquid
if parse_context.line_number
# newlines inside the tag should increase the line number,
# particularly important for multiline {% liquid %} tags
parse_context.line_number += Regexp.last_match(1).count("\n") + Regexp.last_match(3).count("\n")
parse_context.line_number += Regexp.last_match(1).count("\n".freeze) + Regexp.last_match(3).count("\n".freeze)
end
if tag_name == 'liquid'
if tag_name == 'liquid'.freeze
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
@@ -115,14 +113,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
@@ -131,7 +129,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
@@ -154,13 +152,7 @@ module Liquid
private
def render_node(context, output, node)
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
node.render_to_output_buffer(context, output)
rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e
context.handle_error(e, node.line_number)
rescue ::StandardError => e
@@ -168,15 +160,10 @@ 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, "Memory limits exceeded"
raise MemoryError, "Memory limits exceeded".freeze
end
def create_variable(token, parse_context)
@@ -188,11 +175,11 @@ module Liquid
end
def raise_missing_tag_terminator(token, parse_context)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination".freeze, token: token, tag_end: TagEnd.inspect)
end
def raise_missing_variable_terminator(token, parse_context)
raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect)
raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination".freeze, token: token, tag_end: VariableEnd.inspect)
end
def registered_tags

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Container for liquid nodes which conveniently wraps decision making logic
#
@@ -10,14 +8,14 @@ module Liquid
#
class Condition #:nodoc:
@@operators = {
'==' => ->(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|
'=='.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|
if left && right && left.respond_to?(:include?)
right = right.to_s if left.is_a?(String)
left.include?(right)
@@ -80,7 +78,7 @@ module Liquid
end
def inspect
"#<Condition #{[@left, @operator, @right].compact.join(' ')}>"
"#<Condition #{[@left, @operator, @right].compact.join(' '.freeze)}>"
end
protected

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Context keeps the variable stack and resolves variables, as well as keywords
#
@@ -18,32 +16,29 @@ 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_environments: {})
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_environments)
def self.build(environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_registers: {}, static_environments: {})
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_registers, static_environments)
end
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {})
@environments = [environments]
@environments.flatten!
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_registers = {}, static_environments = {})
@environments = environments.is_a?(Array) ? environments : [environments]
@static_environments = [static_environments].flat_map(&:freeze).freeze
@scopes = [(outer_scope || {})]
@registers = registers
@static_registers = static_registers.freeze
@errors = []
@partial = false
@strict_variables = false
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
@base_scope_depth = 0
squash_instance_assigns_with_environments
@interrupts = []
@filters = []
@global_filter = nil
self.exception_renderer = Template.default_exception_renderer
if rethrow_errors
self.exception_renderer = ->(_e) { raise }
end
@interrupts = []
@filters = []
@global_filter = nil
end
# rubocop:enable Metrics/ParameterLists
@@ -136,7 +131,7 @@ module Liquid
Context.build(
resource_limits: resource_limits,
static_environments: static_environments,
registers: StaticRegisters.new(registers)
static_registers: static_registers
).tap do |subcontext|
subcontext.base_scope_depth = base_scope_depth + 1
subcontext.exception_renderer = exception_renderer
@@ -233,7 +228,7 @@ module Liquid
end
def check_overflow
raise StackLevelError, "Nesting too deep" if overflow?
raise StackLevelError, "Nesting too deep".freeze if overflow?
end
def overflow?
@@ -246,16 +241,5 @@ module Liquid
rescue Liquid::InternalError => exc
exc
end
def squash_instance_assigns_with_environments
@scopes.last.each_key do |k|
@environments.each do |env|
if env.key?(k)
scopes.last[k] = lookup_and_evaluate(env, k)
break
end
end
end
end # squash_instance_assigns_with_environments
end # Context
end # Liquid

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Document < BlockBody
def self.parse(tokens, parse_context)
@@ -19,10 +17,10 @@ module Liquid
def unknown_tag(tag, parse_context)
case tag
when 'else', 'end'
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_outer_tag", tag: tag)
when 'else'.freeze, 'end'.freeze
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_outer_tag".freeze, tag: tag)
else
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag".freeze, tag: tag)
end
end
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'set'
module Liquid
@@ -69,7 +67,7 @@ module Liquid
if include?(Enumerable)
blacklist += Enumerable.public_instance_methods
blacklist -= [:sort, :count, :first, :min, :max]
blacklist -= [:sort, :count, :first, :min, :max, :include?]
end
whitelist = [:to_liquid] + (public_instance_methods - blacklist)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Error < ::StandardError
attr_accessor :line_number
@@ -7,7 +5,7 @@ module Liquid
attr_accessor :markup_context
def to_s(with_prefix = true)
str = +""
str = ""
str << message_prefix if with_prefix
str << super()
@@ -22,7 +20,7 @@ module Liquid
private
def message_prefix
str = +""
str = ""
str << if is_a?(SyntaxError)
"Liquid syntax error"
else

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Expression
class MethodLiteral
@@ -16,11 +14,11 @@ module Liquid
end
LITERALS = {
nil => nil, 'nil' => nil, 'null' => nil, '' => nil,
'true' => true,
'false' => false,
'blank' => MethodLiteral.new(:blank?, '').freeze,
'empty' => MethodLiteral.new(:empty?, '').freeze
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
}.freeze
SINGLE_QUOTED_STRING = /\A'(.*)'\z/m

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'time'
require 'date'

View File

@@ -1,5 +1,3 @@
# 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.
#
@@ -46,7 +44,7 @@ module Liquid
class LocalFileSystem
attr_accessor :root
def initialize(root, pattern = "_%s.liquid")
def initialize(root, pattern = "_%s.liquid".freeze)
@root = root
@pattern = pattern
end
@@ -59,9 +57,9 @@ module Liquid
end
def full_path(template_path)
raise FileSystemError, "Illegal template name '#{template_path}'" unless %r{\A[^./][a-zA-Z0-9_/]+\z}.match?(template_path)
raise FileSystemError, "Illegal template name '#{template_path}'" unless template_path =~ %r{\A[^./][a-zA-Z0-9_/]+\z}
full_path = if template_path.include?('/')
full_path = if template_path.include?('/'.freeze)
File.join(root, File.dirname(template_path), @pattern % File.basename(template_path))
else
File.join(root, @pattern % template_path)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class ForloopDrop < Drop
def initialize(name, length, parentloop)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'yaml'
module Liquid
@@ -33,7 +31,7 @@ module Liquid
end
def deep_fetch_translation(name)
name.split('.').reduce(locale) do |level, cur|
name.split('.'.freeze).reduce(locale) do |level, cur|
level[cur] || raise(TranslationError, "Translation for #{name} does not exist in locale #{path}")
end
end

View File

@@ -1,12 +1,10 @@
# 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"
@message = message || "interrupt".freeze
end
end

View File

@@ -1,19 +1,17 @@
# frozen_string_literal: true
require "strscan"
module Liquid
class Lexer
SPECIALS = {
'|' => :pipe,
'.' => :dot,
':' => :colon,
',' => :comma,
'[' => :open_square,
']' => :close_square,
'(' => :open_round,
')' => :close_round,
'?' => :question,
'-' => :dash,
'|'.freeze => :pipe,
'.'.freeze => :dot,
':'.freeze => :colon,
','.freeze => :comma,
'['.freeze => :open_square,
']'.freeze => :close_square,
'('.freeze => :open_round,
')'.freeze => :close_round,
'?'.freeze => :question,
'-'.freeze => :dash,
}.freeze
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
SINGLE_STRING_LITERAL = /'[^\']*'/
@@ -33,21 +31,15 @@ module Liquid
until @ss.eos?
@ss.skip(WHITESPACE_OR_NOTHING)
break if @ss.eos?
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]
tok = if t = @ss.scan(COMPARISON_OPERATOR) then [:comparison, t]
elsif t = @ss.scan(SINGLE_STRING_LITERAL) then [:string, t]
elsif t = @ss.scan(DOUBLE_STRING_LITERAL) then [:string, t]
elsif t = @ss.scan(NUMBER_LITERAL) then [:number, t]
elsif t = @ss.scan(IDENTIFIER) then [:id, t]
elsif t = @ss.scan(DOTDOT) then [:dotdot, t]
else
c = @ss.getch
if (s = SPECIALS[c])
if s = SPECIALS[c]
[s, c]
else
raise SyntaxError, "Unexpected character #{c}"

View File

@@ -25,5 +25,3 @@
render: "Syntax error in tag 'render' - Template name must be a quoted string"
argument:
include: "Argument error in tag 'include' - Illegal template name"
disabled:
tag: "usage is not allowed in this context"

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class ParseContext
attr_accessor :locale, :line_number, :trim_whitespace, :depth
@@ -21,6 +19,7 @@ module Liquid
@partial = value
@options = value ? partial_options : @template_options
@error_mode = @options[:error_mode] || Template.error_mode
value
end
def partial_options

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Parser
def initialize(input)
@@ -68,10 +66,10 @@ module Liquid
end
def argument
str = +""
str = ""
# might be a keyword argument (identifier: expression)
if look(:id) && look(:colon, 1)
str << consume << consume << ' '
str << consume << consume << ' '.freeze
end
str << expression

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
module ParserSwitching
def parse_with_selected_parser(markup)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class PartialCache
def self.load(template_name, context:, parse_context:)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'liquid/profiler/hooks'
module Liquid

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class BlockBody
def render_node_with_profiling(context, output, node)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class RangeLookup
def self.parse(start_markup, end_markup)

View File

@@ -1,6 +0,0 @@
# frozen_string_literal: true
module Liquid
class Register
end
end

View File

@@ -1,32 +0,0 @@
# 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

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class ResourceLimits
attr_accessor :render_length, :render_score, :assign_score,

View File

@@ -1,16 +1,14 @@
# frozen_string_literal: true
require 'cgi'
require 'bigdecimal'
module Liquid
module StandardFilters
HTML_ESCAPE = {
'&' => '&amp;',
'>' => '&gt;',
'<' => '&lt;',
'"' => '&quot;',
"'" => '&#39;',
'&'.freeze => '&amp;'.freeze,
'>'.freeze => '&gt;'.freeze,
'<'.freeze => '&lt;'.freeze,
'"'.freeze => '&quot;'.freeze,
"'".freeze => '&#39;'.freeze,
}.freeze
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
STRIP_HTML_BLOCKS = Regexp.union(
@@ -74,7 +72,7 @@ module Liquid
end
# Truncate a string down to x characters
def truncate(input, length = 50, truncate_string = "...")
def truncate(input, length = 50, truncate_string = "...".freeze)
return if input.nil?
input_str = input.to_s
length = Utils.to_integer(length)
@@ -84,13 +82,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 = "...")
def truncatewords(input, words = 15, truncate_string = "...".freeze)
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(" ").concat(truncate_string.to_s) : input
wordlist.length > l ? wordlist[0..l].join(" ".freeze).concat(truncate_string.to_s) : input
end
# Split input string into an array of substrings separated by given pattern.
@@ -115,7 +113,7 @@ module Liquid
end
def strip_html(input)
empty = ''
empty = ''.freeze
result = input.to_s.gsub(STRIP_HTML_BLOCKS, empty)
result.gsub!(STRIP_HTML_TAGS, empty)
result
@@ -123,11 +121,11 @@ module Liquid
# Remove all newlines from the string
def strip_newlines(input)
input.to_s.gsub(/\r?\n/, '')
input.to_s.gsub(/\r?\n/, ''.freeze)
end
# Join elements of the array with certain character between them
def join(input, glue = ' ')
def join(input, glue = ' '.freeze)
InputIterator.new(input).join(glue)
end
@@ -222,7 +220,7 @@ module Liquid
InputIterator.new(input).map do |e|
e = e.call if e.is_a?(Proc)
if property == "to_liquid"
if property == "to_liquid".freeze
e
elsif e.respond_to?(:[])
r = e[property]
@@ -252,23 +250,23 @@ module Liquid
end
# Replace occurrences of a string with another
def replace(input, string, replacement = '')
def replace(input, string, replacement = ''.freeze)
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 = '')
def replace_first(input, string, replacement = ''.freeze)
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, '')
input.to_s.gsub(string.to_s, ''.freeze)
end
# remove the first occurrences of a substring
def remove_first(input, string)
input.to_s.sub(string.to_s, '')
input.to_s.sub(string.to_s, ''.freeze)
end
# add one string to another
@@ -290,7 +288,7 @@ module Liquid
# Add <br /> tags in front of all newlines in input string
def newline_to_br(input)
input.to_s.gsub(/\n/, "<br />\n")
input.to_s.gsub(/\n/, "<br />\n".freeze)
end
# Reformat a date using Ruby's core Time#strftime( string ) -> string
@@ -327,7 +325,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
@@ -421,7 +419,7 @@ module Liquid
result.is_a?(BigDecimal) ? result.to_f : result
end
def default(input, default_value = '')
def default(input, default_value = ''.freeze)
if !input || input.respond_to?(:empty?) && input.empty?
Usage.increment("default_filter_received_false_value") if input == false # See https://github.com/Shopify/liquid/issues/1127
default_value

View File

@@ -1,36 +0,0 @@
# 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

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'set'
module Liquid

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class TablerowloopDrop < Drop
def initialize(length, cols)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Tag
attr_reader :nodelist, :tag_name, :line_number, :parse_context
@@ -13,15 +11,7 @@ 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)
@@ -43,15 +33,7 @@ module Liquid
end
def render(_context)
''
end
def disabled?(context)
context.registers['disabled_tags'].disabled?(tag_name)
end
def disabled_error_message
"#{tag_name} #{options[:locale].t('errors.disabled.tag')}"
''.freeze
end
# For backwards compatibility with custom tags. In a future release, the semantics
@@ -65,9 +47,5 @@ module Liquid
def blank?
false
end
def disabled_tags
self.class.disabled_tags
end
end
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Assign sets a variable in your template.
#
@@ -13,7 +11,7 @@ module Liquid
Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/om
def self.syntax_error_translation_key
"errors.syntax.assign"
"errors.syntax.assign".freeze
end
attr_reader :to, :from
@@ -61,5 +59,5 @@ module Liquid
end
end
Template.register_tag('assign', Assign)
Template.register_tag('assign'.freeze, Assign)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Break tag to be used to break out of a for loop.
#
@@ -16,5 +14,5 @@ module Liquid
end
end
Template.register_tag('break', Break)
Template.register_tag('break'.freeze, Break)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Capture stores the result of a block into a variable without rendering it inplace.
#
@@ -37,5 +35,5 @@ module Liquid
end
end
Template.register_tag('capture', Capture)
Template.register_tag('capture'.freeze, Capture)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Case < Block
Syntax = /(#{QuotedFragment})/o
@@ -14,7 +12,7 @@ module Liquid
if markup =~ Syntax
@left = Expression.parse(Regexp.last_match(1))
else
raise SyntaxError, options[:locale].t("errors.syntax.case")
raise SyntaxError, options[:locale].t("errors.syntax.case".freeze)
end
end
@@ -29,9 +27,9 @@ module Liquid
def unknown_tag(tag, markup, tokens)
case tag
when 'when'
when 'when'.freeze
record_when_condition(markup)
when 'else'
when 'else'.freeze
record_else_condition(markup)
else
super
@@ -60,12 +58,12 @@ module Liquid
while markup
unless markup =~ WhenSyntax
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_when")
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_when".freeze)
end
markup = Regexp.last_match(2)
block = Condition.new(@left, '==', Expression.parse(Regexp.last_match(1)))
block = Condition.new(@left, '=='.freeze, Expression.parse(Regexp.last_match(1)))
block.attach(body)
@blocks << block
end
@@ -73,7 +71,7 @@ module Liquid
def record_else_condition(markup)
unless markup.strip.empty?
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_else")
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_else".freeze)
end
block = ElseCondition.new
@@ -88,5 +86,5 @@ module Liquid
end
end
Template.register_tag('case', Case)
Template.register_tag('case'.freeze, Case)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Comment < Block
def render_to_output_buffer(_context, output)
@@ -14,5 +12,5 @@ module Liquid
end
end
Template.register_tag('comment', Comment)
Template.register_tag('comment'.freeze, Comment)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Continue tag to be used to break out of a for loop.
#
@@ -16,5 +14,5 @@ module Liquid
end
end
Template.register_tag('continue', Continue)
Template.register_tag('continue'.freeze, Continue)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
#
@@ -29,7 +27,7 @@ module Liquid
@variables = variables_from_string(markup)
@name = @variables.to_s
else
raise SyntaxError, options[:locale].t("errors.syntax.cycle")
raise SyntaxError, options[:locale].t("errors.syntax.cycle".freeze)
end
end

View File

@@ -1,5 +1,3 @@
# 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
@@ -34,5 +32,5 @@ module Liquid
end
end
Template.register_tag('decrement', Decrement)
Template.register_tag('decrement'.freeze, Decrement)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Echo outputs an expression
#
@@ -18,9 +16,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', Echo)
Template.register_tag('echo'.freeze, Echo)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# "For" iterates over an array or collection.
# Several useful variables are available to you within the loop.
@@ -68,7 +66,7 @@ module Liquid
end
def unknown_tag(tag, markup, tokens)
return super unless tag == 'else'
return super unless tag == 'else'.freeze
@else_block = BlockBody.new
end
@@ -97,22 +95,22 @@ module Liquid
set_attribute(key, value)
end
else
raise SyntaxError, options[:locale].t("errors.syntax.for")
raise SyntaxError, options[:locale].t("errors.syntax.for".freeze)
end
end
def strict_parse(markup)
p = Parser.new(markup)
@variable_name = p.consume(:id)
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in".freeze) unless p.id?('in'.freeze)
collection_name = p.expression
@name = "#{@variable_name}-#{collection_name}"
@collection_name = Expression.parse(collection_name)
@reversed = p.id?('reversed')
@reversed = p.id?('reversed'.freeze)
while p.look(:id) && p.look(:colon, 1)
unless (attribute = p.id?('limit') || p.id?('offset'))
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_attribute")
unless attribute = p.id?('limit'.freeze) || p.id?('offset'.freeze)
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_attribute".freeze)
end
p.consume
set_attribute(attribute, p.expression)
@@ -164,7 +162,7 @@ module Liquid
for_stack.push(loop_vars)
begin
context['forloop'] = loop_vars
context['forloop'.freeze] = loop_vars
segment.each do |item|
context[@variable_name] = item
@@ -187,13 +185,13 @@ module Liquid
def set_attribute(key, expr)
case key
when 'offset'
@from = if expr == 'continue'
when 'offset'.freeze
@from = if expr == 'continue'.freeze
:continue
else
Expression.parse(expr)
end
when 'limit'
when 'limit'.freeze
@limit = Expression.parse(expr)
end
end
@@ -213,5 +211,5 @@ module Liquid
end
end
Template.register_tag('for', For)
Template.register_tag('for'.freeze, For)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# If is the conditional block
#
@@ -21,7 +19,7 @@ module Liquid
def initialize(tag_name, markup, options)
super
@blocks = []
push_block('if', markup)
push_block('if'.freeze, markup)
end
def nodelist
@@ -34,7 +32,7 @@ module Liquid
end
def unknown_tag(tag, markup, tokens)
if ['elsif', 'else'].include?(tag)
if ['elsif'.freeze, 'else'.freeze].include?(tag)
push_block(tag, markup)
else
super
@@ -54,7 +52,7 @@ module Liquid
private
def push_block(tag, markup)
block = if tag == 'else'
block = if tag == 'else'.freeze
ElseCondition.new
else
parse_with_selected_parser(markup)
@@ -66,17 +64,17 @@ module Liquid
def lax_parse(markup)
expressions = markup.scan(ExpressionsAndOperators)
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop =~ Syntax
raise SyntaxError, options[:locale].t("errors.syntax.if".freeze) unless expressions.pop =~ Syntax
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, options[:locale].t("errors.syntax.if") unless expressions.pop.to_s =~ Syntax
raise SyntaxError, options[:locale].t("errors.syntax.if".freeze) unless expressions.pop.to_s =~ Syntax
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)
raise SyntaxError, options[:locale].t("errors.syntax.if".freeze) unless BOOLEAN_OPERATORS.include?(operator)
new_condition.send(operator, condition)
condition = new_condition
end
@@ -94,7 +92,7 @@ module Liquid
def parse_binary_comparisons(p)
condition = parse_comparison(p)
first_condition = condition
while (op = (p.id?('and') || p.id?('or')))
while op = (p.id?('and'.freeze) || p.id?('or'.freeze))
child_condition = parse_comparison(p)
condition.send(op, child_condition)
condition = child_condition
@@ -104,7 +102,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 +117,5 @@ module Liquid
end
end
Template.register_tag('if', If)
Template.register_tag('if'.freeze, If)
end

View File

@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Liquid
class Ifchanged < Block
def render_to_output_buffer(context, output)
block_output = +''
block_output = ''
super(context, block_output)
if block_output != context.registers[:ifchanged]
@@ -15,5 +13,5 @@ module Liquid
end
end
Template.register_tag('ifchanged', Ifchanged)
Template.register_tag('ifchanged'.freeze, Ifchanged)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Include allows templates to relate with other templates
#
@@ -37,7 +35,7 @@ module Liquid
end
else
raise SyntaxError, options[:locale].t("errors.syntax.include")
raise SyntaxError, options[:locale].t("errors.syntax.include".freeze)
end
end
@@ -54,7 +52,7 @@ module Liquid
parse_context: parse_context
)
context_variable_name = template_name.split('/').last
context_variable_name = template_name.split('/'.freeze).last
variable = if @variable_name_expr
context.evaluate(@variable_name_expr)
@@ -103,5 +101,5 @@ module Liquid
end
end
Template.register_tag('include', Include)
Template.register_tag('include'.freeze, Include)
end

View File

@@ -1,5 +1,3 @@
# 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
@@ -31,5 +29,5 @@ module Liquid
end
end
Template.register_tag('increment', Increment)
Template.register_tag('increment'.freeze, Increment)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Raw < Block
Syntax = /\A\s*\z/
@@ -12,16 +10,16 @@ module Liquid
end
def parse(tokens)
@body = +''
while (token = tokens.shift)
@body = ''
while token = tokens.shift
if token =~ FullTokenPossiblyInvalid
@body << Regexp.last_match(1) if Regexp.last_match(1) != ""
@body << Regexp.last_match(1) if Regexp.last_match(1) != "".freeze
return if block_delimiter == Regexp.last_match(2)
end
@body << token unless token.empty?
end
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed", block_name: block_name)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed".freeze, block_name: block_name)
end
def render_to_output_buffer(_context, output)
@@ -40,11 +38,11 @@ module Liquid
protected
def ensure_valid_markup(tag_name, markup, parse_context)
unless Syntax.match?(markup)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_unexpected_args", tag: tag_name)
unless markup =~ Syntax
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_unexpected_args".freeze, tag: tag_name)
end
end
end
Template.register_tag('raw', Raw)
Template.register_tag('raw'.freeze, Raw)
end

View File

@@ -1,17 +1,13 @@
# frozen_string_literal: true
module Liquid
class Render < Tag
SYNTAX = /(#{QuotedString})#{QuotedFragment}*/o
disable_tags "include"
attr_reader :template_name_expr, :attributes
def initialize(tag_name, markup, options)
super
raise SyntaxError, options[:locale].t("errors.syntax.render") unless markup =~ SYNTAX
raise SyntaxError, options[:locale].t("errors.syntax.render".freeze) unless markup =~ SYNTAX
template_name = Regexp.last_match(1)
@@ -24,10 +20,6 @@ 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, options[:locale].t("errors.argument.include") unless template_name
@@ -58,5 +50,5 @@ module Liquid
end
end
Template.register_tag('render', Render)
Template.register_tag('render'.freeze, Render)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class TableRow < Block
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
@@ -16,26 +14,26 @@ module Liquid
@attributes[key] = Expression.parse(value)
end
else
raise SyntaxError, options[:locale].t("errors.syntax.table_row")
raise SyntaxError, options[:locale].t("errors.syntax.table_row".freeze)
end
end
def render_to_output_buffer(context, output)
(collection = context.evaluate(@collection_name)) || (return '')
(collection = context.evaluate(@collection_name)) || (return ''.freeze)
from = @attributes.key?('offset') ? context.evaluate(@attributes['offset']).to_i : 0
to = @attributes.key?('limit') ? from + context.evaluate(@attributes['limit']).to_i : nil
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
collection = Utils.slice_collection(collection, from, to)
length = collection.length
cols = context.evaluate(@attributes['cols']).to_i
cols = context.evaluate(@attributes['cols'.freeze]).to_i
output << "<tr class=\"row1\">\n"
context.stack do
tablerowloop = Liquid::TablerowloopDrop.new(length, cols)
context['tablerowloop'] = tablerowloop
context['tablerowloop'.freeze] = tablerowloop
collection.each do |item|
context[@variable_name] = item
@@ -63,5 +61,5 @@ module Liquid
end
end
Template.register_tag('tablerow', TableRow)
Template.register_tag('tablerow'.freeze, TableRow)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require_relative 'if'
module Liquid
@@ -26,5 +24,5 @@ module Liquid
end
end
Template.register_tag('unless', Unless)
Template.register_tag('unless'.freeze, Unless)
end

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
# Templates are central to liquid.
# Interpretating templates is a two step process. First you compile the
@@ -92,14 +90,6 @@ module Liquid
@tags ||= TagRegistry.new
end
def add_register(name, klass)
registers[name.to_s] = klass
end
def registers
@registers ||= {}
end
def error_mode
@error_mode ||= :lax
end
@@ -153,7 +143,12 @@ module Liquid
end
def instance_assigns
@instance_assigns ||= {}
@instance_assigns ||= []
end
def new_outer_scope
@instance_assigns.unshift(last = {})
last
end
def errors
@@ -175,7 +170,7 @@ module Liquid
# filters and tags and might be useful to integrate liquid more with its host application
#
def render(*args)
return '' if @root.nil?
return ''.freeze if @root.nil?
context = case args.first
when Liquid::Context
@@ -188,37 +183,29 @@ module Liquid
c
when Liquid::Drop
drop = args.shift
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
drop.context = Context.new([drop, assigns].concat(instance_assigns), new_outer_scope, registers, @rethrow_errors, @resource_limits)
when Hash
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
Context.new([args.shift, assigns].concat(instance_assigns), new_outer_scope, registers, @rethrow_errors, @resource_limits)
when nil
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits)
Context.new([assigns].concat(instance_assigns), new_outer_scope, registers, @rethrow_errors, @resource_limits)
else
raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
end
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]
options[:registers]&.each do |key, register|
context_register[key] = register
end
registers.merge!(options[:registers]) if options[:registers].is_a?(Hash)
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
@@ -226,7 +213,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)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
class Tokenizer
attr_reader :line_number, :for_liquid_tag

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
module Usage
def self.increment(name)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module Liquid
module Utils
def self.slice_collection(collection, from, to)
@@ -52,7 +50,7 @@ module Liquid
when Numeric
obj
when String
/\A-?\d+\.\d+\z/.match?(obj.strip) ? BigDecimal(obj) : obj.to_i
obj.strip =~ /\A-?\d+\.\d+\z/ ? BigDecimal(obj) : obj.to_i
else
if obj.respond_to?(:to_number)
obj.to_number
@@ -71,7 +69,7 @@ module Liquid
end
case obj
when 'now', 'today'
when 'now'.freeze, 'today'.freeze
Time.now
when /\A\d+\z/, Integer
Time.at(obj.to_i)

View File

@@ -1,5 +1,3 @@
# 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
@@ -104,21 +102,13 @@ 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

View File

@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Liquid
class VariableLookup
SQUARE_BRACKETED = /\A\[(.*)\]\z/m
COMMAND_METHODS = ['size', 'first', 'last'].freeze
COMMAND_METHODS = ['size'.freeze, 'first'.freeze, 'last'.freeze].freeze
attr_reader :name, :lookups

View File

@@ -1,6 +1,5 @@
# encoding: utf-8
# frozen_string_literal: true
module Liquid
VERSION = "4.0.3"
VERSION = "4.0.3".freeze
end

View File

@@ -1,5 +1,4 @@
# encoding: utf-8
# frozen_string_literal: true
lib = File.expand_path('../lib/', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'benchmark/ips'
require_relative 'theme_runner'

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'stackprof'
require_relative 'theme_runner'
@@ -15,7 +13,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

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
class CommentForm < Liquid::Block
Syntax = /(#{Liquid::VariableSignature}+)/

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'yaml'
module Database
@@ -32,8 +30,8 @@ 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'] },
'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,
}

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'json'
module JsonFilter

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
$LOAD_PATH.unshift(__dir__ + '/../../lib')
require_relative '../../lib/liquid'

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module MoneyFilter
def money_with_currency(money)
return '' if money.nil?

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
class Paginate < Liquid::Block
Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module ShopFilter
def asset_url(input)
"/files/1/[shop_id]/[shop_id]/assets/#{input}"

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module TagFilter
def link_to_tag(label, tag)
"<a title=\"Show tag #{tag}\" href=\"/collections/#{@context['handle']}/#{tag}\">#{label}</a>"

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
module WeightFilter
def weight(grams)
format("%.2f", grams / 1000)

View File

@@ -1,5 +1,3 @@
# 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.

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class AssignTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class FoobarTag < Liquid::Tag

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class BlockTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class CaptureTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class ContextTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class DocumentTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class ContextDrop < Liquid::Drop
@@ -33,7 +31,7 @@ class ProductDrop < Liquid::Drop
class CatchallDrop < Liquid::Drop
def liquid_method_missing(method)
"catchall_method: #{method}"
'catchall_method: ' << method.to_s
end
end
@@ -50,7 +48,7 @@ class ProductDrop < Liquid::Drop
end
def user_input
(+"foo").taint
"foo".taint
end
protected
@@ -272,11 +270,4 @@ 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

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class ErrorHandlingTest < Minitest::Test
@@ -211,10 +209,7 @@ 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)
@@ -228,10 +223,7 @@ 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)

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
module MoneyFilter

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class HashOrderingTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
module FunnyFilter

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class ParsingQuirksTest < Minitest::Test

View File

@@ -1,27 +0,0 @@
# 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

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class RenderProfilingTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
module SecurityFilter

View File

@@ -1,5 +1,4 @@
# encoding: utf-8
# frozen_string_literal: true
require 'test_helper'

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class BreakTagTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class ContinueTagTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class EchoTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class ThingWithValue < Liquid::Drop

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class IfElseTagTest < Minitest::Test

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class TestFileSystem

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
require 'test_helper'
class IncrementTagTest < Minitest::Test

Some files were not shown because too many files have changed in this diff Show More