leptris 1.9.370.0-arm-linux → 1.9.371.0-arm-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/Rakefile +1 -1
- data/ext/leptris/native/native.c +20 -0
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/comment.rb +7 -0
- data/lib/leptris/xml/document.rb +13 -1
- data/lib/leptris/xml/ffi.rb +10 -0
- data/lib/leptris/xml/native.so +0 -0
- data/lib/leptris/xml/native_3_3.so +0 -0
- data/lib/leptris/xml.rb +27 -12
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +29 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/include/leptris/error.h +22 -0
- data/vendor-src/libleptris/src/include/leptris/html.h +15 -0
- data/vendor-src/libleptris/src/include/leptris/types.h +6 -1
- data/vendor-src/libleptris/src/leptris/dom/diag.c +32 -1
- data/vendor-src/libleptris/src/leptris/dom/diag.h +16 -0
- data/vendor-src/libleptris/src/leptris/error.c +16 -1
- data/vendor-src/libleptris/src/leptris/html/html_parse.c +103 -4
- data/vendor-src/libleptris/test/CMakeLists.txt +1 -0
- data/vendor-src/libleptris/test/html/test_html_parse_errors.cpp +102 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01aee9fe5d4ef0d0736e6b2baa9782114c8e215e836c876cc2c00b88bfe0570e
|
|
4
|
+
data.tar.gz: 2423fc999e38c686ccf57873d4d3946f802d1eed5a84709932f075df519bf2c5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f717e3fc7197c4f6b44ab6dfd7a7a53860765ce3a740c77c996578704f259bf64ef6cd12f9b7f8ef08ccb4a3c14da55495afd9ba49e2d3190a9daebe366e5088
|
|
7
|
+
data.tar.gz: 3b1b8fe3caa49199ff9d3004d6df63de2b3fcf46b3f471905c69cf4eefd9d737e3b7c10af700173c364e222c598325c2e718e876bfe31548c146a294b6e276aa
|
data/Rakefile
CHANGED
|
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
|
8
8
|
# Pin for `rake compile` and the platform-gem builds. Keep in lockstep
|
|
9
9
|
# with .github/workflows/build.yml (which calls `rake compile`) and the
|
|
10
10
|
# CHANGELOG when libleptris releases.
|
|
11
|
-
LIBLEPTRIS_VERSION = "1.9.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.371"
|
|
12
12
|
# Vendored alongside libleptris for fn:normalize-unicode (TODO
|
|
13
13
|
# .restructure/20): built per platform with a RELOCATABLE @rpath
|
|
14
14
|
# install name, loaded by ffi.rb before libleptris so the
|
data/ext/leptris/native/native.c
CHANGED
|
@@ -1445,6 +1445,25 @@ static VALUE nn_create_child(VALUE self, VALUE name)
|
|
|
1445
1445
|
return out;
|
|
1446
1446
|
}
|
|
1447
1447
|
|
|
1448
|
+
/* The #204 write row: gates + version bump + engine set in ONE C
|
|
1449
|
+
* frame on the TypedData self — the caller skips the binding
|
|
1450
|
+
* wrapper's Ruby arg plumbing (nf_set_binding_attribute's
|
|
1451
|
+
* discipline, parameterized by subclass). */
|
|
1452
|
+
static VALUE nn_set_attribute(VALUE self, VALUE name, VALUE value)
|
|
1453
|
+
{
|
|
1454
|
+
struct native_node *n;
|
|
1455
|
+
int st;
|
|
1456
|
+
|
|
1457
|
+
TypedData_Get_Struct(self, struct native_node, &nn_type, n);
|
|
1458
|
+
document_advance_version(n->document);
|
|
1459
|
+
st = f_set_attr(n->ptr, RSTRING_PTR(StringValue(name)),
|
|
1460
|
+
StringValueCStr(value));
|
|
1461
|
+
if (st != 0)
|
|
1462
|
+
rb_raise(c_runtime_error,
|
|
1463
|
+
"leptris_element_set_attribute failed (%d)", st);
|
|
1464
|
+
return value;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1448
1467
|
static VALUE nn_append_child(VALUE self, VALUE child)
|
|
1449
1468
|
{
|
|
1450
1469
|
struct native_node *n, *c;
|
|
@@ -3537,6 +3556,7 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
3537
3556
|
rb_define_method(c_native_node, "name", nn_name, 0);
|
|
3538
3557
|
rb_define_method(c_native_node, "content", nn_content, 0);
|
|
3539
3558
|
rb_define_method(c_native_node, "content=", nn_content_set, 1);
|
|
3559
|
+
rb_define_method(c_native_node, "set_attribute", nn_set_attribute, 2);
|
|
3540
3560
|
rb_define_method(c_native_node, "attribute", nn_attribute, 1);
|
|
3541
3561
|
rb_define_alias(c_native_node, "[]", "attribute");
|
|
3542
3562
|
/* Unshadowed aliases for consumers whose contract modules shadow
|
data/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/comment.rb
CHANGED
|
@@ -38,4 +38,11 @@ class Leptris::XML::Comment < Leptris::XML::Node
|
|
|
38
38
|
|
|
39
39
|
# leptris-ruby#464: comment serialization face.
|
|
40
40
|
alias_method :to_xml, :to_s
|
|
41
|
+
|
|
42
|
+
# HTML serialization (moxml#389 follow-up): Fragment#to_html
|
|
43
|
+
# maps fragment children through to_html — a surviving in-body
|
|
44
|
+
# comment met the missing face and raised NoMethodError.
|
|
45
|
+
# Identical spelling in both modes (HTML comments carry no
|
|
46
|
+
# self-closing or void forms).
|
|
47
|
+
alias_method :to_html, :to_s
|
|
41
48
|
end
|
data/lib/leptris/xml/document.rb
CHANGED
|
@@ -888,9 +888,21 @@ class Leptris::XML::Document
|
|
|
888
888
|
ok = Leptris::XML::FFI.leptris_document_parse_diag(
|
|
889
889
|
c_ptr, i, kind_buf, msg_buf, 512)
|
|
890
890
|
next nil if ok.zero?
|
|
891
|
+
# leptris-ruby#1771: the machine-readable code + position
|
|
892
|
+
# (the §13.2.5 token name for HTML parse lints).
|
|
893
|
+
code_buf = ::FFI::MemoryPointer.new(:char, 128)
|
|
894
|
+
line_buf = ::FFI::MemoryPointer.new(:int)
|
|
895
|
+
col_buf = ::FFI::MemoryPointer.new(:int)
|
|
896
|
+
Leptris::XML::FFI.leptris_document_parse_diag_code(
|
|
897
|
+
c_ptr, i, code_buf, 128, line_buf, col_buf)
|
|
898
|
+
code = code_buf.read_string
|
|
899
|
+
code = nil if code.empty?
|
|
891
900
|
Leptris::XML::SyntaxError.new(
|
|
892
901
|
msg_buf.read_string.force_encoding(Encoding::UTF_8),
|
|
893
|
-
severity: DIAG_SEVERITY.fetch(kind_buf.read_int, :recoverable)
|
|
902
|
+
severity: DIAG_SEVERITY.fetch(kind_buf.read_int, :recoverable),
|
|
903
|
+
line: line_buf.read_int.zero? ? nil : line_buf.read_int,
|
|
904
|
+
column: col_buf.read_int.zero? ? nil : col_buf.read_int,
|
|
905
|
+
code: code)
|
|
894
906
|
end.compact
|
|
895
907
|
end
|
|
896
908
|
|
data/lib/leptris/xml/ffi.rb
CHANGED
|
@@ -555,6 +555,11 @@ module Leptris
|
|
|
555
555
|
# the parse; only an entirely empty result is an error.
|
|
556
556
|
attach_function :leptris_parse_html_string,
|
|
557
557
|
[:string, :size_t, :pointer], :leptris_document
|
|
558
|
+
# leptris-ruby#1771: the WHATWG engine with per-call options
|
|
559
|
+
# (LEPTRIS_PARSE_COLLECT_HTML_ERRORS records the parse-error
|
|
560
|
+
# token stream on the document).
|
|
561
|
+
attach_function :leptris_parse_html_string_flags,
|
|
562
|
+
[:string, :size_t, :size_t, :pointer], :leptris_document
|
|
558
563
|
# HTML4/libxml2-compatibility mode (1.9.104, #659): the same
|
|
559
564
|
# tolerant tokenizer and Nokogiri document shape, except
|
|
560
565
|
# leading script/style stay in <body> (libxml2's shape —
|
|
@@ -1531,6 +1536,11 @@ attach_function :leptris_parse_string,
|
|
|
1531
1536
|
[:leptris_document], :size_t
|
|
1532
1537
|
attach_function :leptris_document_parse_diag,
|
|
1533
1538
|
[:leptris_document, :size_t, :pointer, :pointer, :size_t], :int
|
|
1539
|
+
# leptris-ruby#1771: the diag's machine-readable code + line +
|
|
1540
|
+
# column (the §13.2.5 parse-error token name for HTML lints).
|
|
1541
|
+
attach_function :leptris_document_parse_diag_code,
|
|
1542
|
+
[:leptris_document, :size_t, :pointer, :size_t, :pointer,
|
|
1543
|
+
:pointer], :int
|
|
1534
1544
|
attach_function :leptris_dtd_parse,
|
|
1535
1545
|
[:string, :size_t], :leptris_dtd
|
|
1536
1546
|
attach_function :leptris_dtd_free, [:leptris_dtd], :void
|
data/lib/leptris/xml/native.so
CHANGED
|
Binary file
|
|
Binary file
|
data/lib/leptris/xml.rb
CHANGED
|
@@ -83,17 +83,27 @@ module Leptris
|
|
|
83
83
|
# (script/style/noscript/template/... lift) and foster
|
|
84
84
|
# parenting (1.9.105) — html5lib corpus 294/1555 vs Nokogiri's
|
|
85
85
|
# 372; the shapes genuinely differ by spec.
|
|
86
|
-
def self.parse_html(html, mode: :html4)
|
|
86
|
+
def self.parse_html(html, mode: :html4, collect_errors: false)
|
|
87
87
|
html = html.to_s
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
# leptris-ruby#1771: collect_errors records the §13.2.5
|
|
89
|
+
# parse-error token stream as document errors (code + line +
|
|
90
|
+
# column); the WHATWG engine only (the html4 compat lane
|
|
91
|
+
# keeps the libxml2 posture).
|
|
92
|
+
if collect_errors && mode == :whatwg
|
|
93
|
+
flags = 64 # LEPTRIS_PARSE_COLLECT_HTML_ERRORS
|
|
94
|
+
raw = Leptris::XML::FFI.leptris_parse_html_string_flags(
|
|
95
|
+
html, html.bytesize, flags, nil)
|
|
96
|
+
else
|
|
97
|
+
entry =
|
|
98
|
+
case mode
|
|
99
|
+
when :html4 then Leptris::XML::FFI.method(:leptris_parse_html4_string)
|
|
100
|
+
when :whatwg then Leptris::XML::FFI.method(:leptris_parse_html_string)
|
|
101
|
+
else
|
|
102
|
+
raise ArgumentError,
|
|
103
|
+
"mode must be :html4 or :whatwg, got #{mode.inspect}"
|
|
104
|
+
end
|
|
105
|
+
raw = entry.call(html, html.bytesize, nil)
|
|
106
|
+
end
|
|
97
107
|
if raw.null?
|
|
98
108
|
raise Leptris::XML::ParseError,
|
|
99
109
|
"HTML parse failed: #{Leptris::XML::FFI.leptris_last_error}"
|
|
@@ -111,16 +121,21 @@ module Leptris
|
|
|
111
121
|
# SyntaxError shape — a message plus optional position — served
|
|
112
122
|
# by Document#errors.
|
|
113
123
|
class SyntaxError < Error
|
|
114
|
-
attr_reader :message, :line, :column, :severity
|
|
124
|
+
attr_reader :message, :line, :column, :severity, :code
|
|
115
125
|
|
|
116
126
|
# severity: :fatal (the strict lane raises on this class) or
|
|
117
127
|
# :recoverable (leptris-ruby#1749) — raise-on-fatal /
|
|
118
128
|
# recover-on-recoverable without string matching.
|
|
119
|
-
|
|
129
|
+
# code: the machine-readable token (leptris-ruby#1771 — the
|
|
130
|
+
# §13.2.5 parse-error name for HTML lints, e.g.
|
|
131
|
+
# "unexpected-tag-in-body"); nil when the diag has no code.
|
|
132
|
+
def initialize(message, line: nil, column: nil, severity: :recoverable,
|
|
133
|
+
code: nil)
|
|
120
134
|
@message = message
|
|
121
135
|
@line = line
|
|
122
136
|
@column = column
|
|
123
137
|
@severity = severity
|
|
138
|
+
@code = code
|
|
124
139
|
super(message)
|
|
125
140
|
end
|
|
126
141
|
|
data/lib/libleptris.so
CHANGED
|
Binary file
|
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.371] - 2026-10-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **html: the §13.2.5 parse-error lint surface (#1771, PR #1772).**
|
|
8
|
+
`LEPTRIS_PARSE_COLLECT_HTML_ERRORS` on the new
|
|
9
|
+
`leptris_parse_html_string_flags` entry records the WHATWG
|
|
10
|
+
parse-error token stream as diagnostics — machine-readable **code**
|
|
11
|
+
(the spec token name: "duplicate-attribute", "eof-in-tag",
|
|
12
|
+
"unexpected-doctype", ...), **line**, **column** — one class
|
|
13
|
+
(RECOVER), per the issue's "a single class + code is enough for
|
|
14
|
+
canon to map" contract. The diag record gains a machine-readable
|
|
15
|
+
code field; the read side gains
|
|
16
|
+
`leptris_document_parse_diag_code` (the existing kind+message face
|
|
17
|
+
is untouched — no ABI break). Slice 1 instruments the sites the
|
|
18
|
+
parser already self-documents: duplicate-attribute (structural
|
|
19
|
+
stash + generic start-tag paths), eof-in-tag (all three drop
|
|
20
|
+
shapes), unexpected-doctype outside the initial mode, and the
|
|
21
|
+
malformed-construct bogus-comment fallback; follow-up slices
|
|
22
|
+
extend the coverage per the §13.2.5 list. Off by default — the
|
|
23
|
+
tree construction is exactly as fast without the bit. Engine suite
|
|
24
|
+
2044/2044 including the html5lib corpus gate and the export-surface
|
|
25
|
+
gate; MSVC format-attribute guard included.
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- guard the h_diag format attribute for MSVC (html)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
3
32
|
## [1.9.370] - 2026-10-18
|
|
4
33
|
|
|
5
34
|
<!-- Edit this section with the actual release notes. -->
|
|
@@ -152,6 +152,28 @@ LEPTRIS_API int leptris_document_parse_diag(LeptrisDocument doc,
|
|
|
152
152
|
char* message,
|
|
153
153
|
size_t message_cap);
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Read one parse diagnostic's machine-readable code and position
|
|
157
|
+
* (leptris-ruby#1771: the §13.2.5 parse-error token name for HTML
|
|
158
|
+
* lints; NULL code for diags without one).
|
|
159
|
+
*
|
|
160
|
+
* @param doc Document handle
|
|
161
|
+
* @param index Diagnostic index (< leptris_document_parse_diag_count)
|
|
162
|
+
* @param code Out: NUL-terminated code buffer (may be NULL)
|
|
163
|
+
* @param code_cap Capacity of code (ignored when code NULL)
|
|
164
|
+
* @param line Out: 1-based line (may be NULL; 0 when unknown)
|
|
165
|
+
* @param col Out: 1-based column (may be NULL; 0 when unknown)
|
|
166
|
+
* @return 1 on success; 0 for NULL doc or out-of-range index
|
|
167
|
+
*
|
|
168
|
+
* Memory: Code is copied into the caller's buffer; diagnostics
|
|
169
|
+
* are owned by the document until leptris_document_free.
|
|
170
|
+
*/
|
|
171
|
+
LEPTRIS_API int leptris_document_parse_diag_code(LeptrisDocument doc,
|
|
172
|
+
size_t index,
|
|
173
|
+
char* code,
|
|
174
|
+
size_t code_cap,
|
|
175
|
+
int* line, int* col);
|
|
176
|
+
|
|
155
177
|
#ifdef __cplusplus
|
|
156
178
|
}
|
|
157
179
|
#endif
|
|
@@ -72,6 +72,21 @@ LEPTRIS_API LeptrisDocument leptris_parse_html4_string(const char* html,
|
|
|
72
72
|
size_t length,
|
|
73
73
|
LeptrisStatus* status);
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Parse HTML with per-call options (leptris-ruby#1771).
|
|
77
|
+
*
|
|
78
|
+
* Identical to leptris_parse_html_string; `flags` may carry
|
|
79
|
+
* LEPTRIS_PARSE_COLLECT_HTML_ERRORS to record the WHATWG §13.2.5
|
|
80
|
+
* parse-error token stream as diagnostics (read via
|
|
81
|
+
* leptris_document_parse_diag_count + leptris_document_parse_diag +
|
|
82
|
+
* leptris_document_parse_diag_code).
|
|
83
|
+
*
|
|
84
|
+
* @return Document, or NULL on failure
|
|
85
|
+
*/
|
|
86
|
+
LEPTRIS_API LeptrisDocument leptris_parse_html_string_flags(
|
|
87
|
+
const char* buf, size_t len, LeptrisParseFlags flags,
|
|
88
|
+
LeptrisStatus* status);
|
|
89
|
+
|
|
75
90
|
#ifdef __cplusplus
|
|
76
91
|
}
|
|
77
92
|
#endif
|
|
@@ -245,7 +245,12 @@ typedef enum {
|
|
|
245
245
|
* is dropped, unclosed elements close at EOF. Each recovery
|
|
246
246
|
* records a parse diagnostic (mismatched-tag / unclosed-element
|
|
247
247
|
* kind). Without the bit the parse fails as before. */
|
|
248
|
-
LEPTRIS_PARSE_RECOVER = 32u
|
|
248
|
+
LEPTRIS_PARSE_RECOVER = 32u,
|
|
249
|
+
/* leptris-ruby#1771: record the WHATWG §13.2.5 parse-error
|
|
250
|
+
* token stream as diagnostics (code + line + column) on the
|
|
251
|
+
* HTML parse — the lint layer validators need. Opt-in: the
|
|
252
|
+
* tree construction stays exactly as fast without it. */
|
|
253
|
+
LEPTRIS_PARSE_COLLECT_HTML_ERRORS = 64u
|
|
249
254
|
} LeptrisParseFlags;
|
|
250
255
|
|
|
251
256
|
/* ============================================================================
|
|
@@ -22,6 +22,7 @@ LeptrisDiag* leptris_diag_emit(LeptrisDiag** list, int* count, int* cap,
|
|
|
22
22
|
LeptrisDiag* d = &(*list)[*count];
|
|
23
23
|
d->kind = kind;
|
|
24
24
|
d->offender_name = NULL;
|
|
25
|
+
d->code = NULL;
|
|
25
26
|
d->line = 0;
|
|
26
27
|
d->col_start = 0;
|
|
27
28
|
d->col_end = 0;
|
|
@@ -46,10 +47,40 @@ LeptrisDiag* leptris_diag_emit(LeptrisDiag** list, int* count, int* cap,
|
|
|
46
47
|
return d;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
LeptrisDiag* leptris_diag_emit_code(LeptrisDiag** list, int* count, int* cap,
|
|
51
|
+
LeptrisDiagKind kind, const char* code,
|
|
52
|
+
int line, int col, const char* fmt, ...) {
|
|
53
|
+
if (!list || !count || !cap) return NULL;
|
|
54
|
+
if (*count == *cap) {
|
|
55
|
+
int nc = *cap ? *cap * 2 : 8;
|
|
56
|
+
LeptrisDiag* nl = (LeptrisDiag*)realloc(
|
|
57
|
+
*list, sizeof(LeptrisDiag) * (size_t)nc);
|
|
58
|
+
if (!nl) return NULL;
|
|
59
|
+
*list = nl;
|
|
60
|
+
*cap = nc;
|
|
61
|
+
}
|
|
62
|
+
LeptrisDiag* d = &(*list)[*count];
|
|
63
|
+
d->kind = kind;
|
|
64
|
+
d->offender_name = NULL;
|
|
65
|
+
d->code = code ? leptris_strdup(code) : NULL;
|
|
66
|
+
d->line = line;
|
|
67
|
+
d->col_start = col;
|
|
68
|
+
d->col_end = 0;
|
|
69
|
+
va_list ap;
|
|
70
|
+
va_start(ap, fmt);
|
|
71
|
+
vsnprintf(d->message, sizeof(d->message), fmt, ap);
|
|
72
|
+
va_end(ap);
|
|
73
|
+
(*count)++;
|
|
74
|
+
return d;
|
|
75
|
+
}
|
|
76
|
+
|
|
49
77
|
void leptris_diag_free(LeptrisDiag** list, int* count, int* cap) {
|
|
50
78
|
if (!list) return;
|
|
51
79
|
if (*list && count) {
|
|
52
|
-
for (int i = 0; i < *count; i++)
|
|
80
|
+
for (int i = 0; i < *count; i++) {
|
|
81
|
+
free((*list)[i].offender_name);
|
|
82
|
+
free((*list)[i].code);
|
|
83
|
+
}
|
|
53
84
|
}
|
|
54
85
|
free(*list);
|
|
55
86
|
*list = NULL;
|
|
@@ -27,6 +27,10 @@ typedef struct LeptrisDiag {
|
|
|
27
27
|
* validated document is freed — musl
|
|
28
28
|
* unmaps the region and the report
|
|
29
29
|
* pass segfaulted reading it. */
|
|
30
|
+
/* #1771: the machine-readable CODE — the §13.2.5 parse-error
|
|
31
|
+
* token name for HTML lints ("unexpected-tag-in-body"), NULL
|
|
32
|
+
* when the diag has no code. Captured at emit (strdup'd). */
|
|
33
|
+
char* code;
|
|
30
34
|
|
|
31
35
|
int line;
|
|
32
36
|
int col_start; /* Jing: element/attr errors */
|
|
@@ -53,6 +57,18 @@ LeptrisDiag* leptris_diag_emit(LeptrisDiag** list, int* count, int* cap,
|
|
|
53
57
|
#endif
|
|
54
58
|
;
|
|
55
59
|
|
|
60
|
+
/* #1771: the code-carrying variant — same record, plus the
|
|
61
|
+
* machine-readable code string (strdup'd into the record). Line/col
|
|
62
|
+
* come from the caller (the tokenizer's own position); the record's
|
|
63
|
+
* node-derived position path does not apply. */
|
|
64
|
+
LeptrisDiag* leptris_diag_emit_code(LeptrisDiag** list, int* count, int* cap,
|
|
65
|
+
LeptrisDiagKind kind, const char* code,
|
|
66
|
+
int line, int col, const char* fmt, ...)
|
|
67
|
+
#if defined(__GNUC__)
|
|
68
|
+
__attribute__((format(printf, 8, 9)))
|
|
69
|
+
#endif
|
|
70
|
+
;
|
|
71
|
+
|
|
56
72
|
/* Release a record list (the messages are inline, so this is one
|
|
57
73
|
* free + reset). */
|
|
58
74
|
void leptris_diag_free(LeptrisDiag** list, int* count, int* cap);
|
|
@@ -153,4 +153,19 @@ LEPTRIS_API int leptris_document_parse_diag(LeptrisDocument doc,
|
|
|
153
153
|
message[message_cap - 1] = '\0';
|
|
154
154
|
}
|
|
155
155
|
return 1;
|
|
156
|
-
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
LEPTRIS_API int leptris_document_parse_diag_code(LeptrisDocument doc,
|
|
159
|
+
size_t index,
|
|
160
|
+
char* code,
|
|
161
|
+
size_t code_cap,
|
|
162
|
+
int* line, int* col) {
|
|
163
|
+
if (!doc || index >= (size_t)doc->parse_diag_count) return 0;
|
|
164
|
+
struct LeptrisDiag* d = (struct LeptrisDiag*)doc->parse_diags + index;
|
|
165
|
+
if (code && code_cap) {
|
|
166
|
+
snprintf(code, code_cap, "%s", d->code ? d->code : "");
|
|
167
|
+
}
|
|
168
|
+
if (line) *line = d->line;
|
|
169
|
+
if (col) *col = d->col_start;
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
@@ -17,8 +17,10 @@
|
|
|
17
17
|
#include "../dom/comment.h"
|
|
18
18
|
#include "../dom/doctype.h"
|
|
19
19
|
#include "../dom/root_doc_map.h"
|
|
20
|
+
#include "../dom/diag.h"
|
|
20
21
|
#include "../dom/cdata.h"
|
|
21
22
|
#include "../dom/pi.h"
|
|
23
|
+
#include <stdarg.h>
|
|
22
24
|
#include <stdio.h>
|
|
23
25
|
#include <stdlib.h>
|
|
24
26
|
#include <stdint.h>
|
|
@@ -2687,6 +2689,15 @@ typedef struct {
|
|
|
2687
2689
|
/* #659 master mode flag (the per-slice flags below derive from
|
|
2688
2690
|
* the same html_parse_shared arg). */
|
|
2689
2691
|
int whatwg;
|
|
2692
|
+
/* #1771: the parse-lint channel — record the §13.2.5
|
|
2693
|
+
* parse-error token stream when the option bit is set. The
|
|
2694
|
+
* input base + length turn token offsets into 1-based
|
|
2695
|
+
* line/column at emit (amortized: last-line memo). */
|
|
2696
|
+
int collect_errors;
|
|
2697
|
+
const char* input_base;
|
|
2698
|
+
size_t input_len;
|
|
2699
|
+
size_t err_line_memo_off;
|
|
2700
|
+
int err_line_memo;
|
|
2690
2701
|
/* #659 frameset mode (WHATWG): a <frameset> before any body
|
|
2691
2702
|
* content REPLACES the body — the commit synthesis emits
|
|
2692
2703
|
* html > [head, frameset]. */
|
|
@@ -2877,6 +2888,8 @@ static int h_in_head_noscript(HBuilder* b) {
|
|
|
2877
2888
|
/* #659: stash the attributes of a dropped structural tag —
|
|
2878
2889
|
* pool-owned flat name/value pairs, applied to the synthesized
|
|
2879
2890
|
* element at commit. */
|
|
2891
|
+
static void h_diag(HBuilder* b, const char* code, size_t off,
|
|
2892
|
+
const char* fmt, ...);
|
|
2880
2893
|
static void h_stash_attrs(HBuilder* b, const char* q, const char* end,
|
|
2881
2894
|
char** attrs, int* n) {
|
|
2882
2895
|
while (q < end && *q != '>' && *n + 1 < 32) {
|
|
@@ -2927,7 +2940,12 @@ static void h_stash_attrs(HBuilder* b, const char* q, const char* end,
|
|
|
2927
2940
|
int dup = 0;
|
|
2928
2941
|
for (int j = 0; j + 1 < *n; j += 2)
|
|
2929
2942
|
if (strcmp(attrs[j], aname) == 0) { dup = 1; break; }
|
|
2930
|
-
if (
|
|
2943
|
+
if (dup) {
|
|
2944
|
+
h_diag(b, "duplicate-attribute",
|
|
2945
|
+
(size_t)(as - b->input_base),
|
|
2946
|
+
"duplicate attribute '%s' ignored; first value "
|
|
2947
|
+
"wins", aname);
|
|
2948
|
+
} else {
|
|
2931
2949
|
attrs[(*n)++] = aname;
|
|
2932
2950
|
attrs[(*n)++] = aval;
|
|
2933
2951
|
}
|
|
@@ -5532,8 +5550,43 @@ static LeptrisTextNode* h_text_node(HBuilder* b, const char* s,
|
|
|
5532
5550
|
return leptris_text_create(dec, dlen, b->pool, b->doc);
|
|
5533
5551
|
}
|
|
5534
5552
|
|
|
5553
|
+
/* #1771: record one §13.2.5 parse-error token. Code is the spec
|
|
5554
|
+
* token name; `off` is the byte offset into the owned input.
|
|
5555
|
+
* Line/column are computed with a forward-only line memo (lint
|
|
5556
|
+
* volumes are ordered, so the walk amortizes). No-op unless the
|
|
5557
|
+
* option bit is set — the tree construction stays exactly as
|
|
5558
|
+
* fast without it. */
|
|
5559
|
+
#if defined(__GNUC__)
|
|
5560
|
+
static void h_diag(HBuilder* b, const char* code, size_t off,
|
|
5561
|
+
const char* fmt, ...)
|
|
5562
|
+
__attribute__((format(printf, 4, 5)));
|
|
5563
|
+
#endif
|
|
5564
|
+
static void h_diag(HBuilder* b, const char* code, size_t off,
|
|
5565
|
+
const char* fmt, ...) {
|
|
5566
|
+
if (!b->collect_errors || !b->doc) return;
|
|
5567
|
+
if (off > b->input_len) off = b->input_len;
|
|
5568
|
+
int line = b->err_line_memo, col = 1;
|
|
5569
|
+
size_t from = b->err_line_memo_off;
|
|
5570
|
+
if (off < from) { from = 0; line = 1; }
|
|
5571
|
+
for (size_t i = from; i < off; i++) {
|
|
5572
|
+
if (b->input_base[i] == '\n') { line++; col = 1; }
|
|
5573
|
+
else col++;
|
|
5574
|
+
}
|
|
5575
|
+
b->err_line_memo = line;
|
|
5576
|
+
b->err_line_memo_off = off;
|
|
5577
|
+
char detail[192];
|
|
5578
|
+
va_list ap;
|
|
5579
|
+
va_start(ap, fmt);
|
|
5580
|
+
vsnprintf(detail, sizeof(detail), fmt, ap);
|
|
5581
|
+
va_end(ap);
|
|
5582
|
+
leptris_diag_emit_code(&b->doc->parse_diags, &b->doc->parse_diag_count,
|
|
5583
|
+
&b->doc->parse_diag_cap, LEPTRIS_DIAG_RECOVER,
|
|
5584
|
+
code, line, col, "%s", detail);
|
|
5585
|
+
}
|
|
5586
|
+
|
|
5535
5587
|
static LeptrisDocument html_parse_shared(
|
|
5536
|
-
const char* buf, size_t len, LeptrisStatus* status, int whatwg
|
|
5588
|
+
const char* buf, size_t len, LeptrisStatus* status, int whatwg,
|
|
5589
|
+
LeptrisParseFlags flags) {
|
|
5537
5590
|
if (status) *status = LEPTRIS_OK;
|
|
5538
5591
|
if (!buf) {
|
|
5539
5592
|
if (status) *status = LEPTRIS_ERROR_NULL_ARG;
|
|
@@ -5561,6 +5614,8 @@ static LeptrisDocument html_parse_shared(
|
|
|
5561
5614
|
b.doc = doc;
|
|
5562
5615
|
b.pool = doc->pool;
|
|
5563
5616
|
b.whatwg = whatwg;
|
|
5617
|
+
b.collect_errors =
|
|
5618
|
+
(flags & LEPTRIS_PARSE_COLLECT_HTML_ERRORS) ? 1 : 0;
|
|
5564
5619
|
b.whatwg_head_set = whatwg;
|
|
5565
5620
|
b.whatwg_foster = whatwg;
|
|
5566
5621
|
b.whatwg_adopt = whatwg;
|
|
@@ -5576,6 +5631,10 @@ static LeptrisDocument html_parse_shared(
|
|
|
5576
5631
|
}
|
|
5577
5632
|
memcpy(owned, buf, len);
|
|
5578
5633
|
owned[len] = '\0';
|
|
5634
|
+
/* #1771: the lint channel's offset base — after `owned` exists. */
|
|
5635
|
+
b.input_base = owned;
|
|
5636
|
+
b.input_len = len;
|
|
5637
|
+
b.err_line_memo = 1;
|
|
5579
5638
|
b.owned = owned;
|
|
5580
5639
|
h_id_luts_init();
|
|
5581
5640
|
|
|
@@ -5724,6 +5783,10 @@ static LeptrisDocument html_parse_shared(
|
|
|
5724
5783
|
}
|
|
5725
5784
|
if (dt_kw && (doc->doctype || b.left_initial ||
|
|
5726
5785
|
h_in_head_noscript(&b))) {
|
|
5786
|
+
h_diag(&b, "unexpected-doctype",
|
|
5787
|
+
(size_t)(p - b.input_base),
|
|
5788
|
+
"DOCTYPE token outside the initial mode "
|
|
5789
|
+
"is ignored");
|
|
5727
5790
|
while (q < end && *q != '>') q++;
|
|
5728
5791
|
p = (q < end) ? q + 1 : end;
|
|
5729
5792
|
text = p;
|
|
@@ -5946,6 +6009,10 @@ static LeptrisDocument html_parse_shared(
|
|
|
5946
6009
|
}
|
|
5947
6010
|
const char* q2 = ns2;
|
|
5948
6011
|
while (q2 < end && *q2 != '>') q2++;
|
|
6012
|
+
h_diag(&b, "unexpected-character-in-tag",
|
|
6013
|
+
(size_t)(ns2 - b.input_base),
|
|
6014
|
+
"malformed tag construct became a bogus "
|
|
6015
|
+
"comment");
|
|
5949
6016
|
h_bogus_comment(&b, ns2, (size_t)(q2 - ns2));
|
|
5950
6017
|
p = (q2 < end) ? q2 + 1 : end;
|
|
5951
6018
|
text = p;
|
|
@@ -5955,6 +6022,8 @@ static LeptrisDocument html_parse_shared(
|
|
|
5955
6022
|
/* #659 eof-in-tag: an unterminated END tag at EOF is
|
|
5956
6023
|
* dropped too (same 13.2.5.44 rule). */
|
|
5957
6024
|
if (b.whatwg && !memchr(p, '>', (size_t)(end - p))) {
|
|
6025
|
+
h_diag(&b, "eof-in-tag", (size_t)(p - b.input_base),
|
|
6026
|
+
"end tag at EOF is dropped");
|
|
5958
6027
|
if (text < p) {
|
|
5959
6028
|
LeptrisTextNode* t = h_text_node(&b, text, p);
|
|
5960
6029
|
if (t) h_append(&b, (LeptrisNodeRef)t);
|
|
@@ -6760,6 +6829,9 @@ static LeptrisDocument html_parse_shared(
|
|
|
6760
6829
|
* a parse error — the tag is dropped, pending text lands,
|
|
6761
6830
|
* parsing ends (webkit01:4: '<di' -> empty body). */
|
|
6762
6831
|
if (b.whatwg && !memchr(p, '>', (size_t)(end - p))) {
|
|
6832
|
+
/* #1771: eof-in-tag (13.2.5.44). */
|
|
6833
|
+
h_diag(&b, "eof-in-tag", (size_t)(p - b.input_base),
|
|
6834
|
+
"start tag at EOF is dropped");
|
|
6763
6835
|
if (text < p) {
|
|
6764
6836
|
LeptrisTextNode* t = h_text_node(&b, text, p);
|
|
6765
6837
|
if (t) h_append(&b, (LeptrisNodeRef)t);
|
|
@@ -6800,6 +6872,10 @@ static LeptrisDocument html_parse_shared(
|
|
|
6800
6872
|
scan++;
|
|
6801
6873
|
}
|
|
6802
6874
|
if (!closed) {
|
|
6875
|
+
/* #1771: eof-in-tag — the unterminated START tag
|
|
6876
|
+
* is dropped (13.2.5.44, webkit02:5). */
|
|
6877
|
+
h_diag(&b, "eof-in-tag", (size_t)(p - b.input_base),
|
|
6878
|
+
"start tag at EOF is dropped");
|
|
6803
6879
|
if (text < p) {
|
|
6804
6880
|
LeptrisTextNode* t =
|
|
6805
6881
|
h_text_node(&b, text, p);
|
|
@@ -7861,6 +7937,14 @@ static LeptrisDocument html_parse_shared(
|
|
|
7861
7937
|
vs = scan;
|
|
7862
7938
|
while (scan < end && *scan != quote) scan++;
|
|
7863
7939
|
vlen = (size_t)(scan - vs);
|
|
7940
|
+
if (scan >= end) {
|
|
7941
|
+
/* #1771: the quote never closed — 13.2.5
|
|
7942
|
+
* eof-in-tag. */
|
|
7943
|
+
h_diag(&b, "eof-in-tag",
|
|
7944
|
+
(size_t)(as - b.input_base),
|
|
7945
|
+
"attribute value at EOF is "
|
|
7946
|
+
"unterminated");
|
|
7947
|
+
}
|
|
7864
7948
|
if (scan < end) scan++;
|
|
7865
7949
|
} else {
|
|
7866
7950
|
vs = scan;
|
|
@@ -7883,6 +7967,13 @@ static LeptrisDocument html_parse_shared(
|
|
|
7883
7967
|
aval = (char*)"";
|
|
7884
7968
|
}
|
|
7885
7969
|
if (aval) {
|
|
7970
|
+
/* #1771: a same-named attribute is ignored (first
|
|
7971
|
+
* value wins, 13.2.5.3 duplicate-attribute). */
|
|
7972
|
+
if (leptris_element_attribute(e, aname))
|
|
7973
|
+
h_diag(&b, "duplicate-attribute",
|
|
7974
|
+
(size_t)(as - b.input_base),
|
|
7975
|
+
"duplicate attribute '%s' ignored; first "
|
|
7976
|
+
"value wins", aname);
|
|
7886
7977
|
/* #659: foreign attribute-name adjustment
|
|
7887
7978
|
* (viewBox, definitionURL, ...). */
|
|
7888
7979
|
const char* aadj =
|
|
@@ -8300,7 +8391,7 @@ LEPTRIS_API LeptrisDocument leptris_parse_html_string(
|
|
|
8300
8391
|
/* #659: THE WHATWG ENGINE — the full "in head" set lifts into
|
|
8301
8392
|
* the implied head (script/style/noscript/template/...). The
|
|
8302
8393
|
* html5lib corpus is this entry's conformance meter. */
|
|
8303
|
-
return html_parse_shared(buf, len, status, 1);
|
|
8394
|
+
return html_parse_shared(buf, len, status, 1, LEPTRIS_PARSE_DEFAULT);
|
|
8304
8395
|
}
|
|
8305
8396
|
|
|
8306
8397
|
LEPTRIS_API LeptrisDocument leptris_parse_html4_string(
|
|
@@ -8308,5 +8399,13 @@ LEPTRIS_API LeptrisDocument leptris_parse_html4_string(
|
|
|
8308
8399
|
/* #659: libxml2/Nokogiri compatibility — leading script/style
|
|
8309
8400
|
* stay in body (title/meta/link/base still lift). The
|
|
8310
8401
|
* committed Nokogiri reference trees measure this entry. */
|
|
8311
|
-
return html_parse_shared(buf, len, status, 0);
|
|
8402
|
+
return html_parse_shared(buf, len, status, 0, LEPTRIS_PARSE_DEFAULT);
|
|
8403
|
+
}
|
|
8404
|
+
|
|
8405
|
+
LEPTRIS_API LeptrisDocument leptris_parse_html_string_flags(
|
|
8406
|
+
const char* buf, size_t len, LeptrisParseFlags flags,
|
|
8407
|
+
LeptrisStatus* status) {
|
|
8408
|
+
/* #1771: the WHATWG engine with per-call options — the parse-
|
|
8409
|
+
* lint bit rides here. */
|
|
8410
|
+
return html_parse_shared(buf, len, status, 1, flags);
|
|
8312
8411
|
}
|
|
@@ -154,6 +154,7 @@ if(LEPTRIS_ENABLE_DUCET)
|
|
|
154
154
|
endif()
|
|
155
155
|
leptris_add_test(test_xquery xquery/test_xquery.cpp)
|
|
156
156
|
leptris_add_test(test_html html/test_html.cpp)
|
|
157
|
+
leptris_add_test(test_html_parse_errors html/test_html_parse_errors.cpp)
|
|
157
158
|
leptris_add_test(test_html_builder html/test_html_builder.cpp)
|
|
158
159
|
leptris_add_test(test_html_borrowed_names html/test_html_borrowed_names.cpp)
|
|
159
160
|
leptris_add_test(test_html5lib html/test_html5lib.cpp)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// test/html/test_html_parse_errors.cpp — the #1771 parse-lint
|
|
2
|
+
// surface: LEPTRIS_PARSE_COLLECT_HTML_ERRORS records the §13.2.5
|
|
3
|
+
// parse-error token stream (code + line + column) on the document's
|
|
4
|
+
// diagnostic list. Opt-in: without the bit the list stays empty and
|
|
5
|
+
// the tree construction is unchanged.
|
|
6
|
+
#include <gtest/gtest.h>
|
|
7
|
+
#include <leptris.h>
|
|
8
|
+
#include <leptris/html.h>
|
|
9
|
+
#include <leptris/error.h>
|
|
10
|
+
#include <cstring>
|
|
11
|
+
|
|
12
|
+
namespace {
|
|
13
|
+
|
|
14
|
+
struct Diag {
|
|
15
|
+
LeptrisDiagKind kind;
|
|
16
|
+
std::string code;
|
|
17
|
+
std::string message;
|
|
18
|
+
int line, col;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
std::vector<Diag> drain(LeptrisDocument doc) {
|
|
22
|
+
std::vector<Diag> out;
|
|
23
|
+
size_t n = leptris_document_parse_diag_count(doc);
|
|
24
|
+
for (size_t i = 0; i < n; i++) {
|
|
25
|
+
LeptrisDiagKind kind = LEPTRIS_DIAG_INVALID;
|
|
26
|
+
char msg[256] = {0};
|
|
27
|
+
char code[64] = {0};
|
|
28
|
+
int line = 0, col = 0;
|
|
29
|
+
EXPECT_TRUE(leptris_document_parse_diag(doc, i, &kind, msg,
|
|
30
|
+
sizeof(msg)));
|
|
31
|
+
EXPECT_TRUE(leptris_document_parse_diag_code(doc, i, code,
|
|
32
|
+
sizeof(code),
|
|
33
|
+
&line, &col));
|
|
34
|
+
out.push_back({kind, code, msg, line, col});
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
} // namespace
|
|
40
|
+
|
|
41
|
+
TEST(HtmlParseErrors, OffByDefaultListStaysEmpty) {
|
|
42
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
43
|
+
const char* xml = "<a id=\"1\" id=\"2\">x</a>";
|
|
44
|
+
LeptrisDocument d = leptris_parse_html_string(xml, strlen(xml), &st);
|
|
45
|
+
ASSERT_NE(d, nullptr);
|
|
46
|
+
EXPECT_EQ(leptris_document_parse_diag_count(d), 0u);
|
|
47
|
+
leptris_document_free(d);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
TEST(HtmlParseErrors, DuplicateAttributeCarriesSpecCode) {
|
|
51
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
52
|
+
const char* xml = "<a id=\"1\" id=\"2\">x</a>";
|
|
53
|
+
LeptrisDocument d = leptris_parse_html_string_flags(
|
|
54
|
+
xml, strlen(xml), LEPTRIS_PARSE_COLLECT_HTML_ERRORS, &st);
|
|
55
|
+
ASSERT_NE(d, nullptr);
|
|
56
|
+
auto diags = drain(d);
|
|
57
|
+
ASSERT_GE(diags.size(), 1u);
|
|
58
|
+
bool found = false;
|
|
59
|
+
for (auto& dd : diags)
|
|
60
|
+
if (dd.code == "duplicate-attribute") found = true;
|
|
61
|
+
EXPECT_TRUE(found);
|
|
62
|
+
EXPECT_EQ(diags[0].kind, LEPTRIS_DIAG_RECOVER);
|
|
63
|
+
leptris_document_free(d);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
TEST(HtmlParseErrors, EofInTagCarriesSpecCode) {
|
|
67
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
68
|
+
const char* xml = "<p>text<a href=\"";
|
|
69
|
+
LeptrisDocument d = leptris_parse_html_string_flags(
|
|
70
|
+
xml, strlen(xml), LEPTRIS_PARSE_COLLECT_HTML_ERRORS, &st);
|
|
71
|
+
ASSERT_NE(d, nullptr);
|
|
72
|
+
auto diags = drain(d);
|
|
73
|
+
ASSERT_GE(diags.size(), 1u);
|
|
74
|
+
EXPECT_EQ(diags[0].code, "eof-in-tag");
|
|
75
|
+
EXPECT_EQ(diags[0].line, 1);
|
|
76
|
+
EXPECT_EQ(diags[0].col, 8);
|
|
77
|
+
leptris_document_free(d);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
TEST(HtmlParseErrors, DoctypeOutsideInitialIgnored) {
|
|
81
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
82
|
+
const char* xml = "<div><!DOCTYPE html></div>";
|
|
83
|
+
LeptrisDocument d = leptris_parse_html_string_flags(
|
|
84
|
+
xml, strlen(xml), LEPTRIS_PARSE_COLLECT_HTML_ERRORS, &st);
|
|
85
|
+
ASSERT_NE(d, nullptr);
|
|
86
|
+
auto diags = drain(d);
|
|
87
|
+
ASSERT_GE(diags.size(), 1u);
|
|
88
|
+
EXPECT_EQ(diags[0].code, "unexpected-doctype");
|
|
89
|
+
leptris_document_free(d);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
TEST(HtmlParseErrors, LineColumnTrackRealLines) {
|
|
93
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
94
|
+
const char* xml = "<p>one</p>\n<p>two</p>\n<a id=\"1\" id=\"2\">x</a>";
|
|
95
|
+
LeptrisDocument d = leptris_parse_html_string_flags(
|
|
96
|
+
xml, strlen(xml), LEPTRIS_PARSE_COLLECT_HTML_ERRORS, &st);
|
|
97
|
+
ASSERT_NE(d, nullptr);
|
|
98
|
+
auto diags = drain(d);
|
|
99
|
+
ASSERT_GE(diags.size(), 1u);
|
|
100
|
+
EXPECT_EQ(diags[0].line, 3);
|
|
101
|
+
leptris_document_free(d);
|
|
102
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
|
|
3
3
|
"name": "leptris",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.371",
|
|
5
5
|
"description": "High-performance XML parser and XPath 1.0 engine in C (libleptris)",
|
|
6
6
|
"homepage": "https://github.com/leptris/leptris",
|
|
7
7
|
"license": "MIT",
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: leptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.371.0
|
|
5
5
|
platform: arm-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|
|
@@ -824,6 +824,7 @@ files:
|
|
|
824
824
|
- vendor-src/libleptris/test/html/test_html5lib.cpp
|
|
825
825
|
- vendor-src/libleptris/test/html/test_html_borrowed_names.cpp
|
|
826
826
|
- vendor-src/libleptris/test/html/test_html_builder.cpp
|
|
827
|
+
- vendor-src/libleptris/test/html/test_html_parse_errors.cpp
|
|
827
828
|
- vendor-src/libleptris/test/memory/test_arena.cpp
|
|
828
829
|
- vendor-src/libleptris/test/memory/test_doc_block.cpp
|
|
829
830
|
- vendor-src/libleptris/test/memory/test_mut_recycle.cpp
|