merb-core 0.9.13 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/Rakefile +5 -3
  2. data/lib/merb-core.rb +84 -41
  3. data/lib/merb-core/bootloader.rb +71 -60
  4. data/lib/merb-core/config.rb +31 -17
  5. data/lib/merb-core/controller/abstract_controller.rb +35 -35
  6. data/lib/merb-core/controller/exceptions.rb +14 -9
  7. data/lib/merb-core/controller/merb_controller.rb +22 -20
  8. data/lib/merb-core/controller/mime.rb +5 -5
  9. data/lib/merb-core/controller/mixins/authentication.rb +11 -8
  10. data/lib/merb-core/controller/mixins/conditional_get.rb +7 -7
  11. data/lib/merb-core/controller/mixins/controller.rb +15 -15
  12. data/lib/merb-core/controller/mixins/render.rb +16 -16
  13. data/lib/merb-core/controller/mixins/responder.rb +23 -23
  14. data/lib/merb-core/controller/template.rb +17 -17
  15. data/lib/merb-core/core_ext/hash.rb +2 -2
  16. data/lib/merb-core/core_ext/kernel.rb +19 -18
  17. data/lib/merb-core/dispatch/cookies.rb +13 -0
  18. data/lib/merb-core/dispatch/default_exception/default_exception.rb +12 -1
  19. data/lib/merb-core/dispatch/dispatcher.rb +6 -5
  20. data/lib/merb-core/dispatch/request.rb +56 -52
  21. data/lib/merb-core/dispatch/request_parsers.rb +7 -7
  22. data/lib/merb-core/dispatch/router.rb +14 -14
  23. data/lib/merb-core/dispatch/router/behavior.rb +31 -31
  24. data/lib/merb-core/dispatch/router/cached_proc.rb +13 -1
  25. data/lib/merb-core/dispatch/router/resources.rb +9 -9
  26. data/lib/merb-core/dispatch/router/route.rb +60 -7
  27. data/lib/merb-core/dispatch/session.rb +21 -15
  28. data/lib/merb-core/dispatch/session/container.rb +10 -8
  29. data/lib/merb-core/dispatch/session/cookie.rb +12 -11
  30. data/lib/merb-core/dispatch/session/memcached.rb +4 -2
  31. data/lib/merb-core/dispatch/session/memory.rb +8 -6
  32. data/lib/merb-core/dispatch/session/store_container.rb +6 -5
  33. data/lib/merb-core/dispatch/worker.rb +28 -10
  34. data/lib/merb-core/gem_ext/erubis.rb +4 -2
  35. data/lib/merb-core/logger.rb +3 -22
  36. data/lib/merb-core/plugins.rb +5 -5
  37. data/lib/merb-core/rack.rb +1 -1
  38. data/lib/merb-core/rack/adapter.rb +5 -1
  39. data/lib/merb-core/rack/adapter/abstract.rb +15 -10
  40. data/lib/merb-core/rack/adapter/ebb.rb +4 -2
  41. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -1
  42. data/lib/merb-core/rack/adapter/fcgi.rb +3 -1
  43. data/lib/merb-core/rack/adapter/irb.rb +10 -1
  44. data/lib/merb-core/rack/adapter/mongrel.rb +5 -2
  45. data/lib/merb-core/rack/adapter/runner.rb +3 -1
  46. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +2 -1
  47. data/lib/merb-core/rack/adapter/thin.rb +4 -1
  48. data/lib/merb-core/rack/adapter/thin_turbo.rb +1 -0
  49. data/lib/merb-core/rack/adapter/webrick.rb +8 -34
  50. data/lib/merb-core/rack/application.rb +2 -2
  51. data/lib/merb-core/rack/handler/mongrel.rb +7 -0
  52. data/lib/merb-core/rack/helpers.rb +1 -1
  53. data/lib/merb-core/rack/middleware.rb +7 -1
  54. data/lib/merb-core/rack/middleware/conditional_get.rb +3 -0
  55. data/lib/merb-core/rack/middleware/content_length.rb +2 -0
  56. data/lib/merb-core/rack/middleware/path_prefix.rb +4 -0
  57. data/lib/merb-core/rack/middleware/profiler.rb +3 -1
  58. data/lib/merb-core/rack/middleware/static.rb +7 -1
  59. data/lib/merb-core/rack/middleware/tracer.rb +1 -0
  60. data/lib/merb-core/rack/stream_wrapper.rb +35 -30
  61. data/lib/merb-core/server.rb +17 -16
  62. data/lib/merb-core/tasks/gem_management.rb +1 -1
  63. data/lib/merb-core/tasks/merb.rb +3 -1
  64. data/lib/merb-core/tasks/merb_rake_helper.rb +1 -1
  65. data/lib/merb-core/test.rb +8 -8
  66. data/lib/merb-core/test/helpers.rb +1 -1
  67. data/lib/merb-core/test/helpers/cookie_jar.rb +16 -2
  68. data/lib/merb-core/test/helpers/mock_request_helper.rb +13 -13
  69. data/lib/merb-core/test/helpers/request_helper.rb +1 -1
  70. data/lib/merb-core/test/helpers/route_helper.rb +2 -2
  71. data/lib/merb-core/test/matchers.rb +3 -3
  72. data/lib/merb-core/test/matchers/request_matchers.rb +1 -1
  73. data/lib/merb-core/test/run_spec.rb +1 -1
  74. data/lib/merb-core/test/tasks/spectasks.rb +1 -1
  75. data/lib/merb-core/test/test_ext/hpricot.rb +1 -1
  76. data/lib/merb-core/test/test_ext/rspec.rb +2 -2
  77. data/lib/merb-core/test/test_ext/string.rb +1 -1
  78. data/lib/merb-core/version.rb +1 -1
  79. metadata +8 -22
  80. data/lib/merb-core/test/matchers/view_matchers.rb +0 -231
  81. data/lib/merb-core/test/webrat.rb +0 -37
  82. data/lib/merb-core/vendor/nokogiri/css.rb +0 -6
  83. data/lib/merb-core/vendor/nokogiri/css/generated_parser.rb +0 -653
  84. data/lib/merb-core/vendor/nokogiri/css/generated_tokenizer.rb +0 -159
  85. data/lib/merb-core/vendor/nokogiri/css/node.rb +0 -95
  86. data/lib/merb-core/vendor/nokogiri/css/parser.rb +0 -24
  87. data/lib/merb-core/vendor/nokogiri/css/parser.y +0 -198
  88. data/lib/merb-core/vendor/nokogiri/css/tokenizer.rb +0 -9
  89. data/lib/merb-core/vendor/nokogiri/css/tokenizer.rex +0 -63
  90. data/lib/merb-core/vendor/nokogiri/css/xpath_visitor.rb +0 -159
