Merge pull request #484 from knu/liquid-to_uri

  Add a new Liquid filter `to_uri`.

Akinori MUSHA преди 10 години
родител
ревизия
5101cd5a8c
променени са 4 файла, в които са добавени 107 реда и са изтрити 0 реда
  1. 20 0
      app/concerns/liquid_droppable.rb
  2. 16 0
      app/concerns/liquid_interpolatable.rb
  3. 34 0
      spec/concerns/liquid_droppable_spec.rb
  4. 37 0
      spec/concerns/liquid_interpolatable_spec.rb

+ 20 - 0
app/concerns/liquid_droppable.rb

@@ -9,6 +9,10 @@ module LiquidDroppable
9 9
       @object = object
10 10
     end
11 11
 
12
+    def to_s
13
+      @object.to_s
14
+    end
15
+
12 16
     def each
13 17
       (public_instance_methods - Drop.public_instance_methods).each { |name|
14 18
         yield [name, __send__(name)]
@@ -23,4 +27,20 @@ module LiquidDroppable
23 27
   def to_liquid
24 28
     self.class::Drop.new(self)
25 29
   end
30
+
31
+  require 'uri'
32
+
33
+  class URIDrop < Drop
34
+    URI::Generic::COMPONENT.each { |attr|
35
+      define_method(attr) {
36
+        @object.__send__(attr)
37
+      }
38
+    }
39
+  end
40
+
41
+  class ::URI::Generic
42
+    def to_liquid
43
+      URIDrop.new(self)
44
+    end
45
+  end
26 46
 end

+ 16 - 0
app/concerns/liquid_interpolatable.rb

@@ -116,6 +116,22 @@ module LiquidInterpolatable
116 116
       CGI.escape(string) rescue string
117 117
     end
118 118
 
119
+    # Parse an input into a URI object, optionally resolving it
120
+    # against a base URI if given.
121
+    #
122
+    # A URI object will have the following properties: scheme,
123
+    # userinfo, host, port, registry, path, opaque, query, and
124
+    # fragment.
125
+    def to_uri(uri, base_uri = nil)
126
+      if base_uri
127
+        URI(base_uri) + uri.to_s
128
+      else
129
+        URI(uri.to_s)
130
+      end
131
+    rescue URI::Error
132
+      nil
133
+    end
134
+
119 135
     # Escape a string for use in XPath expression
120 136
     def to_xpath(string)
121 137
       subs = string.to_s.scan(/\G(?:\A\z|[^"]+|[^']+)/).map { |x|

+ 34 - 0
spec/concerns/liquid_droppable_spec.rb

@@ -0,0 +1,34 @@
1
+require 'spec_helper'
2
+
3
+describe LiquidDroppable do
4
+  before do
5
+    class DroppableTest
6
+      include LiquidDroppable
7
+
8
+      def initialize(value)
9
+        @value = value
10
+      end
11
+
12
+      attr_reader :value
13
+
14
+      def to_s
15
+        "[value:#{value}]"
16
+      end
17
+    end
18
+
19
+    class DroppableTestDrop
20
+      def value
21
+        @object.value
22
+      end
23
+    end
24
+  end
25
+
26
+  describe 'test class' do
27
+    it 'should be droppable' do
28
+      five = DroppableTest.new(5)
29
+      five.to_liquid.class.should == DroppableTestDrop
30
+      Liquid::Template.parse('{{ x.value | plus:3 }}').render('x' => five).should == '8'
31
+      Liquid::Template.parse('{{ x }}').render('x' => five).should == '[value:5]'
32
+    end
33
+  end
34
+end

+ 37 - 0
spec/concerns/liquid_interpolatable_spec.rb

@@ -59,4 +59,41 @@ describe LiquidInterpolatable::Filters do
59 59
       @filter.to_xpath_roundtrip(1).should == '1'
60 60
     end
61 61
   end
62
+
63
+  describe 'to_uri' do
64
+    before do
65
+      @agent = Agents::InterpolatableAgent.new(name: "test", options: { 'foo' => '{% assign u = s | to_uri %}{{ u.path }}' })
66
+      @agent.interpolation_context['s'] = 'http://example.com/dir/1?q=test'
67
+    end
68
+
69
+    it 'should parse an abosule URI' do
70
+      @filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1').should == URI('http://example.net/index.html')
71
+    end
72
+
73
+    it 'should parse an abosule URI with a base URI specified' do
74
+      @filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1').should == URI('http://example.net/index.html')
75
+    end
76
+
77
+    it 'should parse a relative URI with a base URI specified' do
78
+      @filter.to_uri('foo/index.html', 'http://example.com/dir/1').should == URI('http://example.com/dir/foo/index.html')
79
+    end
80
+
81
+    it 'should parse an abosule URI with a base URI specified' do
82
+      @filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1').should == URI('http://example.net/index.html')
83
+    end
84
+
85
+    it 'should stringify a non-string operand' do
86
+      @filter.to_uri(123, 'http://example.com/dir/1').should == URI('http://example.com/dir/123')
87
+    end
88
+
89
+    it 'should return a URI value in interpolation' do
90
+      @agent.interpolated['foo'].should == '/dir/1'
91
+    end
92
+
93
+    it 'should return a URI value resolved against a base URI in interpolation' do
94
+      @agent.options['foo'] = '{% assign u = s | to_uri:"http://example.com/dir/1" %}{{ u.path }}'
95
+      @agent.interpolation_context['s'] = 'foo/index.html'
96
+      @agent.interpolated['foo'].should == '/dir/foo/index.html'
97
+    end
98
+  end
62 99
 end