@@ -26,12 +26,29 @@ module LiquidInterpolatable |
||
| 26 | 26 |
end |
| 27 | 27 |
|
| 28 | 28 |
require 'uri' |
| 29 |
- # Percent encoding for URI conforming to RFC 3986. |
|
| 30 |
- # Ref: http://tools.ietf.org/html/rfc3986#page-12 |
|
| 31 | 29 |
module Filters |
| 30 |
+ # Percent encoding for URI conforming to RFC 3986. |
|
| 31 |
+ # Ref: http://tools.ietf.org/html/rfc3986#page-12 |
|
| 32 | 32 |
def uri_escape(string) |
| 33 | 33 |
CGI::escape string |
| 34 | 34 |
end |
| 35 |
+ |
|
| 36 |
+ # Escape a string for use in XPath expression |
|
| 37 |
+ def to_xpath(string) |
|
| 38 |
+ subs = string.scan(/\G(?:\A\z|[^"]+|[^']+)/).map { |x|
|
|
| 39 |
+ case x |
|
| 40 |
+ when /"/ |
|
| 41 |
+ %Q{'#{x}'}
|
|
| 42 |
+ else |
|
| 43 |
+ %Q{"#{x}"}
|
|
| 44 |
+ end |
|
| 45 |
+ } |
|
| 46 |
+ if subs.size == 1 |
|
| 47 |
+ subs.first |
|
| 48 |
+ else |
|
| 49 |
+ 'concat(' << subs.join(', ') << ')'
|
|
| 50 |
+ end |
|
| 51 |
+ end |
|
| 35 | 52 |
end |
| 36 | 53 |
Liquid::Template.register_filter(LiquidInterpolatable::Filters) |
| 37 | 54 |
|
@@ -1,4 +1,5 @@ |
||
| 1 | 1 |
require 'spec_helper' |
| 2 |
+require 'nokogiri' |
|
| 2 | 3 |
|
| 3 | 4 |
describe LiquidInterpolatable::Filters do |
| 4 | 5 |
before do |
@@ -12,4 +13,21 @@ describe LiquidInterpolatable::Filters do |
||
| 12 | 13 |
@filter.uri_escape('abc:/?=').should == 'abc%3A%2F%3F%3D'
|
| 13 | 14 |
end |
| 14 | 15 |
end |
| 16 |
+ |
|
| 17 |
+ describe 'to_xpath' do |
|
| 18 |
+ before do |
|
| 19 |
+ def @filter.to_xpath_roundtrip(string) |
|
| 20 |
+ Nokogiri::XML('').xpath(to_xpath(string))
|
|
| 21 |
+ end |
|
| 22 |
+ end |
|
| 23 |
+ |
|
| 24 |
+ it 'should escape a string for use in XPath expression' do |
|
| 25 |
+ [ |
|
| 26 |
+ %q{abc}.freeze,
|
|
| 27 |
+ %q{'a"bc'dfa""fds''fa}.freeze,
|
|
| 28 |
+ ].each { |string|
|
|
| 29 |
+ @filter.to_xpath_roundtrip(string).should == string |
|
| 30 |
+ } |
|
| 31 |
+ end |
|
| 32 |
+ end |
|
| 15 | 33 |
end |
@@ -471,7 +471,7 @@ fire: hot |
||
| 471 | 471 |
|
| 472 | 472 |
lambda {
|
| 473 | 473 |
@valid_options['extract']['site_title'] = {
|
| 474 |
- 'css' => "#comic img", 'value' => "'{{title}}'"
|
|
| 474 |
+ 'css' => "#comic img", 'value' => "{{title | to_xpath }}"
|
|
| 475 | 475 |
} |
| 476 | 476 |
@checker.options = @valid_options |
| 477 | 477 |
@checker.receive([@event]) |