Commit Graph

340 Commits

Author SHA1 Message Date
e62995a7a8 feat(emitting): output encoding for UTF and single-byte families
Add PureXML.Parsing.ByteEncoder, the inverse of ByteDecoder, and a
Serializer.serialize(_:encoding:) / PureXML.serialize(_:encoding:) that
emits bytes in a chosen encoding (the libxml2 save-with-encoding model).
Covers the Unicode transformation formats and the single-byte legacy
families, built by inverting the existing vendored to-Unicode tables, so
no new data is introduced. The declaration carries the canonical encoding
name, a UTF-16/32 stream is preceded by a byte-order mark, and any
unrepresentable scalar becomes a decimal numeric character reference, so
output round-trips. CJK output encodings remain (tracked on #106).

Part of #106, #105
2026-06-09 09:32:39 +02:00
c57ee85e59 docs(roadmap): track the remaining libxml2 parity frontier under #105 2026-06-09 09:26:01 +02:00
b42ee11e3a test(validation): cover the Bool forms of the && and || combinators
The error-array forms of && and || were unit-tested; the Bool predicate
forms were not. Add a pure-function test so every combinator overload in
the algebra is exercised, completing the framework's combinator coverage.
2026-06-09 09:08:27 +02:00
16ee379abc test(xsd): prove identity-error location at full selector depth
The identity-constraint location walk handles arbitrary selector depth, but
the existing assertions only exercised a single relative step. Add a nested
selector (group/item) whose duplicate sits in the second group, so the
offender is a grandchild and an intermediate level needs a sibling index:
list/group[2]/item. Locks the multi-level path construction.
2026-06-09 09:02:41 +02:00
36a40eec08 fix(xsd): locate identity-constraint errors at the offending node
Refine the identity-constraint path: rather than locating at the element
that declares the key, walk from the constraint-bearing element down to the
selected target and report the actual offender, so a duplicate key renders
"at path: list/item[2]" and a dangling keyref "at path: orders/line".
Also locate the "no element declaration for the root" XSD error at the root
element, matching the namespace check beside it that already did so. Lock
both with coding-path assertions in the identity tests.
2026-06-09 08:57:33 +02:00
9730903803 fix(xsd): locate identity-constraint errors at their element
The IdentityValidator emitted every key/keyref/unique error with an empty
coding path (at: []), so each rendered "at root of document" regardless of
which element violated the constraint. Thread a [PathKey] through the walk,
the way the content-model validator already does, so the failures carry the
constraining element's path. This restores the validation framework's
path-carrying contract for the one rule that was bypassing it.
2026-06-09 08:50:39 +02:00
74acad4628 feat(parsing): Big5 (Traditional Chinese / HKSCS)
Add the WHATWG big5 decoder over the vendored index-big5 (18,590 entries),
for both the whole-buffer and streaming decoders. A lead in 0x81-0xFE plus
a trail in 0x40-0x7E or 0xA1-0xFE resolves through the index, covering
Traditional Chinese and the HKSCS extensions including the astral CJK
ideographs. Four pointers decode to a base letter plus a combining mark.
Selected by the big5 / big5-hkscs declaration names.

Closes #103
2026-06-09 08:30:57 +02:00
2b2c1fb692 feat(parsing): full GB18030 four-byte sequences
Extend the GBK two-byte subset to full GB18030: a lead byte followed by
a digit opens a four-byte form whose pointer is mapped through the WHATWG
index-gb18030-ranges linear ranges, reaching the supplementary planes.
The 207 ranges are vendored verbatim. Wired into the whole-buffer and
streaming decoders and the encoding-name table (gb18030/gb-18030).

Closes #102
2026-06-09 08:24:00 +02:00
e6b93737ed docs: CJK encodings #99 closed; the #71 audit epic is complete 2026-06-09 08:13:55 +02:00
69e4ba7026 Merge #99 (stage 4): GBK/GB2312 2026-06-09 08:08:54 +02:00
b688952cef feat(parsing): GBK/GB2312 decoding completes the CJK encodings (#99) 2026-06-09 08:08:52 +02:00
7f2991a90b Merge #99 (stage 3): EUC-KR 2026-06-09 08:03:02 +02:00
d8b2db4943 feat(parsing): EUC-KR (CP949) decoding with vendored index (#99) 2026-06-09 08:02:14 +02:00
d637a293d4 Merge #99 (stage 2): EUC-JP 2026-06-09 07:57:53 +02:00
5b5ee7b3fe feat(parsing): EUC-JP decoding with vendored JIS X 0212 index (#99) 2026-06-09 07:57:52 +02:00
dd9af3aa71 Merge #99 (stage 1): Shift-JIS 2026-06-09 07:54:06 +02:00
4ff9306a0e feat(parsing): Shift-JIS decoding with vendored JIS X 0208 index (#99) 2026-06-09 07:54:05 +02:00
fb594889f8 docs: move closed HTML entities #84 to done in roadmap 2026-06-09 07:47:31 +02:00
d91d3b9e87 Merge #84: complete WHATWG named entity table 2026-06-09 07:45:58 +02:00
a07537007e feat(html): vendor the complete WHATWG named entity set (#84) 2026-06-09 07:45:55 +02:00
277d8f8e80 Merge #84: HTML 4.01 named entity set 2026-06-09 07:39:33 +02:00
7eb33c0d08 feat(html): full HTML 4.01 named entity set (#84) 2026-06-09 07:39:32 +02:00
60fc0805bc docs: move closed single-byte encodings #97 to done in roadmap 2026-06-09 07:30:30 +02:00
e3e42f5dc1 Merge #97: complete single-byte legacy encodings 2026-06-09 07:29:26 +02:00
3f45dacf62 feat(parsing): Windows-1255/1256/1258, KOI8-U complete the single-byte set (#97) 2026-06-09 07:29:25 +02:00
3eeef1827e Merge #97: Windows code pages, KOI8-R, Thai 2026-06-09 07:25:19 +02:00
5646e81b94 feat(parsing): Windows-1250/1251/1253/1257, KOI8-R, ISO-8859-11 (#97) 2026-06-09 07:25:18 +02:00
18a5fe21e1 Merge #97: ISO-8859-6/8/10/14/16 2026-06-09 07:19:51 +02:00
3f293ec1e7 feat(parsing): ISO-8859-6/8/10/14/16 vendored from Unicode mappings (#97) 2026-06-09 07:19:50 +02:00
43c7ecc5e3 Merge #97: ISO-8859-3/4/7/13 2026-06-09 07:15:36 +02:00
43dc7b00c4 feat(parsing): ISO-8859-3/4/7/13 vendored from Unicode mappings (#97) 2026-06-09 07:15:35 +02:00
cf8969d08c Merge #97: ISO-8859-2 2026-06-09 07:08:19 +02:00
5f35621ae6 feat(parsing): ISO-8859-2 (Latin-2) vendored from Unicode mapping (#97) 2026-06-09 07:08:19 +02:00
c9b8161ba7 Merge #97: Windows-1254 2026-06-09 07:02:14 +02:00
a005def333 feat(parsing): Windows-1254 (Turkish) encoding (#97) 2026-06-09 07:02:13 +02:00
7c26547915 Merge #97 (partial): single-byte legacy encodings 2026-06-09 06:57:22 +02:00
94890172f2 feat(parsing): single-byte encoding framework + ISO-8859-5/9/15 (#97) 2026-06-09 06:57:21 +02:00
3efb868224 docs: move closed HTML5 tree construction #83 to done in roadmap 2026-06-09 06:39:39 +02:00
3bb4e7a4a0 Merge #83 (stage 11): in-select-in-table 2026-06-09 06:37:35 +02:00
a5b032e9dc feat(html): in-select-in-table closes select on table tags (#83) 2026-06-09 06:37:35 +02:00
7e56265ed2 Merge #83 (stage 10): select content model 2026-06-09 06:32:25 +02:00
3ebbaff07c feat(html): select content model (optgroup/nested-select/input close) (#83) 2026-06-09 06:32:24 +02:00
936a3900d2 Merge: unify head builder onto live TreeNode model 2026-06-09 06:29:00 +02:00
7add3b3fa5 refactor(html): build head on the live TreeNode model, remove DocFrame 2026-06-09 06:29:00 +02:00
b1a15639c0 Merge #83 (stage 9): template content nesting 2026-06-09 06:21:12 +02:00
b245640ee2 fix(html): keep template content nested instead of splitting to body (#83) 2026-06-09 06:21:10 +02:00
b234319657 Merge #83 (stage 8): frameset documents 2026-06-09 06:17:56 +02:00
f637b8e154 feat(html): frameset documents and void frame element (#83) 2026-06-09 06:17:55 +02:00
eb44eb3a49 Merge #83 (stage 7): HTML integration points 2026-06-09 06:06:55 +02:00
2945de0855 feat(html): SVG HTML integration points switch back to HTML namespace (#83) 2026-06-09 06:06:54 +02:00