nokogiri 1.4.3.1-java → 1.5.0-java

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.
Files changed (231) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG.ja.rdoc +113 -0
  3. data/CHANGELOG.rdoc +113 -1
  4. data/Manifest.txt +72 -68
  5. data/README.ja.rdoc +4 -4
  6. data/README.rdoc +31 -7
  7. data/Rakefile +110 -132
  8. data/bin/nokogiri +7 -3
  9. data/ext/java/nokogiri/EncodingHandler.java +124 -0
  10. data/ext/java/nokogiri/HtmlDocument.java +119 -0
  11. data/ext/java/nokogiri/HtmlElementDescription.java +145 -0
  12. data/ext/java/nokogiri/HtmlEntityLookup.java +79 -0
  13. data/ext/java/nokogiri/HtmlSaxParserContext.java +259 -0
  14. data/ext/java/nokogiri/NokogiriService.java +590 -0
  15. data/ext/java/nokogiri/XmlAttr.java +180 -0
  16. data/ext/java/nokogiri/XmlAttributeDecl.java +130 -0
  17. data/ext/java/nokogiri/XmlCdata.java +84 -0
  18. data/ext/java/nokogiri/XmlComment.java +86 -0
  19. data/ext/java/nokogiri/XmlDocument.java +519 -0
  20. data/ext/java/nokogiri/XmlDocumentFragment.java +223 -0
  21. data/ext/java/nokogiri/XmlDtd.java +469 -0
  22. data/ext/java/nokogiri/XmlElement.java +195 -0
  23. data/ext/java/nokogiri/XmlElementContent.java +382 -0
  24. data/ext/java/nokogiri/XmlElementDecl.java +152 -0
  25. data/ext/java/nokogiri/XmlEntityDecl.java +162 -0
  26. data/ext/java/nokogiri/XmlEntityReference.java +97 -0
  27. data/ext/java/nokogiri/XmlNamespace.java +183 -0
  28. data/ext/java/nokogiri/XmlNode.java +1378 -0
  29. data/ext/java/nokogiri/XmlNodeSet.java +267 -0
  30. data/ext/java/nokogiri/XmlProcessingInstruction.java +99 -0
  31. data/ext/java/nokogiri/XmlReader.java +408 -0
  32. data/ext/java/nokogiri/XmlRelaxng.java +144 -0
  33. data/ext/java/nokogiri/XmlSaxParserContext.java +367 -0
  34. data/ext/java/nokogiri/XmlSaxPushParser.java +184 -0
  35. data/ext/java/nokogiri/XmlSchema.java +324 -0
  36. data/ext/java/nokogiri/XmlSyntaxError.java +119 -0
  37. data/ext/java/nokogiri/XmlText.java +119 -0
  38. data/ext/java/nokogiri/XmlXpathContext.java +199 -0
  39. data/ext/java/nokogiri/XsltStylesheet.java +197 -0
  40. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +204 -0
  41. data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +73 -0
  42. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +86 -0
  43. data/ext/java/nokogiri/internals/NokogiriHandler.java +327 -0
  44. data/ext/java/nokogiri/internals/NokogiriHelpers.java +639 -0
  45. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +167 -0
  46. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +130 -0
  47. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +74 -0
  48. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +121 -0
  49. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +79 -0
  50. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +141 -0
  51. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +73 -0
  52. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +67 -0
  53. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +86 -0
  54. data/ext/java/nokogiri/internals/ParserContext.java +276 -0
  55. data/ext/java/nokogiri/internals/PushInputStream.java +411 -0
  56. data/ext/java/nokogiri/internals/ReaderNode.java +531 -0
  57. data/ext/java/nokogiri/internals/SaveContextVisitor.java +567 -0
  58. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +76 -0
  59. data/ext/java/nokogiri/internals/XmlDeclHandler.java +42 -0
  60. data/ext/java/nokogiri/internals/XmlDomParser.java +76 -0
  61. data/ext/java/nokogiri/internals/XmlDomParserContext.java +244 -0
  62. data/ext/java/nokogiri/internals/XmlSaxParser.java +65 -0
  63. data/ext/java/nokogiri/internals/XsltExtensionFunction.java +72 -0
  64. data/ext/nokogiri/depend +358 -32
  65. data/ext/nokogiri/extconf.rb +10 -6
  66. data/ext/nokogiri/nokogiri.c +23 -3
  67. data/ext/nokogiri/nokogiri.h +7 -2
  68. data/ext/nokogiri/xml_document.c +9 -0
  69. data/ext/nokogiri/xml_dtd.c +2 -2
  70. data/ext/nokogiri/xml_io.c +32 -7
  71. data/ext/nokogiri/xml_node.c +45 -25
  72. data/ext/nokogiri/xml_node_set.c +1 -1
  73. data/ext/nokogiri/xml_relax_ng.c +0 -7
  74. data/ext/nokogiri/xml_sax_parser.c +14 -7
  75. data/ext/nokogiri/xml_sax_parser_context.c +40 -0
  76. data/ext/nokogiri/xml_xpath_context.c +33 -2
  77. data/ext/nokogiri/xslt_stylesheet.c +128 -6
  78. data/lib/isorelax.jar +0 -0
  79. data/lib/jing.jar +0 -0
  80. data/lib/nekodtd.jar +0 -0
  81. data/lib/nekohtml.jar +0 -0
  82. data/lib/nokogiri/css/parser.rb +665 -70
  83. data/lib/nokogiri/css/parser.y +3 -1
  84. data/lib/nokogiri/css/parser_extras.rb +91 -0
  85. data/lib/nokogiri/css/tokenizer.rb +148 -3
  86. data/lib/nokogiri/css/tokenizer.rex +1 -1
  87. data/lib/nokogiri/css/xpath_visitor.rb +15 -7
  88. data/lib/nokogiri/css.rb +5 -3
  89. data/lib/nokogiri/decorators/slop.rb +5 -3
  90. data/lib/nokogiri/html/document.rb +142 -19
  91. data/lib/nokogiri/html/document_fragment.rb +19 -17
  92. data/lib/nokogiri/html/element_description_defaults.rb +671 -0
  93. data/lib/nokogiri/html/sax/parser.rb +6 -2
  94. data/lib/nokogiri/html.rb +1 -0
  95. data/lib/nokogiri/nokogiri.jar +0 -0
  96. data/lib/nokogiri/version.rb +76 -26
  97. data/lib/nokogiri/xml/attribute_decl.rb +1 -1
  98. data/lib/nokogiri/xml/builder.rb +7 -0
  99. data/lib/nokogiri/xml/document.rb +43 -2
  100. data/lib/nokogiri/xml/document_fragment.rb +16 -2
  101. data/lib/nokogiri/xml/dtd.rb +12 -1
  102. data/lib/nokogiri/xml/element_decl.rb +1 -1
  103. data/lib/nokogiri/xml/entity_decl.rb +1 -1
  104. data/lib/nokogiri/xml/node/save_options.rb +20 -1
  105. data/lib/nokogiri/xml/node.rb +198 -78
  106. data/lib/nokogiri/xml/node_set.rb +10 -3
  107. data/lib/nokogiri/xml/parse_options.rb +8 -0
  108. data/lib/nokogiri/xml/reader.rb +42 -6
  109. data/lib/nokogiri/xml/sax/document.rb +4 -2
  110. data/lib/nokogiri/xml/schema.rb +7 -1
  111. data/lib/nokogiri/xslt/stylesheet.rb +1 -1
  112. data/lib/nokogiri/xslt.rb +9 -5
  113. data/lib/nokogiri.rb +19 -25
  114. data/lib/xercesImpl.jar +0 -0
  115. data/nokogiri_help_responses.md +40 -0
  116. data/tasks/cross_compile.rb +130 -136
  117. data/tasks/nokogiri.org.rb +18 -0
  118. data/tasks/test.rb +2 -2
  119. data/test/css/test_parser.rb +29 -18
  120. data/test/css/test_tokenizer.rb +8 -0
  121. data/test/decorators/test_slop.rb +16 -0
  122. data/test/files/encoding.html +82 -0
  123. data/test/files/encoding.xhtml +84 -0
  124. data/test/files/metacharset.html +10 -0
  125. data/test/files/noencoding.html +47 -0
  126. data/test/helper.rb +5 -1
  127. data/test/html/sax/test_parser.rb +65 -3
  128. data/test/html/test_document.rb +75 -1
  129. data/test/html/test_document_encoding.rb +61 -0
  130. data/test/html/test_document_fragment.rb +50 -5
  131. data/test/html/test_element_description.rb +4 -2
  132. data/test/html/test_node.rb +9 -0
  133. data/test/test_memory_leak.rb +20 -35
  134. data/test/test_nokogiri.rb +14 -20
  135. data/test/test_reader.rb +23 -6
  136. data/test/test_xslt_transforms.rb +6 -2
  137. data/test/xml/node/test_save_options.rb +10 -2
  138. data/test/xml/sax/test_parser.rb +39 -8
  139. data/test/xml/sax/test_parser_context.rb +50 -0
  140. data/test/xml/sax/test_push_parser.rb +18 -1
  141. data/test/xml/test_attribute_decl.rb +7 -3
  142. data/test/xml/test_builder.rb +17 -0
  143. data/test/xml/test_document.rb +34 -5
  144. data/test/xml/test_document_fragment.rb +14 -2
  145. data/test/xml/test_dtd.rb +28 -3
  146. data/test/xml/test_element_content.rb +1 -1
  147. data/test/xml/test_element_decl.rb +1 -1
  148. data/test/xml/test_entity_decl.rb +12 -10
  149. data/test/xml/test_namespace.rb +7 -5
  150. data/test/xml/test_node.rb +65 -13
  151. data/test/xml/test_node_reparenting.rb +72 -31
  152. data/test/xml/test_node_set.rb +57 -0
  153. data/test/xml/test_schema.rb +5 -0
  154. data/test/xml/test_xpath.rb +32 -0
  155. data/test/xslt/test_custom_functions.rb +94 -0
  156. data/test/xslt/test_exception_handling.rb +37 -0
  157. metadata +512 -517
  158. data/deps.rip +0 -5
  159. data/ext/nokogiri/libcharset-1.dll +0 -0
  160. data/ext/nokogiri/libexslt.dll +0 -0
  161. data/ext/nokogiri/libiconv-2.dll +0 -0
  162. data/ext/nokogiri/libxml2.dll +0 -0
  163. data/ext/nokogiri/libxslt.dll +0 -0
  164. data/ext/nokogiri/zlib1.dll +0 -0
  165. data/lib/nokogiri/css/generated_parser.rb +0 -676
  166. data/lib/nokogiri/css/generated_tokenizer.rb +0 -146
  167. data/lib/nokogiri/ffi/encoding_handler.rb +0 -42
  168. data/lib/nokogiri/ffi/html/document.rb +0 -28
  169. data/lib/nokogiri/ffi/html/element_description.rb +0 -81
  170. data/lib/nokogiri/ffi/html/entity_lookup.rb +0 -16
  171. data/lib/nokogiri/ffi/html/sax/parser_context.rb +0 -38
  172. data/lib/nokogiri/ffi/io_callbacks.rb +0 -42
  173. data/lib/nokogiri/ffi/libxml.rb +0 -411
  174. data/lib/nokogiri/ffi/structs/common_node.rb +0 -38
  175. data/lib/nokogiri/ffi/structs/html_elem_desc.rb +0 -24
  176. data/lib/nokogiri/ffi/structs/html_entity_desc.rb +0 -13
  177. data/lib/nokogiri/ffi/structs/xml_alloc.rb +0 -16
  178. data/lib/nokogiri/ffi/structs/xml_attr.rb +0 -19
  179. data/lib/nokogiri/ffi/structs/xml_attribute.rb +0 -27
  180. data/lib/nokogiri/ffi/structs/xml_buffer.rb +0 -16
  181. data/lib/nokogiri/ffi/structs/xml_char_encoding_handler.rb +0 -11
  182. data/lib/nokogiri/ffi/structs/xml_document.rb +0 -117
  183. data/lib/nokogiri/ffi/structs/xml_dtd.rb +0 -28
  184. data/lib/nokogiri/ffi/structs/xml_element.rb +0 -26
  185. data/lib/nokogiri/ffi/structs/xml_element_content.rb +0 -17
  186. data/lib/nokogiri/ffi/structs/xml_entity.rb +0 -32
  187. data/lib/nokogiri/ffi/structs/xml_enumeration.rb +0 -12
  188. data/lib/nokogiri/ffi/structs/xml_node.rb +0 -28
  189. data/lib/nokogiri/ffi/structs/xml_node_set.rb +0 -53
  190. data/lib/nokogiri/ffi/structs/xml_notation.rb +0 -11
  191. data/lib/nokogiri/ffi/structs/xml_ns.rb +0 -15
  192. data/lib/nokogiri/ffi/structs/xml_parser_context.rb +0 -19
  193. data/lib/nokogiri/ffi/structs/xml_relax_ng.rb +0 -14
  194. data/lib/nokogiri/ffi/structs/xml_sax_handler.rb +0 -51
  195. data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +0 -124
  196. data/lib/nokogiri/ffi/structs/xml_schema.rb +0 -13
  197. data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +0 -31
  198. data/lib/nokogiri/ffi/structs/xml_text_reader.rb +0 -12
  199. data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +0 -38
  200. data/lib/nokogiri/ffi/structs/xml_xpath_object.rb +0 -35
  201. data/lib/nokogiri/ffi/structs/xml_xpath_parser_context.rb +0 -20
  202. data/lib/nokogiri/ffi/structs/xslt_stylesheet.rb +0 -13
  203. data/lib/nokogiri/ffi/weak_bucket.rb +0 -40
  204. data/lib/nokogiri/ffi/xml/attr.rb +0 -41
  205. data/lib/nokogiri/ffi/xml/attribute_decl.rb +0 -27
  206. data/lib/nokogiri/ffi/xml/cdata.rb +0 -19
  207. data/lib/nokogiri/ffi/xml/comment.rb +0 -18
  208. data/lib/nokogiri/ffi/xml/document.rb +0 -166
  209. data/lib/nokogiri/ffi/xml/document_fragment.rb +0 -21
  210. data/lib/nokogiri/ffi/xml/dtd.rb +0 -67
  211. data/lib/nokogiri/ffi/xml/element_content.rb +0 -43
  212. data/lib/nokogiri/ffi/xml/element_decl.rb +0 -19
  213. data/lib/nokogiri/ffi/xml/entity_decl.rb +0 -36
  214. data/lib/nokogiri/ffi/xml/entity_reference.rb +0 -19
  215. data/lib/nokogiri/ffi/xml/namespace.rb +0 -44
  216. data/lib/nokogiri/ffi/xml/node.rb +0 -554
  217. data/lib/nokogiri/ffi/xml/node_set.rb +0 -149
  218. data/lib/nokogiri/ffi/xml/processing_instruction.rb +0 -20
  219. data/lib/nokogiri/ffi/xml/reader.rb +0 -236
  220. data/lib/nokogiri/ffi/xml/relax_ng.rb +0 -85
  221. data/lib/nokogiri/ffi/xml/sax/parser.rb +0 -135
  222. data/lib/nokogiri/ffi/xml/sax/parser_context.rb +0 -67
  223. data/lib/nokogiri/ffi/xml/sax/push_parser.rb +0 -51
  224. data/lib/nokogiri/ffi/xml/schema.rb +0 -109
  225. data/lib/nokogiri/ffi/xml/syntax_error.rb +0 -98
  226. data/lib/nokogiri/ffi/xml/text.rb +0 -18
  227. data/lib/nokogiri/ffi/xml/xpath.rb +0 -9
  228. data/lib/nokogiri/ffi/xml/xpath_context.rb +0 -148
  229. data/lib/nokogiri/ffi/xslt/stylesheet.rb +0 -53
  230. data/lib/nokogiri/version_warning.rb +0 -14
  231. data/test/ffi/test_document.rb +0 -35
