mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
split filter parsing: scan no-arg filters directly, only invoke Lexer when args present
This commit is contained in:
+52
-11
@@ -91,7 +91,9 @@ module Liquid
|
|||||||
|
|
||||||
# Fast path: try to parse without going through Lexer → Parser
|
# Fast path: try to parse without going through Lexer → Parser
|
||||||
# Skip for strict2/rigid modes which require different parsing
|
# Skip for strict2/rigid modes which require different parsing
|
||||||
if parse_context.error_mode == :strict2 || parse_context.error_mode == :rigid || !try_fast_parse(markup, parse_context)
|
# Fast path only for lax/warn modes — strict modes need full error checking
|
||||||
|
error_mode = parse_context.error_mode
|
||||||
|
if error_mode == :strict2 || error_mode == :rigid || error_mode == :strict || !try_fast_parse(markup, parse_context)
|
||||||
strict_parse_with_error_mode_fallback(markup)
|
strict_parse_with_error_mode_fallback(markup)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -175,19 +177,58 @@ module Liquid
|
|||||||
# Must be a pipe for filters
|
# Must be a pipe for filters
|
||||||
return false unless markup.getbyte(pos) == 124 # '|'
|
return false unless markup.getbyte(pos) == 124 # '|'
|
||||||
|
|
||||||
# Parse filters using the standard path but skip the Lexer/Parser for the name
|
# Try fast filter scanning first — handles no-arg and simple-arg filters
|
||||||
# We reuse strict_parse's filter loop by creating a parser from the filter portion only
|
# Falls through to Lexer-based parsing for complex cases
|
||||||
@filters = []
|
@filters = []
|
||||||
filter_markup = markup.byteslice(pos, len - pos)
|
filter_pos = pos
|
||||||
# Use the standard parser for the filter chain (still cheaper than re-lexing the whole thing)
|
|
||||||
p = parse_context.new_parser(filter_markup)
|
|
||||||
|
|
||||||
while p.consume?(:pipe)
|
while filter_pos < len && markup.getbyte(filter_pos) == 124 # '|'
|
||||||
filtername = p.consume(:id)
|
filter_pos += 1
|
||||||
filterargs = p.consume?(:colon) ? parse_filterargs(p) : Const::EMPTY_ARRAY
|
# Skip whitespace
|
||||||
@filters << lax_parse_filter_expressions(filtername, filterargs)
|
filter_pos += 1 while filter_pos < len && markup.getbyte(filter_pos) == 32
|
||||||
|
|
||||||
|
# Scan filter name
|
||||||
|
fname_start = filter_pos
|
||||||
|
b = filter_pos < len ? markup.getbyte(filter_pos) : nil
|
||||||
|
break unless b && ((b >= 97 && b <= 122) || (b >= 65 && b <= 90) || b == 95)
|
||||||
|
filter_pos += 1
|
||||||
|
while filter_pos < len
|
||||||
|
b = markup.getbyte(filter_pos)
|
||||||
|
break unless (b >= 97 && b <= 122) || (b >= 65 && b <= 90) || (b >= 48 && b <= 57) || b == 95 || b == 45
|
||||||
|
filter_pos += 1
|
||||||
|
end
|
||||||
|
filtername = markup.byteslice(fname_start, filter_pos - fname_start)
|
||||||
|
|
||||||
|
# Skip whitespace
|
||||||
|
filter_pos += 1 while filter_pos < len && markup.getbyte(filter_pos) == 32
|
||||||
|
|
||||||
|
# Check for colon (has arguments) — use Lexer for the remaining filter chain
|
||||||
|
if filter_pos < len && markup.getbyte(filter_pos) == 58 # ':'
|
||||||
|
# Rewind to the '|' before this filter and use Lexer for the rest
|
||||||
|
# We already have filters parsed so far as no-arg filters
|
||||||
|
rest_start = fname_start
|
||||||
|
# Go back to find the '|' before this filter name
|
||||||
|
rest_start -= 1 while rest_start > pos && markup.getbyte(rest_start) != 124
|
||||||
|
rest_markup = markup.byteslice(rest_start, len - rest_start)
|
||||||
|
p = parse_context.new_parser(rest_markup)
|
||||||
|
while p.consume?(:pipe)
|
||||||
|
fn = p.consume(:id)
|
||||||
|
fa = p.consume?(:colon) ? parse_filterargs(p) : Const::EMPTY_ARRAY
|
||||||
|
@filters << lax_parse_filter_expressions(fn, fa)
|
||||||
|
end
|
||||||
|
p.consume(:end_of_string)
|
||||||
|
@filters = Const::EMPTY_ARRAY if @filters.empty?
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
# No args — add as simple filter
|
||||||
|
@filters << [filtername, Const::EMPTY_ARRAY]
|
||||||
end
|
end
|
||||||
p.consume(:end_of_string)
|
|
||||||
|
# Skip trailing whitespace
|
||||||
|
filter_pos += 1 while filter_pos < len && (b = markup.getbyte(filter_pos)) && (b == 32 || b == 9 || b == 10 || b == 13)
|
||||||
|
return false unless filter_pos >= len
|
||||||
|
|
||||||
@filters = Const::EMPTY_ARRAY if @filters.empty?
|
@filters = Const::EMPTY_ARRAY if @filters.empty?
|
||||||
true
|
true
|
||||||
rescue SyntaxError
|
rescue SyntaxError
|
||||||
|
|||||||
Reference in New Issue
Block a user