riddl 0.99.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +1 -0
- data/COPYING +165 -0
- data/INSTALL +24 -0
- data/README.rdoc +2 -0
- data/Rakefile +17 -0
- data/TODO +17 -0
- data/contrib/riddl.jpg +0 -0
- data/contrib/riddl.png +0 -0
- data/contrib/riddl.svg +138 -0
- data/lib/riddl/client.rb +423 -0
- data/lib/riddl/commonlogger.rb +16 -0
- data/lib/riddl/constants.rb +5 -0
- data/lib/riddl/error.rb +8 -0
- data/lib/riddl/handlers.rb +14 -0
- data/lib/riddl/handlers/oauth.rb +19 -0
- data/lib/riddl/handlers/plain-type.rb +21 -0
- data/lib/riddl/handlers/relaxng.rb +16 -0
- data/lib/riddl/handlers/xmlschema.rb +16 -0
- data/lib/riddl/header.rb +9 -0
- data/lib/riddl/implementation.rb +57 -0
- data/lib/riddl/ns/common-patterns/addon-security/request.xml +25 -0
- data/lib/riddl/ns/common-patterns/addon-security/response.xml +25 -0
- data/lib/riddl/ns/common-patterns/downloadify/1.0/downloadify.xml +18 -0
- data/lib/riddl/ns/common-patterns/notifications-consumer/1.0/consumer.xml +100 -0
- data/lib/riddl/ns/common-patterns/notifications-producer/1.0/producer.xml +204 -0
- data/lib/riddl/ns/common-patterns/properties/1.0/properties.schema.schema +140 -0
- data/lib/riddl/ns/common-patterns/properties/1.0/properties.schema.xsl +89 -0
- data/lib/riddl/ns/common-patterns/properties/1.0/properties.xml +150 -0
- data/lib/riddl/ns/common/datatypes-1_0.rng +79 -0
- data/lib/riddl/ns/common/relaxng-modular.rng +330 -0
- data/lib/riddl/ns/common/relaxng.rng +10 -0
- data/lib/riddl/ns/declaration/1.0/declaration.rng +114 -0
- data/lib/riddl/ns/description/1.0/description.rng +302 -0
- data/lib/riddl/option.rb +9 -0
- data/lib/riddl/parameter.rb +54 -0
- data/lib/riddl/protocols/http/generator.rb +121 -0
- data/lib/riddl/protocols/http/parser.rb +199 -0
- data/lib/riddl/protocols/websocket.rb +103 -0
- data/lib/riddl/protocols/xmpp/generator.rb +176 -0
- data/lib/riddl/protocols/xmpp/parser.rb +118 -0
- data/lib/riddl/roles.rb +15 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Faccess_token.rb +30 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Fon_behalf.rb +22 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Frequest_token.rb +30 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0/base.rb +67 -0
- data/lib/riddl/server.rb +519 -0
- data/lib/riddl/utils/description.rb +29 -0
- data/lib/riddl/utils/downloadify.rb +14 -0
- data/lib/riddl/utils/erbserve.rb +23 -0
- data/lib/riddl/utils/fileserve.rb +31 -0
- data/lib/riddl/utils/notifications_producer.rb +310 -0
- data/lib/riddl/utils/properties.rb +474 -0
- data/lib/riddl/utils/xsloverlay.rb +21 -0
- data/lib/riddl/wrapper.rb +280 -0
- data/lib/riddl/wrapper/declaration.rb +103 -0
- data/lib/riddl/wrapper/declaration/facade.rb +94 -0
- data/lib/riddl/wrapper/declaration/interface.rb +34 -0
- data/lib/riddl/wrapper/declaration/tile.rb +107 -0
- data/lib/riddl/wrapper/description.rb +69 -0
- data/lib/riddl/wrapper/description/access.rb +108 -0
- data/lib/riddl/wrapper/description/message_and_transformation.rb +131 -0
- data/lib/riddl/wrapper/description/resource.rb +271 -0
- data/lib/riddl/wrapper/layerchecker.rb +33 -0
- data/lib/riddl/wrapper/messageparser.rb +221 -0
- data/lib/riddl/wrapper/resourcechecker.rb +98 -0
- data/ns/common-patterns/addon-security/request.xml +25 -0
- data/ns/common-patterns/addon-security/response.xml +25 -0
- data/ns/common-patterns/downloadify/1.0/downloadify.xml +18 -0
- data/ns/common-patterns/notifications-consumer/1.0/consumer.xml +100 -0
- data/ns/common-patterns/notifications-producer/1.0/producer.xml +204 -0
- data/ns/common-patterns/properties/1.0/properties.schema.schema +140 -0
- data/ns/common-patterns/properties/1.0/properties.schema.xsl +89 -0
- data/ns/common-patterns/properties/1.0/properties.xml +150 -0
- data/ns/common/datatypes-1_0.rng +79 -0
- data/ns/common/relaxng-modular.rng +330 -0
- data/ns/common/relaxng.rng +10 -0
- data/ns/declaration/1.0/declaration.rng +114 -0
- data/ns/description/1.0/description.rng +302 -0
- data/riddl.gemspec +33 -0
- data/test/smartrunner.rb +48 -0
- data/test/tc_declaration-distributed.rb +79 -0
- data/test/tc_declaration-hybrid.rb +71 -0
- data/test/tc_declaration-local.rb +47 -0
- data/test/tc_helloworld.rb +17 -0
- data/test/tc_producer.rb +54 -0
- data/test/tc_properties.rb +72 -0
- data/tools/flash-policy-server.rb +12 -0
- data/tools/riddlcheck +36 -0
- data/tools/riddlcheck-1_0 +36 -0
- data/tools/riddlprocess +51 -0
- data/tools/riddlprocess-1_0 +51 -0
- metadata +291 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module Riddl
|
2
|
+
class Wrapper
|
3
|
+
class Declaration < WrapperUtils
|
4
|
+
|
5
|
+
class Interface
|
6
|
+
def initialize(name,top,base,sub,des)
|
7
|
+
@name = name
|
8
|
+
@top = top
|
9
|
+
@base = base
|
10
|
+
@sub = sub
|
11
|
+
@des = des
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.new_from_interface(interface,sub)
|
15
|
+
Interface.new(interface.name,interface.top,interface.base,sub,interface.des)
|
16
|
+
end
|
17
|
+
|
18
|
+
def real_path(real)
|
19
|
+
t = @top.sub(/^\/*/,'').split('/')
|
20
|
+
real = real.sub(/^\/*/,'').split('/')
|
21
|
+
real = real[t.length..-1]
|
22
|
+
'/' + real.join('/')
|
23
|
+
end
|
24
|
+
|
25
|
+
def real_url(real,base)
|
26
|
+
(@base == '' ? base : @base) + real_path(real)
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :top, :base, :sub, :name, :des
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Riddl
|
2
|
+
class Wrapper
|
3
|
+
class Declaration < WrapperUtils
|
4
|
+
|
5
|
+
class Tile
|
6
|
+
#{{
|
7
|
+
def initialize
|
8
|
+
#{{{
|
9
|
+
@resource = Riddl::Wrapper::Description::Resource.new("/")
|
10
|
+
@base_path = @resource
|
11
|
+
#}}}
|
12
|
+
end
|
13
|
+
|
14
|
+
def visualize(mode,res=@resource,what='')
|
15
|
+
#{{{
|
16
|
+
what += res.path
|
17
|
+
puts what
|
18
|
+
if mode == :layers
|
19
|
+
res.access_methods.each do |k,v|
|
20
|
+
puts " #{k.to_s.upcase}:"
|
21
|
+
v.each_with_index do |l,i|
|
22
|
+
puts " Layer #{i}:"
|
23
|
+
l.each do |r|
|
24
|
+
puts " #{r.class.name.gsub(/[^\:]+::/,'')}: #{r.visualize}"
|
25
|
+
end unless l.nil?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
if mode == :composition
|
30
|
+
res.composition.each do |k,v|
|
31
|
+
puts " #{k.to_s.upcase}:"
|
32
|
+
v.each do |r|
|
33
|
+
puts " #{r.result.class.name.gsub(/[^\:]+::/,'')}: #{r.result.visualize}"
|
34
|
+
r.route.each do |ritem|
|
35
|
+
puts " #{ritem.class.name.gsub(/[^\:]+::/,'')}: #{ritem.visualize}"
|
36
|
+
end unless r.route.nil?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
res.resources.each do |key,r|
|
41
|
+
visualize(mode,r,what + (what == '/' ? '' : '/'))
|
42
|
+
end
|
43
|
+
#}}}
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_description(des,desres,path,index,interface,block,rec=nil,res=@base_path)
|
47
|
+
#{{{
|
48
|
+
res = add_path(path,res,rec)
|
49
|
+
res.add_access_methods(des,desres,index,interface)
|
50
|
+
block.each do |bl|
|
51
|
+
bpath = bl.to_s.gsub(/\/+/,'/').gsub(/\/$/,'')
|
52
|
+
bpath = (bpath == "" ? "/" : bpath)
|
53
|
+
if interface.sub == bpath
|
54
|
+
res.remove_access_methods(des,bl.attributes)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
desres.find("des:resource").each do |desres|
|
58
|
+
cpath = desres.attributes['relative'] || "{}"
|
59
|
+
rec = desres.attributes['recursive']
|
60
|
+
int = Interface.new_from_interface(interface,(interface.sub+"/"+cpath).gsub(/\/+/,'/'))
|
61
|
+
add_description(des,desres,cpath,index,int,block,rec,res)
|
62
|
+
end
|
63
|
+
nil
|
64
|
+
#}}}
|
65
|
+
end
|
66
|
+
|
67
|
+
def compose!(res=@base_path)
|
68
|
+
#{{{
|
69
|
+
res.compose!
|
70
|
+
res.resources.each do |k,r|
|
71
|
+
compose!(r)
|
72
|
+
end
|
73
|
+
#}}}
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_path(path,res,rec=nil)
|
77
|
+
#{{{
|
78
|
+
pres = res
|
79
|
+
path.split('/').each do |pa|
|
80
|
+
next if pa == ""
|
81
|
+
unless pres.resources.has_key?(pa)
|
82
|
+
pres.resources[pa] = Riddl::Wrapper::Description::Resource.new(pa,rec.nil? ? false : true)
|
83
|
+
end
|
84
|
+
pres = pres.resources[pa]
|
85
|
+
end
|
86
|
+
pres
|
87
|
+
#}}}
|
88
|
+
end
|
89
|
+
private :add_path
|
90
|
+
|
91
|
+
def base_path(path)
|
92
|
+
#{{{
|
93
|
+
if path.nil? || path == '/'
|
94
|
+
@base_path
|
95
|
+
else
|
96
|
+
@base_path = add_path(path,@base_path)
|
97
|
+
end
|
98
|
+
#}}}
|
99
|
+
end
|
100
|
+
|
101
|
+
attr_reader :resource
|
102
|
+
#}}}
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/description/resource')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/description/access')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/description/message_and_transformation')
|
4
|
+
|
5
|
+
module Riddl
|
6
|
+
class Wrapper
|
7
|
+
class Description < WrapperUtils
|
8
|
+
|
9
|
+
def paths(res=@resource,what='')
|
10
|
+
rpaths(res,what)
|
11
|
+
end
|
12
|
+
def get_resource(path)
|
13
|
+
get_resource_deep(path,@resource)
|
14
|
+
end
|
15
|
+
|
16
|
+
def visualize(res=@resource,what='')
|
17
|
+
#{{{
|
18
|
+
what += res.path
|
19
|
+
puts what
|
20
|
+
res.access_methods.each do |k,v|
|
21
|
+
puts " #{k.upcase}:"
|
22
|
+
v.each_with_index do |l,i|
|
23
|
+
l.each do |r|
|
24
|
+
puts " #{r.class.name.gsub(/[^\:]+::/,'')}: #{r.visualize}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
res.resources.each do |key,r|
|
29
|
+
visualize(r,what + (what == '/' ? '' : '/'))
|
30
|
+
end
|
31
|
+
#}}}
|
32
|
+
end
|
33
|
+
|
34
|
+
def xml
|
35
|
+
@riddl.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_description(des,res,desres,path=nil,rec=nil)
|
39
|
+
#{{{
|
40
|
+
unless path.nil?
|
41
|
+
unless res.resources.has_key?(path)
|
42
|
+
res.resources[path] = Riddl::Wrapper::Description::Resource.new(path,rec.nil? ? false : true)
|
43
|
+
end
|
44
|
+
res = res.resources[path]
|
45
|
+
end
|
46
|
+
res.add_access_methods(des,desres,0,nil)
|
47
|
+
desres.find("des:resource").each do |desres|
|
48
|
+
cpath = desres.attributes['relative'] || "{}"
|
49
|
+
rec = desres.attributes['recursive']
|
50
|
+
add_description(des,res,desres,cpath,rec)
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
#}}}
|
54
|
+
end
|
55
|
+
private :add_description
|
56
|
+
|
57
|
+
def initialize(riddl)
|
58
|
+
#{{{
|
59
|
+
@resource = Riddl::Wrapper::Description::Resource.new("/")
|
60
|
+
@riddl = riddl
|
61
|
+
des = riddl.root
|
62
|
+
desres = des.find("/des:description/des:resource").first
|
63
|
+
add_description(des,@resource,desres)
|
64
|
+
#}}}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Riddl
|
2
|
+
class Wrapper
|
3
|
+
class Description < WrapperUtils
|
4
|
+
|
5
|
+
class AccessBase# {{{
|
6
|
+
def used=(value)
|
7
|
+
@used = value
|
8
|
+
end
|
9
|
+
def used?
|
10
|
+
@used || false
|
11
|
+
end
|
12
|
+
attr_reader :interface
|
13
|
+
end# }}}
|
14
|
+
|
15
|
+
class RequestInOut < AccessBase# {{{
|
16
|
+
def initialize(des,min,mout,interface)
|
17
|
+
@interface = interface
|
18
|
+
if des.nil?
|
19
|
+
@in = min
|
20
|
+
@out = mout
|
21
|
+
else
|
22
|
+
@in = Riddl::Wrapper::Description::Message.new(des,min)
|
23
|
+
@out = mout.nil? ? nil : Riddl::Wrapper::Description::Message.new(des,mout)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def self.new_from_message(min,mout)
|
27
|
+
RequestInOut.new(nil,min,mout,nil)
|
28
|
+
end
|
29
|
+
def hash
|
30
|
+
@in.hash + (@out.nil? ? 0 : @out.hash)
|
31
|
+
end
|
32
|
+
attr_reader :in, :out
|
33
|
+
def visualize; "in #{@in.name.inspect} out #{@out.nil? ? "NIL" : @out.name.inspect}"; end
|
34
|
+
end# }}}
|
35
|
+
|
36
|
+
class RequestTransformation < AccessBase# {{{
|
37
|
+
def initialize(des,mtrans,interface)
|
38
|
+
@interface = interface
|
39
|
+
if des.nil?
|
40
|
+
@trans = mtrans
|
41
|
+
else
|
42
|
+
@trans = Riddl::Wrapper::Description::Transformation.new(des,mtrans)
|
43
|
+
end
|
44
|
+
@out = nil
|
45
|
+
end
|
46
|
+
def self.new_from_transformation(mtrans1,mtrans2)
|
47
|
+
tmp = XML::Smart::string("<transformation/>")
|
48
|
+
tmp.root.add mtrans1.content.root.children
|
49
|
+
tmp.root.add mtrans2.content.root.children
|
50
|
+
RequestTransformation.new(nil,Riddl::Wrapper::Description::Transformation.new_from_xml("#{mtrans2.name}_#{mtrans2.name}_merged",tmp),nil)
|
51
|
+
end
|
52
|
+
def transform(min)
|
53
|
+
tmp = self.dup
|
54
|
+
if min.class == RequestInOut && !min.out.nil?
|
55
|
+
tmp.out = min.out.transform(@trans)
|
56
|
+
end
|
57
|
+
tmp
|
58
|
+
end
|
59
|
+
attr_reader :trans
|
60
|
+
attr_accessor :out
|
61
|
+
def hash
|
62
|
+
@trans.hash + (@out.nil? ? 0 : @out.hash)
|
63
|
+
end
|
64
|
+
def visualize; "transformation #{@trans.name.inspect}"; end
|
65
|
+
end# }}}
|
66
|
+
|
67
|
+
class RequestStarOut < AccessBase# {{{
|
68
|
+
def initialize(des,mout,interface)
|
69
|
+
@interface = interface
|
70
|
+
if des.nil?
|
71
|
+
@out = mout
|
72
|
+
else
|
73
|
+
@out = mout.nil? ? nil : Riddl::Wrapper::Description::Message.new(des,mout)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
def self.new_from_message(mout)
|
77
|
+
RequestStarOut.new(nil,mout,nil)
|
78
|
+
end
|
79
|
+
attr_reader :out
|
80
|
+
def hash
|
81
|
+
@out.nil? ? 0 : @out.hash
|
82
|
+
end
|
83
|
+
def visualize; "out #{@out.nil? ? "NIL" : @out.name.inspect}"; end
|
84
|
+
end# }}}
|
85
|
+
|
86
|
+
class RequestPass < AccessBase# {{{
|
87
|
+
def initialize(interface)
|
88
|
+
@interface = interface
|
89
|
+
end
|
90
|
+
def visualize; ""; end
|
91
|
+
def hash
|
92
|
+
0
|
93
|
+
end
|
94
|
+
end# }}}
|
95
|
+
|
96
|
+
class WebSocket < AccessBase# {{{
|
97
|
+
def visualize; ""; end
|
98
|
+
def initialize(interface)
|
99
|
+
@interface = interface
|
100
|
+
end
|
101
|
+
def hash
|
102
|
+
0
|
103
|
+
end
|
104
|
+
end# }}}
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Riddl
|
2
|
+
class Wrapper
|
3
|
+
class Description < WrapperUtils
|
4
|
+
|
5
|
+
class HashBase
|
6
|
+
#{{{
|
7
|
+
def initialize(layer,name,type,content=nil)
|
8
|
+
@name = name
|
9
|
+
@hash = nil
|
10
|
+
if layer.nil?
|
11
|
+
@content = content
|
12
|
+
else
|
13
|
+
@content = layer.find("des:#{type}[@name='#{name}']").first.to_doc
|
14
|
+
@content.root.find("@name").delete_all!
|
15
|
+
@content.register_namespace 'des', Riddl::Wrapper::DESCRIPTION
|
16
|
+
@content.register_namespace 'dec', Riddl::Wrapper::DECLARATION
|
17
|
+
end
|
18
|
+
update_hash!
|
19
|
+
end
|
20
|
+
def update_hash!
|
21
|
+
# TODO too simple
|
22
|
+
@hash = @content.to_s.hash
|
23
|
+
end
|
24
|
+
def traverse?(other)
|
25
|
+
other.name.nil? ? false : (self.hash == other.hash)
|
26
|
+
end
|
27
|
+
attr_reader :name, :content, :hash
|
28
|
+
#}}}
|
29
|
+
end
|
30
|
+
|
31
|
+
class Transformation < HashBase
|
32
|
+
#{{{
|
33
|
+
def initialize(layer,name,xml=nil)
|
34
|
+
super layer,name,:transformation,xml
|
35
|
+
end
|
36
|
+
def self.new_from_xml(name,xml)
|
37
|
+
Transformation.new(nil,name,xml)
|
38
|
+
end
|
39
|
+
#}}}
|
40
|
+
end
|
41
|
+
|
42
|
+
class Message < HashBase
|
43
|
+
#{{{
|
44
|
+
def initialize(layer,name)
|
45
|
+
super layer,name,:message
|
46
|
+
end
|
47
|
+
def initialize_copy(o)
|
48
|
+
@content = @content.dup
|
49
|
+
end
|
50
|
+
def transform(trans)
|
51
|
+
ret = self.dup
|
52
|
+
unless trans.name.nil?
|
53
|
+
trans.content.root.children.each do |e|
|
54
|
+
case e.qname.name
|
55
|
+
when 'add_header'
|
56
|
+
raise "TODO"
|
57
|
+
when 'add_before'
|
58
|
+
raise "TODO"
|
59
|
+
when 'add_after'
|
60
|
+
raise "TODO"
|
61
|
+
when 'add_as_first'
|
62
|
+
t = ret.content.root
|
63
|
+
n = t.find("header[last()]").first
|
64
|
+
if n.nil?
|
65
|
+
m = t.find("*[not(header)]").first
|
66
|
+
if m.nil?
|
67
|
+
t.add(e.children)
|
68
|
+
else
|
69
|
+
m.add_before(e.children)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
n.add_after(e.children)
|
73
|
+
end
|
74
|
+
when 'add_as_last'
|
75
|
+
ret.content.root.add(e.children)
|
76
|
+
ret.update_hash!
|
77
|
+
when 'remove_each'
|
78
|
+
ret.content.find("parameter[@name=\"#{e.attributes['name']}\"]").delete_all!
|
79
|
+
when 'remove_first'
|
80
|
+
if e.attributes['name']
|
81
|
+
case e.attributes['type']
|
82
|
+
when 'parameter', nil
|
83
|
+
node = ret.content.find("//parameter[@name=\"#{e.attributes['name']}\"]").first
|
84
|
+
opt = node.add_before("optional")
|
85
|
+
opt.add(node)
|
86
|
+
when 'header'
|
87
|
+
ret.content.find("header[@name=\"#{e.attributes['name']}\"]").delete_all!
|
88
|
+
end
|
89
|
+
else
|
90
|
+
case e.attributes['type']
|
91
|
+
when 'parameter', nil
|
92
|
+
ret.content.find("//parameter[first()]").delete_all!
|
93
|
+
when 'header'
|
94
|
+
ret.content.find("//header[first()]").delete_all!
|
95
|
+
end
|
96
|
+
end
|
97
|
+
when 'remove_last'
|
98
|
+
if e.attributes['name']
|
99
|
+
case e.attributes['type']
|
100
|
+
when 'parameter', nil
|
101
|
+
node = ret.content.find("//parameter[@name=\"#{e.attributes['name']}\"]").last
|
102
|
+
opt = node.add_before("optional")
|
103
|
+
opt.add(node)
|
104
|
+
when 'header'
|
105
|
+
ret.content.find("header[@name=\"#{e.attributes['name']}\"]").delete_all!
|
106
|
+
end
|
107
|
+
else
|
108
|
+
case e.attributes['type']
|
109
|
+
when 'parameter', nil
|
110
|
+
ret.content.find("//parameter[last()]").delete_all!
|
111
|
+
when 'header'
|
112
|
+
ret.content.find("//header[last()]").delete_all!
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
return ret
|
119
|
+
end
|
120
|
+
#}}}
|
121
|
+
end
|
122
|
+
|
123
|
+
class Star
|
124
|
+
#{{{
|
125
|
+
def name; "*"; end
|
126
|
+
#}}}
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|