makiri 0.11.0.rc1-aarch64-linux → 0.12.0-aarch64-linux
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/CHANGELOG.md +81 -0
- data/NOKOGIRI_DIFFERENCES.md +65 -13
- data/lib/makiri/3.2/makiri.so +0 -0
- data/lib/makiri/3.3/makiri.so +0 -0
- data/lib/makiri/3.4/makiri.so +0 -0
- data/lib/makiri/4.0/makiri.so +0 -0
- data/lib/makiri/element.rb +16 -0
- data/lib/makiri/node_path.rb +8 -1
- data/lib/makiri/version.rb +1 -1
- data/script/check_alloc_failures.rb +6 -0
- data/script/check_unsafe_boundaries.rb +2 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz: '
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '080648651b5e8e38a405373a252b0ded69f1e5a672c6e5031e0f31058b09fa80'
|
|
4
|
+
data.tar.gz: c13624a3a5ed5e94e4d0adc761280e498fbf3e34891ba41d46cfeeed762bcf68
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba444c67f4c84cbe0d3a9317ddcfbbf6854daf1c9fa0a020e16e319ac9d8e98e693fa0b245ba8f3abb3bf9e0f7837af77238c7c0d4557d9d268d1b0465bd24cd
|
|
7
|
+
data.tar.gz: c822e0c488221872b85fc6d8390dea3ee1b72def3c35ae160750102a26115047a84ca0f06df2f0b3ee34b7b3dacc011edbb7c56de27cff93e96fb7e9f9132360
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,86 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.12.0] - 2026-10-01
|
|
4
|
+
|
|
5
|
+
Most changes accept what the DOM allows where 0.11.0 raised. The XML
|
|
6
|
+
serializers (`to_xml`, `canonicalize`) raise instead when the tree holds
|
|
7
|
+
something XML cannot write.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
HTML:
|
|
12
|
+
|
|
13
|
+
* `to_html` / `inner_html` write a `<template>`'s contents, not its own
|
|
14
|
+
children (added with `add_child`), as browsers do.
|
|
15
|
+
* `create_element_ns` in the HTML namespace accepts an upper-case name
|
|
16
|
+
(`BR`, `DIV`), as the DOM does. It makes an unknown element: not void, and
|
|
17
|
+
not matched by type selectors. Importing such an XHTML element from XML
|
|
18
|
+
behaves the same way.
|
|
19
|
+
|
|
20
|
+
XML:
|
|
21
|
+
|
|
22
|
+
* Text, attribute values and comments accept the characters the DOM allows:
|
|
23
|
+
`"\f"`, U+0001, NUL, and `--` in a comment.
|
|
24
|
+
* `set_attribute_ns` accepts names XML cannot write, such as `p:a}b`.
|
|
25
|
+
* `to_xml` and `canonicalize` raise while any of the above is in the tree.
|
|
26
|
+
* `create_cdata` with `]]>` and `create_processing_instruction` with `?>`
|
|
27
|
+
now raise `ArgumentError`.
|
|
28
|
+
* `canonicalize` adds the namespace declarations a name needs instead of
|
|
29
|
+
raising. It still raises where it would have to invent a prefix.
|
|
30
|
+
|
|
31
|
+
HTML to XML (`import_node`):
|
|
32
|
+
|
|
33
|
+
* The copy is in its namespace at once. Before, it was in none until
|
|
34
|
+
inserted.
|
|
35
|
+
* The copy gets no `xmlns` attribute.
|
|
36
|
+
* An attribute XML cannot write (`x-on:click`, `@click`) is copied as it is
|
|
37
|
+
instead of raising.
|
|
38
|
+
* A `<template>` keeps its own children, after its contents.
|
|
39
|
+
|
|
40
|
+
Other:
|
|
41
|
+
|
|
42
|
+
* `Node#path` round-trips when a sibling with a different prefix or case
|
|
43
|
+
would also match the same XPath step.
|
|
44
|
+
|
|
45
|
+
## [0.11.0] - 2026-09-30
|
|
46
|
+
|
|
47
|
+
No code changes since 0.11.0.rc2. Coming from 0.10.x, read the rc2 and rc1
|
|
48
|
+
notes below as well.
|
|
49
|
+
|
|
50
|
+
## [0.11.0.rc2] - 2026-09-30
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
* `Makiri::HTML::Document#create_element_ns(namespace_uri, qualified_name)`
|
|
55
|
+
(DOM `createElementNS`). An SVG or MathML element made this way keeps its
|
|
56
|
+
name's case and behaves like a parsed one. An upper-case name in the HTML
|
|
57
|
+
namespace that names a known element (`BR`, `DIV`) raises `Makiri::Error`.
|
|
58
|
+
* `Makiri::XML::Element#set_loose_dom_attribute(qualified_name, value)` (DOM
|
|
59
|
+
`setAttribute`): the attribute is in no namespace and keeps the name as
|
|
60
|
+
given (`xmlns`, `xlink:href`, `v-on:click`). `to_xml` raises while the
|
|
61
|
+
document holds one XML cannot write.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
* A NUL in an element, attribute, doctype or PI target name raises
|
|
66
|
+
`ArgumentError`, like any other invalid name. A namespace that does not fit
|
|
67
|
+
the name still raises `Makiri::Error`.
|
|
68
|
+
* HTML type selectors are case-sensitive on SVG and MathML elements, as in
|
|
69
|
+
browsers: `fegaussianblur` no longer matches `feGaussianBlur`.
|
|
70
|
+
* `set_attribute_ns` accepts the XML namespace with any prefix or none again
|
|
71
|
+
(rc1 raised); `to_xml` writes such an attribute as `xml:name`.
|
|
72
|
+
* XML `set_attribute_ns` accepts a namespace declaration XML forbids, such as
|
|
73
|
+
`xmlns:foo=""`. It binds nothing, and `to_xml` raises while it is present.
|
|
74
|
+
* XML `create_document_type` accepts any public and system id, and any name
|
|
75
|
+
without whitespace, NUL or `>`. `to_xml` raises if the doctype cannot be
|
|
76
|
+
written as XML.
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
* `import_node` from XML to HTML keeps an upper-case XHTML element name
|
|
81
|
+
(`Foo`) instead of lower-casing it, and raises for one that names a known
|
|
82
|
+
element (`BR`).
|
|
83
|
+
|
|
3
84
|
## [0.11.0.rc1] - 2026-09-29
|
|
4
85
|
|
|
5
86
|
### Changed
|
data/NOKOGIRI_DIFFERENCES.md
CHANGED
|
@@ -107,6 +107,19 @@ what browsers do - rather than libxml2. Detailed, test-backed notes live in
|
|
|
107
107
|
invents one (`ns1`, `ns2`, ...) rather than shadow the other, as browsers do.
|
|
108
108
|
* An element in no namespace stays that way under a default namespace,
|
|
109
109
|
serialized as `xmlns=""`.
|
|
110
|
+
* `create_document_type` takes what the DOM's `createDocumentType` takes -
|
|
111
|
+
any id, and a name without whitespace, NUL or `>` - and `to_xml` refuses a
|
|
112
|
+
doctype XML cannot write (`create_document_type("q", "abcde", %(x"'y))`).
|
|
113
|
+
Nokogiri writes that system id as `"x"'y"`, which parses but reads
|
|
114
|
+
back as the id `x"'y` - a literal expands no references.
|
|
115
|
+
* `set_attribute_ns(XMLNS_NS, "xmlns:foo", "")` - a declaration Namespaces in
|
|
116
|
+
XML forbids, which the DOM's `setAttributeNS` accepts - is kept as an
|
|
117
|
+
attribute that binds nothing, and `to_xml` refuses the tree while it is
|
|
118
|
+
there. `root["xmlns:foo"] = ""` still raises.
|
|
119
|
+
* An attribute in the XML namespace is written as `xml:local`, whatever
|
|
120
|
+
prefix it was given (`set_attribute_ns(XML_NS, "a:bb")`, as the DOM
|
|
121
|
+
allows): Namespaces in XML binds that namespace to `xml` alone. It re-reads
|
|
122
|
+
to the same namespace and local name. `canonicalize` writes it so too.
|
|
110
123
|
* Nodes from the factories (`create_element` and friends) still take their
|
|
111
124
|
namespace from the context they are first inserted into, so a subtree can be
|
|
112
125
|
built detached and attached afterwards. Only later moves carry.
|
|
@@ -165,7 +178,17 @@ what browsers do - rather than libxml2. Detailed, test-backed notes live in
|
|
|
165
178
|
The names HTML actually uses (`data-*`, `aria-*`, `@click`, `:href`,
|
|
166
179
|
`v-on:x`, custom elements) are accepted.
|
|
167
180
|
* `set_attribute_ns(nil, "x:y")` raises, as the DOM's `setAttributeNS` does:
|
|
168
|
-
a prefix needs a namespace.
|
|
181
|
+
a prefix needs a namespace. `[]=` (HTML) and `set_loose_dom_attribute`
|
|
182
|
+
(XML) are the DOM's `setAttribute`, which makes such an attribute.
|
|
183
|
+
* A refused name raises `ArgumentError` - a NUL in it too - and a namespace
|
|
184
|
+
that does not fit the name (`set_attribute_ns`, `create_element_ns`)
|
|
185
|
+
raises `Makiri::Error`. Invalid UTF-8 raises `Makiri::Error` for every
|
|
186
|
+
argument, names included.
|
|
187
|
+
* `create_element_ns` keeps the case of an HTML-namespace name, as the DOM
|
|
188
|
+
does: `create_element_ns(XHTML, "BR")` is an unknown element named `BR`,
|
|
189
|
+
not a void `br`, and type selectors do not match it (XPath name tests do,
|
|
190
|
+
folding case on HTML elements as browsers do). Nokogiri has no
|
|
191
|
+
`create_element_ns`.
|
|
169
192
|
* An HTML `<template>` follows the WHATWG content model, which Nokogiri does
|
|
170
193
|
not: its parsed contents live in the separate fragment `Element#content_fragment`
|
|
171
194
|
returns, `template.children` is empty, and `inner_html` / `inner_html=`
|
|
@@ -175,6 +198,11 @@ what browsers do - rather than libxml2. Detailed, test-backed notes live in
|
|
|
175
198
|
ordinary element, with the parsed nodes as its children, so
|
|
176
199
|
`template.inner_html` and `template.children` answer the other way round and
|
|
177
200
|
there is no `content_fragment`.
|
|
201
|
+
* `Makiri::XML` has no template contents: an XHTML `<template>`'s children
|
|
202
|
+
are its children. Crossing into HTML they become its contents, and back
|
|
203
|
+
they become children - what a browser's XML parser, which puts them in the
|
|
204
|
+
contents, and its importNode give for the same document. An XML
|
|
205
|
+
`<template>` whose children should stay children has no way to say so.
|
|
178
206
|
* An HTML document has one root element and no text child, as the DOM requires;
|
|
179
207
|
`doc << element` beside an existing root raises.
|
|
180
208
|
* An insertion the DOM refuses - a child under a text, comment, PI, doctype
|
|
@@ -182,13 +210,20 @@ what browsers do - rather than libxml2. Detailed, test-backed notes live in
|
|
|
182
210
|
`Makiri::Error` in both representations. Nokogiri refuses the same ones with
|
|
183
211
|
`ArgumentError` (or `RuntimeError` for a second XML root).
|
|
184
212
|
* Moving HTML into an XML document (`xml_doc.import_node(html_node)`, or
|
|
185
|
-
inserting one)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
213
|
+
inserting one) copies it as the DOM's clone does: every element in its
|
|
214
|
+
namespace from the start (an imported `<p>` is XHTML before it is
|
|
215
|
+
inserted), every attribute named as it is, and no `xmlns` attribute added -
|
|
216
|
+
`to_xml` and `canonicalize` write the declarations the output needs.
|
|
217
|
+
Nokogiri's copy of an HTML5 `<div>` is in no namespace, and libxml2
|
|
218
|
+
declares `xmlns:svg` on it for an SVG child (in `namespace_definitions`),
|
|
219
|
+
writing the child as `<svg:svg>`. One XML cannot write that way -
|
|
220
|
+
in no namespace with a colon or no XML name, `v-on:click`, `:href`,
|
|
221
|
+
`@click`, `fb:like` - crosses DOM-loose, and `to_xml` refuses the tree
|
|
222
|
+
while it is there; so does an element named with a colon (`<fb:like>`).
|
|
223
|
+
Nokogiri copies them and writes output that is not namespace-well-formed.
|
|
224
|
+
* One exception to the DOM: an HTML attribute named `xml:lang` (in no
|
|
225
|
+
namespace) becomes the XML namespace's `xml:lang`, as the XML reader reads
|
|
226
|
+
that name, so XHTML-style HTML still writes as XML.
|
|
192
227
|
* A known gap, in Lexbor's tag table: an HTML document that already holds a
|
|
193
228
|
parsed element named with a colon (`<x:y>`, one local name) and then
|
|
194
229
|
receives, by `import_node` from another document, a prefixed element
|
|
@@ -257,8 +292,15 @@ what browsers do - rather than libxml2. Detailed, test-backed notes live in
|
|
|
257
292
|
.matches?("p")` is true, on both representations). Nokogiri raises
|
|
258
293
|
`NoMethodError` there - it implements `#matches?` as a search from
|
|
259
294
|
`ancestors.last`, which a detached node does not have.
|
|
260
|
-
*
|
|
261
|
-
|
|
295
|
+
* Type selectors in an HTML document follow the HTML Standard's
|
|
296
|
+
case-sensitivity rule, as browsers do: lower-cased for an HTML element (`LI`
|
|
297
|
+
matches `<li>`), as written for any other (`feGaussianBlur` matches the SVG
|
|
298
|
+
element, `fegaussianblur` does not). An HTML element named in upper case
|
|
299
|
+
(`create_element_ns(XHTML, "DIV")`, which keeps its name as the DOM does)
|
|
300
|
+
therefore matches no type selector.
|
|
301
|
+
* `Nokogiri::HTML5` is case-sensitive on HTML elements too, so `LI` does not
|
|
302
|
+
match `<li>` there. `Makiri::XML`'s `#css` is case-sensitive, as XML names
|
|
303
|
+
are.
|
|
262
304
|
|
|
263
305
|
## Serialization
|
|
264
306
|
|
|
@@ -285,8 +327,18 @@ what browsers do - rather than libxml2. Detailed, test-backed notes live in
|
|
|
285
327
|
and attribute values (`[]=`, `set_attribute_ns`) - and stored/read back
|
|
286
328
|
verbatim, matching the WHATWG DOM / browsers (`document.createTextNode("\0")`).
|
|
287
329
|
It is still rejected in names, tag names, namespaces, PI target/data, CSS
|
|
288
|
-
selectors, and XPath expressions/variable names
|
|
330
|
+
selectors, and XPath expressions/variable names. A NUL in a name given to a
|
|
331
|
+
factory or setter (element, attribute, doctype and PI target names) raises
|
|
332
|
+
`ArgumentError`, as any other refused name does; anywhere else it raises
|
|
333
|
+
`Makiri::Error`.
|
|
289
334
|
* On re-parse, the HTML tokenizer replaces a U+0000 in text/attributes with
|
|
290
335
|
U+FFFD (WHATWG), so a serialized-then-reparsed round-trip is not byte-identical.
|
|
291
|
-
* `Makiri::XML`
|
|
292
|
-
|
|
336
|
+
* `Makiri::XML` holds the character data the DOM holds, NUL included:
|
|
337
|
+
text or an attribute value with a character XML has no `Char` for (`\f`,
|
|
338
|
+
U+0001, U+0000), a comment with `--`. Nokogiri takes the same, but NUL
|
|
339
|
+
(`ArgumentError`, a Ruby C-string limit). Where they part is the output. `to_xml` / `canonicalize` raise for such a tree; Nokogiri writes
|
|
340
|
+
`\f` in text as U+FFFD (the data changes) and a comment's `--` or an
|
|
341
|
+
attribute value's `\f` as it stands (the output does not parse).
|
|
342
|
+
`create_cdata` refuses `]]>` and `create_processing_instruction` `?>`,
|
|
343
|
+
raising `ArgumentError` as the DOM's factories do; Nokogiri takes the PI
|
|
344
|
+
and writes `<?t a?>b?>`, which re-reads as another tree.
|
data/lib/makiri/3.2/makiri.so
CHANGED
|
Binary file
|
data/lib/makiri/3.3/makiri.so
CHANGED
|
Binary file
|
data/lib/makiri/3.4/makiri.so
CHANGED
|
Binary file
|
data/lib/makiri/4.0/makiri.so
CHANGED
|
Binary file
|
data/lib/makiri/element.rb
CHANGED
|
@@ -22,5 +22,21 @@ module Makiri
|
|
|
22
22
|
def path_step
|
|
23
23
|
name_step("", unprefixed_element_namespace)
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
# See {NodePath#path}. An element step selects by expanded name, not by the
|
|
27
|
+
# string of the test: `*[local-name()='BR' and ...]`, written for `h:BR`,
|
|
28
|
+
# also selects the unprefixed `BR` beside it. A bare name test on an HTML
|
|
29
|
+
# element folds ASCII case, as the engine (and browsers) match it, so `div`
|
|
30
|
+
# also selects the `DIV` createElementNS makes. Compared as strings, each
|
|
31
|
+
# pair was counted apart, and the path found the other one first.
|
|
32
|
+
def path_selects?(other, test)
|
|
33
|
+
return false unless other.element? && other.namespace_uri.to_s == namespace_uri.to_s
|
|
34
|
+
|
|
35
|
+
mine = local_name
|
|
36
|
+
theirs = other.local_name
|
|
37
|
+
return mine == theirs unless test == name && unprefixed_element_namespace
|
|
38
|
+
|
|
39
|
+
mine.downcase(:ascii) == theirs.downcase(:ascii)
|
|
40
|
+
end
|
|
25
41
|
end
|
|
26
42
|
end
|
data/lib/makiri/node_path.rb
CHANGED
|
@@ -48,7 +48,7 @@ module Makiri
|
|
|
48
48
|
parent_node = parent
|
|
49
49
|
return test unless parent_node # a detached top: #path answers "?" anyway
|
|
50
50
|
|
|
51
|
-
siblings = parent_node.children.select { |c| c
|
|
51
|
+
siblings = parent_node.children.select { |c| path_selects?(c, test) }
|
|
52
52
|
return test if siblings.length <= 1
|
|
53
53
|
|
|
54
54
|
"#{test}[#{siblings.index(self) + 1}]"
|
|
@@ -73,6 +73,13 @@ module Makiri
|
|
|
73
73
|
nil
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
# Whether +test+, this node's own step, selects +other+, a sibling: the
|
|
77
|
+
# position counts exactly those. By default the tests are compared, which
|
|
78
|
+
# is the engine's answer for every kind but an element (see Element).
|
|
79
|
+
def path_selects?(other, test)
|
|
80
|
+
other.path_node_test == test
|
|
81
|
+
end
|
|
82
|
+
|
|
76
83
|
# The name test for an element (+axis+ "") or attribute (+axis+ "@"): the
|
|
77
84
|
# bare name when an unprefixed test reaches this node - it is in
|
|
78
85
|
# +plain_namespace+ and its name is a plain NCName - else by expanded name.
|
data/lib/makiri/version.rb
CHANGED
|
@@ -142,7 +142,12 @@ SCENARIOS = {
|
|
|
142
142
|
el = doc.create_element("made")
|
|
143
143
|
el.add_child(doc.create_text_node("inner"))
|
|
144
144
|
el["k"] = "v"
|
|
145
|
+
el.set_loose_dom_attribute("v-on:x", "1")
|
|
146
|
+
el.set_loose_dom_attribute("xmlns", "urn:loose")
|
|
147
|
+
el.set_loose_dom_attribute("k", "v2")
|
|
145
148
|
doc.root.add_child(el)
|
|
149
|
+
el.remove_attribute_ns(nil, "v-on:x")
|
|
150
|
+
el.delete("xmlns")
|
|
146
151
|
el.content = "rewritten"
|
|
147
152
|
el.add_previous_sibling(doc.create_element("before"))
|
|
148
153
|
el.add_next_sibling(doc.create_element("after"))
|
|
@@ -263,6 +268,7 @@ SCENARIOS = {
|
|
|
263
268
|
d = Makiri::HTML::Document.parse("<html><body><div id='a'><p>one</p></div></body></html>")
|
|
264
269
|
a = d.at_css("#a")
|
|
265
270
|
a.add_child(d.create_element("made"))
|
|
271
|
+
a.add_child(d.create_element_ns("http://www.w3.org/2000/svg", "s:feBlend"))
|
|
266
272
|
a.add_child(d.create_text_node("inner"))
|
|
267
273
|
a.add_child(d.create_comment(" note "))
|
|
268
274
|
a.add_child(d.create_processing_instruction("tgt", "pd"))
|
|
@@ -59,6 +59,7 @@ UNSAFE_ISLANDS = {
|
|
|
59
59
|
"lexbor/adapter/html/build.rs" => 19,
|
|
60
60
|
"lexbor/adapter/html/mod.rs" => 60,
|
|
61
61
|
"lexbor/adapter/html/mutate.rs" => 9,
|
|
62
|
+
"lexbor/adapter/html/serialize.rs" => 9,
|
|
62
63
|
"lexbor/adapter/post_parse.rs" => 13,
|
|
63
64
|
"lexbor/adapter/source_loc.rs" => 2,
|
|
64
65
|
"lexbor/adapter/text_index.rs" => 1,
|
|
@@ -461,7 +462,7 @@ end
|
|
|
461
462
|
# is generated, so its signature is Lexbor's. A new hand declaration of a
|
|
462
463
|
# header-declared function belongs in build.rs's allowlist instead; one with no
|
|
463
464
|
# header belongs in build.rs's UNDECLARED_EXPORTS as well as here.
|
|
464
|
-
LEXBOR_HAND_DECLS =
|
|
465
|
+
LEXBOR_HAND_DECLS = 4
|
|
465
466
|
abi_decls = comments_removed(File.binread(File.join(RUST, "lexbor/abi.rs"))).scan(LEXBOR_DECL).length
|
|
466
467
|
if abi_decls != LEXBOR_HAND_DECLS
|
|
467
468
|
errors << "lexbor/abi.rs hand-declares #{abi_decls} Lexbor functions (expected " \
|