makiri 0.2.0 → 0.4.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 +4 -4
- data/.github/workflows/conformance.yml +22 -0
- data/.github/workflows/libfuzzer.yml +83 -0
- data/.github/workflows/release.yml +12 -7
- data/.github/workflows/security.yml +88 -3
- data/.github/workflows/valgrind.yml +135 -0
- data/CHANGELOG.md +152 -15
- data/README.md +183 -13
- data/Rakefile +294 -7
- data/ext/makiri/bridge/bridge.h +28 -0
- data/ext/makiri/bridge/ruby_string.c +282 -12
- data/ext/makiri/core/mkr_alloc.c +40 -3
- data/ext/makiri/core/mkr_alloc.h +28 -5
- data/ext/makiri/core/mkr_buf.c +47 -3
- data/ext/makiri/core/mkr_buf.h +112 -3
- data/ext/makiri/core/mkr_core.c +143 -0
- data/ext/makiri/core/mkr_core.h +11 -2
- data/ext/makiri/core/mkr_hash.h +1 -1
- data/ext/makiri/core/mkr_span.h +186 -0
- data/ext/makiri/core/mkr_text.h +8 -8
- data/ext/makiri/core/mkr_utf8.c +101 -0
- data/ext/makiri/core/mkr_utf8.h +88 -0
- data/ext/makiri/extconf.rb +123 -10
- data/ext/makiri/fuzz/Makefile +95 -0
- data/ext/makiri/fuzz/check_fuzzer.cc +4 -0
- data/ext/makiri/fuzz/xml_fuzz.c +24 -0
- data/ext/makiri/fuzz/xpath_fuzz.c +109 -0
- data/ext/makiri/glue/glue.h +55 -11
- data/ext/makiri/glue/ruby_doc.c +129 -59
- data/ext/makiri/glue/ruby_html_css.c +292 -0
- data/ext/makiri/glue/{ruby_mutate.c → ruby_html_mutate.c} +248 -52
- data/ext/makiri/glue/ruby_html_node.c +859 -0
- data/ext/makiri/glue/ruby_html_serialize.c +154 -0
- data/ext/makiri/glue/ruby_node.c +74 -729
- data/ext/makiri/glue/ruby_node_set.c +167 -32
- data/ext/makiri/glue/ruby_xml.c +602 -0
- data/ext/makiri/glue/ruby_xml_node.c +1373 -0
- data/ext/makiri/glue/ruby_xpath.c +63 -30
- data/ext/makiri/glue/ruby_xpath.h +19 -0
- data/ext/makiri/lexbor_compat/compat.h +42 -9
- data/ext/makiri/lexbor_compat/compat_internal.h +1 -1
- data/ext/makiri/lexbor_compat/dom_index.c +2 -2
- data/ext/makiri/lexbor_compat/post_parse.c +100 -10
- data/ext/makiri/lexbor_compat/source_loc.c +15 -13
- data/ext/makiri/lexbor_compat/text_index.c +14 -8
- data/ext/makiri/lexbor_compat/utf8_input.c +19 -33
- data/ext/makiri/makiri.c +184 -6
- data/ext/makiri/makiri.h +43 -2
- data/ext/makiri/xml/mkr_xml.h +125 -0
- data/ext/makiri/xml/mkr_xml_chars.c +195 -0
- data/ext/makiri/xml/mkr_xml_index.c +169 -0
- data/ext/makiri/xml/mkr_xml_index.h +48 -0
- data/ext/makiri/xml/mkr_xml_mutate.c +817 -0
- data/ext/makiri/xml/mkr_xml_mutate.h +139 -0
- data/ext/makiri/xml/mkr_xml_node.c +399 -0
- data/ext/makiri/xml/mkr_xml_node.h +184 -0
- data/ext/makiri/xml/mkr_xml_tree.c +1515 -0
- data/ext/makiri/xpath/mkr_css.c +1023 -0
- data/ext/makiri/xpath/mkr_css.h +65 -0
- data/ext/makiri/xpath/mkr_xpath.c +96 -32
- data/ext/makiri/xpath/mkr_xpath.h +109 -4
- data/ext/makiri/xpath/mkr_xpath_engine_html.c +17 -0
- data/ext/makiri/xpath/mkr_xpath_engine_xml.c +12 -0
- data/ext/makiri/xpath/{mkr_xpath_eval.c → mkr_xpath_eval_body.h} +551 -241
- data/ext/makiri/xpath/{mkr_xpath_funcs.c → mkr_xpath_funcs_body.h} +318 -276
- data/ext/makiri/xpath/mkr_xpath_internal.h +177 -206
- data/ext/makiri/xpath/mkr_xpath_lex.c +95 -125
- data/ext/makiri/xpath/mkr_xpath_node_access_html.h +138 -0
- data/ext/makiri/xpath/mkr_xpath_node_access_xml.h +145 -0
- data/ext/makiri/xpath/mkr_xpath_number.c +109 -0
- data/ext/makiri/xpath/mkr_xpath_parse.c +83 -94
- data/ext/makiri/xpath/mkr_xpath_prelude_html.h +30 -0
- data/ext/makiri/xpath/mkr_xpath_prelude_xml.h +28 -0
- data/ext/makiri/xpath/mkr_xpath_shared.c +609 -0
- data/ext/makiri/xpath/mkr_xpath_value_body.h +801 -0
- data/ext/makiri/xpath/mkr_xpath_xml_selftest.c +76 -0
- data/lib/makiri/{attribute.rb → attr.rb} +7 -3
- data/lib/makiri/cdata_section.rb +19 -0
- data/lib/makiri/comment.rb +10 -0
- data/lib/makiri/compat_aliases.rb +30 -0
- data/lib/makiri/document.rb +9 -73
- data/lib/makiri/document_fragment.rb +14 -9
- data/lib/makiri/element.rb +4 -4
- data/lib/makiri/html/document.rb +106 -0
- data/lib/makiri/html/node_methods.rb +19 -0
- data/lib/makiri/html.rb +12 -0
- data/lib/makiri/node.rb +58 -15
- data/lib/makiri/node_set.rb +8 -0
- data/lib/makiri/processing_instruction.rb +10 -0
- data/lib/makiri/text.rb +1 -1
- data/lib/makiri/version.rb +1 -1
- data/lib/makiri/xml/builder.rb +263 -0
- data/lib/makiri/xml/document.rb +24 -0
- data/lib/makiri/xml/node_methods.rb +84 -0
- data/lib/makiri/xml.rb +10 -0
- data/lib/makiri/xpath_context.rb +1 -1
- data/lib/makiri.rb +24 -5
- data/script/build_native_gem.rb +2 -2
- data/script/check_alloc_failures.rb +266 -0
- data/script/check_c_safety.rb +77 -2
- data/script/check_c_safety_allowlist.yml +102 -0
- data/script/check_leaks.rb +64 -0
- data/script/leaks_harness.rb +64 -0
- data/vendor/lexbor/CMakeLists.txt +6 -0
- data/vendor/lexbor/README.md +12 -0
- data/vendor/lexbor/config.cmake +1 -1
- data/vendor/lexbor/source/lexbor/core/base.h +1 -1
- data/vendor/lexbor/source/lexbor/core/config.cmake +9 -1
- data/vendor/lexbor/source/lexbor/css/selectors/pseudo_state.c +2 -3
- data/vendor/lexbor/source/lexbor/css/selectors/state.c +3 -0
- data/vendor/lexbor/source/lexbor/dom/interfaces/element.c +21 -0
- data/vendor/lexbor/source/lexbor/dom/interfaces/element.h +5 -0
- data/vendor/lexbor/source/lexbor/encoding/decode.c +33 -4
- data/vendor/lexbor/source/lexbor/html/base.h +1 -1
- data/vendor/lexbor/source/lexbor/html/interfaces/select_element.c +4 -0
- data/vendor/lexbor/source/lexbor/html/serialize.c +545 -41
- data/vendor/lexbor/source/lexbor/html/serialize.h +2 -1
- data/vendor/lexbor/source/lexbor/html/tokenizer.h +2 -2
- data/vendor/lexbor/source/lexbor/html/tree/insertion_mode/in_body.c +1 -1
- data/vendor/lexbor/source/lexbor/html/tree.c +6 -6
- data/vendor/lexbor/source/lexbor/selectors/selectors.c +12 -3
- data/vendor/lexbor/source/lexbor/url/base.h +1 -1
- data/vendor/lexbor/source/lexbor/url/url.c +5 -2
- data/vendor/lexbor/source/lexbor/url/url.h +9 -0
- data/vendor/lexbor/version +1 -1
- metadata +53 -9
- data/ext/makiri/glue/ruby_css.c +0 -185
- data/ext/makiri/glue/ruby_serialize.c +0 -92
- data/ext/makiri/xpath/mkr_xpath_value.c +0 -1286
- data/lib/makiri/cdata.rb +0 -6
|
@@ -27,7 +27,8 @@ enum lxb_html_serialize_opt {
|
|
|
27
27
|
LXB_HTML_SERIALIZE_OPT_WITHOUT_CLOSING = 0x08,
|
|
28
28
|
LXB_HTML_SERIALIZE_OPT_TAG_WITH_NS = 0x10,
|
|
29
29
|
LXB_HTML_SERIALIZE_OPT_WITHOUT_TEXT_INDENT = 0x20,
|
|
30
|
-
LXB_HTML_SERIALIZE_OPT_FULL_DOCTYPE = 0x40
|
|
30
|
+
LXB_HTML_SERIALIZE_OPT_FULL_DOCTYPE = 0x40,
|
|
31
|
+
LXB_HTML_SERIALIZE_OPT_HTML5TEST = 0x80
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
|
|
@@ -310,7 +310,7 @@ lxb_html_tokenizer_temp_append_data(lxb_html_tokenizer_t *tkz,
|
|
|
310
310
|
{
|
|
311
311
|
size_t size = data - tkz->begin;
|
|
312
312
|
|
|
313
|
-
if ((tkz->
|
|
313
|
+
if (size > (size_t)(tkz->end - tkz->pos)) {
|
|
314
314
|
if(lxb_html_tokenizer_temp_realloc(tkz, size)) {
|
|
315
315
|
return tkz->status;
|
|
316
316
|
}
|
|
@@ -325,7 +325,7 @@ lxb_inline lxb_status_t
|
|
|
325
325
|
lxb_html_tokenizer_temp_append(lxb_html_tokenizer_t *tkz,
|
|
326
326
|
const lxb_char_t *data, size_t size)
|
|
327
327
|
{
|
|
328
|
-
if ((tkz->
|
|
328
|
+
if (size > (size_t)(tkz->end - tkz->pos)) {
|
|
329
329
|
if(lxb_html_tokenizer_temp_realloc(tkz, size)) {
|
|
330
330
|
return tkz->status;
|
|
331
331
|
}
|
|
@@ -1691,7 +1691,7 @@ lxb_html_tree_insertion_mode_in_body_rprt(lxb_html_tree_t *tree,
|
|
|
1691
1691
|
node = lxb_html_tree_current_node(tree);
|
|
1692
1692
|
|
|
1693
1693
|
if (lxb_html_tree_node_is(node, LXB_TAG_RTC) == false
|
|
1694
|
-
|
|
1694
|
+
&& lxb_html_tree_node_is(node, LXB_TAG_RUBY) == false)
|
|
1695
1695
|
{
|
|
1696
1696
|
lxb_html_tree_parse_error(tree, token,
|
|
1697
1697
|
LXB_HTML_RULES_ERROR_MIELINOPELST);
|
|
@@ -462,8 +462,8 @@ lxb_html_tree_append_attributes(lxb_html_tree_t *tree,
|
|
|
462
462
|
doc = lxb_html_interface_document(element->node.owner_document);
|
|
463
463
|
|
|
464
464
|
while (token_attr != NULL) {
|
|
465
|
-
attr =
|
|
466
|
-
|
|
465
|
+
attr = lxb_dom_element_attr_by_local_name_ns_data(element,
|
|
466
|
+
token_attr->name, ns);
|
|
467
467
|
if (attr != NULL) {
|
|
468
468
|
token_attr = token_attr->next;
|
|
469
469
|
continue;
|
|
@@ -1184,7 +1184,7 @@ lxb_html_tree_element_in_scope_h123456(lxb_html_tree_t *tree)
|
|
|
1184
1184
|
break;
|
|
1185
1185
|
}
|
|
1186
1186
|
|
|
1187
|
-
if (lxb_html_tag_is_category(node->local_name,
|
|
1187
|
+
if (lxb_html_tag_is_category(node->local_name, node->ns,
|
|
1188
1188
|
LXB_HTML_TAG_CATEGORY_SCOPE))
|
|
1189
1189
|
{
|
|
1190
1190
|
return NULL;
|
|
@@ -1220,7 +1220,7 @@ lxb_html_tree_element_in_scope_tbody_thead_tfoot(lxb_html_tree_t *tree)
|
|
|
1220
1220
|
break;
|
|
1221
1221
|
}
|
|
1222
1222
|
|
|
1223
|
-
if (lxb_html_tag_is_category(node->local_name,
|
|
1223
|
+
if (lxb_html_tag_is_category(node->local_name, node->ns,
|
|
1224
1224
|
LXB_HTML_TAG_CATEGORY_SCOPE_TABLE))
|
|
1225
1225
|
{
|
|
1226
1226
|
return NULL;
|
|
@@ -1255,7 +1255,7 @@ lxb_html_tree_element_in_scope_td_th(lxb_html_tree_t *tree)
|
|
|
1255
1255
|
break;
|
|
1256
1256
|
}
|
|
1257
1257
|
|
|
1258
|
-
if (lxb_html_tag_is_category(node->local_name,
|
|
1258
|
+
if (lxb_html_tag_is_category(node->local_name, node->ns,
|
|
1259
1259
|
LXB_HTML_TAG_CATEGORY_SCOPE_TABLE))
|
|
1260
1260
|
{
|
|
1261
1261
|
return NULL;
|
|
@@ -1290,7 +1290,7 @@ lxb_html_tree_element_in_scope_option_optgroup(lxb_html_tree_t *tree)
|
|
|
1290
1290
|
break;
|
|
1291
1291
|
}
|
|
1292
1292
|
|
|
1293
|
-
if (lxb_html_tag_is_category(node->local_name,
|
|
1293
|
+
if (lxb_html_tag_is_category(node->local_name, node->ns,
|
|
1294
1294
|
LXB_HTML_TAG_CATEGORY_SCOPE))
|
|
1295
1295
|
{
|
|
1296
1296
|
return NULL;
|
|
@@ -1310,7 +1310,9 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
|
|
|
1310
1310
|
}
|
|
1311
1311
|
|
|
1312
1312
|
return lxb_selectors_match_class(element->attr_class->value,
|
|
1313
|
-
&entry->selector->name,
|
|
1313
|
+
&entry->selector->name,
|
|
1314
|
+
node->owner_document->compat_mode
|
|
1315
|
+
== LXB_DOM_DOCUMENT_CMODE_QUIRKS);
|
|
1314
1316
|
|
|
1315
1317
|
case LXB_CSS_SELECTOR_TYPE_ATTRIBUTE:
|
|
1316
1318
|
return lxb_selectors_match_attribute(entry->selector, node, entry);
|
|
@@ -1368,8 +1370,15 @@ lxb_selectors_match_id(const lxb_css_selector_t *selector, lxb_dom_node_t *node)
|
|
|
1368
1370
|
trg = element->attr_id->value;
|
|
1369
1371
|
src = &selector->name;
|
|
1370
1372
|
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
+
if (trg->length != src->length) {
|
|
1374
|
+
return false;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
if (node->owner_document->compat_mode == LXB_DOM_DOCUMENT_CMODE_QUIRKS) {
|
|
1378
|
+
return lexbor_str_data_ncasecmp(trg->data, src->data, src->length);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
return lexbor_str_data_ncmp(trg->data, src->data, src->length);
|
|
1373
1382
|
}
|
|
1374
1383
|
|
|
1375
1384
|
static bool
|
|
@@ -499,6 +499,7 @@ lxb_url_scheme_length = sizeof(lxb_url_scheme_res) / sizeof(lxb_url_scheme_data_
|
|
|
499
499
|
if (tmp == NULL) { \
|
|
500
500
|
return NULL; \
|
|
501
501
|
} \
|
|
502
|
+
memcpy(tmp, (sbuf_begin), offset); \
|
|
502
503
|
} \
|
|
503
504
|
else { \
|
|
504
505
|
tmp = lexbor_realloc((sbuf_begin), new_len); \
|
|
@@ -509,7 +510,7 @@ lxb_url_scheme_length = sizeof(lxb_url_scheme_res) / sizeof(lxb_url_scheme_data_
|
|
|
509
510
|
} \
|
|
510
511
|
\
|
|
511
512
|
(sbuf) = tmp + offset; \
|
|
512
|
-
(last) =
|
|
513
|
+
(last) = tmp + lst; \
|
|
513
514
|
(sbuf_begin) = tmp; \
|
|
514
515
|
(sbuf_end) = tmp + new_len; \
|
|
515
516
|
} \
|
|
@@ -860,7 +861,7 @@ lxb_url_is_url_codepoint(lxb_codepoint_t cp)
|
|
|
860
861
|
return lxb_url_codepoint_alphanumeric[(lxb_char_t) cp] != 0xFF;
|
|
861
862
|
}
|
|
862
863
|
|
|
863
|
-
|
|
864
|
+
bool
|
|
864
865
|
lxb_url_is_special(const lxb_url_t *url)
|
|
865
866
|
{
|
|
866
867
|
return url->scheme.type != LXB_URL_SCHEMEL_TYPE__UNKNOWN;
|
|
@@ -5080,6 +5081,8 @@ lxb_url_search_params_parse(lxb_url_search_params_t *search_params,
|
|
|
5080
5081
|
return status;
|
|
5081
5082
|
}
|
|
5082
5083
|
|
|
5084
|
+
last = entry;
|
|
5085
|
+
|
|
5083
5086
|
lexbor_str_init(&entry->value, mraw, 0);
|
|
5084
5087
|
if (entry->value.data == NULL) {
|
|
5085
5088
|
return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
|
|
@@ -763,6 +763,15 @@ LXB_API lxb_status_t
|
|
|
763
763
|
lxb_url_search_params_serialize(lxb_url_search_params_t *search_params,
|
|
764
764
|
lexbor_callback_f cb, void *ctx);
|
|
765
765
|
|
|
766
|
+
/**
|
|
767
|
+
* Returns whether the URL is special.
|
|
768
|
+
*
|
|
769
|
+
* @param[in] lxb_url_t *. Cannot be NULL.
|
|
770
|
+
* @return true if URL is special, false otherwise.
|
|
771
|
+
*/
|
|
772
|
+
LXB_API bool
|
|
773
|
+
lxb_url_is_special(const lxb_url_t *url);
|
|
774
|
+
|
|
766
775
|
/*
|
|
767
776
|
* Inline functions.
|
|
768
777
|
*/
|
data/vendor/lexbor/version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
LEXBOR_VERSION=3.
|
|
1
|
+
LEXBOR_VERSION=3.1.0
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: makiri
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- takahashim
|
|
@@ -65,8 +65,10 @@ extra_rdoc_files: []
|
|
|
65
65
|
files:
|
|
66
66
|
- ".github/workflows/ci.yml"
|
|
67
67
|
- ".github/workflows/conformance.yml"
|
|
68
|
+
- ".github/workflows/libfuzzer.yml"
|
|
68
69
|
- ".github/workflows/release.yml"
|
|
69
70
|
- ".github/workflows/security.yml"
|
|
71
|
+
- ".github/workflows/valgrind.yml"
|
|
70
72
|
- ".gitmodules"
|
|
71
73
|
- CHANGELOG.md
|
|
72
74
|
- LICENSE
|
|
@@ -83,16 +85,27 @@ files:
|
|
|
83
85
|
- ext/makiri/core/mkr_core.c
|
|
84
86
|
- ext/makiri/core/mkr_core.h
|
|
85
87
|
- ext/makiri/core/mkr_hash.h
|
|
88
|
+
- ext/makiri/core/mkr_span.h
|
|
86
89
|
- ext/makiri/core/mkr_text.h
|
|
90
|
+
- ext/makiri/core/mkr_utf8.c
|
|
91
|
+
- ext/makiri/core/mkr_utf8.h
|
|
87
92
|
- ext/makiri/extconf.rb
|
|
93
|
+
- ext/makiri/fuzz/Makefile
|
|
94
|
+
- ext/makiri/fuzz/check_fuzzer.cc
|
|
95
|
+
- ext/makiri/fuzz/xml_fuzz.c
|
|
96
|
+
- ext/makiri/fuzz/xpath_fuzz.c
|
|
88
97
|
- ext/makiri/glue/glue.h
|
|
89
|
-
- ext/makiri/glue/ruby_css.c
|
|
90
98
|
- ext/makiri/glue/ruby_doc.c
|
|
91
|
-
- ext/makiri/glue/
|
|
99
|
+
- ext/makiri/glue/ruby_html_css.c
|
|
100
|
+
- ext/makiri/glue/ruby_html_mutate.c
|
|
101
|
+
- ext/makiri/glue/ruby_html_node.c
|
|
102
|
+
- ext/makiri/glue/ruby_html_serialize.c
|
|
92
103
|
- ext/makiri/glue/ruby_node.c
|
|
93
104
|
- ext/makiri/glue/ruby_node_set.c
|
|
94
|
-
- ext/makiri/glue/
|
|
105
|
+
- ext/makiri/glue/ruby_xml.c
|
|
106
|
+
- ext/makiri/glue/ruby_xml_node.c
|
|
95
107
|
- ext/makiri/glue/ruby_xpath.c
|
|
108
|
+
- ext/makiri/glue/ruby_xpath.h
|
|
96
109
|
- ext/makiri/lexbor_compat/compat.h
|
|
97
110
|
- ext/makiri/lexbor_compat/compat_internal.h
|
|
98
111
|
- ext/makiri/lexbor_compat/dom_index.c
|
|
@@ -102,33 +115,64 @@ files:
|
|
|
102
115
|
- ext/makiri/lexbor_compat/utf8_input.c
|
|
103
116
|
- ext/makiri/makiri.c
|
|
104
117
|
- ext/makiri/makiri.h
|
|
118
|
+
- ext/makiri/xml/mkr_xml.h
|
|
119
|
+
- ext/makiri/xml/mkr_xml_chars.c
|
|
120
|
+
- ext/makiri/xml/mkr_xml_index.c
|
|
121
|
+
- ext/makiri/xml/mkr_xml_index.h
|
|
122
|
+
- ext/makiri/xml/mkr_xml_mutate.c
|
|
123
|
+
- ext/makiri/xml/mkr_xml_mutate.h
|
|
124
|
+
- ext/makiri/xml/mkr_xml_node.c
|
|
125
|
+
- ext/makiri/xml/mkr_xml_node.h
|
|
126
|
+
- ext/makiri/xml/mkr_xml_tree.c
|
|
127
|
+
- ext/makiri/xpath/mkr_css.c
|
|
128
|
+
- ext/makiri/xpath/mkr_css.h
|
|
105
129
|
- ext/makiri/xpath/mkr_xpath.c
|
|
106
130
|
- ext/makiri/xpath/mkr_xpath.h
|
|
107
|
-
- ext/makiri/xpath/
|
|
108
|
-
- ext/makiri/xpath/
|
|
131
|
+
- ext/makiri/xpath/mkr_xpath_engine_html.c
|
|
132
|
+
- ext/makiri/xpath/mkr_xpath_engine_xml.c
|
|
133
|
+
- ext/makiri/xpath/mkr_xpath_eval_body.h
|
|
134
|
+
- ext/makiri/xpath/mkr_xpath_funcs_body.h
|
|
109
135
|
- ext/makiri/xpath/mkr_xpath_internal.h
|
|
110
136
|
- ext/makiri/xpath/mkr_xpath_lex.c
|
|
137
|
+
- ext/makiri/xpath/mkr_xpath_node_access_html.h
|
|
138
|
+
- ext/makiri/xpath/mkr_xpath_node_access_xml.h
|
|
139
|
+
- ext/makiri/xpath/mkr_xpath_number.c
|
|
111
140
|
- ext/makiri/xpath/mkr_xpath_parse.c
|
|
112
|
-
- ext/makiri/xpath/
|
|
141
|
+
- ext/makiri/xpath/mkr_xpath_prelude_html.h
|
|
142
|
+
- ext/makiri/xpath/mkr_xpath_prelude_xml.h
|
|
143
|
+
- ext/makiri/xpath/mkr_xpath_shared.c
|
|
144
|
+
- ext/makiri/xpath/mkr_xpath_value_body.h
|
|
145
|
+
- ext/makiri/xpath/mkr_xpath_xml_selftest.c
|
|
113
146
|
- lib/makiri.rb
|
|
114
|
-
- lib/makiri/
|
|
115
|
-
- lib/makiri/
|
|
147
|
+
- lib/makiri/attr.rb
|
|
148
|
+
- lib/makiri/cdata_section.rb
|
|
116
149
|
- lib/makiri/comment.rb
|
|
150
|
+
- lib/makiri/compat_aliases.rb
|
|
117
151
|
- lib/makiri/css.rb
|
|
118
152
|
- lib/makiri/document.rb
|
|
119
153
|
- lib/makiri/document_fragment.rb
|
|
120
154
|
- lib/makiri/document_type.rb
|
|
121
155
|
- lib/makiri/element.rb
|
|
156
|
+
- lib/makiri/html.rb
|
|
157
|
+
- lib/makiri/html/document.rb
|
|
158
|
+
- lib/makiri/html/node_methods.rb
|
|
122
159
|
- lib/makiri/node.rb
|
|
123
160
|
- lib/makiri/node_set.rb
|
|
124
161
|
- lib/makiri/processing_instruction.rb
|
|
125
162
|
- lib/makiri/text.rb
|
|
126
163
|
- lib/makiri/version.rb
|
|
164
|
+
- lib/makiri/xml.rb
|
|
165
|
+
- lib/makiri/xml/builder.rb
|
|
166
|
+
- lib/makiri/xml/document.rb
|
|
167
|
+
- lib/makiri/xml/node_methods.rb
|
|
127
168
|
- lib/makiri/xpath.rb
|
|
128
169
|
- lib/makiri/xpath_context.rb
|
|
129
170
|
- script/build_native_gem.rb
|
|
171
|
+
- script/check_alloc_failures.rb
|
|
130
172
|
- script/check_c_safety.rb
|
|
131
173
|
- script/check_c_safety_allowlist.yml
|
|
174
|
+
- script/check_leaks.rb
|
|
175
|
+
- script/leaks_harness.rb
|
|
132
176
|
- sig/makiri.rbs
|
|
133
177
|
- vendor/lexbor/.travis.yml
|
|
134
178
|
- vendor/lexbor/CHANGELOG.md
|
data/ext/makiri/glue/ruby_css.c
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
#include "glue.h"
|
|
2
|
-
|
|
3
|
-
#include <lexbor/css/css.h>
|
|
4
|
-
#include <lexbor/selectors/selectors.h>
|
|
5
|
-
|
|
6
|
-
/*
|
|
7
|
-
* CSS selector queries, delegated to Lexbor's lxb_selectors engine.
|
|
8
|
-
*
|
|
9
|
-
* Node#css(selector) -> NodeSet (descendants matching, document order)
|
|
10
|
-
* Node#at_css(selector) -> first matching descendant, or nil
|
|
11
|
-
*
|
|
12
|
-
* Selectors are compiled per call (a per-context cache is a later concern).
|
|
13
|
-
* A malformed selector raises Makiri::CSS::SyntaxError.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
typedef struct {
|
|
17
|
-
VALUE set;
|
|
18
|
-
lxb_dom_node_t *root; /* excluded from results: css is descendant-only */
|
|
19
|
-
size_t count;
|
|
20
|
-
int overflow;
|
|
21
|
-
int first_only;
|
|
22
|
-
} mkr_css_ctx_t;
|
|
23
|
-
|
|
24
|
-
static lxb_status_t
|
|
25
|
-
mkr_css_find_cb(lxb_dom_node_t *node, lxb_css_selector_specificity_t spec,
|
|
26
|
-
void *ctx_)
|
|
27
|
-
{
|
|
28
|
-
(void)spec;
|
|
29
|
-
mkr_css_ctx_t *c = (mkr_css_ctx_t *)ctx_;
|
|
30
|
-
|
|
31
|
-
if (node == c->root) {
|
|
32
|
-
return LXB_STATUS_OK; /* descendant-only, like Nokogiri's node.css */
|
|
33
|
-
}
|
|
34
|
-
if (c->count >= MKR_NODE_SET_MAX) {
|
|
35
|
-
c->overflow = 1;
|
|
36
|
-
return LXB_STATUS_STOP; /* fail closed without raising mid-traversal */
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
mkr_node_set_push(c->set, node);
|
|
40
|
-
c->count++;
|
|
41
|
-
return c->first_only ? LXB_STATUS_STOP : LXB_STATUS_OK;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/* Callback for matches?: signals that the node matched the selector. */
|
|
45
|
-
static lxb_status_t
|
|
46
|
-
mkr_css_match_cb(lxb_dom_node_t *node, lxb_css_selector_specificity_t spec,
|
|
47
|
-
void *ctx_)
|
|
48
|
-
{
|
|
49
|
-
(void)node; (void)spec;
|
|
50
|
-
*(int *)ctx_ = 1;
|
|
51
|
-
return LXB_STATUS_STOP;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/* Compile +rb_selector+, hand the established engine + parsed list to +run+
|
|
55
|
-
* (which performs the actual find / match_node against +node+), then tear the
|
|
56
|
-
* Lexbor CSS object graph down in the required order and fail closed. Centralises
|
|
57
|
-
* the engine lifecycle so the construction/teardown order — a delicate
|
|
58
|
-
* Lexbor-specific detail — lives in exactly one place. Raises
|
|
59
|
-
* Makiri::CSS::SyntaxError on a bad selector, Makiri::Error on engine init
|
|
60
|
-
* failure; any result-specific limits are checked by the caller after return. */
|
|
61
|
-
static void
|
|
62
|
-
mkr_with_compiled_selector(VALUE rb_selector, lxb_dom_node_t *node,
|
|
63
|
-
lxb_status_t (*run)(lxb_selectors_t *, lxb_dom_node_t *,
|
|
64
|
-
lxb_css_selector_list_t *, void *),
|
|
65
|
-
void *u)
|
|
66
|
-
{
|
|
67
|
-
mkr_ruby_borrowed_text_t sv = mkr_ruby_verified_text(rb_selector, "CSS selector");
|
|
68
|
-
const lxb_char_t *s = (const lxb_char_t *)sv.ptr;
|
|
69
|
-
size_t slen = sv.len;
|
|
70
|
-
|
|
71
|
-
/* Lexbor CSS object graph: memory arena -> parser -> selector parser, plus
|
|
72
|
-
* the traversal engine. All transient; torn down before we return. */
|
|
73
|
-
lxb_css_memory_t *mem = lxb_css_memory_create();
|
|
74
|
-
lxb_css_parser_t *parser = lxb_css_parser_create();
|
|
75
|
-
lxb_css_selectors_t *css_sel = lxb_css_selectors_create();
|
|
76
|
-
lxb_selectors_t *selectors = lxb_selectors_create();
|
|
77
|
-
lxb_css_selector_list_t *list = NULL;
|
|
78
|
-
|
|
79
|
-
int ok = (mem != NULL && parser != NULL && css_sel != NULL && selectors != NULL);
|
|
80
|
-
if (ok) {
|
|
81
|
-
ok = (lxb_css_memory_init(mem, 128) == LXB_STATUS_OK)
|
|
82
|
-
&& (lxb_css_parser_init(parser, NULL) == LXB_STATUS_OK)
|
|
83
|
-
&& (lxb_css_selectors_init(css_sel) == LXB_STATUS_OK)
|
|
84
|
-
&& (lxb_selectors_init(selectors) == LXB_STATUS_OK);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
int syntax_error = 0;
|
|
88
|
-
if (ok) {
|
|
89
|
-
lxb_css_parser_memory_set(parser, mem);
|
|
90
|
-
lxb_css_parser_selectors_set(parser, css_sel);
|
|
91
|
-
list = lxb_css_selectors_parse(parser, s, slen);
|
|
92
|
-
if (list == NULL || parser->status != LXB_STATUS_OK) {
|
|
93
|
-
syntax_error = 1;
|
|
94
|
-
} else {
|
|
95
|
-
(void)run(selectors, node, list, u);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/* Teardown (order mirrors Lexbor's own examples). Destroying the memory
|
|
100
|
-
* arena frees the parsed selector list, so we do not free it separately. */
|
|
101
|
-
if (selectors != NULL) lxb_selectors_destroy(selectors, true);
|
|
102
|
-
if (parser != NULL) lxb_css_parser_destroy(parser, true);
|
|
103
|
-
if (mem != NULL) lxb_css_memory_destroy(mem, true);
|
|
104
|
-
if (css_sel != NULL) lxb_css_selectors_destroy(css_sel, true);
|
|
105
|
-
|
|
106
|
-
if (!ok) {
|
|
107
|
-
rb_raise(mkr_eError, "failed to initialise CSS selector engine");
|
|
108
|
-
}
|
|
109
|
-
if (syntax_error) {
|
|
110
|
-
rb_raise(mkr_eCSSSyntaxError, "invalid CSS selector: %" PRIsVALUE, sv.value);
|
|
111
|
-
}
|
|
112
|
-
RB_GC_GUARD(sv.value);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/* find: collect descendants matching the selector (MATCH_FIRST dedups a node
|
|
116
|
-
* that matches several selectors in a comma list). */
|
|
117
|
-
static lxb_status_t
|
|
118
|
-
mkr_run_find(lxb_selectors_t *selectors, lxb_dom_node_t *root,
|
|
119
|
-
lxb_css_selector_list_t *list, void *u)
|
|
120
|
-
{
|
|
121
|
-
lxb_selectors_opt_set(selectors, LXB_SELECTORS_OPT_MATCH_FIRST);
|
|
122
|
-
return lxb_selectors_find(selectors, root, list, mkr_css_find_cb, u);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/* match_node: does THIS node match? */
|
|
126
|
-
static lxb_status_t
|
|
127
|
-
mkr_run_match(lxb_selectors_t *selectors, lxb_dom_node_t *node,
|
|
128
|
-
lxb_css_selector_list_t *list, void *u)
|
|
129
|
-
{
|
|
130
|
-
return lxb_selectors_match_node(selectors, node, list, mkr_css_match_cb, u);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/* Run +selector+ against self's subtree. first_only stops after one match.
|
|
134
|
-
* Raises Makiri::CSS::SyntaxError on a bad selector, Makiri::Error on
|
|
135
|
-
* allocation failure or an over-large result. */
|
|
136
|
-
static VALUE
|
|
137
|
-
mkr_css_query(VALUE self, VALUE rb_selector, int first_only)
|
|
138
|
-
{
|
|
139
|
-
lxb_dom_node_t *root = mkr_node_unwrap(self);
|
|
140
|
-
VALUE document = mkr_node_document(self);
|
|
141
|
-
VALUE set = mkr_node_set_new(document);
|
|
142
|
-
|
|
143
|
-
mkr_css_ctx_t ctx = { .set = set, .root = root, .count = 0,
|
|
144
|
-
.overflow = 0, .first_only = first_only };
|
|
145
|
-
mkr_with_compiled_selector(rb_selector, root, mkr_run_find, &ctx);
|
|
146
|
-
|
|
147
|
-
if (ctx.overflow) {
|
|
148
|
-
rb_raise(mkr_eError, "CSS result set exceeded the node limit (%u)",
|
|
149
|
-
MKR_NODE_SET_MAX);
|
|
150
|
-
}
|
|
151
|
-
return set;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/* Node#matches?(selector): does THIS node match the CSS selector? (Like
|
|
155
|
-
* Nokogiri — tested against the node itself, not its descendants.) A malformed
|
|
156
|
-
* selector raises Makiri::CSS::SyntaxError. */
|
|
157
|
-
static VALUE
|
|
158
|
-
mkr_node_matches(VALUE self, VALUE rb_selector)
|
|
159
|
-
{
|
|
160
|
-
lxb_dom_node_t *node = mkr_node_unwrap(self);
|
|
161
|
-
int matched = 0;
|
|
162
|
-
mkr_with_compiled_selector(rb_selector, node, mkr_run_match, &matched);
|
|
163
|
-
return matched ? Qtrue : Qfalse;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
static VALUE
|
|
167
|
-
mkr_node_css(VALUE self, VALUE rb_selector)
|
|
168
|
-
{
|
|
169
|
-
return mkr_css_query(self, rb_selector, 0);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
static VALUE
|
|
173
|
-
mkr_node_at_css(VALUE self, VALUE rb_selector)
|
|
174
|
-
{
|
|
175
|
-
VALUE set = mkr_css_query(self, rb_selector, 1);
|
|
176
|
-
return rb_funcall(set, rb_intern("first"), 0);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
void
|
|
180
|
-
mkr_init_css(void)
|
|
181
|
-
{
|
|
182
|
-
rb_define_method(mkr_cNode, "css", mkr_node_css, 1);
|
|
183
|
-
rb_define_method(mkr_cNode, "at_css", mkr_node_at_css, 1);
|
|
184
|
-
rb_define_method(mkr_cNode, "matches?", mkr_node_matches, 1);
|
|
185
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
#include "glue.h"
|
|
2
|
-
|
|
3
|
-
#include <lexbor/html/serialize.h>
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
* HTML serialization, delegated to Lexbor's serializer.
|
|
7
|
-
*
|
|
8
|
-
* Node#to_html / #to_s / #outer_html -> the node and its subtree (outer)
|
|
9
|
-
* Node#inner_html -> the node's children only (inner)
|
|
10
|
-
*
|
|
11
|
-
* We use the callback variants so output streams straight into a Ruby String;
|
|
12
|
-
* Lexbor emits UTF-8, which is the string's encoding.
|
|
13
|
-
*
|
|
14
|
-
* Mutating setters (inner_html=, outer_html=) arrive with the v0.2 mutation
|
|
15
|
-
* API and are not defined here.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
static lxb_status_t
|
|
19
|
-
mkr_serialize_cb(const lxb_char_t *data, size_t len, void *ctx)
|
|
20
|
-
{
|
|
21
|
-
rb_str_cat((VALUE)ctx, (const char *)data, (long)len);
|
|
22
|
-
return LXB_STATUS_OK;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/* Read the optional `pretty:` keyword. */
|
|
26
|
-
static int
|
|
27
|
-
mkr_serialize_pretty_opt(int argc, VALUE *argv)
|
|
28
|
-
{
|
|
29
|
-
VALUE opts = Qnil;
|
|
30
|
-
rb_scan_args(argc, argv, "0:", &opts);
|
|
31
|
-
if (NIL_P(opts)) {
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
return RTEST(rb_hash_aref(opts, ID2SYM(rb_intern("pretty"))));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* Outer HTML: the node itself plus its descendants.
|
|
38
|
-
* Pass `pretty: true` for indented output. */
|
|
39
|
-
static VALUE
|
|
40
|
-
mkr_node_to_html(int argc, VALUE *argv, VALUE self)
|
|
41
|
-
{
|
|
42
|
-
int pretty = mkr_serialize_pretty_opt(argc, argv);
|
|
43
|
-
lxb_dom_node_t *node = mkr_node_unwrap(self);
|
|
44
|
-
VALUE str = rb_utf8_str_new(NULL, 0);
|
|
45
|
-
|
|
46
|
-
/* A document fragment has no tag of its own; "outer" == its children, so
|
|
47
|
-
* the deep (children) serializer is the right one (the tree serializer
|
|
48
|
-
* rejects a fragment node). */
|
|
49
|
-
int deep = (node->type == LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT);
|
|
50
|
-
lxb_status_t st;
|
|
51
|
-
if (deep) {
|
|
52
|
-
st = pretty
|
|
53
|
-
? lxb_html_serialize_pretty_deep_cb(node, LXB_HTML_SERIALIZE_OPT_UNDEF,
|
|
54
|
-
0, mkr_serialize_cb, (void *)str)
|
|
55
|
-
: lxb_html_serialize_deep_cb(node, mkr_serialize_cb, (void *)str);
|
|
56
|
-
} else {
|
|
57
|
-
st = pretty
|
|
58
|
-
? lxb_html_serialize_pretty_tree_cb(node, LXB_HTML_SERIALIZE_OPT_UNDEF,
|
|
59
|
-
0, mkr_serialize_cb, (void *)str)
|
|
60
|
-
: lxb_html_serialize_tree_cb(node, mkr_serialize_cb, (void *)str);
|
|
61
|
-
}
|
|
62
|
-
if (st != LXB_STATUS_OK) {
|
|
63
|
-
rb_raise(mkr_eError, "HTML serialization failed");
|
|
64
|
-
}
|
|
65
|
-
return str;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/* Inner HTML: the node's children, without the node's own tag. */
|
|
69
|
-
static VALUE
|
|
70
|
-
mkr_node_inner_html(int argc, VALUE *argv, VALUE self)
|
|
71
|
-
{
|
|
72
|
-
int pretty = mkr_serialize_pretty_opt(argc, argv);
|
|
73
|
-
lxb_dom_node_t *node = mkr_node_unwrap(self);
|
|
74
|
-
VALUE str = rb_utf8_str_new(NULL, 0);
|
|
75
|
-
lxb_status_t st = pretty
|
|
76
|
-
? lxb_html_serialize_pretty_deep_cb(node, LXB_HTML_SERIALIZE_OPT_UNDEF,
|
|
77
|
-
0, mkr_serialize_cb, (void *)str)
|
|
78
|
-
: lxb_html_serialize_deep_cb(node, mkr_serialize_cb, (void *)str);
|
|
79
|
-
if (st != LXB_STATUS_OK) {
|
|
80
|
-
rb_raise(mkr_eError, "HTML serialization failed");
|
|
81
|
-
}
|
|
82
|
-
return str;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
void
|
|
86
|
-
mkr_init_serialize(void)
|
|
87
|
-
{
|
|
88
|
-
rb_define_method(mkr_cNode, "to_html", mkr_node_to_html, -1);
|
|
89
|
-
rb_define_method(mkr_cNode, "to_s", mkr_node_to_html, -1);
|
|
90
|
-
rb_define_method(mkr_cNode, "outer_html", mkr_node_to_html, -1);
|
|
91
|
-
rb_define_method(mkr_cNode, "inner_html", mkr_node_inner_html, -1);
|
|
92
|
-
}
|