@@ -1,4 +1,4 @@
1
- class Nokogiri::CSS::GeneratedParser
1
+ class Nokogiri::CSS::Parser
2
2
 
3
3
  token FUNCTION INCLUDES DASHMATCH LBRACE HASH PLUS GREATER S STRING IDENT
4
4
  token COMMA NUMBER PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL
@@ -233,3 +233,5 @@ end
233
233
 
234
234
  ---- header
235
235
 
236
+ require 'nokogiri/css/parser_extras'
237
+
@@ -0,0 +1,91 @@
1
+ require 'thread'
2
+
3
+ module Nokogiri
4
+ module CSS
5
+ class Parser < Racc::Parser
6
+ @cache_on = true
7
+ @cache = {}
8
+ @mutex = Mutex.new
9
+
10
+ class << self
11
+ # Turn on CSS parse caching
12
+ attr_accessor :cache_on
13
+ alias :cache_on? :cache_on
14
+ alias :set_cache :cache_on=
15
+
16
+ # Get the css selector in +string+ from the cache
17
+ def [] string
18
+ return unless @cache_on
19
+ @mutex.synchronize { @cache[string] }
20
+ end
21
+
22
+ # Set the css selector in +string+ in the cache to +value+
23
+ def []= string, value
24
+ return value unless @cache_on
25
+ @mutex.synchronize { @cache[string] = value }
26
+ end
27
+
28
+ # Clear the cache
29
+ def clear_cache
30
+ @mutex.synchronize { @cache = {} }
31
+ end
32
+
33
+ # Execute +block+ without cache
34
+ def without_cache &block
35
+ tmp = @cache_on
36
+ @cache_on = false
37
+ block.call
38
+ @cache_on = tmp
39
+ end
40
+
41
+ ###
42
+ # Parse this CSS selector in +selector+. Returns an AST.
43
+ def parse selector
44
+ @warned ||= false
45
+ unless @warned
46
+ $stderr.puts('Nokogiri::CSS::Parser.parse is deprecated, call Nokogiri::CSS.parse(), this will be removed August 1st or version 1.4.0 (whichever is first)')
47
+ @warned = true
48
+ end
49
+ new.parse selector
50
+ end
51
+ end
52
+
53
+ # Create a new CSS parser with respect to +namespaces+
54
+ def initialize namespaces = {}
55
+ @tokenizer = Tokenizer.new
56
+ @namespaces = namespaces
57
+ super()
58
+ end
59
+
60
+ def parse string
61
+ @tokenizer.scan_setup string
62
+ do_parse
63
+ end
64
+
65
+ def next_token
66
+ @tokenizer.next_token
67
+ end
68
+
69
+ # Get the xpath for +string+ using +options+
70
+ def xpath_for string, options={}
71
+ key = "#{string}#{options[:ns]}#{options[:prefix]}"
72
+ v = self.class[key]
73
+ return v if v
74
+
75
+ args = [
76
+ options[:prefix] || '//',
77
+ options[:visitor] || XPathVisitor.new
78
+ ]
79
+ self.class[key] = parse(string).map { |ast|
80
+ ast.to_xpath(*args)
81
+ }
82
+ end
83
+
84
+ # On CSS parser error, raise an exception
85
+ def on_error error_token_id, error_value, value_stack
86
+ after = value_stack.compact.last
87
+ raise SyntaxError.new("unexpected '#{error_value}' after '#{after}'")
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,7 +1,152 @@
1
+ #--
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by rex 1.0.5
4
+ # from lexical definition file "lib/nokogiri/css/tokenizer.rex".
5
+ #++
6
+
1
7
  module Nokogiri
