merb-core 0.9.12 → 0.9.13
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/lib/merb-core/bootloader.rb +1 -0
- data/lib/merb-core/controller/merb_controller.rb +1 -0
- data/lib/merb-core/dispatch/router.rb +14 -10
- data/lib/merb-core/dispatch/router/behavior.rb +2 -0
- data/lib/merb-core/dispatch/router/resources.rb +13 -8
- data/lib/merb-core/dispatch/router/route.rb +18 -9
- data/lib/merb-core/rack/adapter/abstract.rb +1 -1
- data/lib/merb-core/rack/adapter/mongrel.rb +9 -1
- data/lib/merb-core/tasks/gem_management.rb +16 -5
- data/lib/merb-core/test.rb +7 -6
- data/lib/merb-core/test/helpers.rb +1 -2
- data/lib/merb-core/test/matchers.rb +4 -1
- data/lib/merb-core/test/matchers/view_matchers.rb +101 -273
- data/lib/merb-core/test/run_spec.rb +40 -0
- data/lib/merb-core/test/run_specs.rb +32 -41
- data/lib/merb-core/test/test_ext/rspec.rb +0 -1
- data/lib/merb-core/test/webrat.rb +37 -0
- data/lib/merb-core/vendor/nokogiri/css.rb +6 -0
- data/lib/merb-core/vendor/nokogiri/css/generated_parser.rb +653 -0
- data/lib/merb-core/vendor/nokogiri/css/generated_tokenizer.rb +159 -0
- data/lib/merb-core/vendor/nokogiri/css/node.rb +95 -0
- data/lib/merb-core/vendor/nokogiri/css/parser.rb +24 -0
- data/lib/merb-core/vendor/nokogiri/css/parser.y +198 -0
- data/lib/merb-core/vendor/nokogiri/css/tokenizer.rb +9 -0
- data/lib/merb-core/vendor/nokogiri/css/tokenizer.rex +63 -0
- data/lib/merb-core/vendor/nokogiri/css/xpath_visitor.rb +159 -0
- data/lib/merb-core/version.rb +1 -1
- metadata +17 -4
- data/lib/merb-core/test/helpers/view_helper.rb +0 -121
@@ -0,0 +1,63 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module CSS
|
3
|
+
class GeneratedTokenizer
|
4
|
+
|
5
|
+
macro
|
6
|
+
nl \n|\r\n|\r|\f
|
7
|
+
w [\s\r\n\f]*
|
8
|
+
nonascii [^\\\\0-\\\\177]
|
9
|
+
num -?([0-9]+|[0-9]*\.[0-9]+)
|
10
|
+
unicode \\\\\\\\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?
|
11
|
+
|
12
|
+
escape {unicode}|\\\\\\\[^\n\r\f0-9a-f]
|
13
|
+
nmchar [_a-z0-9-]|{nonascii}|{escape}
|
14
|
+
nmstart [_a-z]|{nonascii}|{escape}
|
15
|
+
ident [-]?({nmstart})({nmchar})*
|
16
|
+
name ({nmchar})+
|
17
|
+
string1 "([^\n\r\f"]|\\{nl}|{nonascii}|{escape})*"
|
18
|
+
string2 '([^\n\r\f']|\\{nl}|{nonascii}|{escape})*'
|
19
|
+
string {string1}|{string2}
|
20
|
+
invalid1 \"([^\n\r\f\\"]|\\{nl}|{nonascii}|{escape})*
|
21
|
+
invalid2 \'([^\n\r\f\\']|\\{nl}|{nonascii}|{escape})*
|
22
|
+
invalid {invalid1}|{invalid2}
|
23
|
+
Comment \/\*(.|[\r\n])*?\*\/
|
24
|
+
|
25
|
+
rule
|
26
|
+
|
27
|
+
# [:state] pattern [actions]
|
28
|
+
|
29
|
+
~= { [:INCLUDES, text] }
|
30
|
+
\|= { [:DASHMATCH, text] }
|
31
|
+
\^= { [:PREFIXMATCH, text] }
|
32
|
+
\$= { [:SUFFIXMATCH, text] }
|
33
|
+
\*= { [:SUBSTRINGMATCH, text] }
|
34
|
+
!= { [:NOT_EQUAL, text] }
|
35
|
+
{ident}\(\s* { [:FUNCTION, text] }
|
36
|
+
@{ident} { [:IDENT, text] }
|
37
|
+
{ident} { [:IDENT, text] }
|
38
|
+
{num} { [:NUMBER, text] }
|
39
|
+
\#{name} { [:HASH, text] }
|
40
|
+
{w}\+ { [:PLUS, text] }
|
41
|
+
{w}> { [:GREATER, text] }
|
42
|
+
{w}, { [:COMMA, text] }
|
43
|
+
{w}~ { [:TILDE, text] }
|
44
|
+
\:not\( { [:NOT, text] }
|
45
|
+
@{ident} { [:ATKEYWORD, text] }
|
46
|
+
{num}% { [:PERCENTAGE, text] }
|
47
|
+
{num}{ident} { [:DIMENSION, text] }
|
48
|
+
<!-- { [:CDO, text] }
|
49
|
+
--> { [:CDC, text] }
|
50
|
+
{w}\/\/ { [:DOUBLESLASH, text] }
|
51
|
+
{w}\/ { [:SLASH, text] }
|
52
|
+
|
53
|
+
U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})? {[:UNICODE_RANGE, text] }
|
54
|
+
|
55
|
+
{Comment} /* ignore comments */
|
56
|
+
[\s\t\r\n\f]+ { [:S, text] }
|
57
|
+
[\.*:\[\]=\)] { [text, text] }
|
58
|
+
{string} { [:STRING, text] }
|
59
|
+
{invalid} { [:INVALID, text] }
|
60
|
+
. { [text, text] }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module CSS
|
3
|
+
class XPathVisitor
|
4
|
+
def visit_function node
|
5
|
+
# note that nth-child and nth-last-child are preprocessed in css/node.rb.
|
6
|
+
case node.value.first
|
7
|
+
when /^text\(/
|
8
|
+
'child::text()'
|
9
|
+
when /^self\(/
|
10
|
+
"self::#{node.value[1]}"
|
11
|
+
when /^(eq|nth|nth-of-type|nth-child)\(/
|
12
|
+
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
|
13
|
+
an_plus_b(node.value[1])
|
14
|
+
else
|
15
|
+
"position() = " + node.value[1]
|
16
|
+
end
|
17
|
+
when /^(first|first-of-type)\(/
|
18
|
+
"position() = 1"
|
19
|
+
when /^(last|last-of-type)\(/
|
20
|
+
"position() = last()"
|
21
|
+
when /^(nth-last-child|nth-last-of-type)\(/
|
22
|
+
"position() = last() - #{node.value[1]}"
|
23
|
+
when /^contains\(/
|
24
|
+
"contains(., #{node.value[1]})"
|
25
|
+
when /^gt\(/
|
26
|
+
"position() > #{node.value[1]}"
|
27
|
+
when /^only-child\(/
|
28
|
+
"last() = 1"
|
29
|
+
else
|
30
|
+
node.value.first + ')'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def visit_not node
|
35
|
+
'not(' + node.value.first.accept(self) + ')'
|
36
|
+
end
|
37
|
+
|
38
|
+
def visit_preceding_selector node
|
39
|
+
node.value.last.accept(self) +
|
40
|
+
'[preceding-sibling::' +
|
41
|
+
node.value.first.accept(self) +
|
42
|
+
']'
|
43
|
+
end
|
44
|
+
|
45
|
+
def visit_direct_adjacent_selector node
|
46
|
+
node.value.last.accept(self) +
|
47
|
+
'[preceding-sibling::' +
|
48
|
+
node.value.first.accept(self) +
|
49
|
+
'][position()=1]'
|
50
|
+
end
|
51
|
+
|
52
|
+
def visit_id node
|
53
|
+
node.value.first =~ /^#(.*)$/
|
54
|
+
"@id = '#{$1}'"
|
55
|
+
end
|
56
|
+
|
57
|
+
def visit_attribute_condition node
|
58
|
+
attribute = if (node.value.first.type == :FUNCTION) or (node.value.first.value.first =~ /::/)
|
59
|
+
''
|
60
|
+
else
|
61
|
+
'@'
|
62
|
+
end
|
63
|
+
attribute += node.value.first.accept(self)
|
64
|
+
|
65
|
+
# Support non-standard css
|
66
|
+
attribute.gsub!(/^@@/, '@')
|
67
|
+
|
68
|
+
return attribute unless node.value.length == 3
|
69
|
+
|
70
|
+
value = node.value.last
|
71
|
+
value = "'#{value}'" if value !~ /^['"]/
|
72
|
+
|
73
|
+
case node.value[1]
|
74
|
+
when '*='
|
75
|
+
"contains(#{attribute}, #{value})"
|
76
|
+
when '^='
|
77
|
+
"starts-with(#{attribute}, #{value})"
|
78
|
+
when '|='
|
79
|
+
"#{attribute} = #{value} or starts-with(#{attribute}, concat(#{value}, '-'))"
|
80
|
+
when '~='
|
81
|
+
"contains(concat(\" \", #{attribute}, \" \"),concat(\" \", #{value}, \" \"))"
|
82
|
+
when '$='
|
83
|
+
"substring(#{attribute}, string-length(#{attribute}) - " +
|
84
|
+
"string-length(#{value}) + 1, string-length(#{value})) = #{value}"
|
85
|
+
else
|
86
|
+
attribute + " #{node.value[1]} " + "#{value}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def visit_pseudo_class node
|
91
|
+
if node.value.first.is_a?(Nokogiri::CSS::Node) and node.value.first.type == :FUNCTION
|
92
|
+
node.value.first.accept(self)
|
93
|
+
else
|
94
|
+
case node.value.first
|
95
|
+
when "first" then "position() = 1"
|
96
|
+
when "last" then "position() = last()"
|
97
|
+
when "first-of-type" then "position() = 1"
|
98
|
+
when "last-of-type" then "position() = last()"
|
99
|
+
when "only-of-type" then "last() = 1"
|
100
|
+
when "empty" then "not(node())"
|
101
|
+
when "parent" then "node()"
|
102
|
+
else
|
103
|
+
'1 = 1'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def visit_class_condition node
|
109
|
+
"contains(concat(' ', @class, ' '),concat(' ', '#{node.value.first}', ' '))"
|
110
|
+
end
|
111
|
+
|
112
|
+
def visit_combinator node
|
113
|
+
node.value.first.accept(self) + ' and ' +
|
114
|
+
node.value.last.accept(self)
|
115
|
+
end
|
116
|
+
|
117
|
+
def visit_conditional_selector node
|
118
|
+
node.value.first.accept(self) + '[' +
|
119
|
+
node.value.last.accept(self) + ']'
|
120
|
+
end
|
121
|
+
|
122
|
+
def visit_descendant_selector node
|
123
|
+
node.value.first.accept(self) +
|
124
|
+
'//' +
|
125
|
+
node.value.last.accept(self)
|
126
|
+
end
|
127
|
+
|
128
|
+
def visit_child_selector node
|
129
|
+
node.value.first.accept(self) +
|
130
|
+
'/' +
|
131
|
+
node.value.last.accept(self)
|
132
|
+
end
|
133
|
+
|
134
|
+
def visit_element_name node
|
135
|
+
node.value.first
|
136
|
+
end
|
137
|
+
|
138
|
+
def accept node
|
139
|
+
node.accept(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
def an_plus_b node
|
144
|
+
raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
|
145
|
+
|
146
|
+
a = node.value[0].to_i
|
147
|
+
b = node.value[3].to_i
|
148
|
+
|
149
|
+
if (b == 0)
|
150
|
+
return "(position() mod #{a}) = 0"
|
151
|
+
else
|
152
|
+
compare = (a < 0) ? "<=" : ">="
|
153
|
+
return "(position() #{compare} #{b}) and (((position()-#{b}) mod #{a.abs}) = 0)"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/merb-core/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: merb-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-11-03 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -215,7 +215,6 @@ files:
|
|
215
215
|
- lib/merb-core/test/helpers/multipart_request_helper.rb
|
216
216
|
- lib/merb-core/test/helpers/request_helper.rb
|
217
217
|
- lib/merb-core/test/helpers/route_helper.rb
|
218
|
-
- lib/merb-core/test/helpers/view_helper.rb
|
219
218
|
- lib/merb-core/test/helpers.rb
|
220
219
|
- lib/merb-core/test/matchers
|
221
220
|
- lib/merb-core/test/matchers/controller_matchers.rb
|
@@ -223,6 +222,7 @@ files:
|
|
223
222
|
- lib/merb-core/test/matchers/route_matchers.rb
|
224
223
|
- lib/merb-core/test/matchers/view_matchers.rb
|
225
224
|
- lib/merb-core/test/matchers.rb
|
225
|
+
- lib/merb-core/test/run_spec.rb
|
226
226
|
- lib/merb-core/test/run_specs.rb
|
227
227
|
- lib/merb-core/test/tasks
|
228
228
|
- lib/merb-core/test/tasks/spectasks.rb
|
@@ -231,7 +231,20 @@ files:
|
|
231
231
|
- lib/merb-core/test/test_ext/object.rb
|
232
232
|
- lib/merb-core/test/test_ext/rspec.rb
|
233
233
|
- lib/merb-core/test/test_ext/string.rb
|
234
|
+
- lib/merb-core/test/webrat.rb
|
234
235
|
- lib/merb-core/test.rb
|
236
|
+
- lib/merb-core/vendor
|
237
|
+
- lib/merb-core/vendor/nokogiri
|
238
|
+
- lib/merb-core/vendor/nokogiri/css
|
239
|
+
- lib/merb-core/vendor/nokogiri/css/generated_parser.rb
|
240
|
+
- lib/merb-core/vendor/nokogiri/css/generated_tokenizer.rb
|
241
|
+
- lib/merb-core/vendor/nokogiri/css/node.rb
|
242
|
+
- lib/merb-core/vendor/nokogiri/css/parser.rb
|
243
|
+
- lib/merb-core/vendor/nokogiri/css/parser.y
|
244
|
+
- lib/merb-core/vendor/nokogiri/css/tokenizer.rb
|
245
|
+
- lib/merb-core/vendor/nokogiri/css/tokenizer.rex
|
246
|
+
- lib/merb-core/vendor/nokogiri/css/xpath_visitor.rb
|
247
|
+
- lib/merb-core/vendor/nokogiri/css.rb
|
235
248
|
- lib/merb-core/version.rb
|
236
249
|
- lib/merb-core.rb
|
237
250
|
has_rdoc: true
|
@@ -256,7 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
269
|
requirements:
|
257
270
|
- install the json gem to get faster json parsing
|
258
271
|
rubyforge_project:
|
259
|
-
rubygems_version: 1.3.
|
272
|
+
rubygems_version: 1.3.1
|
260
273
|
signing_key:
|
261
274
|
specification_version: 2
|
262
275
|
summary: Merb. Pocket rocket web framework.
|
@@ -1,121 +0,0 @@
|
|
1
|
-
module Merb
|
2
|
-
module Test
|
3
|
-
module ViewHelper
|
4
|
-
|
5
|
-
# Small utility class for working with the Hpricot parser class
|
6
|
-
class DocumentOutput
|
7
|
-
|
8
|
-
# ==== Parameters
|
9
|
-
# response_body<String>:: The response body to parse with Hpricot.
|
10
|
-
def initialize(response_body)
|
11
|
-
@parser = Hpricot.parse(response_body)
|
12
|
-
end
|
13
|
-
|
14
|
-
# ==== Parameters
|
15
|
-
# css_query<String>::
|
16
|
-
# A CSS query to find the element for, e.g. "ul.links".
|
17
|
-
#
|
18
|
-
# ==== Returns
|
19
|
-
# String:: The content of the first tag matching the query.
|
20
|
-
def content_for(css_query)
|
21
|
-
match = @parser.search(css_query).first
|
22
|
-
match.inner_text unless match.nil?
|
23
|
-
end
|
24
|
-
|
25
|
-
# ==== Parameters
|
26
|
-
# css_query<String>:: A CSS query to find the elements for.
|
27
|
-
#
|
28
|
-
# ==== Returns
|
29
|
-
# Array[String]:: Content of all tags matching the query.
|
30
|
-
def content_for_all(css_query)
|
31
|
-
matches = @parser.search(css_query).collect{|ele| ele.inner_text}
|
32
|
-
end
|
33
|
-
|
34
|
-
# ==== Parameters
|
35
|
-
# css_query<String>:: A CSS query to find the elements for.
|
36
|
-
#
|
37
|
-
# ==== Returns
|
38
|
-
# Hpricot::Elements:: All tags matching the query.
|
39
|
-
def [](css_query)
|
40
|
-
@parser.search(css_query)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# ==== Parameters
|
45
|
-
# css_query<String>:: A CSS query to find the element for.
|
46
|
-
# output<DocumentOutput>::
|
47
|
-
# The output to look for the element in. Defaults to process_output.
|
48
|
-
#
|
49
|
-
# ==== Returns
|
50
|
-
# String:: The content of the first tag matching the query.
|
51
|
-
def tag(css_query, output = process_output)
|
52
|
-
output.content_for(css_query)
|
53
|
-
end
|
54
|
-
|
55
|
-
# ==== Parameters
|
56
|
-
# css_query<String>:: A CSS query to find the elements for.
|
57
|
-
# output<DocumentOutput>::
|
58
|
-
# The output to look for the element in. Defaults to process_output.
|
59
|
-
#
|
60
|
-
# ==== Returns
|
61
|
-
# Array[String]:: Content of all tags matching the query.
|
62
|
-
def tags(css_query, output = process_output)
|
63
|
-
output.content_for_all(css_query)
|
64
|
-
end
|
65
|
-
|
66
|
-
# ==== Parameters
|
67
|
-
# css_query<String>:: A CSS query to find the element for.
|
68
|
-
# output<DocumentOutput>::
|
69
|
-
# The output to look for the element in. Defaults to process_output.
|
70
|
-
#
|
71
|
-
# ==== Returns
|
72
|
-
# Hpricot::Elem:: The first tag matching the query.
|
73
|
-
def element(css_query, output = process_output)
|
74
|
-
output[css_query].first
|
75
|
-
end
|
76
|
-
|
77
|
-
# ==== Parameters
|
78
|
-
# css_query<String>:: A CSS query to find the elements for.
|
79
|
-
# output<DocumentOutput>::
|
80
|
-
# The output to look for the elements in. Defaults to process_output.
|
81
|
-
#
|
82
|
-
# ==== Returns
|
83
|
-
# Array[Hpricot::Elem]:: All tags matching the query.
|
84
|
-
def elements(css_query, output = process_output)
|
85
|
-
Hpricot::Elements[*css_query.to_s.split(",").map{|s| s.strip}.map do |query|
|
86
|
-
output[query]
|
87
|
-
end.flatten]
|
88
|
-
end
|
89
|
-
|
90
|
-
# ==== Parameters
|
91
|
-
# css_query<String>:: A CSS query to find the elements for.
|
92
|
-
# text<String, Regexp>:: A pattern to match tag contents for.
|
93
|
-
# output<DocumentOutput>::
|
94
|
-
# The output to look for the elements in. Defaults to process_output.
|
95
|
-
#
|
96
|
-
# ==== Returns
|
97
|
-
# Array[Hpricot::Elem]:: All tags matching the query and pattern.
|
98
|
-
def get_elements(css_query, text, output = nil)
|
99
|
-
els = elements(*[css_query, output].compact)
|
100
|
-
case text
|
101
|
-
when String then els.reject {|t| !t.contains?(text) }
|
102
|
-
when Regexp then els.reject {|t| !t.matches?(text) }
|
103
|
-
else []
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
protected
|
108
|
-
|
109
|
-
# ==== Returns
|
110
|
-
# DocumentOutput:: Document output from the response body.
|
111
|
-
def process_output
|
112
|
-
return @output unless @output.nil?
|
113
|
-
return @output = DocumentOutput.new(@response_output) unless @response_output.nil?
|
114
|
-
|
115
|
-
raise "The response output was not in its usual places, please provide the output" if @controller.nil? || @controller.body.empty?
|
116
|
-
@response_output = @controller.body
|
117
|
-
@output = DocumentOutput.new(@controller.body)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|