nokolexbor 0.3.1 → 0.3.3
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 +4 -4
- data/ext/nokolexbor/libxml/xpathInternals.h +4 -5
- data/ext/nokolexbor/nl_cdata.c +1 -1
- data/ext/nokolexbor/nl_comment.c +1 -1
- data/ext/nokolexbor/nl_document.c +2 -0
- data/ext/nokolexbor/nl_document_fragment.c +39 -0
- data/ext/nokolexbor/nl_error.c +93 -0
- data/ext/nokolexbor/nl_node.c +32 -18
- data/ext/nokolexbor/nl_processing_instruction.c +47 -0
- data/ext/nokolexbor/nl_text.c +1 -1
- data/ext/nokolexbor/nl_xpath_context.c +105 -0
- data/ext/nokolexbor/nokolexbor.c +6 -52
- data/ext/nokolexbor/nokolexbor.h +4 -1
- data/ext/nokolexbor/xml_xpath.c +7 -0
- data/lib/nokolexbor/document.rb +4 -0
- data/lib/nokolexbor/document_fragment.rb +31 -0
- data/lib/nokolexbor/node.rb +49 -1
- data/lib/nokolexbor/node_set.rb +17 -0
- data/lib/nokolexbor/version.rb +1 -1
- data/lib/nokolexbor.rb +1 -0
- data/patches/0001-lexbor-support-text-pseudo-element.patch +4 -13
- data/patches/0002-lexbor-match-id-class-case-sensitive.patch +2 -2
- data/vendor/lexbor/source/lexbor/core/lexbor.h +8 -0
- data/vendor/lexbor/source/lexbor/ports/posix/lexbor/core/memory.c +24 -4
- data/vendor/lexbor/source/lexbor/ports/windows_nt/lexbor/core/memory.c +24 -4
- data/vendor/lexbor/source/lexbor/selectors/selectors.c +1 -2
- metadata +6 -3
- data/ext/nokolexbor/memory.c +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 042127a2ed4027c52d3718c148921604cae07c274dddb7f3702c7caf0708863f
|
4
|
+
data.tar.gz: 60230b55b773ef41abdca313adc3ffdba38a0b8462c9d23c3365e57c68b63bd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f06063b84e62e23ba093a397ba6ffdbd802480e711ca24966d5b78be8bc8a7299754ab8bb4cd5d77d6dfe39efa7c21c705b105fe9d626d62eddc5e2e5a6ec9fb
|
7
|
+
data.tar.gz: 86ddfdb650b78827071385cfca708ddbffcd35204a71f439315f800e8e60ee73c2d49ce46e28192ac454df8bab7ef8cbc937b97830e0b488290dbadccd8e51d6
|
@@ -477,11 +477,10 @@ XMLPUBFUN xmlXPathParserContextPtr XMLCALL
|
|
477
477
|
XMLPUBFUN void XMLCALL
|
478
478
|
nl_xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt);
|
479
479
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
valuePush (xmlXPathParserContextPtr ctxt,
|
480
|
+
XMLPUBFUN xmlXPathObjectPtr XMLCALL
|
481
|
+
nl_xmlXPathValuePop (xmlXPathParserContextPtr ctxt);
|
482
|
+
XMLPUBFUN int XMLCALL
|
483
|
+
nl_xmlXPathValuePush (xmlXPathParserContextPtr ctxt,
|
485
484
|
xmlXPathObjectPtr value);
|
486
485
|
|
487
486
|
XMLPUBFUN xmlXPathObjectPtr XMLCALL
|
data/ext/nokolexbor/nl_cdata.c
CHANGED
@@ -20,7 +20,7 @@ nl_cdata_new(int argc, VALUE *argv, VALUE klass)
|
|
20
20
|
|
21
21
|
document = nl_rb_document_unwrap(rb_document);
|
22
22
|
|
23
|
-
const char*
|
23
|
+
const char *c_content = StringValuePtr(rb_content);
|
24
24
|
size_t content_len = RSTRING_LEN(rb_content);
|
25
25
|
lxb_dom_cdata_section_t *element = lxb_dom_document_create_cdata_section(document, (const lxb_char_t *)c_content, content_len);
|
26
26
|
if (element == NULL) {
|
data/ext/nokolexbor/nl_comment.c
CHANGED
@@ -20,7 +20,7 @@ nl_comment_new(int argc, VALUE *argv, VALUE klass)
|
|
20
20
|
|
21
21
|
document = nl_rb_document_unwrap(rb_document);
|
22
22
|
|
23
|
-
const char*
|
23
|
+
const char *c_content = StringValuePtr(rb_content);
|
24
24
|
size_t content_len = RSTRING_LEN(rb_content);
|
25
25
|
lxb_dom_comment_t *element = lxb_dom_document_create_comment(document, (const lxb_char_t *)c_content, content_len);
|
26
26
|
if (element == NULL) {
|
@@ -41,6 +41,8 @@ nl_document_parse(VALUE self, VALUE rb_string_or_io)
|
|
41
41
|
rb_raise(rb_eRuntimeError, "Error creating document");
|
42
42
|
}
|
43
43
|
|
44
|
+
lxb_dom_document_scripting_set(lxb_dom_interface_document(document), true);
|
45
|
+
|
44
46
|
lxb_status_t status = lxb_html_document_parse(document, (const lxb_char_t *)html_c, html_len);
|
45
47
|
if (status != LXB_STATUS_OK) {
|
46
48
|
nl_raise_lexbor_error(status);
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#include "nokolexbor.h"
|
2
|
+
|
3
|
+
VALUE cNokolexborDocumentFragment;
|
4
|
+
extern VALUE cNokolexborNode;
|
5
|
+
extern VALUE mNokolexbor;
|
6
|
+
|
7
|
+
static VALUE
|
8
|
+
nl_document_fragment_new(int argc, VALUE *argv, VALUE klass)
|
9
|
+
{
|
10
|
+
lxb_dom_document_t *document;
|
11
|
+
VALUE rb_document;
|
12
|
+
VALUE rest;
|
13
|
+
|
14
|
+
rb_scan_args(argc, argv, "1*", &rb_document, &rest);
|
15
|
+
|
16
|
+
if (!rb_obj_is_kind_of(rb_document, cNokolexborDocument)) {
|
17
|
+
rb_raise(rb_eArgError, "Document must be a Nokolexbor::Document");
|
18
|
+
}
|
19
|
+
|
20
|
+
document = nl_rb_document_unwrap(rb_document);
|
21
|
+
|
22
|
+
lxb_dom_document_fragment_t *node = lxb_dom_document_create_document_fragment(document);
|
23
|
+
if (node == NULL) {
|
24
|
+
rb_raise(rb_eRuntimeError, "Error creating document fragment");
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE rb_node = nl_rb_node_create(&node->node, rb_document);
|
28
|
+
|
29
|
+
rb_obj_call_init(rb_node, argc, argv);
|
30
|
+
|
31
|
+
return rb_node;
|
32
|
+
}
|
33
|
+
|
34
|
+
void Init_nl_document_fragment(void)
|
35
|
+
{
|
36
|
+
cNokolexborDocumentFragment = rb_define_class_under(mNokolexbor, "DocumentFragment", cNokolexborNode);
|
37
|
+
|
38
|
+
rb_define_singleton_method(cNokolexborDocumentFragment, "new", nl_document_fragment_new, -1);
|
39
|
+
}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
#include "nokolexbor.h"
|
2
|
+
|
3
|
+
VALUE eLexborError;
|
4
|
+
VALUE eLexborMemoryAllocationError;
|
5
|
+
VALUE eLexborSmallBufferError;
|
6
|
+
VALUE eLexborObjectIsNullError;
|
7
|
+
VALUE eLexborIncompleteObjectError;
|
8
|
+
VALUE eLexborNoFreeSlotError;
|
9
|
+
VALUE eLexborTooSmallSizeError;
|
10
|
+
VALUE eLexborNotExistsError;
|
11
|
+
VALUE eLexborWrongArgsError;
|
12
|
+
VALUE eLexborWrongStageError;
|
13
|
+
VALUE eLexborUnexpectedResultError;
|
14
|
+
VALUE eLexborUnexpectedDataError;
|
15
|
+
VALUE eLexborOverflowError;
|
16
|
+
VALUE eLexborContinueStatus;
|
17
|
+
VALUE eLexborSmallBufferStatus;
|
18
|
+
VALUE eLexborAbortedStatus;
|
19
|
+
VALUE eLexborStoppedStatus;
|
20
|
+
VALUE eLexborNextStatus;
|
21
|
+
VALUE eLexborStopStatus;
|
22
|
+
extern VALUE mNokolexbor;
|
23
|
+
|
24
|
+
void nl_raise_lexbor_error(lxb_status_t error)
|
25
|
+
{
|
26
|
+
switch (error) {
|
27
|
+
case LXB_STATUS_ERROR:
|
28
|
+
rb_exc_raise(eLexborError);
|
29
|
+
case LXB_STATUS_ERROR_MEMORY_ALLOCATION:
|
30
|
+
rb_exc_raise(eLexborMemoryAllocationError);
|
31
|
+
case LXB_STATUS_ERROR_OBJECT_IS_NULL:
|
32
|
+
rb_exc_raise(eLexborObjectIsNullError);
|
33
|
+
case LXB_STATUS_ERROR_SMALL_BUFFER:
|
34
|
+
rb_exc_raise(eLexborSmallBufferError);
|
35
|
+
case LXB_STATUS_ERROR_INCOMPLETE_OBJECT:
|
36
|
+
rb_exc_raise(eLexborIncompleteObjectError);
|
37
|
+
case LXB_STATUS_ERROR_NO_FREE_SLOT:
|
38
|
+
rb_exc_raise(eLexborNoFreeSlotError);
|
39
|
+
case LXB_STATUS_ERROR_TOO_SMALL_SIZE:
|
40
|
+
rb_exc_raise(eLexborTooSmallSizeError);
|
41
|
+
case LXB_STATUS_ERROR_NOT_EXISTS:
|
42
|
+
rb_exc_raise(eLexborNotExistsError);
|
43
|
+
case LXB_STATUS_ERROR_WRONG_ARGS:
|
44
|
+
rb_exc_raise(eLexborWrongArgsError);
|
45
|
+
case LXB_STATUS_ERROR_WRONG_STAGE:
|
46
|
+
rb_exc_raise(eLexborWrongStageError);
|
47
|
+
case LXB_STATUS_ERROR_UNEXPECTED_RESULT:
|
48
|
+
rb_exc_raise(eLexborUnexpectedResultError);
|
49
|
+
case LXB_STATUS_ERROR_UNEXPECTED_DATA:
|
50
|
+
rb_raise(eLexborUnexpectedDataError, "Invalid syntax");
|
51
|
+
case LXB_STATUS_ERROR_OVERFLOW:
|
52
|
+
rb_exc_raise(eLexborOverflowError);
|
53
|
+
case LXB_STATUS_CONTINUE:
|
54
|
+
rb_exc_raise(eLexborContinueStatus);
|
55
|
+
case LXB_STATUS_SMALL_BUFFER:
|
56
|
+
rb_exc_raise(eLexborSmallBufferStatus);
|
57
|
+
case LXB_STATUS_ABORTED:
|
58
|
+
rb_exc_raise(eLexborAbortedStatus);
|
59
|
+
case LXB_STATUS_STOPPED:
|
60
|
+
rb_exc_raise(eLexborStoppedStatus);
|
61
|
+
case LXB_STATUS_NEXT:
|
62
|
+
rb_exc_raise(eLexborNextStatus);
|
63
|
+
case LXB_STATUS_STOP:
|
64
|
+
rb_exc_raise(eLexborStopStatus);
|
65
|
+
case LXB_STATUS_OK:
|
66
|
+
return;
|
67
|
+
default:
|
68
|
+
rb_raise(eLexborError, "Unknown error (%d)", error);
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
void Init_nl_error(void)
|
73
|
+
{
|
74
|
+
eLexborError = rb_define_class_under(mNokolexbor, "LexborError", rb_eStandardError);
|
75
|
+
eLexborMemoryAllocationError = rb_define_class_under(mNokolexbor, "LexborMemoryAllocationError", eLexborError);
|
76
|
+
eLexborSmallBufferError = rb_define_class_under(mNokolexbor, "LexborSmallBufferError", eLexborError);
|
77
|
+
eLexborObjectIsNullError = rb_define_class_under(mNokolexbor, "LexborObjectIsNullError", eLexborError);
|
78
|
+
eLexborIncompleteObjectError = rb_define_class_under(mNokolexbor, "LexborIncompleteObjectError", eLexborError);
|
79
|
+
eLexborNoFreeSlotError = rb_define_class_under(mNokolexbor, "LexborNoFreeSlotError", eLexborError);
|
80
|
+
eLexborTooSmallSizeError = rb_define_class_under(mNokolexbor, "LexborTooSmallSizeError", eLexborError);
|
81
|
+
eLexborNotExistsError = rb_define_class_under(mNokolexbor, "LexborNotExistsError", eLexborError);
|
82
|
+
eLexborWrongArgsError = rb_define_class_under(mNokolexbor, "LexborWrongArgsError", eLexborError);
|
83
|
+
eLexborWrongStageError = rb_define_class_under(mNokolexbor, "LexborWrongStageError", eLexborError);
|
84
|
+
eLexborUnexpectedResultError = rb_define_class_under(mNokolexbor, "LexborUnexpectedResultError", eLexborError);
|
85
|
+
eLexborUnexpectedDataError = rb_define_class_under(mNokolexbor, "LexborUnexpectedDataError", eLexborError);
|
86
|
+
eLexborOverflowError = rb_define_class_under(mNokolexbor, "LexborOverflowError", eLexborError);
|
87
|
+
eLexborContinueStatus = rb_define_class_under(mNokolexbor, "LexborContinueStatus", eLexborError);
|
88
|
+
eLexborSmallBufferStatus = rb_define_class_under(mNokolexbor, "LexborSmallBufferStatus", eLexborError);
|
89
|
+
eLexborAbortedStatus = rb_define_class_under(mNokolexbor, "LexborAbortedStatus", eLexborError);
|
90
|
+
eLexborStoppedStatus = rb_define_class_under(mNokolexbor, "LexborStoppedStatus", eLexborError);
|
91
|
+
eLexborNextStatus = rb_define_class_under(mNokolexbor, "LexborNextStatus", eLexborError);
|
92
|
+
eLexborStopStatus = rb_define_class_under(mNokolexbor, "LexborStopStatus", eLexborError);
|
93
|
+
}
|
data/ext/nokolexbor/nl_node.c
CHANGED
@@ -9,7 +9,9 @@ extern VALUE mNokolexbor;
|
|
9
9
|
extern VALUE cNokolexborDocument;
|
10
10
|
extern VALUE cNokolexborText;
|
11
11
|
extern VALUE cNokolexborComment;
|
12
|
+
extern VALUE cNokolexborProcessingInstruction;
|
12
13
|
extern VALUE cNokolexborNodeSet;
|
14
|
+
extern VALUE cNokolexborDocumentFragment;
|
13
15
|
extern VALUE eLexborError;
|
14
16
|
VALUE cNokolexborNode;
|
15
17
|
VALUE cNokolexborElement;
|
@@ -41,8 +43,9 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
|
|
41
43
|
// break;
|
42
44
|
// case LXB_DOM_NODE_TYPE_ENTITY:
|
43
45
|
// break;
|
44
|
-
|
45
|
-
|
46
|
+
case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
|
47
|
+
rb_class = cNokolexborProcessingInstruction;
|
48
|
+
break;
|
46
49
|
case LXB_DOM_NODE_TYPE_COMMENT:
|
47
50
|
rb_class = cNokolexborComment;
|
48
51
|
break;
|
@@ -50,8 +53,9 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
|
|
50
53
|
// break;
|
51
54
|
// case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
|
52
55
|
// break;
|
53
|
-
|
54
|
-
|
56
|
+
case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
|
57
|
+
rb_class = cNokolexborDocumentFragment;
|
58
|
+
break;
|
55
59
|
// case LXB_DOM_NODE_TYPE_NOTATION:
|
56
60
|
// break;
|
57
61
|
default:
|
@@ -91,7 +95,7 @@ nl_node_new(int argc, VALUE *argv, VALUE klass)
|
|
91
95
|
|
92
96
|
document = nl_rb_document_unwrap(rb_document);
|
93
97
|
|
94
|
-
const char*
|
98
|
+
const char *c_name = StringValuePtr(rb_name);
|
95
99
|
size_t name_len = RSTRING_LEN(rb_name);
|
96
100
|
lxb_dom_element_t *element = lxb_dom_document_create_element(document, (const lxb_char_t *)c_name, name_len, NULL);
|
97
101
|
if (element == NULL) {
|
@@ -657,17 +661,19 @@ nl_node_name(VALUE self)
|
|
657
661
|
}
|
658
662
|
|
659
663
|
static lxb_dom_node_t *
|
660
|
-
nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_char_t *html, size_t size)
|
664
|
+
nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_dom_element_t *element, lxb_char_t *html, size_t size)
|
661
665
|
{
|
662
666
|
size_t tag_name_len;
|
663
667
|
lxb_html_document_t *html_doc = lxb_html_interface_document(doc);
|
664
|
-
const lxb_char_t *tag_name = lxb_tag_name_by_id(lxb_html_document_tags(html_doc), LXB_TAG__UNDEF, &tag_name_len);
|
665
|
-
if (tag_name == NULL) {
|
666
|
-
rb_raise(rb_eRuntimeError, "Error getting tag name");
|
667
|
-
}
|
668
|
-
lxb_dom_element_t *element = lxb_dom_document_create_element(doc, tag_name, tag_name_len, NULL);
|
669
668
|
if (element == NULL) {
|
670
|
-
|
669
|
+
const lxb_char_t *tag_name = lxb_tag_name_by_id(lxb_html_document_tags(html_doc), LXB_TAG__UNDEF, &tag_name_len);
|
670
|
+
if (tag_name == NULL) {
|
671
|
+
rb_raise(rb_eRuntimeError, "Error getting tag name");
|
672
|
+
}
|
673
|
+
element = lxb_dom_document_create_element(doc, tag_name, tag_name_len, NULL);
|
674
|
+
if (element == NULL) {
|
675
|
+
rb_raise(rb_eRuntimeError, "Error creating element");
|
676
|
+
}
|
671
677
|
}
|
672
678
|
lxb_dom_node_t *frag_root = lxb_html_document_parse_fragment(html_doc, element, html, size);
|
673
679
|
if (frag_root == NULL) {
|
@@ -677,14 +683,22 @@ nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_char_t *html, size_t size)
|
|
677
683
|
}
|
678
684
|
|
679
685
|
static VALUE
|
680
|
-
|
686
|
+
nl_node_parse(VALUE self, VALUE html)
|
681
687
|
{
|
682
688
|
Check_Type(html, T_STRING);
|
683
689
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
684
690
|
lxb_dom_document_t *doc = node->owner_document;
|
685
691
|
|
686
|
-
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(html), RSTRING_LEN(html));
|
687
|
-
|
692
|
+
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, lxb_dom_interface_element(node), (lxb_char_t *)RSTRING_PTR(html), RSTRING_LEN(html));
|
693
|
+
lexbor_array_t *array = lexbor_array_create();
|
694
|
+
|
695
|
+
while (frag_root->first_child != NULL) {
|
696
|
+
lxb_dom_node_t *child = frag_root->first_child;
|
697
|
+
lxb_dom_node_remove(child);
|
698
|
+
lexbor_array_push(array, child);
|
699
|
+
}
|
700
|
+
lxb_dom_node_destroy(frag_root);
|
701
|
+
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
688
702
|
}
|
689
703
|
|
690
704
|
static VALUE
|
@@ -703,7 +717,7 @@ nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
|
|
703
717
|
}
|
704
718
|
|
705
719
|
if (TYPE(new) == T_STRING) {
|
706
|
-
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
|
720
|
+
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
|
707
721
|
lexbor_array_t *array = lexbor_array_create();
|
708
722
|
|
709
723
|
while (frag_root->first_child != NULL) {
|
@@ -734,7 +748,7 @@ nl_node_add_child(VALUE self, VALUE new)
|
|
734
748
|
lxb_dom_document_t *doc = node->owner_document;
|
735
749
|
|
736
750
|
if (TYPE(new) == T_STRING) {
|
737
|
-
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
|
751
|
+
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
|
738
752
|
lexbor_array_t *array = lexbor_array_create();
|
739
753
|
|
740
754
|
while (frag_root->first_child != NULL) {
|
@@ -859,7 +873,7 @@ void Init_nl_node(void)
|
|
859
873
|
rb_define_method(cNokolexborNode, "destroy", nl_node_destroy, 0);
|
860
874
|
rb_define_method(cNokolexborNode, "attrs", nl_node_attrs, 0);
|
861
875
|
rb_define_method(cNokolexborNode, "name", nl_node_name, 0);
|
862
|
-
rb_define_method(cNokolexborNode, "
|
876
|
+
rb_define_method(cNokolexborNode, "parse", nl_node_parse, 1);
|
863
877
|
rb_define_method(cNokolexborNode, "add_sibling", nl_node_add_sibling, 2);
|
864
878
|
rb_define_method(cNokolexborNode, "add_child", nl_node_add_child, 1);
|
865
879
|
rb_define_method(cNokolexborNode, "node_type", nl_node_get_type, 0);
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#include "nokolexbor.h"
|
2
|
+
|
3
|
+
VALUE cNokolexborProcessingInstruction;
|
4
|
+
extern VALUE cNokolexborNode;
|
5
|
+
extern VALUE mNokolexbor;
|
6
|
+
|
7
|
+
static VALUE
|
8
|
+
nl_processing_instruction_new(int argc, VALUE *argv, VALUE klass)
|
9
|
+
{
|
10
|
+
lxb_dom_document_t *document;
|
11
|
+
VALUE rb_name;
|
12
|
+
VALUE rb_content;
|
13
|
+
VALUE rb_document;
|
14
|
+
VALUE rest;
|
15
|
+
|
16
|
+
rb_scan_args(argc, argv, "3*", &rb_name, &rb_content, &rb_document, &rest);
|
17
|
+
|
18
|
+
if (!rb_obj_is_kind_of(rb_document, cNokolexborDocument)) {
|
19
|
+
rb_raise(rb_eArgError, "Document must be a Nokolexbor::Document");
|
20
|
+
}
|
21
|
+
|
22
|
+
document = nl_rb_document_unwrap(rb_document);
|
23
|
+
|
24
|
+
const char *c_name = StringValuePtr(rb_name);
|
25
|
+
size_t name_len = RSTRING_LEN(rb_name);
|
26
|
+
const char *c_content = StringValuePtr(rb_content);
|
27
|
+
size_t content_len = RSTRING_LEN(rb_content);
|
28
|
+
lxb_dom_processing_instruction_t *node = lxb_dom_document_create_processing_instruction(document, (const lxb_char_t *)c_name, name_len, (const lxb_char_t *)c_content, content_len);
|
29
|
+
if (node == NULL) {
|
30
|
+
rb_raise(rb_eRuntimeError, "Error creating processing instruction");
|
31
|
+
}
|
32
|
+
|
33
|
+
VALUE rb_node = nl_rb_node_create(&node->char_data.node, rb_document);
|
34
|
+
|
35
|
+
if (rb_block_given_p()) {
|
36
|
+
rb_yield(rb_node);
|
37
|
+
}
|
38
|
+
|
39
|
+
return rb_node;
|
40
|
+
}
|
41
|
+
|
42
|
+
void Init_nl_processing_instruction(void)
|
43
|
+
{
|
44
|
+
cNokolexborProcessingInstruction = rb_define_class_under(mNokolexbor, "ProcessingInstruction", cNokolexborNode);
|
45
|
+
|
46
|
+
rb_define_singleton_method(cNokolexborProcessingInstruction, "new", nl_processing_instruction_new, -1);
|
47
|
+
}
|
data/ext/nokolexbor/nl_text.c
CHANGED
@@ -20,7 +20,7 @@ nl_text_new(int argc, VALUE *argv, VALUE klass)
|
|
20
20
|
|
21
21
|
document = nl_rb_document_unwrap(rb_document);
|
22
22
|
|
23
|
-
const char*
|
23
|
+
const char *c_text = StringValuePtr(rb_text);
|
24
24
|
size_t text_len = RSTRING_LEN(rb_text);
|
25
25
|
lxb_dom_text_t *element = lxb_dom_document_create_text_node(document, (const lxb_char_t *)c_text, text_len);
|
26
26
|
if (element == NULL) {
|
@@ -15,12 +15,110 @@ VALUE cNokolexborXpathContext;
|
|
15
15
|
VALUE mNokolexborXpath;
|
16
16
|
VALUE cNokolexborXpathSyntaxError;
|
17
17
|
|
18
|
+
static const xmlChar *NOKOGIRI_PREFIX = (const xmlChar *)"nokogiri";
|
19
|
+
static const xmlChar *NOKOGIRI_URI = (const xmlChar *)"http://www.nokogiri.org/default_ns/ruby/extensions_functions";
|
20
|
+
static const xmlChar *NOKOGIRI_BUILTIN_PREFIX = (const xmlChar *)"nokogiri-builtin";
|
21
|
+
static const xmlChar *NOKOGIRI_BUILTIN_URI = (const xmlChar *)"https://www.nokogiri.org/default_ns/ruby/builtins";
|
22
|
+
|
18
23
|
static void
|
19
24
|
free_xml_xpath_context(xmlXPathContextPtr ctx)
|
20
25
|
{
|
21
26
|
nl_xmlXPathFreeContext(ctx);
|
22
27
|
}
|
23
28
|
|
29
|
+
/* find a CSS class in an HTML element's `class` attribute */
|
30
|
+
static const xmlChar *
|
31
|
+
builtin_css_class(const xmlChar *str, const xmlChar *val)
|
32
|
+
{
|
33
|
+
int val_len;
|
34
|
+
|
35
|
+
if (str == NULL) {
|
36
|
+
return (NULL);
|
37
|
+
}
|
38
|
+
if (val == NULL) {
|
39
|
+
return (NULL);
|
40
|
+
}
|
41
|
+
|
42
|
+
val_len = nl_xmlStrlen(val);
|
43
|
+
if (val_len == 0) {
|
44
|
+
return (str);
|
45
|
+
}
|
46
|
+
|
47
|
+
while (*str != 0) {
|
48
|
+
if ((*str == *val) && !nl_xmlStrncmp(str, val, val_len)) {
|
49
|
+
const xmlChar *next_byte = str + val_len;
|
50
|
+
|
51
|
+
/* only match if the next byte is whitespace or end of string */
|
52
|
+
if ((*next_byte == 0) || (IS_BLANK_CH(*next_byte))) {
|
53
|
+
return ((const xmlChar *)str);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
/* advance str to whitespace */
|
58
|
+
while ((*str != 0) && !IS_BLANK_CH(*str)) {
|
59
|
+
str++;
|
60
|
+
}
|
61
|
+
|
62
|
+
/* advance str to start of next word or end of string */
|
63
|
+
while ((*str != 0) && IS_BLANK_CH(*str)) {
|
64
|
+
str++;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
return (NULL);
|
69
|
+
}
|
70
|
+
|
71
|
+
/* xmlXPathFunction to wrap builtin_css_class() */
|
72
|
+
static void
|
73
|
+
xpath_builtin_css_class(xmlXPathParserContextPtr ctxt, int nargs)
|
74
|
+
{
|
75
|
+
xmlXPathObjectPtr hay, needle;
|
76
|
+
|
77
|
+
CHECK_ARITY(2);
|
78
|
+
|
79
|
+
CAST_TO_STRING;
|
80
|
+
needle = nl_xmlXPathValuePop(ctxt);
|
81
|
+
if ((needle == NULL) || (needle->type != XPATH_STRING)) {
|
82
|
+
nl_xmlXPathFreeObject(needle);
|
83
|
+
XP_ERROR(XPATH_INVALID_TYPE);
|
84
|
+
}
|
85
|
+
|
86
|
+
CAST_TO_STRING;
|
87
|
+
hay = nl_xmlXPathValuePop(ctxt);
|
88
|
+
if ((hay == NULL) || (hay->type != XPATH_STRING)) {
|
89
|
+
nl_xmlXPathFreeObject(hay);
|
90
|
+
nl_xmlXPathFreeObject(needle);
|
91
|
+
XP_ERROR(XPATH_INVALID_TYPE);
|
92
|
+
}
|
93
|
+
|
94
|
+
if (builtin_css_class(hay->stringval, needle->stringval)) {
|
95
|
+
nl_xmlXPathValuePush(ctxt, nl_xmlXPathNewBoolean(1));
|
96
|
+
} else {
|
97
|
+
nl_xmlXPathValuePush(ctxt, nl_xmlXPathNewBoolean(0));
|
98
|
+
}
|
99
|
+
|
100
|
+
nl_xmlXPathFreeObject(hay);
|
101
|
+
nl_xmlXPathFreeObject(needle);
|
102
|
+
}
|
103
|
+
|
104
|
+
/* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should ignore namespaces */
|
105
|
+
static void
|
106
|
+
xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
|
107
|
+
{
|
108
|
+
xmlXPathObjectPtr element_name;
|
109
|
+
size_t tmp_len;
|
110
|
+
|
111
|
+
CHECK_ARITY(1);
|
112
|
+
CAST_TO_STRING;
|
113
|
+
CHECK_TYPE(XPATH_STRING);
|
114
|
+
element_name = nl_xmlXPathValuePop(ctxt);
|
115
|
+
|
116
|
+
const lxb_char_t *node_name = lxb_dom_node_name_qualified(ctxt->context->node, &tmp_len);
|
117
|
+
nl_xmlXPathValuePush(ctxt, nl_xmlXPathNewBoolean(nl_xmlStrEqual((xmlChar *)node_name, element_name->stringval)));
|
118
|
+
|
119
|
+
nl_xmlXPathFreeObject(element_name);
|
120
|
+
}
|
121
|
+
|
24
122
|
/*
|
25
123
|
* call-seq:
|
26
124
|
* register_ns(prefix, uri)
|
@@ -228,6 +326,13 @@ nl_xpath_context_new(VALUE klass, VALUE rb_node)
|
|
228
326
|
ctx = nl_xmlXPathNewContext(node->owner_document);
|
229
327
|
ctx->node = node;
|
230
328
|
|
329
|
+
nl_xmlXPathRegisterNs(ctx, NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
330
|
+
nl_xmlXPathRegisterNs(ctx, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
|
331
|
+
nl_xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
|
332
|
+
xpath_builtin_css_class);
|
333
|
+
nl_xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
|
334
|
+
xpath_builtin_local_name_is);
|
335
|
+
|
231
336
|
self = Data_Wrap_Struct(klass, 0, free_xml_xpath_context, ctx);
|
232
337
|
rb_iv_set(self, "@document", nl_rb_document_get(rb_node));
|
233
338
|
|
data/ext/nokolexbor/nokolexbor.c
CHANGED
@@ -1,67 +1,21 @@
|
|
1
1
|
#include "nokolexbor.h"
|
2
2
|
|
3
3
|
VALUE mNokolexbor;
|
4
|
-
VALUE eLexborError;
|
5
|
-
VALUE eLexborSyntaxError;
|
6
|
-
|
7
|
-
void nl_raise_lexbor_error(lxb_status_t error)
|
8
|
-
{
|
9
|
-
switch (error) {
|
10
|
-
case LXB_STATUS_ERROR:
|
11
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR");
|
12
|
-
case LXB_STATUS_ERROR_MEMORY_ALLOCATION:
|
13
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_MEMORY_ALLOCATION");
|
14
|
-
case LXB_STATUS_ERROR_OBJECT_IS_NULL:
|
15
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_OBJECT_IS_NULL");
|
16
|
-
case LXB_STATUS_ERROR_SMALL_BUFFER:
|
17
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_SMALL_BUFFER");
|
18
|
-
case LXB_STATUS_ERROR_INCOMPLETE_OBJECT:
|
19
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_INCOMPLETE_OBJECT");
|
20
|
-
case LXB_STATUS_ERROR_NO_FREE_SLOT:
|
21
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_NO_FREE_SLOT");
|
22
|
-
case LXB_STATUS_ERROR_TOO_SMALL_SIZE:
|
23
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_TOO_SMALL_SIZE");
|
24
|
-
case LXB_STATUS_ERROR_NOT_EXISTS:
|
25
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_NOT_EXISTS");
|
26
|
-
case LXB_STATUS_ERROR_WRONG_ARGS:
|
27
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_WRONG_ARGS");
|
28
|
-
case LXB_STATUS_ERROR_WRONG_STAGE:
|
29
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_WRONG_STAGE");
|
30
|
-
case LXB_STATUS_ERROR_UNEXPECTED_RESULT:
|
31
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_UNEXPECTED_RESULT");
|
32
|
-
case LXB_STATUS_ERROR_UNEXPECTED_DATA:
|
33
|
-
rb_raise(eLexborSyntaxError, "LXB_STATUS_ERROR_UNEXPECTED_DATA");
|
34
|
-
case LXB_STATUS_ERROR_OVERFLOW:
|
35
|
-
rb_raise(eLexborError, "LXB_STATUS_ERROR_OVERFLOW");
|
36
|
-
case LXB_STATUS_CONTINUE:
|
37
|
-
rb_raise(eLexborError, "LXB_STATUS_CONTINUE");
|
38
|
-
case LXB_STATUS_SMALL_BUFFER:
|
39
|
-
rb_raise(eLexborError, "LXB_STATUS_SMALL_BUFFER");
|
40
|
-
case LXB_STATUS_ABORTED:
|
41
|
-
rb_raise(eLexborError, "LXB_STATUS_ABORTED");
|
42
|
-
case LXB_STATUS_STOPPED:
|
43
|
-
rb_raise(eLexborError, "LXB_STATUS_STOPPED");
|
44
|
-
case LXB_STATUS_NEXT:
|
45
|
-
rb_raise(eLexborError, "LXB_STATUS_NEXT");
|
46
|
-
case LXB_STATUS_STOP:
|
47
|
-
rb_raise(eLexborError, "LXB_STATUS_STOP");
|
48
|
-
case LXB_STATUS_OK:
|
49
|
-
return;
|
50
|
-
default:
|
51
|
-
rb_raise(eLexborError, "LXB_ERROR_UKNOWN(%d)", error);
|
52
|
-
}
|
53
|
-
}
|
54
4
|
|
55
5
|
void Init_nokolexbor(void)
|
56
6
|
{
|
7
|
+
#ifndef NOKOLEXBOR_ASAN
|
8
|
+
lexbor_memory_setup(ruby_xmalloc, ruby_xrealloc, ruby_xcalloc, ruby_xfree);
|
9
|
+
#endif
|
57
10
|
mNokolexbor = rb_define_module("Nokolexbor");
|
58
|
-
|
59
|
-
eLexborSyntaxError = rb_define_class_under(mNokolexbor, "LexborSyntaxError", eLexborError);
|
11
|
+
Init_nl_error();
|
60
12
|
Init_nl_node();
|
61
13
|
Init_nl_document();
|
62
14
|
Init_nl_text();
|
63
15
|
Init_nl_comment();
|
64
16
|
Init_nl_cdata();
|
17
|
+
Init_nl_processing_instruction();
|
65
18
|
Init_nl_node_set();
|
19
|
+
Init_nl_document_fragment();
|
66
20
|
Init_nl_xpath_context();
|
67
21
|
}
|
data/ext/nokolexbor/nokolexbor.h
CHANGED
@@ -9,12 +9,15 @@
|
|
9
9
|
|
10
10
|
extern VALUE cNokolexborDocument;
|
11
11
|
|
12
|
+
void Init_nl_error(void);
|
12
13
|
void Init_nl_document(void);
|
13
14
|
void Init_nl_node(void);
|
14
|
-
void Init_nl_node_set(void);
|
15
15
|
void Init_nl_text(void);
|
16
16
|
void Init_nl_comment(void);
|
17
17
|
void Init_nl_cdata(void);
|
18
|
+
void Init_nl_processing_instruction(void);
|
19
|
+
void Init_nl_node_set(void);
|
20
|
+
void Init_nl_document_fragment(void);
|
18
21
|
void Init_nl_xpath_context(void);
|
19
22
|
|
20
23
|
void nl_raise_lexbor_error(lxb_status_t error);
|
data/ext/nokolexbor/xml_xpath.c
CHANGED
@@ -2897,6 +2897,10 @@ valuePop(xmlXPathParserContextPtr ctxt)
|
|
2897
2897
|
ctxt->valueTab[ctxt->valueNr] = NULL;
|
2898
2898
|
return (ret);
|
2899
2899
|
}
|
2900
|
+
|
2901
|
+
xmlXPathObjectPtr
|
2902
|
+
nl_xmlXPathValuePop(xmlXPathParserContextPtr ctxt) { return valuePop(ctxt); }
|
2903
|
+
|
2900
2904
|
/**
|
2901
2905
|
* valuePush:
|
2902
2906
|
* @ctxt: an XPath evaluation context
|
@@ -2941,6 +2945,9 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
|
|
2941
2945
|
return (ctxt->valueNr++);
|
2942
2946
|
}
|
2943
2947
|
|
2948
|
+
int
|
2949
|
+
nl_xmlXPathValuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) { return valuePush(ctxt, value); }
|
2950
|
+
|
2944
2951
|
/**
|
2945
2952
|
* nl_xmlXPathPopBoolean:
|
2946
2953
|
* @ctxt: an XPath parser context
|
data/lib/nokolexbor/document.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nokolexbor
|
4
|
+
class DocumentFragment < Nokolexbor::Node
|
5
|
+
def self.parse(tags)
|
6
|
+
new(Nokolexbor::Document.new, tags, nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(document, tags = nil, ctx = nil)
|
10
|
+
return self unless tags
|
11
|
+
|
12
|
+
ctx ||= document
|
13
|
+
node_set = ctx.parse(tags)
|
14
|
+
node_set.each { |child| child.parent = self } unless node_set.empty?
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def name
|
19
|
+
"#document-fragment"
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :outer_html, :inner_html
|
23
|
+
alias_method :to_html, :outer_html
|
24
|
+
alias_method :to_s, :outer_html
|
25
|
+
alias_method :serialize, :outer_html
|
26
|
+
|
27
|
+
def fragment(data)
|
28
|
+
document.fragment(data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/nokolexbor/node.rb
CHANGED
@@ -182,6 +182,10 @@ module Nokolexbor
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
|
+
def fragment(tags)
|
186
|
+
Nokolexbor::DocumentFragment.new(document, tags, self)
|
187
|
+
end
|
188
|
+
|
185
189
|
alias_method :inner_html=, :children=
|
186
190
|
|
187
191
|
def css(*args)
|
@@ -192,6 +196,16 @@ module Nokolexbor
|
|
192
196
|
at_css_impl(args.join(', '))
|
193
197
|
end
|
194
198
|
|
199
|
+
def nokogiri_css(*args)
|
200
|
+
rules, handler, ns, _ = extract_params(args)
|
201
|
+
|
202
|
+
nokogiri_css_internal(self, rules, handler, ns)
|
203
|
+
end
|
204
|
+
|
205
|
+
def nokogiri_at_css(*args)
|
206
|
+
nokogiri_css(*args).first
|
207
|
+
end
|
208
|
+
|
195
209
|
def xpath(*args)
|
196
210
|
paths, handler, ns, binds = extract_params(args)
|
197
211
|
|
@@ -299,6 +313,10 @@ module Nokolexbor
|
|
299
313
|
|
300
314
|
private
|
301
315
|
|
316
|
+
def nokogiri_css_internal(node, rules, handler, ns)
|
317
|
+
xpath_internal(node, css_rules_to_xpath(rules, ns), handler, ns, nil)
|
318
|
+
end
|
319
|
+
|
302
320
|
def xpath_internal(node, paths, handler, ns, binds)
|
303
321
|
# document = node.document
|
304
322
|
# return NodeSet.new(document) unless document
|
@@ -326,6 +344,34 @@ module Nokolexbor
|
|
326
344
|
ctx.evaluate(path, handler)
|
327
345
|
end
|
328
346
|
|
347
|
+
def css_rules_to_xpath(rules, ns)
|
348
|
+
rules.map { |rule| xpath_query_from_css_rule(rule, ns) }
|
349
|
+
end
|
350
|
+
|
351
|
+
def ensure_nokogiri
|
352
|
+
unless defined?(Nokogiri) && defined?(Nokogiri::CSS)
|
353
|
+
require 'nokogiri'
|
354
|
+
end
|
355
|
+
rescue LoadError
|
356
|
+
fail('nokogiri_css and nokogiri_at_css require Nokogiri to be installed')
|
357
|
+
end
|
358
|
+
|
359
|
+
def xpath_query_from_css_rule(rule, ns)
|
360
|
+
ensure_nokogiri
|
361
|
+
if defined? Nokogiri::CSS::XPathVisitor::BuiltinsConfig
|
362
|
+
visitor = Nokogiri::CSS::XPathVisitor.new(
|
363
|
+
builtins: Nokogiri::CSS::XPathVisitor::BuiltinsConfig::OPTIMAL,
|
364
|
+
doctype: :html4,
|
365
|
+
)
|
366
|
+
else
|
367
|
+
visitor = Nokogiri::CSS::XPathVisitorOptimallyUseBuiltins.new
|
368
|
+
end
|
369
|
+
self.class::IMPLIED_XPATH_CONTEXTS.map do |implied_xpath_context|
|
370
|
+
Nokogiri::CSS.xpath_for(rule.to_s, { prefix: implied_xpath_context, ns: ns,
|
371
|
+
visitor: visitor, })
|
372
|
+
end.join(" | ")
|
373
|
+
end
|
374
|
+
|
329
375
|
def extract_params(params)
|
330
376
|
handler = params.find do |param|
|
331
377
|
![Hash, String, Symbol].include?(param.class)
|
@@ -344,5 +390,7 @@ module Nokolexbor
|
|
344
390
|
|
345
391
|
[params, handler, ns, binds]
|
346
392
|
end
|
393
|
+
|
394
|
+
IMPLIED_XPATH_CONTEXTS = [".//"].freeze
|
347
395
|
end
|
348
|
-
end
|
396
|
+
end
|
data/lib/nokolexbor/node_set.rb
CHANGED
@@ -126,6 +126,23 @@ module Nokolexbor
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
129
|
+
|
130
|
+
def nokogiri_css(*args)
|
131
|
+
rules, handler, ns, _ = extract_params(args)
|
132
|
+
paths = css_rules_to_xpath(rules, ns)
|
133
|
+
|
134
|
+
NodeSet.new(@document) do |set|
|
135
|
+
each do |node|
|
136
|
+
node.send(:xpath_internal, node, paths, handler, ns, nil).each do |inner_node|
|
137
|
+
set << inner_node
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
IMPLIED_XPATH_CONTEXTS = [".//", "self::"].freeze # :nodoc:
|
129
146
|
|
130
147
|
end
|
131
148
|
end
|
data/lib/nokolexbor/version.rb
CHANGED
data/lib/nokolexbor.rb
CHANGED
@@ -25,6 +25,7 @@ require 'nokolexbor/version'
|
|
25
25
|
require 'nokolexbor/node'
|
26
26
|
require 'nokolexbor/document'
|
27
27
|
require 'nokolexbor/node_set'
|
28
|
+
require 'nokolexbor/document_fragment'
|
28
29
|
require 'nokolexbor/attribute'
|
29
30
|
require 'nokolexbor/xpath'
|
30
31
|
require 'nokolexbor/xpath_context'
|
@@ -13,7 +13,7 @@ index 2b19f18..5e56181 100644
|
|
13
13
|
lxb_css_selector_pseudo_element_id_t;
|
14
14
|
|
15
15
|
diff --git i/source/lexbor/css/selectors/pseudo_res.h w/source/lexbor/css/selectors/pseudo_res.h
|
16
|
-
index 398d1bb..
|
16
|
+
index 398d1bb..ddd5f3e 100644
|
17
17
|
--- i/source/lexbor/css/selectors/pseudo_res.h
|
18
18
|
+++ w/source/lexbor/css/selectors/pseudo_res.h
|
19
19
|
@@ -124,7 +124,8 @@ static const lxb_css_selectors_pseudo_data_t lxb_css_selectors_pseudo_data_pseud
|
@@ -36,7 +36,7 @@ index 398d1bb..b35bfab 100644
|
|
36
36
|
{"grammar-error", (void *) &lxb_css_selectors_pseudo_data_pseudo_element[LXB_CSS_SELECTOR_PSEUDO_ELEMENT_GRAMMAR_ERROR], 13, 0},
|
37
37
|
{"before", (void *) &lxb_css_selectors_pseudo_data_pseudo_element[LXB_CSS_SELECTOR_PSEUDO_ELEMENT_BEFORE], 6, 0},
|
38
38
|
diff --git i/source/lexbor/selectors/selectors.c w/source/lexbor/selectors/selectors.c
|
39
|
-
index
|
39
|
+
index fef05d3..1ceaa19 100644
|
40
40
|
--- i/source/lexbor/selectors/selectors.c
|
41
41
|
+++ w/source/lexbor/selectors/selectors.c
|
42
42
|
@@ -156,6 +156,12 @@ lxb_selectors_descendant(lxb_selectors_t *selectors, lxb_selectors_entry_t *entr
|
@@ -91,16 +91,7 @@ index c2d18ea..84b5b14 100644
|
|
91
91
|
|
92
92
|
node = node->next;
|
93
93
|
}
|
94
|
-
@@ -
|
95
|
-
{
|
96
|
-
node = node->next;
|
97
|
-
|
98
|
-
+ if (node == NULL) return NULL;
|
99
|
-
+
|
100
|
-
do {
|
101
|
-
if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
|
102
|
-
if (lxb_selectors_match(selectors, entry, selector, node)) {
|
103
|
-
@@ -290,6 +316,12 @@ lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry
|
94
|
+
@@ -289,6 +313,12 @@ lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry
|
104
95
|
{
|
105
96
|
return node;
|
106
97
|
}
|
@@ -113,7 +104,7 @@ index c2d18ea..84b5b14 100644
|
|
113
104
|
|
114
105
|
node = node->next;
|
115
106
|
}
|
116
|
-
@@ -
|
107
|
+
@@ -1428,6 +1458,8 @@ lxb_selectors_pseudo_element(lxb_selectors_t *selectors,
|
117
108
|
lxb_css_selector_pseudo_t *pseudo = &selector->u.pseudo;
|
118
109
|
|
119
110
|
switch (pseudo->type) {
|
@@ -2,7 +2,7 @@ diff --git i/source/lexbor/selectors/selectors.c w/source/lexbor/selectors/selec
|
|
2
2
|
index c2d18ea..84b5b14 100644
|
3
3
|
--- i/source/lexbor/selectors/selectors.c
|
4
4
|
+++ w/source/lexbor/selectors/selectors.c
|
5
|
-
@@ -
|
5
|
+
@@ -750,7 +780,7 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
|
6
6
|
src = &selector->name;
|
7
7
|
|
8
8
|
if (trg->length == src->length
|
@@ -11,7 +11,7 @@ index c2d18ea..84b5b14 100644
|
|
11
11
|
{
|
12
12
|
return true;
|
13
13
|
}
|
14
|
-
@@ -
|
14
|
+
@@ -765,7 +795,7 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
|
15
15
|
}
|
16
16
|
|
17
17
|
return lxb_selectors_match_class(element->attr_class->value,
|
@@ -13,6 +13,10 @@ extern "C" {
|
|
13
13
|
|
14
14
|
#include "lexbor/core/def.h"
|
15
15
|
|
16
|
+
typedef void *(*lexbor_memory_malloc_f)(size_t size);
|
17
|
+
typedef void *(*lexbor_memory_realloc_f)(void *dst, size_t size);
|
18
|
+
typedef void *(*lexbor_memory_calloc_f)(size_t num, size_t size);
|
19
|
+
typedef void (*lexbor_memory_free_f)(void *dst);
|
16
20
|
|
17
21
|
LXB_API void *
|
18
22
|
lexbor_malloc(size_t size);
|
@@ -26,6 +30,10 @@ lexbor_calloc(size_t num, size_t size);
|
|
26
30
|
LXB_API void *
|
27
31
|
lexbor_free(void *dst);
|
28
32
|
|
33
|
+
LXB_API lxb_status_t
|
34
|
+
lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc,
|
35
|
+
lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free);
|
36
|
+
|
29
37
|
|
30
38
|
#ifdef __cplusplus
|
31
39
|
} /* extern "C" */
|
@@ -6,28 +6,48 @@
|
|
6
6
|
|
7
7
|
#include "lexbor/core/base.h"
|
8
8
|
|
9
|
+
static lexbor_memory_malloc_f lexbor_memory_malloc = malloc;
|
10
|
+
static lexbor_memory_realloc_f lexbor_memory_realloc = realloc;
|
11
|
+
static lexbor_memory_calloc_f lexbor_memory_calloc = calloc;
|
12
|
+
static lexbor_memory_free_f lexbor_memory_free = free;
|
9
13
|
|
10
14
|
void *
|
11
15
|
lexbor_malloc(size_t size)
|
12
16
|
{
|
13
|
-
return
|
17
|
+
return lexbor_memory_malloc(size);
|
14
18
|
}
|
15
19
|
|
16
20
|
void *
|
17
21
|
lexbor_realloc(void *dst, size_t size)
|
18
22
|
{
|
19
|
-
return
|
23
|
+
return lexbor_memory_realloc(dst, size);
|
20
24
|
}
|
21
25
|
|
22
26
|
void *
|
23
27
|
lexbor_calloc(size_t num, size_t size)
|
24
28
|
{
|
25
|
-
return
|
29
|
+
return lexbor_memory_calloc(num, size);
|
26
30
|
}
|
27
31
|
|
28
32
|
void *
|
29
33
|
lexbor_free(void *dst)
|
30
34
|
{
|
31
|
-
|
35
|
+
lexbor_memory_free(dst);
|
32
36
|
return NULL;
|
33
37
|
}
|
38
|
+
|
39
|
+
lxb_status_t
|
40
|
+
lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc,
|
41
|
+
lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free)
|
42
|
+
{
|
43
|
+
if (new_malloc == NULL || new_realloc == NULL || new_calloc == NULL || new_free == NULL) {
|
44
|
+
return LXB_STATUS_ERROR_OBJECT_IS_NULL;
|
45
|
+
}
|
46
|
+
|
47
|
+
lexbor_memory_malloc = new_malloc;
|
48
|
+
lexbor_memory_realloc = new_realloc;
|
49
|
+
lexbor_memory_calloc = new_calloc;
|
50
|
+
lexbor_memory_free = new_free;
|
51
|
+
|
52
|
+
return LXB_STATUS_OK;
|
53
|
+
}
|
@@ -6,28 +6,48 @@
|
|
6
6
|
|
7
7
|
#include "lexbor/core/base.h"
|
8
8
|
|
9
|
+
static lexbor_memory_malloc_f lexbor_memory_malloc = malloc;
|
10
|
+
static lexbor_memory_realloc_f lexbor_memory_realloc = realloc;
|
11
|
+
static lexbor_memory_calloc_f lexbor_memory_calloc = calloc;
|
12
|
+
static lexbor_memory_free_f lexbor_memory_free = free;
|
9
13
|
|
10
14
|
void *
|
11
15
|
lexbor_malloc(size_t size)
|
12
16
|
{
|
13
|
-
return
|
17
|
+
return lexbor_memory_malloc(size);
|
14
18
|
}
|
15
19
|
|
16
20
|
void *
|
17
21
|
lexbor_realloc(void *dst, size_t size)
|
18
22
|
{
|
19
|
-
return
|
23
|
+
return lexbor_memory_realloc(dst, size);
|
20
24
|
}
|
21
25
|
|
22
26
|
void *
|
23
27
|
lexbor_calloc(size_t num, size_t size)
|
24
28
|
{
|
25
|
-
return
|
29
|
+
return lexbor_memory_calloc(num, size);
|
26
30
|
}
|
27
31
|
|
28
32
|
void *
|
29
33
|
lexbor_free(void *dst)
|
30
34
|
{
|
31
|
-
|
35
|
+
lexbor_memory_free(dst);
|
32
36
|
return NULL;
|
33
37
|
}
|
38
|
+
|
39
|
+
lxb_status_t
|
40
|
+
lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc,
|
41
|
+
lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free)
|
42
|
+
{
|
43
|
+
if (new_malloc == NULL || new_realloc == NULL || new_calloc == NULL || new_free == NULL) {
|
44
|
+
return LXB_STATUS_ERROR_OBJECT_IS_NULL;
|
45
|
+
}
|
46
|
+
|
47
|
+
lexbor_memory_malloc = new_malloc;
|
48
|
+
lexbor_memory_realloc = new_realloc;
|
49
|
+
lexbor_memory_calloc = new_calloc;
|
50
|
+
lexbor_memory_free = new_free;
|
51
|
+
|
52
|
+
return LXB_STATUS_OK;
|
53
|
+
}
|
@@ -262,7 +262,7 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
|
|
262
262
|
{
|
263
263
|
node = node->next;
|
264
264
|
|
265
|
-
|
265
|
+
while (node != NULL) {
|
266
266
|
if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
|
267
267
|
if (lxb_selectors_match(selectors, entry, selector, node)) {
|
268
268
|
return node;
|
@@ -273,7 +273,6 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
|
|
273
273
|
|
274
274
|
node = node->next;
|
275
275
|
}
|
276
|
-
while (node != NULL);
|
277
276
|
|
278
277
|
return NULL;
|
279
278
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nokolexbor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yicheng Zhou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -78,12 +78,14 @@ files:
|
|
78
78
|
- ext/nokolexbor/libxml/xpath.h
|
79
79
|
- ext/nokolexbor/libxml/xpathInternals.h
|
80
80
|
- ext/nokolexbor/libxml/xpointer.h
|
81
|
-
- ext/nokolexbor/memory.c
|
82
81
|
- ext/nokolexbor/nl_cdata.c
|
83
82
|
- ext/nokolexbor/nl_comment.c
|
84
83
|
- ext/nokolexbor/nl_document.c
|
84
|
+
- ext/nokolexbor/nl_document_fragment.c
|
85
|
+
- ext/nokolexbor/nl_error.c
|
85
86
|
- ext/nokolexbor/nl_node.c
|
86
87
|
- ext/nokolexbor/nl_node_set.c
|
88
|
+
- ext/nokolexbor/nl_processing_instruction.c
|
87
89
|
- ext/nokolexbor/nl_text.c
|
88
90
|
- ext/nokolexbor/nl_xpath_context.c
|
89
91
|
- ext/nokolexbor/nokolexbor.c
|
@@ -119,6 +121,7 @@ files:
|
|
119
121
|
- lib/nokolexbor.rb
|
120
122
|
- lib/nokolexbor/attribute.rb
|
121
123
|
- lib/nokolexbor/document.rb
|
124
|
+
- lib/nokolexbor/document_fragment.rb
|
122
125
|
- lib/nokolexbor/node.rb
|
123
126
|
- lib/nokolexbor/node_set.rb
|
124
127
|
- lib/nokolexbor/version.rb
|
data/ext/nokolexbor/memory.c
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* This file overrides the default `lexbor_malloc` and other
|
3
|
-
* related functions to reduce memory bloat and allow Ruby to
|
4
|
-
* GC more often.
|
5
|
-
* By calling `ruby_xmalloc` instead of `malloc`, Ruby can
|
6
|
-
* count the memory usage of the C extension and run GC
|
7
|
-
* whenever `malloc_increase_byte` exceeds the limit. Similar
|
8
|
-
* to Nokogiri's solution by calling `xmlMemSetup`.
|
9
|
-
* The downside will be the downgrade of performance because
|
10
|
-
* of more frequent GC.
|
11
|
-
*/
|
12
|
-
|
13
|
-
#include "lexbor/core/base.h"
|
14
|
-
#include <ruby.h>
|
15
|
-
|
16
|
-
// Disable using ruby memory functions when ASAN is enabled,
|
17
|
-
// otherwise memory leak info will be all about ruby which
|
18
|
-
// is useless.
|
19
|
-
#ifndef NOKOLEXBOR_ASAN
|
20
|
-
|
21
|
-
void *
|
22
|
-
lexbor_malloc(size_t size)
|
23
|
-
{
|
24
|
-
return ruby_xmalloc(size);
|
25
|
-
}
|
26
|
-
|
27
|
-
void *
|
28
|
-
lexbor_realloc(void *dst, size_t size)
|
29
|
-
{
|
30
|
-
return ruby_xrealloc(dst, size);
|
31
|
-
}
|
32
|
-
|
33
|
-
void *
|
34
|
-
lexbor_calloc(size_t num, size_t size)
|
35
|
-
{
|
36
|
-
return ruby_xcalloc(num, size);
|
37
|
-
}
|
38
|
-
|
39
|
-
void *
|
40
|
-
lexbor_free(void *dst)
|
41
|
-
{
|
42
|
-
ruby_xfree(dst);
|
43
|
-
return NULL;
|
44
|
-
}
|
45
|
-
|
46
|
-
#endif
|