2
- module CSS
3
- class Tokenizer < GeneratedTokenizer
4
- alias :scan :scan_setup
8
+ module CSS
9
+ class Tokenizer
10
+ require 'strscan'
11
+
12
+ class ScanError < StandardError ; end
13
+
14
+ attr_reader :lineno
15
+ attr_reader :filename
16
+ attr_accessor :state
17
+
18
+ def scan_setup(str)
19
+ @ss = StringScanner.new(str)
20
+ @lineno = 1
21
+ @state = nil
22
+ end
23
+
24
+ def action
25
+ yield
26
+ end
27
+
28
+ def scan_str(str)
29
+ scan_setup(str)
30
+ do_parse
31
+ end
32
+ alias :scan :scan_str
33
+
34
+ def load_file( filename )
35
+ @filename = filename
36
+ open(filename, "r") do |f|
37
+ scan_setup(f.read)
5
38
  end
6
39
  end
40
+
41
+ def scan_file( filename )
42
+ load_file(filename)
43
+ do_parse
44
+ end
45
+
46
+
47
+ def next_token
48
+ return if @ss.eos?
49
+
50
+ # skips empty actions
51
+ until token = _next_token or @ss.eos?; end
52
+ token
53
+ end
54
+
55
+ def _next_token
56
+ text = @ss.peek(1)
57
+ @lineno += 1 if text == "\n"
58
+ token = case @state
59
+ when nil
60
+ case
61
+ when (text = @ss.scan(/has\([\s]*/))
62
+ action { [:HAS, text] }
63
+
64
+ when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*\([\s]*/))
65
+ action { [:FUNCTION, text] }
66
+
67
+ when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*/))
68
+ action { [:IDENT, text] }
69
+
70
+ when (text = @ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])+/))
71
+ action { [:HASH, text] }
72
+
73
+ when (text = @ss.scan(/[\s]*~=[\s]*/))
74
+ action { [:INCLUDES, text] }
75
+
76
+ when (text = @ss.scan(/[\s]*\|=[\s]*/))
77
+ action { [:DASHMATCH, text] }
78
+
79
+ when (text = @ss.scan(/[\s]*\^=[\s]*/))
80
+ action { [:PREFIXMATCH, text] }
81
+
82
+ when (text = @ss.scan(/[\s]*\$=[\s]*/))
83
+ action { [:SUFFIXMATCH, text] }
84
+
85
+ when (text = @ss.scan(/[\s]*\*=[\s]*/))
86
+ action { [:SUBSTRINGMATCH, text] }
87
+
88
+ when (text = @ss.scan(/[\s]*!=[\s]*/))
89
+ action { [:NOT_EQUAL, text] }
90
+
91
+ when (text = @ss.scan(/[\s]*=[\s]*/))
92
+ action { [:EQUAL, text] }
93
+
94
+ when (text = @ss.scan(/[\s]*\)/))
95
+ action { [:RPAREN, text] }
96
+
97
+ when (text = @ss.scan(/[\s]*\[[\s]*/))
98
+ action { [:LSQUARE, text] }
99
+
100
+ when (text = @ss.scan(/[\s]*\]/))
101
+ action { [:RSQUARE, text] }
102
+
103
+ when (text = @ss.scan(/[\s]*\+[\s]*/))
104
+ action { [:PLUS, text] }
105
+
106
+ when (text = @ss.scan(/[\s]*>[\s]*/))
107
+ action { [:GREATER, text] }
108
+
109
+ when (text = @ss.scan(/[\s]*,[\s]*/))
110
+ action { [:COMMA, text] }
111
+
112
+ when (text = @ss.scan(/[\s]*~[\s]*/))
113
+ action { [:TILDE, text] }
114
+
115
+ when (text = @ss.scan(/\:not\([\s]*/))
116
+ action { [:NOT, text] }
117
+
118
+ when (text = @ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/))
119
+ action { [:NUMBER, text] }
120
+
121
+ when (text = @ss.scan(/[\s]*\/\/[\s]*/))
122
+ action { [:DOUBLESLASH, text] }
123
+
124
+ when (text = @ss.scan(/[\s]*\/[\s]*/))
125
+ action { [:SLASH, text] }
126
+
127
+ when (text = @ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/))
128
+ action {[:UNICODE_RANGE, text] }
129
+
130
+ when (text = @ss.scan(/[\s]+/))
131
+ action { [:S, text] }
132
+
133
+ when (text = @ss.scan(/"([^\n\r\f"]|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*"|'([^\n\r\f']|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*'/))
134
+ action { [:STRING, text] }
135
+
136
+ when (text = @ss.scan(/./))
137
+ action { [text, text] }
138
+
139
+ else
140
+ text = @ss.string[@ss.pos .. -1]
141
+ raise ScanError, "can not match: '" + text + "'"
142
+ end # if
143
+
144
+ else
145
+ raise ScanError, "undefined state: '" + state.to_s + "'"
146
+ end # case state
147
+ token
148
+ end # def _next_token
149
+
150
+ end # class
151
+ end
7
152
  end
@@ -1,6 +1,6 @@
1
1
  module Nokogiri
2
2
  module CSS
3
- class GeneratedTokenizer < GeneratedParser
3
+ class Tokenizer
4
4
 
5
5
  macro
6
6
  nl \n|\r\n|\r|\f
@@ -11,18 +11,25 @@ module Nokogiri
11
11
  'child::text()'
12
12
  when /^self\(/
13
13
  "self::#{node.value[1]}"
14
- when /^(eq|nth|nth-of-type|nth-child)\(/
14
+ when /^eq\(/
15
+ "position() = #{node.value[1]}"
16
+ when /^(nth|nth-of-type|nth-child)\(/
15
17
  if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
16
18
  an_plus_b(node.value[1])
17
19
  else
18
- "position() = " + node.value[1]
20
+ "position() = #{node.value[1]}"
21
+ end
22
+ when /^(nth-last-child|nth-last-of-type)\(/
23
+ if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
24
+ an_plus_b(node.value[1], :last => true)
25
+ else
26
+ index = node.value[1].to_i - 1
27
+ index == 0 ? "position() = last()" : "position() = last() - #{index}"
19
28
  end
20
29
  when /^(first|first-of-type)\(/
21
30
  "position() = 1"
22
31
  when /^(last|last-of-type)\(/
23
32
  "position() = last()"
24
- when /^(nth-last-child|nth-last-of-type)\(/
25
- "position() = last() - #{node.value[1]}"
26
33
  when /^contains\(/
27
34
  "contains(., #{node.value[1]})"
28
35
  when /^gt\(/
@@ -144,17 +151,18 @@ module Nokogiri
144
151
  end
145
152
 
146
153
  private
147
- def an_plus_b node
154
+ def an_plus_b node, options={}
148
155
  raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
149
156
 
150
157
  a = node.value[0].to_i
151
158
  b = node.value[3].to_i
159
+ position = options[:last] ? "(last()-position()+1)" : "position()"
152
160
 
153
161
  if (b == 0)
154
- return "(position() mod #{a}) = 0"
162
+ return "(#{position} mod #{a}) = 0"
155
163
  else
156
164
  compare = (a < 0) ? "<=" : ">="
157
- return "(position() #{compare} #{b}) and (((position()-#{b}) mod #{a.abs}) = 0)"
165
+ return "(#{position} #{compare} #{b}) and (((#{position}-#{b}) mod #{a.abs}) = 0)"
158
166
  end
159
167
  end
160
168
 
data/lib/nokogiri/css.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'nokogiri/css/node'
2
2
  require 'nokogiri/css/xpath_visitor'
3
- require 'nokogiri/css/generated_parser'
4
- require 'nokogiri/css/generated_tokenizer'
5
- require 'nokogiri/css/tokenizer'
3
+ x = $-w
4
+ $-w = false
6
5
  require 'nokogiri/css/parser'
6
+ $-w = x
7
+
8
+ require 'nokogiri/css/tokenizer'
7
9
  require 'nokogiri/css/syntax_error'
8
10
 
9
11
  module Nokogiri
@@ -7,20 +7,22 @@ module Nokogiri
7
7
  ###
8
8
  # look for node with +name+. See Nokogiri.Slop
9
9
  def method_missing name, *args, &block
10
+ prefix = implied_xpath_context
11
+
10
12
  if args.empty?
11
- list = xpath("./#{name}")
13
+ list = xpath("#{prefix}#{name.to_s.sub(/^_/, '')}")
12
14
  elsif args.first.is_a? Hash
13
15
  hash = args.first
14
16
  if hash[:css]
15
17
  list = css("#{name}#{hash[:css]}")
16
18
  elsif hash[:xpath]
17
19
  conds = Array(hash[:xpath]).join(' and ')
18
- list = xpath("./#{name}[#{conds}]")
20
+ list = xpath("#{prefix}#{name}[#{conds}]")
19
21
  end
20
22
  else
21
23
  CSS::Parser.without_cache do
22
24
  list = xpath(
23
- *CSS.xpath_for("#{name}#{args.first}", :prefix => "./")
25
+ *CSS.xpath_for("#{name}#{args.first}", :prefix => prefix)
24
26
  )
25
27
  end
26
28
  end
@@ -3,25 +3,44 @@ module Nokogiri
3
3
  class Document < Nokogiri::XML::Document
4
4
  ###
5
5
  # Get the meta tag encoding for this document. If there is no meta tag,
6
- # then nil is returned
6
+ # then nil is returned.
7
7
  def meta_encoding
8
- return nil unless meta = css('meta').find { |node|
9
- node['http-equiv'] =~ /Content-Type/i
10
- }
11
-
12
- /charset\s*=\s*([\w-]+)/i.match(meta['content'])[1]
8
+ meta = meta_content_type and
9
+ /charset\s*=\s*([\w-]+)/i.match(meta['content'])[1]
13
10
  end
14
11
 
15
12
  ###
16
- # Set the meta tag encoding for this document. If there is no meta
17
- # content tag, nil is returned and the encoding is not set.
13
+ # Set the meta tag encoding for this document. If there is no meta
14
+ # content tag, the encoding is not set.
18
15
  def meta_encoding= encoding
19
- return nil unless meta = css('meta').find { |node|
20
- node['http-equiv'] =~ /Content-Type/i
16
+ meta = meta_content_type and
17
+ meta['content'] = "text/html; charset=%s" % encoding
18
+ end
19
+
20
+ def meta_content_type
21
+ css('meta[@http-equiv]').find { |node|
22
+ node['http-equiv'] =~ /\AContent-Type\z/i
21
23
  }
24
+ end
25
+ private :meta_content_type
22
26
 
23
- meta['content'] = "text/html; charset=%s" % encoding
24
- encoding
27
+ ###
28
+ # Get the title string of this document. Return nil if there is
29
+ # no title tag.
30
+ def title
31
+ title = at('title') and title.inner_text
32
+ end
33
+
34
+ ###
35
+ # Set the title string of this document. If there is no head
36
+ # element, the title is not set.
37
+ def title=(text)
38
+ unless title = at('title')
39
+ head = at('head') or return nil
40
+ title = Nokogiri::XML::Node.new('title', self)
41
+ head << title
42
+ end
43
+ title.children = XML::Text.new(text, self)
25
44
  end
26
45
 
27
46
  ####
@@ -38,11 +57,8 @@ module Nokogiri
38
57
  # config.format.as_xml
39
58
  # end
40
59
  #
41
- def serialize options = {}, &block
42
- options[:save_with] ||= XML::Node::SaveOptions::FORMAT |
43
- XML::Node::SaveOptions::AS_HTML |
44
- XML::Node::SaveOptions::NO_DECLARATION |
45
- XML::Node::SaveOptions::NO_EMPTY_TAGS
60
+ def serialize options = {}
61
+ options[:save_with] ||= XML::Node::SaveOptions::DEFAULT_HTML
46
62
  super
47
63
  end
48
64
 
@@ -54,14 +70,14 @@ module Nokogiri
54
70
 
55
71
  class << self
56
72
  ###
57
- # Parse HTML. +thing+ may be a String, or any object that
73
+ # Parse HTML. +string_or_io+ may be a String, or any object that
58
74
  # responds to _read_ and _close_ such as an IO, or StringIO.
59
75
  # +url+ is resource where this document is located. +encoding+ is the
60
76
  # encoding that should be used when processing the document. +options+
61
77
  # is a number that sets options in the parser, such as
62
78
  # Nokogiri::XML::ParseOptions::RECOVER. See the constants in
63
79
  # Nokogiri::XML::ParseOptions.
64
- def parse string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML, &block
80
+ def parse string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML
65
81
 
66
82
  options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
67
83
  # Give the options to the user
@@ -75,16 +91,123 @@ module Nokogiri
75
91
 
76
92
  if string_or_io.respond_to?(:read)
77
93
  url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
94
+ if !encoding
95
+ # Perform advanced encoding detection that libxml2 does
96
+ # not do.
97
+ string_or_io = EncodingReader.new(string_or_io)
98
+ begin
99
+ return read_io(string_or_io, url, encoding, options.to_i)
100
+ rescue EncodingFoundException => e
101
+ # A retry is required because libxml2 has a problem in
102
+ # that it cannot switch encoding well in the middle of
103
+ # parsing, especially if it has already seen a
104
+ # non-ASCII character when it finds an encoding hint.
105
+ encoding = e.encoding
106
+ end
107
+ end
78
108
  return read_io(string_or_io, url, encoding, options.to_i)
79
109
  end
80
110
 
81
111
  # read_memory pukes on empty docs
82
112
  return new if string_or_io.nil? or string_or_io.empty?
83
113
 
114
+ if !encoding
115
+ encoding = EncodingReader.detect_encoding(string_or_io)
116
+ end
117
+
84
118
  read_memory(string_or_io, url, encoding, options.to_i)
85
119
  end
86
120
  end
87
121
 
122
+ class EncodingFoundException < Exception # :nodoc:
123
+ attr_reader :encoding
124
+
125
+ def initialize(encoding)
126
+ @encoding = encoding
127
+ super("encoding found: %s" % encoding)
128
+ end
129
+ end
130
+
131
+ class EncodingReader # :nodoc:
132
+ class SAXHandler < Nokogiri::XML::SAX::Document # :nodoc:
133
+ attr_reader :encoding
134
+
135
+ def found(encoding)
136
+ @encoding = encoding
137
+ throw :found
138
+ end
139
+
140
+ def not_found(encoding)
141
+ found nil
142
+ end
143
+
144
+ def start_element(name, attrs = [])
145
+ case name
146
+ when /\A(?:div|h1|img|p|br)\z/
147
+ not_found
148
+ when 'meta'
149
+ attr = Hash[attrs]
150
+ charset = attr['charset'] and
151
+ found charset
152
+ http_equiv = attr['http-equiv'] and
153
+ http_equiv.match(/\AContent-Type\z/i) and
154
+ content = attr['content'] and
155
+ m = content.match(/;\s*charset\s*=\s*([\w-]+)/) and
156
+ found m[1]
157
+ end
158
+ end
159
+ end
160
+
161
+ def self.detect_encoding(chunk)
162
+ m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and
163
+ return Nokogiri.XML(m[1]).encoding
164
+
165
+ if Nokogiri.jruby?
166
+ m = chunk.match(/(<meta\s)(.*)(charset\s*=\s*([\w-]+))(.*)/i) and
167
+ return m[4]
168
+ end
169
+
170
+ handler = SAXHandler.new
171
+ parser = Nokogiri::HTML::SAX::Parser.new(handler)
172
+ catch(:found) {
173
+ parser.parse(chunk)
174
+ }
175
+ handler.encoding
176
+ rescue
177
+ nil
178
+ end
179
+
180
+ def initialize(io)
181
+ @io = io
182
+ @firstchunk = nil
183
+ end
184
+
185
+ def read(len)
186
+ # no support for a call without len
187
+
188
+ if !@firstchunk
189
+ @firstchunk = @io.read(len) or return nil
190
+
191
+ # This implementation expects that the first call from
192
+ # htmlReadIO() is made with a length long enough (~1KB) to
193
+ # achieve advanced encoding detection.
194
+ if encoding = EncodingReader.detect_encoding(@firstchunk)
195
+ # The first chunk is stored for the next read in retry.
196
+ raise EncodingFoundException, encoding
197
+ end
198
+ end
199
+
200
+ ret = @firstchunk.slice!(0, len)
201
+ if (len -= ret.length) > 0
202
+ rest = @io.read(len) and ret << rest
203
+ end
204
+ if ret.empty?
205
+ nil
206
+ else
207
+ ret
208
+ end
209
+ end
210
+ end
88
211
  end
89
212
  end
90
213
  end
@@ -1,6 +1,8 @@
1
1
  module Nokogiri
2
2
  module HTML
3
3
  class DocumentFragment < Nokogiri::XML::DocumentFragment
4
+ attr_accessor :errors
5
+
4
6
  ####
5
7
  # Create a Nokogiri::XML::DocumentFragment from +tags+, using +encoding+
6
8
  def self.parse tags, encoding = nil
@@ -15,24 +17,24 @@ module Nokogiri
15
17
  def initialize document, tags = nil, ctx = nil
16
18
  return self unless tags
17
19
 
18
- children = if ctx
19
- ctx.parse("<div>#{tags.strip}</div>").first.children
20
- else
21
- ###
22
- # This is a horrible hack, but I don't care
23
- if tags.strip =~ /^<body/i
24
- path = "/html/body"
25
- else
26
- path = "/html/body/node()"
27
- end
20
+ if ctx
21
+ preexisting_errors = document.errors.dup
22
+ node_set = ctx.parse("<div>#{tags}</div>")
23
+ node_set.first.children.each { |child| child.parent = self } unless node_set.empty?
24
+ self.errors = document.errors - preexisting_errors
25
+ else
26
+ # This is a horrible hack, but I don't care
27
+ if tags.strip =~ /^<body/i
28
+ path = "/html/body"
29
+ else
30
+ path = "/html/body/node()"
31
+ end
28
32
 
29
- HTML::Document.parse(
30
- "<html><body>#{tags.strip}</body></html>",
31
- nil,
32
- document.encoding
33
- ).xpath(path)
34
- end
35
- children.each { |child| child.parent = self }
33
+ temp_doc = HTML::Document.parse "<html><body>#{tags}", nil, document.encoding
34
+ temp_doc.xpath(path).each { |child| child.parent = self }
35
+ self.errors = temp_doc.errors
36
+ end
37
+ children
36
38
  end
37
39
  end
38
40
  end