diff --git a/History.md b/History.md index 935151bc0..5d0c092ba 100644 --- a/History.md +++ b/History.md @@ -1,10 +1,12 @@ # Liquid Change Log -## 5.1.1 (unreleased) +## 5.2.0 (unreleased) -### Fixes +### Features +* Add `remove_last`, and `replace_last` filters (#1422) [Anders Hagbard] -* Fix some internal errors in filters from invalid input [Dylan Thacker-Smith] +### Fixes +* Fix some internal errors in filters from invalid input (#1476) [Dylan Thacker-Smith] ## 5.1.0 / 2021-09-09 diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index 98e38f5f4..f361c02bf 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -308,14 +308,34 @@ def replace_first(input, string, replacement = '') input.to_s.sub(string.to_s, replacement.to_s) end + # Replace the last occurrences of a string with another + def replace_last(input, string, replacement) + input = input.to_s + string = string.to_s + replacement = replacement.to_s + + start_index = input.rindex(string) + + return input unless start_index + + output = input.dup + output[start_index, string.length] = replacement + output + end + # remove a substring def remove(input, string) - input.to_s.gsub(string.to_s, '') + replace(input, string, '') end # remove the first occurrences of a substring def remove_first(input, string) - input.to_s.sub(string.to_s, '') + replace_first(input, string, '') + end + + # remove the last occurences of a substring + def remove_last(input, string) + replace_last(input, string, '') end # add one string to another diff --git a/test/integration/standard_filter_test.rb b/test/integration/standard_filter_test.rb index e7b34c164..694d24d77 100644 --- a/test/integration/standard_filter_test.rb +++ b/test/integration/standard_filter_test.rb @@ -539,19 +539,31 @@ def test_first_last end def test_replace - assert_equal('2 2 2 2', @filters.replace('1 1 1 1', '1', 2)) + assert_equal('b b b b', @filters.replace('a a a a', 'a', 'b')) assert_equal('2 2 2 2', @filters.replace('1 1 1 1', 1, 2)) - assert_equal('2 1 1 1', @filters.replace_first('1 1 1 1', '1', 2)) + assert_equal('1 1 1 1', @filters.replace('1 1 1 1', 2, 3)) + assert_template_result('2 2 2 2', "{{ '1 1 1 1' | replace: '1', 2 }}") + + assert_equal('b a a a', @filters.replace_first('a a a a', 'a', 'b')) assert_equal('2 1 1 1', @filters.replace_first('1 1 1 1', 1, 2)) + assert_equal('1 1 1 1', @filters.replace_first('1 1 1 1', 2, 3)) assert_template_result('2 1 1 1', "{{ '1 1 1 1' | replace_first: '1', 2 }}") + + assert_equal('a a a b', @filters.replace_last('a a a a', 'a', 'b')) + assert_equal('1 1 1 2', @filters.replace_last('1 1 1 1', 1, 2)) + assert_equal('1 1 1 1', @filters.replace_last('1 1 1 1', 2, 3)) + assert_template_result('1 1 1 2', "{{ '1 1 1 1' | replace_last: '1', 2 }}") end def test_remove assert_equal(' ', @filters.remove("a a a a", 'a')) - assert_equal(' ', @filters.remove("1 1 1 1", 1)) - assert_equal('a a a', @filters.remove_first("a a a a", 'a ')) - assert_equal(' 1 1 1', @filters.remove_first("1 1 1 1", 1)) - assert_template_result('a a a', "{{ 'a a a a' | remove_first: 'a ' }}") + assert_template_result(' ', "{{ '1 1 1 1' | remove: 1 }}") + + assert_equal('b a a', @filters.remove_first("a b a a", 'a ')) + assert_template_result(' 1 1 1', "{{ '1 1 1 1' | remove_first: 1 }}") + + assert_equal('a a b', @filters.remove_last("a a b a", ' a')) + assert_template_result('1 1 1 ', "{{ '1 1 1 1' | remove_last: 1 }}") end def test_pipes_in_string_arguments