@albertomarturelo/sii-core 0.19.2 → 0.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/format/text.d.ts +4 -4
- package/dist/format/text.d.ts.map +1 -1
- package/dist/format/text.js +22 -9
- package/dist/format/text.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ All notable changes to `@albertomarturelo/sii-core` are documented here. The for
|
|
|
4
4
|
loosely based on [Keep a Changelog](https://keepachangelog.com/); the package is
|
|
5
5
|
pre-1.0, so MINOR bumps may carry breaking changes (pin or use `~` downstream).
|
|
6
6
|
|
|
7
|
+
## 0.19.3 — 2026-11-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`repairMojibake` repairs SII's Windows-1252 double encoding (#271).** A UTF-8 second byte in
|
|
12
|
+
0x80–0x9F (the capitals « À »–« ß »: « Ó », « É », « Ñ », « Ú ») arrives as one of cp1252's
|
|
13
|
+
characters above U+00FF, which the guard took for clean text, leaving the whole string broken
|
|
14
|
+
(« LIQUIDACIÓN … deberá »). They map back to their byte before the test and the round trip.
|
|
15
|
+
Every text repaired since 0.19.1 gains it: the F22's estado, historial, observaciones, códigos
|
|
16
|
+
and terceros, and the mipyme DTE borradores. Clean text with « “ », « – » or « € » is untouched.
|
|
17
|
+
|
|
7
18
|
## 0.19.2 — 2026-11-09
|
|
8
19
|
|
|
9
20
|
### Fixed
|
package/dist/format/text.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** Repair SII's double-encoded text by re-encoding the decoded string as
|
|
2
|
-
* as UTF-8 again. Applied ONLY when the string carries the tell-tale `Ã`/`Â` + continuation
|
|
3
|
-
*
|
|
4
|
-
* is left untouched. */
|
|
1
|
+
/** Repair SII's double-encoded text by re-encoding the decoded string as Windows-1252 and decoding
|
|
2
|
+
* it as UTF-8 again. Applied ONLY when the string carries the tell-tale `Ã`/`Â` + continuation
|
|
3
|
+
* pair (the continuation byte in its Latin-1 or cp1252 form), holds nothing else beyond one byte,
|
|
4
|
+
* and the round trip decodes cleanly, so legitimately-accented text is left untouched. */
|
|
5
5
|
export declare function repairMojibake(v: string): string;
|
|
6
6
|
/** A wire value as text, repaired: null stays null, anything else is `String(v)` through
|
|
7
7
|
* `repairMojibake`. For the free-text fields a facade curates (glosas, descripciones). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/format/text.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/format/text.ts"],"names":[],"mappings":"AAmBA;;;2FAG2F;AAC3F,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAehD;AAED;2FAC2F;AAC3F,eAAO,MAAM,YAAY,GAAI,GAAG,OAAO,KAAG,MAAM,GAAG,IACe,CAAC"}
|
package/dist/format/text.js
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
// SII text as SII meant it. Some endpoints serve DOUBLE-ENCODED text: the UTF-8 bytes of an
|
|
2
2
|
// already-mojibaked string, so even a correct decode yields "Fundación" / "Ñuñoa". Observed on
|
|
3
3
|
// the DTE borradores (`listaBorrador`, 2026-09-08), one F22 terceros title (2026-10-21) and the
|
|
4
|
-
// F22 estado
|
|
5
|
-
// facade needed it (conventions/sii-wire.md).
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
// F22 estado and historial glosas (2026-11-09, GH-264) and the F22 código glosas (2026-11-10,
|
|
5
|
+
// GH-267, GH-271). Hoisted here after the third facade needed it (conventions/sii-wire.md).
|
|
6
|
+
// Display-side only: nothing sent to SII passes here.
|
|
7
|
+
// SII's double encoding is Windows-1252, not Latin-1 (GH-271): a UTF-8 byte in 0x80–0x9F was read
|
|
8
|
+
// as cp1252's printable character there, so « Ó » (C3 93) arrives as `Ó` (U+201C). These are the
|
|
9
|
+
// characters cp1252 puts at 0x80–0x9F, in byte order; its five undefined bytes (81, 8D, 8F, 90, 9D)
|
|
10
|
+
// decode to the C1 control of the same value, which already is that byte.
|
|
11
|
+
const CP1252_HIGH = '\u20ac\u0081\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\u008d\u017d\u008f' +
|
|
12
|
+
'\u0090\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\u009d\u017e\u0178';
|
|
13
|
+
const CP1252_BYTE = new Map(Array.from(CP1252_HIGH, (ch, i) => [ch, 0x80 + i]));
|
|
14
|
+
/** The byte a character stood for when SII decoded UTF-8 as cp1252; its code point otherwise. */
|
|
15
|
+
const cp1252Byte = (ch) => CP1252_BYTE.get(ch) ?? ch.codePointAt(0) ?? 0;
|
|
16
|
+
/** Repair SII's double-encoded text by re-encoding the decoded string as Windows-1252 and decoding
|
|
17
|
+
* it as UTF-8 again. Applied ONLY when the string carries the tell-tale `Ã`/`Â` + continuation
|
|
18
|
+
* pair (the continuation byte in its Latin-1 or cp1252 form), holds nothing else beyond one byte,
|
|
19
|
+
* and the round trip decodes cleanly, so legitimately-accented text is left untouched. */
|
|
10
20
|
export function repairMojibake(v) {
|
|
11
|
-
if (!/[
|
|
21
|
+
if (!/[ÂÃ]/.test(v))
|
|
22
|
+
return v; // every tell-tale pair starts with  or Ã
|
|
23
|
+
const codes = Array.from(v, cp1252Byte);
|
|
24
|
+
const tellTale = codes.some((c, i) => (c === 0xc2 || c === 0xc3) && (codes[i + 1] ?? 0) >= 0x80 && (codes[i + 1] ?? 0) <= 0xbf);
|
|
25
|
+
if (!tellTale)
|
|
12
26
|
return v;
|
|
13
|
-
const codes = Array.from(v, (ch) => ch.charCodeAt(0));
|
|
14
27
|
if (codes.some((c) => c > 0xff))
|
|
15
|
-
return v; // a
|
|
28
|
+
return v; // a char that is no cp1252 byte ⇒ not a mojibake string
|
|
16
29
|
try {
|
|
17
30
|
const decoded = new TextDecoder('utf-8', { fatal: true }).decode(Uint8Array.from(codes));
|
|
18
31
|
return decoded.includes('\ufffd') ? v : decoded;
|
package/dist/format/text.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/format/text.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,kGAAkG;AAClG,gGAAgG;AAChG,4FAA4F;AAC5F,kGAAkG;
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/format/text.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,kGAAkG;AAClG,gGAAgG;AAChG,8FAA8F;AAC9F,4FAA4F;AAC5F,sDAAsD;AAEtD,kGAAkG;AAClG,kGAAkG;AAClG,oGAAoG;AACpG,0EAA0E;AAC1E,MAAM,WAAW,GACf,kGAAkG;IAClG,kGAAkG,CAAC;AACrG,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,iGAAiG;AACjG,MAAM,UAAU,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAEzF;;;2FAG2F;AAC3F,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,0CAA0C;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAC3F,CAAC;IACF,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,wDAAwD;IACnG,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACzF,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC,CAAC,6DAA6D;IACzE,CAAC;AACH,CAAC;AAED;2FAC2F;AAC3F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAU,EAAiB,EAAE,CACxD,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@albertomarturelo/sii-core",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared SII domain core: rut, config (prod hostnames), contracts, tasks, seams. A Node library; external side-effects (portal, secrets, audit, clock) are injected via seams (ADR-003).",
|
|
6
6
|
"license": "MIT",
|