@@ -1,159 +0,0 @@
1
- #
2
- # DO NOT MODIFY!!!!
3
- # This file is automatically generated by rex 1.0.1
4
- # from lexical definition file "lib/nokogiri/css/tokenizer.rex".
5
- #
6
-
7
- module Nokogiri
8
- module CSS
9
- class GeneratedTokenizer
10
- require 'strscan'
11
-
12
- class ScanError < StandardError ; end
13
-
14
- attr_reader :lineno
15
- attr_reader :filename
16
-
17
- def scan_setup ; end
18
-
19
- def action &block
20
- yield
21
- end
22
-
23
- def scan_str( str )
24
- scan_evaluate str
25
- do_parse
26
- end
27
-
28
- def load_file( filename )
29
- @filename = filename
30
- open(filename, "r") do |f|
31
- scan_evaluate f.read
32
- end
33
- end
34
-
35
- def scan_file( filename )
36
- load_file filename
37
- do_parse
38
- end
39
-
40
- def next_token
41
- @rex_tokens.shift
42
- end
43
-
44
- def scan_evaluate( str )
45
- scan_setup
46
- @rex_tokens = []
47
- @lineno = 1
48
- ss = StringScanner.new(str)
49
- state = nil
50
- until ss.eos?
51
- text = ss.peek(1)
52
- @lineno += 1 if text == "\n"
53
- case state
54
- when nil
55
- case
56
- when (text = ss.scan(/~=/i))
57
- @rex_tokens.push action { [:INCLUDES, text] }
58
-
59
- when (text = ss.scan(/\|=/i))
60
- @rex_tokens.push action { [:DASHMATCH, text] }
61
-
62
- when (text = ss.scan(/\^=/i))
63
- @rex_tokens.push action { [:PREFIXMATCH, text] }
64
-
65
- when (text = ss.scan(/\$=/i))
66
- @rex_tokens.push action { [:SUFFIXMATCH, text] }
67
-
68
- when (text = ss.scan(/\*=/i))
69
- @rex_tokens.push action { [:SUBSTRINGMATCH, text] }
70
-
71
- when (text = ss.scan(/!=/i))
72
- @rex_tokens.push action { [:NOT_EQUAL, text] }
73
-
74
- 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))
75
- @rex_tokens.push action { [:FUNCTION, text] }
76
-
77
- 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))
78
- @rex_tokens.push action { [:IDENT, text] }
79
-
80
- 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))
81
- @rex_tokens.push action { [:IDENT, text] }
82
-
83
- when (text = ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/i))
84
- @rex_tokens.push action { [:NUMBER, text] }
85
-
86
- 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))
87
- @rex_tokens.push action { [:HASH, text] }
88
-
89
- when (text = ss.scan(/[\s\r\n\f]*\+/i))
90
- @rex_tokens.push action { [:PLUS, text] }
91
-
92
- when (text = ss.scan(/[\s\r\n\f]*>/i))
93
- @rex_tokens.push action { [:GREATER, text] }
94
-
95
- when (text = ss.scan(/[\s\r\n\f]*,/i))
96
- @rex_tokens.push action { [:COMMA, text] }
97
-
98
- when (text = ss.scan(/[\s\r\n\f]*~/i))
99
- @rex_tokens.push action { [:TILDE, text] }
100
-
101
- when (text = ss.scan(/\:not\(/i))
102
- @rex_tokens.push action { [:NOT, text] }
103
-
104
- 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))
105
- @rex_tokens.push action { [:ATKEYWORD, text] }
106
-
107
- when (text = ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)%/i))
108
- @rex_tokens.push action { [:PERCENTAGE, text] }
109
-
110
- 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))
111
- @rex_tokens.push action { [:DIMENSION, text] }
112
-
113
- when (text = ss.scan(/<!--/i))
114
- @rex_tokens.push action { [:CDO, text] }
115
-
116
- when (text = ss.scan(/-->/i))
117
- @rex_tokens.push action { [:CDC, text] }
118
-
119
- when (text = ss.scan(/[\s\r\n\f]*\/\//i))
120
- @rex_tokens.push action { [:DOUBLESLASH, text] }
121
-
122
- when (text = ss.scan(/[\s\r\n\f]*\//i))
123
- @rex_tokens.push action { [:SLASH, text] }
124
-
125
- when (text = ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/i))
126
- @rex_tokens.push action {[:UNICODE_RANGE, text] }
127
-
128
- when (text = ss.scan(/\/\*(.|[\r\n])*?\*\//i))
129
- ;
130
-
131
- when (text = ss.scan(/[\s\t\r\n\f]+/i))
132
- @rex_tokens.push action { [:S, text] }
133
-
134
- when (text = ss.scan(/[\.*:\[\]=\)]/i))
135
- @rex_tokens.push action { [text, text] }
136
-
137
- 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))
138
- @rex_tokens.push action { [:STRING, text] }
139
-
140
- 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))
141
- @rex_tokens.push action { [:INVALID, text] }
142
-
143
- when (text = ss.scan(/./i))
144
- @rex_tokens.push action { [text, text] }
145
-
146
- else
147
- text = ss.string[ss.pos .. -1]
148
- raise ScanError, "can not match: '" + text + "'"
149
- end # if
150
-
151
- else
152
- raise ScanError, "undefined state: '" + state.to_s + "'"
153
- end # case state
154
- end # until ss
155
- end # def scan_evaluate
156
-
157
- end # class
158
- end
159
- end
@@ -1,95 +0,0 @@
1
- module Nokogiri
2
- module CSS
3
- class Node
4
- attr_accessor :type, :value
5
- def initialize type, value
6
- @type = type
7
- @value = value
8
- end
9
-
10
- def accept visitor
11
- visitor.send(:"visit_#{type.to_s.downcase}", self)
12
- end
13
-
14
- def to_xpath prefix = '//', preprocess = true
15
- self.preprocess! if preprocess
16
- prefix + XPathVisitor.new.accept(self)
17
- end
18
-
19
- def preprocess!
20
- ### Deal with nth-child
21
- matches = find_by_type(
22
- [:CONDITIONAL_SELECTOR,
23
- [:ELEMENT_NAME],
24
- [:PSEUDO_CLASS,
25
- [:FUNCTION]
26
- ]
27
- ]
28
- )
29
- matches.each do |match|
30
- if match.value[1].value[0].value[0] =~ /^nth-child/
31
- tag_name = match.value[0].value.first
32
- match.value[0].value = ['*']
33
- match.value[1] = Node.new(:COMBINATOR, [
34
- match.value[1].value[0],
35
- Node.new(:FUNCTION, ['self(', tag_name])
36
- ])
37
- end
38
- if match.value[1].value[0].value[0] =~ /^nth-last-child/
39
- tag_name = match.value[0].value.first
40
- match.value[0].value = ['*']
41
- match.value[1] = Node.new(:COMBINATOR, [
42
- match.value[1].value[0],
43
- Node.new(:FUNCTION, ['self(', tag_name])
44
- ])
45
- end
46
- end
47
-
48
- ### Deal with first-child, last-child
49
- matches = find_by_type(
50
- [:CONDITIONAL_SELECTOR,
51
- [:ELEMENT_NAME], [:PSEUDO_CLASS]
52
- ])
53
- matches.each do |match|
54
- if ['first-child', 'last-child'].include?(match.value[1].value.first)
55
- which = match.value[1].value.first.gsub(/-\w*$/, '')
56
- tag_name = match.value[0].value.first
57
- match.value[0].value = ['*']
58
- match.value[1] = Node.new(:COMBINATOR, [
59
- Node.new(:FUNCTION, ["#{which}("]),
60
- Node.new(:FUNCTION, ['self(', tag_name])
61
- ])
62
- elsif 'only-child' == match.value[1].value.first
63
- tag_name = match.value[0].value.first
64
- match.value[0].value = ['*']
65
- match.value[1] = Node.new(:COMBINATOR, [
66
- Node.new(:FUNCTION, ["#{match.value[1].value.first}("]),
67
- Node.new(:FUNCTION, ['self(', tag_name])
68
- ])
69
- end
70
- end
71
-
72
- self
73
- end
74
-
75
- def find_by_type(types)
76
- matches = []
77
- matches << self if to_type == types
78
- @value.each do |v|
79
- matches += v.find_by_type(types) if v.respond_to?(:find_by_type)
80
- end
81
- matches
82
- end
83
-
84
- def to_type
85
- [@type] + @value.map { |n|
86
- n.to_type if n.respond_to?(:to_type)
87
- }.compact
88
- end
89
-
90
- def to_a
91
- [@type] + @value.map { |n| n.respond_to?(:to_a) ? n.to_a : [n] }
92
- end
93
- end
94
- end
95
- end
@@ -1,24 +0,0 @@
1
- module Nokogiri
2
- module CSS
3
- class Parser < GeneratedParser
4
- class << self
5
- def parse string
6
- new.parse(string)
7
- end
8
- end
9
-
10
- def initialize
11
- @tokenizer = Tokenizer.new
12
- end
13
-
14
- def parse string
15
- @tokenizer.scan string
16
- do_parse
17
- end
18
-
19
- def next_token
20
- @tokenizer.next_token
21
- end
22
- end
23
- end
24
- end
@@ -1,198 +0,0 @@
1
- class Nokogiri::CSS::GeneratedParser
2
-
3
- token FUNCTION INCLUDES DASHMATCH LBRACE HASH PLUS GREATER S STRING IDENT
4
- token COMMA URI CDO CDC NUMBER PERCENTAGE LENGTH EMS EXS ANGLE TIME FREQ
5
- token IMPORTANT_SYM IMPORT_SYM MEDIA_SYM PAGE_SYM CHARSET_SYM DIMENSION
6
- token PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL SLASH DOUBLESLASH
7
- token NOT
8
-
9
- rule
10
- selector
11
- : selector COMMA s_0toN simple_selector_1toN {
12
- result = [val.first, val.last].flatten
13
- }
14
- | simple_selector_1toN { result = val.flatten }
15
- ;
16
- combinator
17
- : PLUS s_0toN { result = :DIRECT_ADJACENT_SELECTOR }
18
- | GREATER s_0toN { result = :CHILD_SELECTOR }
19
- | TILDE s_0toN { result = :PRECEDING_SELECTOR }
20
- | S { result = :DESCENDANT_SELECTOR }
21
- | DOUBLESLASH s_0toN { result = :DESCENDANT_SELECTOR }
22
- | SLASH s_0toN { result = :CHILD_SELECTOR }
23
- ;
24
- simple_selector
25
- : element_name hcap_0toN {
26
- result = if val[1].nil?
27
- val.first
28
- else
29
- Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
30
- end
31
- }
32
- | element_name negation {
33
- result = Node.new(:CONDITIONAL_SELECTOR, val)
34
- }
35
- | function
36
- | function attrib {
37
- result = Node.new(:CONDITIONAL_SELECTOR, val)
38
- }
39
- | hcap_1toN {
40
- result = Node.new(:CONDITIONAL_SELECTOR,
41
- [Node.new(:ELEMENT_NAME, ['*']), val.first]
42
- )
43
- }
44
- ;
45
- simple_selector_1toN
46
- : simple_selector combinator simple_selector_1toN {
47
- result = Node.new(val[1], [val.first, val.last])
48
- }
49
- | simple_selector
50
- ;
51
- class
52
- : '.' IDENT { result = Node.new(:CLASS_CONDITION, [val[1]]) }
53
- ;
54
- element_name
55
- : IDENT { result = Node.new(:ELEMENT_NAME, val) }
56
- | '*' { result = Node.new(:ELEMENT_NAME, val) }
57
- ;
58
- attrib
59
- : '[' s_0toN IDENT s_0toN attrib_val_0or1 ']' {
60
- result = Node.new(:ATTRIBUTE_CONDITION,
61
- [Node.new(:ELEMENT_NAME, [val[2]])] + (val[4] || [])
62
- )
63
- }
64
- | '[' s_0toN function s_0toN attrib_val_0or1 ']' {
65
- result = Node.new(:ATTRIBUTE_CONDITION,
66
- [val[2]] + (val[4] || [])
67
- )
68
- }
69
- | '[' s_0toN NUMBER s_0toN ']' {
70
- # Non standard, but hpricot supports it.
71
- result = Node.new(:PSEUDO_CLASS,
72
- [Node.new(:FUNCTION, ['nth-child(', val[2]])]
73
- )
74
- }
75
- ;
76
- function
77
- : FUNCTION ')' {
78
- result = Node.new(:FUNCTION, [val.first.strip])
79
- }
80
- | FUNCTION expr ')' {
81
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
82
- }
83
- | FUNCTION an_plus_b ')' {
84
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
85
- }
86
- | NOT expr ')' {
87
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
88
- }
89
- ;
90
- expr
91
- : NUMBER
92
- | STRING
93
- ;
94
- an_plus_b
95
- : NUMBER IDENT PLUS NUMBER # 5n+3 -5n+3
96
- {
97
- if val[1] == 'n'
98
- result = Node.new(:AN_PLUS_B, val)
99
- else
100
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
101
- end
102
- }
103
- | IDENT PLUS NUMBER { # n+3, -n+3
104
- if val[0] == 'n'
105
- val.unshift("1")
106
- result = Node.new(:AN_PLUS_B, val)
107
- elsif val[0] == '-n'
108
- val[0] = 'n'
109
- val.unshift("-1")
110
- result = Node.new(:AN_PLUS_B, val)
111
- else
112
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
113
- end
114
- }
115
- | NUMBER IDENT # 5n, -5n
116
- {
117
- if val[1] == 'n'
118
- val << "+"
119
- val << "0"
120
- result = Node.new(:AN_PLUS_B, val)
121
- else
122
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
123
- end
124
- }
125
- | IDENT # even, odd
126
- {
127
- if val[0] == 'even'
128
- val = ["2","n","+","0"]
129
- result = Node.new(:AN_PLUS_B, val)
130
- elsif val[0] == 'odd'
131
- val = ["2","n","+","1"]
132
- result = Node.new(:AN_PLUS_B, val)
133
- else
134
- raise Racc::ParseError, "parse error on IDENT '#{val[0]}'"
135
- end
136
- }
137
- ;
138
- pseudo
139
- : ':' function {
140
- result = Node.new(:PSEUDO_CLASS, [val[1]])
141
- }
142
- | ':' IDENT { result = Node.new(:PSEUDO_CLASS, [val[1]]) }
143
- ;
144
- hcap_0toN
145
- : hcap_1toN
146
- |
147
- ;
148
- hcap_1toN
149
- : attribute_id hcap_1toN {
150
- result = Node.new(:COMBINATOR, val)
151
- }
152
- | class hcap_1toN {
153
- result = Node.new(:COMBINATOR, val)
154
- }
155
- | attrib hcap_1toN {
156
- result = Node.new(:COMBINATOR, val)
157
- }
158
- | pseudo hcap_1toN {
159
- result = Node.new(:COMBINATOR, val)
160
- }
161
- | attribute_id
162
- | class
163
- | attrib
164
- | pseudo
165
- ;
166
- attribute_id
167
- : HASH { result = Node.new(:ID, val) }
168
- ;
169
- attrib_val_0or1
170
- : eql_incl_dash s_0toN IDENT s_0toN { result = [val.first, val[2]] }
171
- | eql_incl_dash s_0toN STRING s_0toN { result = [val.first, val[2]] }
172
- |
173
- ;
174
- eql_incl_dash
175
- : '='
176
- | PREFIXMATCH
177
- | SUFFIXMATCH
178
- | SUBSTRINGMATCH
179
- | NOT_EQUAL
180
- | INCLUDES
181
- | DASHMATCH
182
- ;
183
- negation
184
- : NOT s_0toN negation_arg s_0toN ')' {
185
- result = Node.new(:NOT, [val[2]])
186
- }
187
- ;
188
- negation_arg
189
- : hcap_1toN
190
- ;
191
- s_0toN
192
- : S s_0toN
193
- |
194
- ;
195
- end
196
-
197
- ---- header
198
-