Moving over Nokogiri extensions and vendoring nokogiri CSS support for people without nokogiri installed
This commit is contained in:
parent
11f291ceb3
commit
a8e0e7578a
@ -6,9 +6,10 @@ module Webrat
|
|||||||
# Require nokogiri and fall back on rexml
|
# Require nokogiri and fall back on rexml
|
||||||
begin
|
begin
|
||||||
require "nokogiri"
|
require "nokogiri"
|
||||||
|
require "webrat/nokogiri"
|
||||||
rescue LoadError => e
|
rescue LoadError => e
|
||||||
if require "rexml/document"
|
if require "rexml/document"
|
||||||
require "merb-core/vendor/nokogiri/css"
|
require "webrat/vendor/nokogiri/css"
|
||||||
warn("Standard REXML library is slow. Please consider installing nokogiri.\nUse \"sudo gem install nokogiri\"")
|
warn("Standard REXML library is slow. Please consider installing nokogiri.\nUse \"sudo gem install nokogiri\"")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
15
lib/webrat/nokogiri.rb
Normal file
15
lib/webrat/nokogiri.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class XPathVisitor
|
||||||
|
|
||||||
|
def visit_pseudo_class_text(node)
|
||||||
|
"@type='text'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_pseudo_class_password(node)
|
||||||
|
"@type='password'"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
6
lib/webrat/vendor/nokogiri/css.rb
vendored
Normal file
6
lib/webrat/vendor/nokogiri/css.rb
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
require 'merb-core/vendor/nokogiri/css/node'
|
||||||
|
require 'merb-core/vendor/nokogiri/css/xpath_visitor'
|
||||||
|
require 'merb-core/vendor/nokogiri/css/generated_tokenizer'
|
||||||
|
require 'merb-core/vendor/nokogiri/css/generated_parser'
|
||||||
|
require 'merb-core/vendor/nokogiri/css/tokenizer'
|
||||||
|
require 'merb-core/vendor/nokogiri/css/parser'
|
653
lib/webrat/vendor/nokogiri/css/generated_parser.rb
vendored
Normal file
653
lib/webrat/vendor/nokogiri/css/generated_parser.rb
vendored
Normal file
@ -0,0 +1,653 @@
|
|||||||
|
#
|
||||||
|
# DO NOT MODIFY!!!!
|
||||||
|
# This file is automatically generated by racc 1.4.5
|
||||||
|
# from racc grammer file "lib/nokogiri/css/parser.y".
|
||||||
|
#
|
||||||
|
|
||||||
|
require 'racc/parser'
|
||||||
|
|
||||||
|
|
||||||
|
module Nokogiri
|
||||||
|
|
||||||
|
module CSS
|
||||||
|
|
||||||
|
class GeneratedParser < Racc::Parser
|
||||||
|
|
||||||
|
##### racc 1.4.5 generates ###
|
||||||
|
|
||||||
|
racc_reduce_table = [
|
||||||
|
0, 0, :racc_error,
|
||||||
|
4, 46, :_reduce_1,
|
||||||
|
1, 46, :_reduce_2,
|
||||||
|
2, 49, :_reduce_3,
|
||||||
|
2, 49, :_reduce_4,
|
||||||
|
2, 49, :_reduce_5,
|
||||||
|
1, 49, :_reduce_6,
|
||||||
|
2, 49, :_reduce_7,
|
||||||
|
2, 49, :_reduce_8,
|
||||||
|
2, 50, :_reduce_9,
|
||||||
|
2, 50, :_reduce_10,
|
||||||
|
1, 50, :_reduce_none,
|
||||||
|
2, 50, :_reduce_12,
|
||||||
|
1, 50, :_reduce_13,
|
||||||
|
3, 48, :_reduce_14,
|
||||||
|
1, 48, :_reduce_none,
|
||||||
|
2, 57, :_reduce_16,
|
||||||
|
1, 51, :_reduce_17,
|
||||||
|
1, 51, :_reduce_18,
|
||||||
|
6, 55, :_reduce_19,
|
||||||
|
6, 55, :_reduce_20,
|
||||||
|
5, 55, :_reduce_21,
|
||||||
|
2, 54, :_reduce_22,
|
||||||
|
3, 54, :_reduce_23,
|
||||||
|
3, 54, :_reduce_24,
|
||||||
|
3, 54, :_reduce_25,
|
||||||
|
1, 59, :_reduce_none,
|
||||||
|
1, 59, :_reduce_none,
|
||||||
|
4, 60, :_reduce_28,
|
||||||
|
3, 60, :_reduce_29,
|
||||||
|
2, 60, :_reduce_30,
|
||||||
|
1, 60, :_reduce_31,
|
||||||
|
2, 61, :_reduce_32,
|
||||||
|
2, 61, :_reduce_33,
|
||||||
|
1, 52, :_reduce_none,
|
||||||
|
0, 52, :_reduce_none,
|
||||||
|
2, 56, :_reduce_36,
|
||||||
|
2, 56, :_reduce_37,
|
||||||
|
2, 56, :_reduce_38,
|
||||||
|
2, 56, :_reduce_39,
|
||||||
|
1, 56, :_reduce_none,
|
||||||
|
1, 56, :_reduce_none,
|
||||||
|
1, 56, :_reduce_none,
|
||||||
|
1, 56, :_reduce_none,
|
||||||
|
1, 62, :_reduce_44,
|
||||||
|
4, 58, :_reduce_45,
|
||||||
|
4, 58, :_reduce_46,
|
||||||
|
0, 58, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
1, 63, :_reduce_none,
|
||||||
|
5, 53, :_reduce_55,
|
||||||
|
1, 64, :_reduce_none,
|
||||||
|
2, 47, :_reduce_none,
|
||||||
|
0, 47, :_reduce_none ]
|
||||||
|
|
||||||
|
racc_reduce_n = 59
|
||||||
|
|
||||||
|
racc_shift_n = 97
|
||||||
|
|
||||||
|
racc_action_table = [
|
||||||
|
5, 79, 81, 27, 10, 26, 94, 93, 42, 2,
|
||||||
|
42, 30, 56, 5, 5, 28, 79, 81, 10, 42,
|
||||||
|
42, 42, 47, 2, 51, 42, 42, 10, 82, 84,
|
||||||
|
85, 52, 78, 10, 10, 7, 9, 12, 15, 42,
|
||||||
|
10, 17, 77, 82, 84, 85, 10, 78, 7, 7,
|
||||||
|
9, 12, 15, 42, 5, 17, 68, 77, 10, 9,
|
||||||
|
69, 15, 10, 2, 17, 9, 9, 15, 15, 50,
|
||||||
|
17, 17, 9, 5, 15, 26, 21, 17, 9, 54,
|
||||||
|
15, 23, 63, 17, 37, 38, 39, 64, 42, 7,
|
||||||
|
9, 12, 15, 44, 9, 17, 15, 42, 15, 17,
|
||||||
|
76, 42, 86, 31, 42, 89, 42, 25, 7, 91,
|
||||||
|
33, 92, 34, 35, 53, 42, 42 ]
|
||||||
|
|
||||||
|
racc_action_check = [
|
||||||
|
0, 73, 73, 6, 0, 7, 90, 90, 63, 0,
|
||||||
|
28, 7, 29, 17, 55, 6, 71, 71, 55, 33,
|
||||||
|
34, 35, 17, 55, 22, 37, 38, 4, 73, 73,
|
||||||
|
73, 23, 73, 1, 11, 0, 0, 0, 0, 42,
|
||||||
|
67, 0, 73, 71, 71, 71, 14, 71, 17, 55,
|
||||||
|
55, 55, 55, 44, 36, 55, 50, 71, 36, 4,
|
||||||
|
52, 4, 16, 36, 4, 1, 11, 1, 11, 21,
|
||||||
|
1, 11, 67, 41, 67, 5, 5, 67, 14, 27,
|
||||||
|
14, 5, 41, 14, 13, 13, 13, 41, 64, 36,
|
||||||
|
36, 36, 36, 16, 16, 36, 16, 65, 18, 16,
|
||||||
|
69, 15, 72, 9, 75, 80, 83, 5, 41, 87,
|
||||||
|
13, 88, 13, 13, 24, 93, 94 ]
|
||||||
|
|
||||||
|
racc_action_pointer = [
|
||||||
|
-2, 27, nil, nil, 21, 65, 3, -5, nil, 92,
|
||||||
|
nil, 28, nil, 77, 40, 92, 56, 11, 58, nil,
|
||||||
|
nil, 62, -18, 20, 72, nil, nil, 79, 1, -30,
|
||||||
|
nil, nil, nil, 10, 11, 12, 52, 16, 17, nil,
|
||||||
|
nil, 71, 30, nil, 44, nil, nil, nil, nil, nil,
|
||||||
|
40, nil, 53, nil, nil, 12, nil, nil, nil, nil,
|
||||||
|
nil, nil, nil, -1, 79, 88, nil, 34, nil, 84,
|
||||||
|
nil, 13, 61, -2, nil, 95, nil, nil, nil, nil,
|
||||||
|
64, nil, nil, 97, nil, nil, nil, 68, 69, nil,
|
||||||
|
-4, nil, nil, 106, 107, nil, nil ]
|
||||||
|
|
||||||
|
racc_action_default = [
|
||||||
|
-59, -42, -17, -13, -41, -59, -59, -59, -2, -59,
|
||||||
|
-44, -43, -18, -15, -40, -58, -35, -59, -11, -38,
|
||||||
|
-37, -31, -59, -26, -59, -22, -27, -59, -58, -59,
|
||||||
|
-26, -16, -39, -58, -58, -58, -59, -58, -58, -6,
|
||||||
|
-36, -59, -58, -34, -58, -9, -10, -33, -32, -12,
|
||||||
|
-59, -23, -30, -24, 97, -59, -25, -5, -8, -7,
|
||||||
|
-14, -3, -4, -58, -58, -58, -57, -59, -29, -59,
|
||||||
|
-1, -47, -59, -47, -56, -58, -28, -48, -52, -53,
|
||||||
|
-59, -54, -49, -58, -50, -51, -21, -59, -59, -19,
|
||||||
|
-59, -20, -55, -58, -58, -45, -46 ]
|
||||||
|
|
||||||
|
racc_goto_table = [
|
||||||
|
41, 19, 8, 80, 20, 87, 48, 22, 6, 29,
|
||||||
|
49, 32, 46, 55, 40, 45, 43, 36, 57, 58,
|
||||||
|
59, 24, 61, 62, 75, nil, nil, 66, nil, 67,
|
||||||
|
65, nil, nil, nil, nil, nil, nil, nil, 60, nil,
|
||||||
|
nil, nil, nil, nil, nil, nil, nil, nil, 71, 72,
|
||||||
|
73, nil, nil, nil, nil, nil, nil, 70, nil, nil,
|
||||||
|
88, nil, nil, nil, nil, nil, nil, 74, 90, nil,
|
||||||
|
nil, nil, nil, nil, nil, nil, nil, nil, 95, 96 ]
|
||||||
|
|
||||||
|
racc_goto_check = [
|
||||||
|
2, 11, 3, 13, 11, 13, 9, 14, 1, 14,
|
||||||
|
10, 11, 8, 2, 11, 7, 11, 4, 2, 2,
|
||||||
|
2, 15, 2, 2, 19, nil, nil, 2, nil, 2,
|
||||||
|
9, nil, nil, nil, nil, nil, nil, nil, 3, nil,
|
||||||
|
nil, nil, nil, nil, nil, nil, nil, nil, 2, 2,
|
||||||
|
2, nil, nil, nil, nil, nil, nil, 3, nil, nil,
|
||||||
|
2, nil, nil, nil, nil, nil, nil, 11, 2, nil,
|
||||||
|
nil, nil, nil, nil, nil, nil, nil, nil, 2, 2 ]
|
||||||
|
|
||||||
|
racc_goto_pointer = [
|
||||||
|
nil, 8, -15, 2, 4, nil, nil, -1, -4, -11,
|
||||||
|
-8, 0, nil, -68, 2, 16, nil, nil, nil, -43 ]
|
||||||
|
|
||||||
|
racc_goto_default = [
|
||||||
|
nil, nil, nil, nil, nil, 13, 16, nil, nil, 18,
|
||||||
|
1, 3, 4, nil, nil, nil, 11, 14, 83, nil ]
|
||||||
|
|
||||||
|
racc_token_table = {
|
||||||
|
false => 0,
|
||||||
|
Object.new => 1,
|
||||||
|
:FUNCTION => 2,
|
||||||
|
:INCLUDES => 3,
|
||||||
|
:DASHMATCH => 4,
|
||||||
|
:LBRACE => 5,
|
||||||
|
:HASH => 6,
|
||||||
|
:PLUS => 7,
|
||||||
|
:GREATER => 8,
|
||||||
|
:S => 9,
|
||||||
|
:STRING => 10,
|
||||||
|
:IDENT => 11,
|
||||||
|
:COMMA => 12,
|
||||||
|
:URI => 13,
|
||||||
|
:CDO => 14,
|
||||||
|
:CDC => 15,
|
||||||
|
:NUMBER => 16,
|
||||||
|
:PERCENTAGE => 17,
|
||||||
|
:LENGTH => 18,
|
||||||
|
:EMS => 19,
|
||||||
|
:EXS => 20,
|
||||||
|
:ANGLE => 21,
|
||||||
|
:TIME => 22,
|
||||||
|
:FREQ => 23,
|
||||||
|
:IMPORTANT_SYM => 24,
|
||||||
|
:IMPORT_SYM => 25,
|
||||||
|
:MEDIA_SYM => 26,
|
||||||
|
:PAGE_SYM => 27,
|
||||||
|
:CHARSET_SYM => 28,
|
||||||
|
:DIMENSION => 29,
|
||||||
|
:PREFIXMATCH => 30,
|
||||||
|
:SUFFIXMATCH => 31,
|
||||||
|
:SUBSTRINGMATCH => 32,
|
||||||
|
:TILDE => 33,
|
||||||
|
:NOT_EQUAL => 34,
|
||||||
|
:SLASH => 35,
|
||||||
|
:DOUBLESLASH => 36,
|
||||||
|
:NOT => 37,
|
||||||
|
"." => 38,
|
||||||
|
"*" => 39,
|
||||||
|
"[" => 40,
|
||||||
|
"]" => 41,
|
||||||
|
")" => 42,
|
||||||
|
":" => 43,
|
||||||
|
"=" => 44 }
|
||||||
|
|
||||||
|
racc_use_result_var = true
|
||||||
|
|
||||||
|
racc_nt_base = 45
|
||||||
|
|
||||||
|
Racc_arg = [
|
||||||
|
racc_action_table,
|
||||||
|
racc_action_check,
|
||||||
|
racc_action_default,
|
||||||
|
racc_action_pointer,
|
||||||
|
racc_goto_table,
|
||||||
|
racc_goto_check,
|
||||||
|
racc_goto_default,
|
||||||
|
racc_goto_pointer,
|
||||||
|
racc_nt_base,
|
||||||
|
racc_reduce_table,
|
||||||
|
racc_token_table,
|
||||||
|
racc_shift_n,
|
||||||
|
racc_reduce_n,
|
||||||
|
racc_use_result_var ]
|
||||||
|
|
||||||
|
Racc_token_to_s_table = [
|
||||||
|
'$end',
|
||||||
|
'error',
|
||||||
|
'FUNCTION',
|
||||||
|
'INCLUDES',
|
||||||
|
'DASHMATCH',
|
||||||
|
'LBRACE',
|
||||||
|
'HASH',
|
||||||
|
'PLUS',
|
||||||
|
'GREATER',
|
||||||
|
'S',
|
||||||
|
'STRING',
|
||||||
|
'IDENT',
|
||||||
|
'COMMA',
|
||||||
|
'URI',
|
||||||
|
'CDO',
|
||||||
|
'CDC',
|
||||||
|
'NUMBER',
|
||||||
|
'PERCENTAGE',
|
||||||
|
'LENGTH',
|
||||||
|
'EMS',
|
||||||
|
'EXS',
|
||||||
|
'ANGLE',
|
||||||
|
'TIME',
|
||||||
|
'FREQ',
|
||||||
|
'IMPORTANT_SYM',
|
||||||
|
'IMPORT_SYM',
|
||||||
|
'MEDIA_SYM',
|
||||||
|
'PAGE_SYM',
|
||||||
|
'CHARSET_SYM',
|
||||||
|
'DIMENSION',
|
||||||
|
'PREFIXMATCH',
|
||||||
|
'SUFFIXMATCH',
|
||||||
|
'SUBSTRINGMATCH',
|
||||||
|
'TILDE',
|
||||||
|
'NOT_EQUAL',
|
||||||
|
'SLASH',
|
||||||
|
'DOUBLESLASH',
|
||||||
|
'NOT',
|
||||||
|
'"."',
|
||||||
|
'"*"',
|
||||||
|
'"["',
|
||||||
|
'"]"',
|
||||||
|
'")"',
|
||||||
|
'":"',
|
||||||
|
'"="',
|
||||||
|
'$start',
|
||||||
|
'selector',
|
||||||
|
's_0toN',
|
||||||
|
'simple_selector_1toN',
|
||||||
|
'combinator',
|
||||||
|
'simple_selector',
|
||||||
|
'element_name',
|
||||||
|
'hcap_0toN',
|
||||||
|
'negation',
|
||||||
|
'function',
|
||||||
|
'attrib',
|
||||||
|
'hcap_1toN',
|
||||||
|
'class',
|
||||||
|
'attrib_val_0or1',
|
||||||
|
'expr',
|
||||||
|
'an_plus_b',
|
||||||
|
'pseudo',
|
||||||
|
'attribute_id',
|
||||||
|
'eql_incl_dash',
|
||||||
|
'negation_arg']
|
||||||
|
|
||||||
|
Racc_debug_parser = false
|
||||||
|
|
||||||
|
##### racc system variables end #####
|
||||||
|
|
||||||
|
# reduce 0 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 13
|
||||||
|
def _reduce_1( val, _values, result )
|
||||||
|
result = [val.first, val.last].flatten
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 13
|
||||||
|
def _reduce_2( val, _values, result )
|
||||||
|
result = val.flatten
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 16
|
||||||
|
def _reduce_3( val, _values, result )
|
||||||
|
result = :DIRECT_ADJACENT_SELECTOR
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 17
|
||||||
|
def _reduce_4( val, _values, result )
|
||||||
|
result = :CHILD_SELECTOR
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 18
|
||||||
|
def _reduce_5( val, _values, result )
|
||||||
|
result = :PRECEDING_SELECTOR
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 19
|
||||||
|
def _reduce_6( val, _values, result )
|
||||||
|
result = :DESCENDANT_SELECTOR
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 20
|
||||||
|
def _reduce_7( val, _values, result )
|
||||||
|
result = :DESCENDANT_SELECTOR
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 21
|
||||||
|
def _reduce_8( val, _values, result )
|
||||||
|
result = :CHILD_SELECTOR
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 31
|
||||||
|
def _reduce_9( val, _values, result )
|
||||||
|
result = if val[1].nil?
|
||||||
|
val.first
|
||||||
|
else
|
||||||
|
Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 34
|
||||||
|
def _reduce_10( val, _values, result )
|
||||||
|
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 11 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 38
|
||||||
|
def _reduce_12( val, _values, result )
|
||||||
|
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 43
|
||||||
|
def _reduce_13( val, _values, result )
|
||||||
|
result = Node.new(:CONDITIONAL_SELECTOR,
|
||||||
|
[Node.new(:ELEMENT_NAME, ['*']), val.first]
|
||||||
|
)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 48
|
||||||
|
def _reduce_14( val, _values, result )
|
||||||
|
result = Node.new(val[1], [val.first, val.last])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 15 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 51
|
||||||
|
def _reduce_16( val, _values, result )
|
||||||
|
result = Node.new(:CLASS_CONDITION, [val[1]])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 54
|
||||||
|
def _reduce_17( val, _values, result )
|
||||||
|
result = Node.new(:ELEMENT_NAME, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 55
|
||||||
|
def _reduce_18( val, _values, result )
|
||||||
|
result = Node.new(:ELEMENT_NAME, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 63
|
||||||
|
def _reduce_19( val, _values, result )
|
||||||
|
result = Node.new(:ATTRIBUTE_CONDITION,
|
||||||
|
[Node.new(:ELEMENT_NAME, [val[2]])] + (val[4] || [])
|
||||||
|
)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 68
|
||||||
|
def _reduce_20( val, _values, result )
|
||||||
|
result = Node.new(:ATTRIBUTE_CONDITION,
|
||||||
|
[val[2]] + (val[4] || [])
|
||||||
|
)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 74
|
||||||
|
def _reduce_21( val, _values, result )
|
||||||
|
# Non standard, but hpricot supports it.
|
||||||
|
result = Node.new(:PSEUDO_CLASS,
|
||||||
|
[Node.new(:FUNCTION, ['nth-child(', val[2]])]
|
||||||
|
)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 79
|
||||||
|
def _reduce_22( val, _values, result )
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 82
|
||||||
|
def _reduce_23( val, _values, result )
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 85
|
||||||
|
def _reduce_24( val, _values, result )
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 88
|
||||||
|
def _reduce_25( val, _values, result )
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 26 omitted
|
||||||
|
|
||||||
|
# reduce 27 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 102
|
||||||
|
def _reduce_28( val, _values, result )
|
||||||
|
if val[1] == 'n'
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 113
|
||||||
|
def _reduce_29( val, _values, result )
|
||||||
|
# n+3, -n+3
|
||||||
|
if val[0] == 'n'
|
||||||
|
val.unshift("1")
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
elsif val[0] == '-n'
|
||||||
|
val[0] = 'n'
|
||||||
|
val.unshift("-1")
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 124
|
||||||
|
def _reduce_30( val, _values, result )
|
||||||
|
if val[1] == 'n'
|
||||||
|
val << "+"
|
||||||
|
val << "0"
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 136
|
||||||
|
def _reduce_31( val, _values, result )
|
||||||
|
if val[0] == 'even'
|
||||||
|
val = ["2","n","+","0"]
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
elsif val[0] == 'odd'
|
||||||
|
val = ["2","n","+","1"]
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[0]}'"
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 141
|
||||||
|
def _reduce_32( val, _values, result )
|
||||||
|
result = Node.new(:PSEUDO_CLASS, [val[1]])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 141
|
||||||
|
def _reduce_33( val, _values, result )
|
||||||
|
result = Node.new(:PSEUDO_CLASS, [val[1]])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 34 omitted
|
||||||
|
|
||||||
|
# reduce 35 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 151
|
||||||
|
def _reduce_36( val, _values, result )
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 154
|
||||||
|
def _reduce_37( val, _values, result )
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 157
|
||||||
|
def _reduce_38( val, _values, result )
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 160
|
||||||
|
def _reduce_39( val, _values, result )
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 40 omitted
|
||||||
|
|
||||||
|
# reduce 41 omitted
|
||||||
|
|
||||||
|
# reduce 42 omitted
|
||||||
|
|
||||||
|
# reduce 43 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 166
|
||||||
|
def _reduce_44( val, _values, result )
|
||||||
|
result = Node.new(:ID, val)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 169
|
||||||
|
def _reduce_45( val, _values, result )
|
||||||
|
result = [val.first, val[2]]
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 170
|
||||||
|
def _reduce_46( val, _values, result )
|
||||||
|
result = [val.first, val[2]]
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 47 omitted
|
||||||
|
|
||||||
|
# reduce 48 omitted
|
||||||
|
|
||||||
|
# reduce 49 omitted
|
||||||
|
|
||||||
|
# reduce 50 omitted
|
||||||
|
|
||||||
|
# reduce 51 omitted
|
||||||
|
|
||||||
|
# reduce 52 omitted
|
||||||
|
|
||||||
|
# reduce 53 omitted
|
||||||
|
|
||||||
|
# reduce 54 omitted
|
||||||
|
|
||||||
|
module_eval <<'.,.,', 'lib/nokogiri/css/parser.y', 186
|
||||||
|
def _reduce_55( val, _values, result )
|
||||||
|
result = Node.new(:NOT, [val[2]])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
.,.,
|
||||||
|
|
||||||
|
# reduce 56 omitted
|
||||||
|
|
||||||
|
# reduce 57 omitted
|
||||||
|
|
||||||
|
# reduce 58 omitted
|
||||||
|
|
||||||
|
def _reduce_none( val, _values, result )
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
end # class GeneratedParser
|
||||||
|
|
||||||
|
end # module CSS
|
||||||
|
|
||||||
|
end # module Nokogiri
|
159
lib/webrat/vendor/nokogiri/css/generated_tokenizer.rb
vendored
Normal file
159
lib/webrat/vendor/nokogiri/css/generated_tokenizer.rb
vendored
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#
|
||||||
|
# DO NOT MODIFY!!!!
|
||||||
|
# This file is automatically generated by rex 1.0.1
|
||||||
|
# from lexical definition file "lib/nokogiri/css/tokenizer.rex".
|
||||||
|
#
|
||||||
|
|
||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class GeneratedTokenizer
|
||||||
|
require 'strscan'
|
||||||
|
|
||||||
|
class ScanError < StandardError ; end
|
||||||
|
|
||||||
|
attr_reader :lineno
|
||||||
|
attr_reader :filename
|
||||||
|
|
||||||
|
def scan_setup ; end
|
||||||
|
|
||||||
|
def action &block
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
|
||||||
|
def scan_str( str )
|
||||||
|
scan_evaluate str
|
||||||
|
do_parse
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_file( filename )
|
||||||
|
@filename = filename
|
||||||
|
open(filename, "r") do |f|
|
||||||
|
scan_evaluate f.read
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def scan_file( filename )
|
||||||
|
load_file filename
|
||||||
|
do_parse
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_token
|
||||||
|
@rex_tokens.shift
|
||||||
|
end
|
||||||
|
|
||||||
|
def scan_evaluate( str )
|
||||||
|
scan_setup
|
||||||
|
@rex_tokens = []
|
||||||
|
@lineno = 1
|
||||||
|
ss = StringScanner.new(str)
|
||||||
|
state = nil
|
||||||
|
until ss.eos?
|
||||||
|
text = ss.peek(1)
|
||||||
|
@lineno += 1 if text == "\n"
|
||||||
|
case state
|
||||||
|
when nil
|
||||||
|
case
|
||||||
|
when (text = ss.scan(/~=/i))
|
||||||
|
@rex_tokens.push action { [:INCLUDES, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\|=/i))
|
||||||
|
@rex_tokens.push action { [:DASHMATCH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\^=/i))
|
||||||
|
@rex_tokens.push action { [:PREFIXMATCH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\$=/i))
|
||||||
|
@rex_tokens.push action { [:SUFFIXMATCH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\*=/i))
|
||||||
|
@rex_tokens.push action { [:SUBSTRINGMATCH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/!=/i))
|
||||||
|
@rex_tokens.push action { [:NOT_EQUAL, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[-]?([_a-z]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])([_a-z0-9-]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*\(\s*/i))
|
||||||
|
@rex_tokens.push action { [:FUNCTION, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/@[-]?([_a-z]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])([_a-z0-9-]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*/i))
|
||||||
|
@rex_tokens.push action { [:IDENT, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[-]?([_a-z]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])([_a-z0-9-]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*/i))
|
||||||
|
@rex_tokens.push action { [:IDENT, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/i))
|
||||||
|
@rex_tokens.push action { [:NUMBER, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\#([_a-z0-9-]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])+/i))
|
||||||
|
@rex_tokens.push action { [:HASH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\r\n\f]*\+/i))
|
||||||
|
@rex_tokens.push action { [:PLUS, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\r\n\f]*>/i))
|
||||||
|
@rex_tokens.push action { [:GREATER, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\r\n\f]*,/i))
|
||||||
|
@rex_tokens.push action { [:COMMA, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\r\n\f]*~/i))
|
||||||
|
@rex_tokens.push action { [:TILDE, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\:not\(/i))
|
||||||
|
@rex_tokens.push action { [:NOT, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/@[-]?([_a-z]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])([_a-z0-9-]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*/i))
|
||||||
|
@rex_tokens.push action { [:ATKEYWORD, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)%/i))
|
||||||
|
@rex_tokens.push action { [:PERCENTAGE, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)[-]?([_a-z]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])([_a-z0-9-]|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*/i))
|
||||||
|
@rex_tokens.push action { [:DIMENSION, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/<!--/i))
|
||||||
|
@rex_tokens.push action { [:CDO, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/-->/i))
|
||||||
|
@rex_tokens.push action { [:CDC, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\r\n\f]*\/\//i))
|
||||||
|
@rex_tokens.push action { [:DOUBLESLASH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\r\n\f]*\//i))
|
||||||
|
@rex_tokens.push action { [:SLASH, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/i))
|
||||||
|
@rex_tokens.push action {[:UNICODE_RANGE, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\/\*(.|[\r\n])*?\*\//i))
|
||||||
|
;
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\s\t\r\n\f]+/i))
|
||||||
|
@rex_tokens.push action { [:S, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/[\.*:\[\]=\)]/i))
|
||||||
|
@rex_tokens.push action { [text, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/"([^\n\r\f"]|\\n|\r\n|\r|\f|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*"|'([^\n\r\f']|\\n|\r\n|\r|\f|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*'/i))
|
||||||
|
@rex_tokens.push action { [:STRING, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/\"([^\n\r\f\"]|\\n|\r\n|\r|\f|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*|([^\n\r\f\']|\\n|\r\n|\r|\f|[^\0-\177]|\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9a-f])*/i))
|
||||||
|
@rex_tokens.push action { [:INVALID, text] }
|
||||||
|
|
||||||
|
when (text = ss.scan(/./i))
|
||||||
|
@rex_tokens.push action { [text, text] }
|
||||||
|
|
||||||
|
else
|
||||||
|
text = ss.string[ss.pos .. -1]
|
||||||
|
raise ScanError, "can not match: '" + text + "'"
|
||||||
|
end # if
|
||||||
|
|
||||||
|
else
|
||||||
|
raise ScanError, "undefined state: '" + state.to_s + "'"
|
||||||
|
end # case state
|
||||||
|
end # until ss
|
||||||
|
end # def scan_evaluate
|
||||||
|
|
||||||
|
end # class
|
||||||
|
end
|
||||||
|
end
|
95
lib/webrat/vendor/nokogiri/css/node.rb
vendored
Normal file
95
lib/webrat/vendor/nokogiri/css/node.rb
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class Node
|
||||||
|
attr_accessor :type, :value
|
||||||
|
def initialize type, value
|
||||||
|
@type = type
|
||||||
|
@value = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def accept visitor
|
||||||
|
visitor.send(:"visit_#{type.to_s.downcase}", self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xpath prefix = '//', preprocess = true
|
||||||
|
self.preprocess! if preprocess
|
||||||
|
prefix + XPathVisitor.new.accept(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def preprocess!
|
||||||
|
### Deal with nth-child
|
||||||
|
matches = find_by_type(
|
||||||
|
[:CONDITIONAL_SELECTOR,
|
||||||
|
[:ELEMENT_NAME],
|
||||||
|
[:PSEUDO_CLASS,
|
||||||
|
[:FUNCTION]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
matches.each do |match|
|
||||||
|
if match.value[1].value[0].value[0] =~ /^nth-child/
|
||||||
|
tag_name = match.value[0].value.first
|
||||||
|
match.value[0].value = ['*']
|
||||||
|
match.value[1] = Node.new(:COMBINATOR, [
|
||||||
|
match.value[1].value[0],
|
||||||
|
Node.new(:FUNCTION, ['self(', tag_name])
|
||||||
|
])
|
||||||
|
end
|
||||||
|
if match.value[1].value[0].value[0] =~ /^nth-last-child/
|
||||||
|
tag_name = match.value[0].value.first
|
||||||
|
match.value[0].value = ['*']
|
||||||
|
match.value[1] = Node.new(:COMBINATOR, [
|
||||||
|
match.value[1].value[0],
|
||||||
|
Node.new(:FUNCTION, ['self(', tag_name])
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
### Deal with first-child, last-child
|
||||||
|
matches = find_by_type(
|
||||||
|
[:CONDITIONAL_SELECTOR,
|
||||||
|
[:ELEMENT_NAME], [:PSEUDO_CLASS]
|
||||||
|
])
|
||||||
|
matches.each do |match|
|
||||||
|
if ['first-child', 'last-child'].include?(match.value[1].value.first)
|
||||||
|
which = match.value[1].value.first.gsub(/-\w*$/, '')
|
||||||
|
tag_name = match.value[0].value.first
|
||||||
|
match.value[0].value = ['*']
|
||||||
|
match.value[1] = Node.new(:COMBINATOR, [
|
||||||
|
Node.new(:FUNCTION, ["#{which}("]),
|
||||||
|
Node.new(:FUNCTION, ['self(', tag_name])
|
||||||
|
])
|
||||||
|
elsif 'only-child' == match.value[1].value.first
|
||||||
|
tag_name = match.value[0].value.first
|
||||||
|
match.value[0].value = ['*']
|
||||||
|
match.value[1] = Node.new(:COMBINATOR, [
|
||||||
|
Node.new(:FUNCTION, ["#{match.value[1].value.first}("]),
|
||||||
|
Node.new(:FUNCTION, ['self(', tag_name])
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_by_type(types)
|
||||||
|
matches = []
|
||||||
|
matches << self if to_type == types
|
||||||
|
@value.each do |v|
|
||||||
|
matches += v.find_by_type(types) if v.respond_to?(:find_by_type)
|
||||||
|
end
|
||||||
|
matches
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_type
|
||||||
|
[@type] + @value.map { |n|
|
||||||
|
n.to_type if n.respond_to?(:to_type)
|
||||||
|
}.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
[@type] + @value.map { |n| n.respond_to?(:to_a) ? n.to_a : [n] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
24
lib/webrat/vendor/nokogiri/css/parser.rb
vendored
Normal file
24
lib/webrat/vendor/nokogiri/css/parser.rb
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class Parser < GeneratedParser
|
||||||
|
class << self
|
||||||
|
def parse string
|
||||||
|
new.parse(string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@tokenizer = Tokenizer.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse string
|
||||||
|
@tokenizer.scan string
|
||||||
|
do_parse
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_token
|
||||||
|
@tokenizer.next_token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
198
lib/webrat/vendor/nokogiri/css/parser.y
vendored
Normal file
198
lib/webrat/vendor/nokogiri/css/parser.y
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
class Nokogiri::CSS::GeneratedParser
|
||||||
|
|
||||||
|
token FUNCTION INCLUDES DASHMATCH LBRACE HASH PLUS GREATER S STRING IDENT
|
||||||
|
token COMMA URI CDO CDC NUMBER PERCENTAGE LENGTH EMS EXS ANGLE TIME FREQ
|
||||||
|
token IMPORTANT_SYM IMPORT_SYM MEDIA_SYM PAGE_SYM CHARSET_SYM DIMENSION
|
||||||
|
token PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL SLASH DOUBLESLASH
|
||||||
|
token NOT
|
||||||
|
|
||||||
|
rule
|
||||||
|
selector
|
||||||
|
: selector COMMA s_0toN simple_selector_1toN {
|
||||||
|
result = [val.first, val.last].flatten
|
||||||
|
}
|
||||||
|
| simple_selector_1toN { result = val.flatten }
|
||||||
|
;
|
||||||
|
combinator
|
||||||
|
: PLUS s_0toN { result = :DIRECT_ADJACENT_SELECTOR }
|
||||||
|
| GREATER s_0toN { result = :CHILD_SELECTOR }
|
||||||
|
| TILDE s_0toN { result = :PRECEDING_SELECTOR }
|
||||||
|
| S { result = :DESCENDANT_SELECTOR }
|
||||||
|
| DOUBLESLASH s_0toN { result = :DESCENDANT_SELECTOR }
|
||||||
|
| SLASH s_0toN { result = :CHILD_SELECTOR }
|
||||||
|
;
|
||||||
|
simple_selector
|
||||||
|
: element_name hcap_0toN {
|
||||||
|
result = if val[1].nil?
|
||||||
|
val.first
|
||||||
|
else
|
||||||
|
Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
|
||||||
|
end
|
||||||
|
}
|
||||||
|
| element_name negation {
|
||||||
|
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
||||||
|
}
|
||||||
|
| function
|
||||||
|
| function attrib {
|
||||||
|
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
||||||
|
}
|
||||||
|
| hcap_1toN {
|
||||||
|
result = Node.new(:CONDITIONAL_SELECTOR,
|
||||||
|
[Node.new(:ELEMENT_NAME, ['*']), val.first]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
simple_selector_1toN
|
||||||
|
: simple_selector combinator simple_selector_1toN {
|
||||||
|
result = Node.new(val[1], [val.first, val.last])
|
||||||
|
}
|
||||||
|
| simple_selector
|
||||||
|
;
|
||||||
|
class
|
||||||
|
: '.' IDENT { result = Node.new(:CLASS_CONDITION, [val[1]]) }
|
||||||
|
;
|
||||||
|
element_name
|
||||||
|
: IDENT { result = Node.new(:ELEMENT_NAME, val) }
|
||||||
|
| '*' { result = Node.new(:ELEMENT_NAME, val) }
|
||||||
|
;
|
||||||
|
attrib
|
||||||
|
: '[' s_0toN IDENT s_0toN attrib_val_0or1 ']' {
|
||||||
|
result = Node.new(:ATTRIBUTE_CONDITION,
|
||||||
|
[Node.new(:ELEMENT_NAME, [val[2]])] + (val[4] || [])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
| '[' s_0toN function s_0toN attrib_val_0or1 ']' {
|
||||||
|
result = Node.new(:ATTRIBUTE_CONDITION,
|
||||||
|
[val[2]] + (val[4] || [])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
| '[' s_0toN NUMBER s_0toN ']' {
|
||||||
|
# Non standard, but hpricot supports it.
|
||||||
|
result = Node.new(:PSEUDO_CLASS,
|
||||||
|
[Node.new(:FUNCTION, ['nth-child(', val[2]])]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
function
|
||||||
|
: FUNCTION ')' {
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip])
|
||||||
|
}
|
||||||
|
| FUNCTION expr ')' {
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
||||||
|
}
|
||||||
|
| FUNCTION an_plus_b ')' {
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
||||||
|
}
|
||||||
|
| NOT expr ')' {
|
||||||
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
expr
|
||||||
|
: NUMBER
|
||||||
|
| STRING
|
||||||
|
;
|
||||||
|
an_plus_b
|
||||||
|
: NUMBER IDENT PLUS NUMBER # 5n+3 -5n+3
|
||||||
|
{
|
||||||
|
if val[1] == 'n'
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
| IDENT PLUS NUMBER { # n+3, -n+3
|
||||||
|
if val[0] == 'n'
|
||||||
|
val.unshift("1")
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
elsif val[0] == '-n'
|
||||||
|
val[0] = 'n'
|
||||||
|
val.unshift("-1")
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
| NUMBER IDENT # 5n, -5n
|
||||||
|
{
|
||||||
|
if val[1] == 'n'
|
||||||
|
val << "+"
|
||||||
|
val << "0"
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
| IDENT # even, odd
|
||||||
|
{
|
||||||
|
if val[0] == 'even'
|
||||||
|
val = ["2","n","+","0"]
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
elsif val[0] == 'odd'
|
||||||
|
val = ["2","n","+","1"]
|
||||||
|
result = Node.new(:AN_PLUS_B, val)
|
||||||
|
else
|
||||||
|
raise Racc::ParseError, "parse error on IDENT '#{val[0]}'"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
;
|
||||||
|
pseudo
|
||||||
|
: ':' function {
|
||||||
|
result = Node.new(:PSEUDO_CLASS, [val[1]])
|
||||||
|
}
|
||||||
|
| ':' IDENT { result = Node.new(:PSEUDO_CLASS, [val[1]]) }
|
||||||
|
;
|
||||||
|
hcap_0toN
|
||||||
|
: hcap_1toN
|
||||||
|
|
|
||||||
|
;
|
||||||
|
hcap_1toN
|
||||||
|
: attribute_id hcap_1toN {
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
}
|
||||||
|
| class hcap_1toN {
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
}
|
||||||
|
| attrib hcap_1toN {
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
}
|
||||||
|
| pseudo hcap_1toN {
|
||||||
|
result = Node.new(:COMBINATOR, val)
|
||||||
|
}
|
||||||
|
| attribute_id
|
||||||
|
| class
|
||||||
|
| attrib
|
||||||
|
| pseudo
|
||||||
|
;
|
||||||
|
attribute_id
|
||||||
|
: HASH { result = Node.new(:ID, val) }
|
||||||
|
;
|
||||||
|
attrib_val_0or1
|
||||||
|
: eql_incl_dash s_0toN IDENT s_0toN { result = [val.first, val[2]] }
|
||||||
|
| eql_incl_dash s_0toN STRING s_0toN { result = [val.first, val[2]] }
|
||||||
|
|
|
||||||
|
;
|
||||||
|
eql_incl_dash
|
||||||
|
: '='
|
||||||
|
| PREFIXMATCH
|
||||||
|
| SUFFIXMATCH
|
||||||
|
| SUBSTRINGMATCH
|
||||||
|
| NOT_EQUAL
|
||||||
|
| INCLUDES
|
||||||
|
| DASHMATCH
|
||||||
|
;
|
||||||
|
negation
|
||||||
|
: NOT s_0toN negation_arg s_0toN ')' {
|
||||||
|
result = Node.new(:NOT, [val[2]])
|
||||||
|
}
|
||||||
|
;
|
||||||
|
negation_arg
|
||||||
|
: hcap_1toN
|
||||||
|
;
|
||||||
|
s_0toN
|
||||||
|
: S s_0toN
|
||||||
|
|
|
||||||
|
;
|
||||||
|
end
|
||||||
|
|
||||||
|
---- header
|
||||||
|
|
9
lib/webrat/vendor/nokogiri/css/tokenizer.rb
vendored
Normal file
9
lib/webrat/vendor/nokogiri/css/tokenizer.rb
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class Tokenizer < GeneratedTokenizer
|
||||||
|
def scan(str)
|
||||||
|
scan_evaluate(str)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
63
lib/webrat/vendor/nokogiri/css/tokenizer.rex
vendored
Normal file
63
lib/webrat/vendor/nokogiri/css/tokenizer.rex
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class GeneratedTokenizer
|
||||||
|
|
||||||
|
macro
|
||||||
|
nl \n|\r\n|\r|\f
|
||||||
|
w [\s\r\n\f]*
|
||||||
|
nonascii [^\\\\0-\\\\177]
|
||||||
|
num -?([0-9]+|[0-9]*\.[0-9]+)
|
||||||
|
unicode \\\\\\\\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?
|
||||||
|
|
||||||
|
escape {unicode}|\\\\\\\[^\n\r\f0-9a-f]
|
||||||
|
nmchar [_a-z0-9-]|{nonascii}|{escape}
|
||||||
|
nmstart [_a-z]|{nonascii}|{escape}
|
||||||
|
ident [-]?({nmstart})({nmchar})*
|
||||||
|
name ({nmchar})+
|
||||||
|
string1 "([^\n\r\f"]|\\{nl}|{nonascii}|{escape})*"
|
||||||
|
string2 '([^\n\r\f']|\\{nl}|{nonascii}|{escape})*'
|
||||||
|
string {string1}|{string2}
|
||||||
|
invalid1 \"([^\n\r\f\\"]|\\{nl}|{nonascii}|{escape})*
|
||||||
|
invalid2 \'([^\n\r\f\\']|\\{nl}|{nonascii}|{escape})*
|
||||||
|
invalid {invalid1}|{invalid2}
|
||||||
|
Comment \/\*(.|[\r\n])*?\*\/
|
||||||
|
|
||||||
|
rule
|
||||||
|
|
||||||
|
# [:state] pattern [actions]
|
||||||
|
|
||||||
|
~= { [:INCLUDES, text] }
|
||||||
|
\|= { [:DASHMATCH, text] }
|
||||||
|
\^= { [:PREFIXMATCH, text] }
|
||||||
|
\$= { [:SUFFIXMATCH, text] }
|
||||||
|
\*= { [:SUBSTRINGMATCH, text] }
|
||||||
|
!= { [:NOT_EQUAL, text] }
|
||||||
|
{ident}\(\s* { [:FUNCTION, text] }
|
||||||
|
@{ident} { [:IDENT, text] }
|
||||||
|
{ident} { [:IDENT, text] }
|
||||||
|
{num} { [:NUMBER, text] }
|
||||||
|
\#{name} { [:HASH, text] }
|
||||||
|
{w}\+ { [:PLUS, text] }
|
||||||
|
{w}> { [:GREATER, text] }
|
||||||
|
{w}, { [:COMMA, text] }
|
||||||
|
{w}~ { [:TILDE, text] }
|
||||||
|
\:not\( { [:NOT, text] }
|
||||||
|
@{ident} { [:ATKEYWORD, text] }
|
||||||
|
{num}% { [:PERCENTAGE, text] }
|
||||||
|
{num}{ident} { [:DIMENSION, text] }
|
||||||
|
<!-- { [:CDO, text] }
|
||||||
|
--> { [:CDC, text] }
|
||||||
|
{w}\/\/ { [:DOUBLESLASH, text] }
|
||||||
|
{w}\/ { [:SLASH, text] }
|
||||||
|
|
||||||
|
U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})? {[:UNICODE_RANGE, text] }
|
||||||
|
|
||||||
|
{Comment} /* ignore comments */
|
||||||
|
[\s\t\r\n\f]+ { [:S, text] }
|
||||||
|
[\.*:\[\]=\)] { [text, text] }
|
||||||
|
{string} { [:STRING, text] }
|
||||||
|
{invalid} { [:INVALID, text] }
|
||||||
|
. { [text, text] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
159
lib/webrat/vendor/nokogiri/css/xpath_visitor.rb
vendored
Normal file
159
lib/webrat/vendor/nokogiri/css/xpath_visitor.rb
vendored
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
module Nokogiri
|
||||||
|
module CSS
|
||||||
|
class XPathVisitor
|
||||||
|
def visit_function node
|
||||||
|
# note that nth-child and nth-last-child are preprocessed in css/node.rb.
|
||||||
|
case node.value.first
|
||||||
|
when /^text\(/
|
||||||
|
'child::text()'
|
||||||
|
when /^self\(/
|
||||||
|
"self::#{node.value[1]}"
|
||||||
|
when /^(eq|nth|nth-of-type|nth-child)\(/
|
||||||
|
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
|
||||||
|
an_plus_b(node.value[1])
|
||||||
|
else
|
||||||
|
"position() = " + node.value[1]
|
||||||
|
end
|
||||||
|
when /^(first|first-of-type)\(/
|
||||||
|
"position() = 1"
|
||||||
|
when /^(last|last-of-type)\(/
|
||||||
|
"position() = last()"
|
||||||
|
when /^(nth-last-child|nth-last-of-type)\(/
|
||||||
|
"position() = last() - #{node.value[1]}"
|
||||||
|
when /^contains\(/
|
||||||
|
"contains(., #{node.value[1]})"
|
||||||
|
when /^gt\(/
|
||||||
|
"position() > #{node.value[1]}"
|
||||||
|
when /^only-child\(/
|
||||||
|
"last() = 1"
|
||||||
|
else
|
||||||
|
node.value.first + ')'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_not node
|
||||||
|
'not(' + node.value.first.accept(self) + ')'
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_preceding_selector node
|
||||||
|
node.value.last.accept(self) +
|
||||||
|
'[preceding-sibling::' +
|
||||||
|
node.value.first.accept(self) +
|
||||||
|
']'
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_direct_adjacent_selector node
|
||||||
|
node.value.last.accept(self) +
|
||||||
|
'[preceding-sibling::' +
|
||||||
|
node.value.first.accept(self) +
|
||||||
|
'][position()=1]'
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_id node
|
||||||
|
node.value.first =~ /^#(.*)$/
|
||||||
|
"@id = '#{$1}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_attribute_condition node
|
||||||
|
attribute = if (node.value.first.type == :FUNCTION) or (node.value.first.value.first =~ /::/)
|
||||||
|
''
|
||||||
|
else
|
||||||
|
'@'
|
||||||
|
end
|
||||||
|
attribute += node.value.first.accept(self)
|
||||||
|
|
||||||
|
# Support non-standard css
|
||||||
|
attribute.gsub!(/^@@/, '@')
|
||||||
|
|
||||||
|
return attribute unless node.value.length == 3
|
||||||
|
|
||||||
|
value = node.value.last
|
||||||
|
value = "'#{value}'" if value !~ /^['"]/
|
||||||
|
|
||||||
|
case node.value[1]
|
||||||
|
when '*='
|
||||||
|
"contains(#{attribute}, #{value})"
|
||||||
|
when '^='
|
||||||
|
"starts-with(#{attribute}, #{value})"
|
||||||
|
when '|='
|
||||||
|
"#{attribute} = #{value} or starts-with(#{attribute}, concat(#{value}, '-'))"
|
||||||
|
when '~='
|
||||||
|
"contains(concat(\" \", #{attribute}, \" \"),concat(\" \", #{value}, \" \"))"
|
||||||
|
when '$='
|
||||||
|
"substring(#{attribute}, string-length(#{attribute}) - " +
|
||||||
|
"string-length(#{value}) + 1, string-length(#{value})) = #{value}"
|
||||||
|
else
|
||||||
|
attribute + " #{node.value[1]} " + "#{value}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_pseudo_class node
|
||||||
|
if node.value.first.is_a?(Nokogiri::CSS::Node) and node.value.first.type == :FUNCTION
|
||||||
|
node.value.first.accept(self)
|
||||||
|
else
|
||||||
|
case node.value.first
|
||||||
|
when "first" then "position() = 1"
|
||||||
|
when "last" then "position() = last()"
|
||||||
|
when "first-of-type" then "position() = 1"
|
||||||
|
when "last-of-type" then "position() = last()"
|
||||||
|
when "only-of-type" then "last() = 1"
|
||||||
|
when "empty" then "not(node())"
|
||||||
|
when "parent" then "node()"
|
||||||
|
else
|
||||||
|
'1 = 1'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_class_condition node
|
||||||
|
"contains(concat(' ', @class, ' '),concat(' ', '#{node.value.first}', ' '))"
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_combinator node
|
||||||
|
node.value.first.accept(self) + ' and ' +
|
||||||
|
node.value.last.accept(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_conditional_selector node
|
||||||
|
node.value.first.accept(self) + '[' +
|
||||||
|
node.value.last.accept(self) + ']'
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_descendant_selector node
|
||||||
|
node.value.first.accept(self) +
|
||||||
|
'//' +
|
||||||
|
node.value.last.accept(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_child_selector node
|
||||||
|
node.value.first.accept(self) +
|
||||||
|
'/' +
|
||||||
|
node.value.last.accept(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_element_name node
|
||||||
|
node.value.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def accept node
|
||||||
|
node.accept(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def an_plus_b node
|
||||||
|
raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
|
||||||
|
|
||||||
|
a = node.value[0].to_i
|
||||||
|
b = node.value[3].to_i
|
||||||
|
|
||||||
|
if (b == 0)
|
||||||
|
return "(position() mod #{a}) = 0"
|
||||||
|
else
|
||||||
|
compare = (a < 0) ? "<=" : ">="
|
||||||
|
return "(position() #{compare} #{b}) and (((position()-#{b}) mod #{a.abs}) = 0)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
75
spec/webrat/nokogiri_spec.rb
Normal file
75
spec/webrat/nokogiri_spec.rb
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
||||||
|
|
||||||
|
describe "Nokogiri Extension" do
|
||||||
|
include Webrat::Matchers
|
||||||
|
|
||||||
|
def fail
|
||||||
|
raise_error(Spec::Expectations::ExpectationNotMetError)
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@text_and_password = <<-HTML
|
||||||
|
<div>
|
||||||
|
<input type="text"/>
|
||||||
|
<input type="password"/>
|
||||||
|
<span type="text"/>
|
||||||
|
</div>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
@text_only = <<-HTML
|
||||||
|
<div>
|
||||||
|
<input type="text" disabled="disabled" />
|
||||||
|
</div>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
@password_only = <<-HTML
|
||||||
|
<div>
|
||||||
|
<input type="password"/>
|
||||||
|
<div>
|
||||||
|
HTML
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ":text" do
|
||||||
|
it "passes have_selector(:text) if a node with type=text exists" do
|
||||||
|
@text_and_password.should have_selector(":text")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes not have_selector(:text) if no node with text=text exists" do
|
||||||
|
@password_only.should_not have_selector(":text")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails have_selector(:text) if no node with type=text exists" do
|
||||||
|
lambda { @password_only.should have_selector(":text") }.should fail
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails not have_selector(:text) if a node with type=text exists" do
|
||||||
|
lambda { @text_only.should_not have_selector(":text") }.should fail
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works together with other selectors" do
|
||||||
|
@text_and_password.should have_selector("input:text[type*='te']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ":password" do
|
||||||
|
it "passes have_selector(:password) if a node with type=password exists" do
|
||||||
|
@text_and_password.should have_selector(":password")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes not have_selector(:text) if no node with text=text exists" do
|
||||||
|
@text_only.should_not have_selector(":password")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails have_selector(:password) if no node with type=password exists" do
|
||||||
|
lambda { @text_only.should have_selector(":password") }.should fail
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails not have_selector(:password) if a node with type=password exists" do
|
||||||
|
lambda { @password_only.should_not have_selector(":password") }.should fail
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works together with other selectors" do
|
||||||
|
@text_and_password.should have_selector("input:password[type*='pa']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user