nokogumbo 1.4.9 → 1.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ecb515ec9c492a01dce23eed6eb7336695f166d6
4
- data.tar.gz: c1ac4272ee113e56ecd72302847886042165a1fb
2
+ SHA256:
3
+ metadata.gz: 96fa61565f78d5491e0b6d5b505cf936524745eb848b8b6584fc15e20c7ae35b
4
+ data.tar.gz: e5416f71bbe90323f04b8aad4dc48b28947e43a9eb46f446f8ca1444f519a07b
5
5
  SHA512:
6
- metadata.gz: b979502577d944afa23cf0db4307494c6e53c320c3efc87c8066174d8ae3eee8902f60164375869dd6bd154abb1f6f69c42db9fbb0bc7fbd86d1b2f3e33bafd3
7
- data.tar.gz: abd153cd24e504dc82c80d38ad91c8dd3dae25e913d650d0c92a8823cb1638dcf99baa43eb40a6a36573f9de7d14d78e2d77921062e341f0e82d49290a2f7ad7
6
+ metadata.gz: 676bf3585d38cd4ad5c72b8b3afd4952e248c747683ae1072dd43f6ce1ccd279177e4d0c75a9821ed76d32806333128152231349d8d113ae5d81279580b13004
7
+ data.tar.gz: 3459078d96977399e75551c4a3ee5623091f48569984b771e540ec111125f5af91e39a8d78cbd3ce9280326b1b9395dc4a0b0d7f0a72294876682cb9fe35e3d9
data/README.md CHANGED
@@ -89,5 +89,5 @@ Installation
89
89
  Related efforts
90
90
  ============
91
91
 
