From 1310c4978d15023982b2edbf25a7f8ed86cdcd3c Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Fri, 11 Feb 2022 11:37:06 -0500 Subject: [PATCH] Fix kwarg parsing inconsistency with Liquid::C Liquid::C parses liquid filter arguments with dashes in them, Liquid does not. For tags that accept kwargs and dumps them on the HTML tag, this is an important feature. e.g. {{ ... | image_tag: loading: 'lazy', data-something: 'value!' }} Without this change, Liquid would incorrectly parse the `data-something` kwarg as a single argument and would skip over the invalid characters. See https://github.com/Shopify/theme-check/issues/539 for more context --- lib/liquid.rb | 2 +- test/integration/filter_kwarg_test.rb | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/integration/filter_kwarg_test.rb diff --git a/lib/liquid.rb b/lib/liquid.rb index 28337943..7772bb5f 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -36,7 +36,7 @@ module Liquid VariableIncompleteEnd = /\}\}?/ QuotedString = /"[^"]*"|'[^']*'/ QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o - TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o + TagAttributes = /(\w[\w-]*)\s*\:\s*(#{QuotedFragment})/o AnyStartingTag = /#{TagStart}|#{VariableStart}/o PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/om TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om diff --git a/test/integration/filter_kwarg_test.rb b/test/integration/filter_kwarg_test.rb new file mode 100644 index 00000000..2bd3cbdf --- /dev/null +++ b/test/integration/filter_kwarg_test.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'test_helper' + +class FilterKwargTest < Minitest::Test + module KwargFilter + def html_tag(_tag, attributes) + attributes + .map { |key, value| "#{key}='#{value}'" } + .join(' ') + end + end + + include Liquid + + def test_can_parse_data_kwargs + with_global_filter(KwargFilter) do + assert_equal( + "data-src='src' data-widths='100, 200'", + Template.parse("{{ 'img' | html_tag: data-src: 'src', data-widths: '100, 200' }}").render(nil, nil) + ) + end + end +end