92
- * [ruby-gumbo](https://github.com/galdor/ruby-gumbo#readme) - a ruby binding
92
+ * [ruby-gumbo](https://github.com/nevir/ruby-gumbo#readme) - a ruby binding
93
93
  for the Gumbo HTML5 parser.
@@ -40,4 +40,21 @@ unless have_library('gumbo', 'gumbo_parse')
40
40
  end
41
41
  end
42
42
 
43
+ # We use some Gumbo Internals, and not all distros ship the internal headers.
44
+ header_typedefs = {
45
+ 'error.h' => 'GumboErrorType',
46
+ 'insertion_mode.h' => 'GumboInsertionMode',
47
+ 'parser.h' => 'GumboParser',
48
+ 'string_buffer.h' => 'GumboStringBuffer',
49
+ 'token_type.h' => 'GumboTokenType',
50
+ }
51
+
52
+ header_typedefs.each_pair do |header, type|
53
+ unless find_type(type, header)
54
+ require 'fileutils'
55
+ FileUtils.cp Dir["#{rakehome}/gumbo-parser/src/#{header}"],
56
+ "#{rakehome}/ext/nokogumboc"
57
+ end
58
+ end
59
+
43
60
  create_makefile('nokogumboc')
@@ -19,10 +19,13 @@
19
19
  //
20
20
 
21
21
  #include <ruby.h>
22
- #include <gumbo.h>
22
+ #include "gumbo.h"
23
+ #include "error.h"
24
+ #include "parser.h"
23
25
 
24
26
  // class constants
25
27
  static VALUE Document;
28
+ static VALUE XMLSyntaxError;
26
29
 
27
30
  #ifdef NGLIB
28
31
  #include <nokogiri.h>
@@ -181,11 +184,14 @@ static xmlNodePtr walk_tree(xmlDocPtr document, GumboNode *node) {
181
184
  }
182
185
 
183
186
  // Parse a string using gumbo_parse into a Nokogiri document
184
- static VALUE parse(VALUE self, VALUE string) {
185
- GumboOutput *output = gumbo_parse_with_options(
186
- &kGumboDefaultOptions, RSTRING_PTR(string),
187
- (size_t) RSTRING_LEN(string)
188
- );
187
+ static VALUE parse(VALUE self, VALUE string, VALUE max_parse_errors) {
188
+ GumboOptions options;
189
+ memcpy(&options, &kGumboDefaultOptions, sizeof options);
190
+ options.max_errors = NUM2INT(max_parse_errors);
191
+
192
+ const char *input = RSTRING_PTR(string);
193
+ size_t input_len = RSTRING_LEN(string);
194
+ GumboOutput *output = gumbo_parse_with_options(&options, input, input_len);
189
195
  xmlDocPtr doc = xmlNewDoc(CONST_CAST "1.0");
190
196
  #ifdef NGLIB
191
197
  doc->type = XML_HTML_DOCUMENT_NODE;
@@ -210,9 +216,49 @@ static VALUE parse(VALUE self, VALUE string) {
210
216
  xmlAddChild((xmlNodePtr)doc, node);
211
217
  }
212
218
  }
213
- gumbo_destroy_output(&kGumboDefaultOptions, output);
214
219
 
215
- return Nokogiri_wrap_xml_document(Document, doc);
220
+ VALUE rdoc = Nokogiri_wrap_xml_document(Document, doc);
221
+
222
+ // Add parse errors to rdoc.
223
+ if (output->errors.length) {
224
+ GumboVector *errors = &output->errors;
225
+ GumboParser parser = { ._options = &options };
226
+ GumboStringBuffer msg;
227
+ VALUE rerrors = rb_ary_new2(errors->length);
228
+
229
+ gumbo_string_buffer_init(&parser, &msg);
230
+ for (int i=0; i < errors->length; i++) {
231
+ GumboError *err = errors->data[i];
232
+ gumbo_string_buffer_clear(&parser, &msg);
233
+ // Work around bug in gumbo_caret_diagnostic_to_string.
234
+ // See https://github.com/google/gumbo-parser/pull/371
235
+ // The bug occurs when the error starts with a newline (unless it's the
236
+ // first character in the input--but that shouldn't cause an error in
237
+ // the first place.
238
+ if (*err->original_text == '\n' && err->original_text != input)
239
+ --err->original_text;
240
+ gumbo_caret_diagnostic_to_string(&parser, err, input, &msg);
241
+ VALUE err_str = rb_str_new(msg.data, msg.length);
242
+ VALUE syntax_error = rb_class_new_instance(1, &err_str, XMLSyntaxError);
243
+ rb_iv_set(syntax_error, "@domain", INT2NUM(1)); // XML_FROM_PARSER
244
+ rb_iv_set(syntax_error, "@code", INT2NUM(1)); // XML_ERR_INTERNAL_ERROR
245
+ rb_iv_set(syntax_error, "@level", INT2NUM(2)); // XML_ERR_ERROR
246
+ rb_iv_set(syntax_error, "@file", Qnil);
247
+ rb_iv_set(syntax_error, "@line", INT2NUM(err->position.line));
248
+ rb_iv_set(syntax_error, "@str1", Qnil);
249
+ rb_iv_set(syntax_error, "@str2", Qnil);
250
+ rb_iv_set(syntax_error, "@str3", Qnil);
251
+ rb_iv_set(syntax_error, "@int1", INT2NUM(err->type));
252
+ rb_iv_set(syntax_error, "@column", INT2NUM(err->position.column));
253
+ rb_ary_push(rerrors, syntax_error);
254
+ }
255
+ rb_iv_set(rdoc, "@errors", rerrors);
256
+ gumbo_string_buffer_destroy(&parser, &msg);
257
+ }
258
+
259
+ gumbo_destroy_output(&options, output);
260
+
261
+ return rdoc;
216
262
  }
217
263
 
218
264
  // Initialize the Nokogumbo class and fetch constants we will use later
@@ -224,10 +270,11 @@ void Init_nokogumboc() {
224
270
  VALUE Nokogiri = rb_const_get(rb_cObject, rb_intern("Nokogiri"));
225
271
  VALUE HTML = rb_const_get(Nokogiri, rb_intern("HTML"));
226
272
  Document = rb_const_get(HTML, rb_intern("Document"));
273
+ VALUE XML = rb_const_get(Nokogiri, rb_intern("XML"));
274
+ XMLSyntaxError = rb_const_get(XML, rb_intern("SyntaxError"));
227
275
 
228
276
  #ifndef NGLIB
229
277
  // more class constants
230
- VALUE XML = rb_const_get(Nokogiri, rb_intern("XML"));
231
278
  Element = rb_const_get(XML, rb_intern("Element"));
232
279
  Text = rb_const_get(XML, rb_intern("Text"));
233
280
  CDATA = rb_const_get(XML, rb_intern("CDATA"));
@@ -244,5 +291,5 @@ void Init_nokogumboc() {
244
291
 
245
292
  // define Nokogumbo class with a singleton parse method
246
293
  VALUE Gumbo = rb_define_class("Nokogumbo", rb_cObject);
247
- rb_define_singleton_method(Gumbo, "parse", parse, 1);
294
+ rb_define_singleton_method(Gumbo, "parse", parse, 2);
248
295
  }
data/lib/nokogumbo.rb CHANGED
@@ -4,14 +4,14 @@ require 'nokogumboc'
4
4
  module Nokogiri
5
5
  # Parse an HTML document. +string+ contains the document. +string+
6
6
  # may also be an IO-like object. Returns a +Nokogiri::HTML::Document+.
7
- def self.HTML5(string)
8
- Nokogiri::HTML5.parse(string)
7
+ def self.HTML5(*args)
8
+ Nokogiri::HTML5.parse(*args)
9
9
  end
10
10
 
11
11
  module HTML5
12
12
  # Parse an HTML document. +string+ contains the document. +string+
13
13
  # may also be an IO-like object. Returns a +Nokogiri::HTML::Document+.
14
- def self.parse(string)
14
+ def self.parse(string, options={})
15
15
  if string.respond_to? :read
16
16
  string = string.read
17
17
  end
@@ -21,7 +21,7 @@ module Nokogiri
21
21
  string = reencode(string)
22
22
  end
23
23
 
24
- Nokogumbo.parse(string.to_s)
24
+ Nokogumbo.parse(string.to_s, options[:max_parse_errors] || 0)
25
25
  end
26
26
 
27
27
  # Fetch and parse a HTML document from the web, following redirects,
@@ -67,7 +67,7 @@ module Nokogiri
67
67
 
68
68
  case response
69
69
  when Net::HTTPSuccess
70
- doc = parse(reencode(response.body, response['content-type']))
70
+ doc = parse(reencode(response.body, response['content-type']), options)
71
71
  doc.instance_variable_set('@response', response)
72
72
  doc.class.send(:attr_reader, :response)
73
73
  doc
@@ -83,8 +83,8 @@ module Nokogiri
83
83
  # while fragment is on the Gumbo TODO list, simulate it by doing
84
84
  # a full document parse and ignoring the parent <html>, <head>, and <body>
85
85
  # tags, and collecting up the children of each.
86
- def self.fragment(string)
87
- doc = parse(string)
86
+ def self.fragment(*args)
87
+ doc = parse(*args)
88
88
  fragment = Nokogiri::HTML::DocumentFragment.new(doc)
89
89
 
90
90
  if doc.children.length != 1 or doc.children.first.name != 'html'
data/test-nokogumbo.rb CHANGED
@@ -78,7 +78,7 @@ class TestNokogumbo < Minitest::Test
78
78
  end
79
79
 
80
80
  def test_html5_doctype
81
- doc = Nokogumbo.parse("<!DOCTYPE html><html></html>")
81
+ doc = Nokogiri::HTML5.parse("<!DOCTYPE html><html></html>")
82
82
  assert_match /<!DOCTYPE html>/, doc.to_html
83
83
  end
84
84
 
@@ -125,6 +125,44 @@ class TestNokogumbo < Minitest::Test
125
125
  assert_equal ["html", "comment", "html", "comment"], doc.children.map(&:name)
126
126
  end
127
127
 
128
+ def test_parse_errors
129
+ doc = Nokogiri::HTML5("<!DOCTYPE html><html><!-- -- --></a>", max_parse_errors: 10)
130
+ assert_equal doc.errors.length, 2
131
+ doc = Nokogiri::HTML5("<!DOCTYPE html><html>", max_parse_errors: 10)
132
+ assert_empty doc.errors
133
+ end
134
+
135
+ def test_max_parse_errors
136
+ # This document contains 2 parse errors, but we force limit to 1.
137
+ doc = Nokogiri::HTML5("<!DOCTYPE html><html><!-- -- --></a>", max_parse_errors: 1)
138
+ assert_equal 1, doc.errors.length
139
+ doc = Nokogiri::HTML5("<!DOCTYPE html><html>", max_parse_errors: 1)
140
+ assert_empty doc.errors
141
+ end
142
+
143
+ def test_default_max_parse_errors
144
+ # This document contains 200 parse errors, but default limit is 0.
145
+ doc = Nokogiri::HTML5("<!DOCTYPE html><html>" + "</p>" * 200)
146
+ assert_equal 0, doc.errors.length
147
+ end
148
+
149
+ def test_parse_fragment_errors
150
+ doc = Nokogiri::HTML5.fragment("<\r\n", max_parse_errors: 10)
151
+ refute_empty doc.errors
152
+ end
153
+
154
+ def test_fragment_max_parse_errors
155
+ # This fragment contains 3 parse errors, but we force limit to 1.
156
+ doc = Nokogiri::HTML5.fragment("<!-- -- --></a>", max_parse_errors: 1)
157
+ assert_equal 1, doc.errors.length
158
+ end
159
+
160
+ def test_fragment_default_max_parse_errors
161
+ # This fragment contains 201 parse errors, but default limit is 0.
162
+ doc = Nokogiri::HTML5.fragment("</p>" * 200)
163
+ assert_equal 0, doc.errors.length
164
+ end
165
+
128
166
  private
129
167
 
130
168
  def buffer
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nokogumbo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.9
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-01 00:00:00.000000000 Z
11
+ date: 2018-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: Nokogumbo allows a Ruby program to invoke the Gumbo HTML5 parser and
@@ -32,11 +32,10 @@ extensions:
32
32
  - ext/nokogumboc/extconf.rb
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - ext/nokogumboc/extconf.rb
36
- - ext/nokogumboc/nokogumbo.c
37
- - lib/nokogumbo.rb
38
35
  - LICENSE.txt
39
36
  - README.md
37
+ - ext/nokogumboc/extconf.rb
38
+ - ext/nokogumboc/nokogumbo.c
40
39
  - gumbo-parser/src/attribute.c
41
40
  - gumbo-parser/src/attribute.h
42
41
  - gumbo-parser/src/char_ref.c
@@ -69,10 +68,11 @@ files:
69
68
  - gumbo-parser/src/vector.c
70
69
  - gumbo-parser/src/vector.h
71
70
  - gumbo-parser/visualc/include/strings.h
71
+ - lib/nokogumbo.rb
72
72
  - test-nokogumbo.rb
73
73
  homepage: https://github.com/rubys/nokogumbo/#readme
74
74
  licenses:
75
- - Apache 2.0
75
+ - Apache-2.0
76
76
  metadata: {}
77
77
  post_install_message:
78
78
  rdoc_options: []
@@ -80,17 +80,17 @@ require_paths:
80
80
  - lib
81
81
  required_ruby_version: !ruby/object:Gem::Requirement
82
82
  requirements:
83
- - - '>='
83
+ - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  required_rubygems_version: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - '>='
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  requirements: []
92
92
  rubyforge_project:
93
- rubygems_version: 2.0.14.1
93
+ rubygems_version: 2.7.4
94
94
  signing_key:
95
95
  specification_version: 4
96
96
  summary: Nokogiri interface to the Gumbo HTML5 parser