@ifc-lite/encoding 2.1.0 → 2.2.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.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Stable RFC-4122-shaped UUID derived purely from `seed`.
3
+ *
4
+ * - 8-4-4-4-12 lowercase hex
5
+ * - version nibble fixed to '4'
6
+ * - variant nibble in {8, 9, a, b}
7
+ */
8
+ export declare function uuidFromSeed(seed: string): string;
9
+ //# sourceMappingURL=deterministic-uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deterministic-uuid.d.ts","sourceRoot":"","sources":["../src/deterministic-uuid.ts"],"names":[],"mappings":"AA+DA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqCjD"}
@@ -0,0 +1,97 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Deterministic, input-only UUID generation.
6
+ *
7
+ * Produces an RFC-4122-shaped identifier (8-4-4-4-12 lowercase hex) whose 128
8
+ * bits are derived purely from a seed string. The same seed always yields the
9
+ * same UUID, with no dependence on the system clock or any random source.
10
+ *
11
+ * Two callers need exactly that, which is why this sits in `@ifc-lite/encoding`
12
+ * beside {@link generateUuid} rather than in either of them:
13
+ * - `@ifc-lite/clash` makes a BCF topic guid a stable function of a clash-group
14
+ * id, so a re-run of the same coordination produces byte-identical topic
15
+ * guids and the round trip back to clashes stays anchored.
16
+ * - `@ifc-lite/bcf` fills the `DocumentReference/@Guid` that BCF 3.0 requires
17
+ * and BCF 2.1 leaves optional, so exporting one project twice yields the same
18
+ * bytes instead of a fresh random identifier each time (#3612).
19
+ *
20
+ * `@ifc-lite/clash` depends on `@ifc-lite/bcf`, so sharing had to go through a
21
+ * package below both; a second copy of the algorithm would have been two
22
+ * implementations of one identity scheme, kept in step by nothing but prose.
23
+ *
24
+ * The 128 bits are filled from four 32-bit words. Each word starts from an
25
+ * FNV-1a hash of the seed mixed with a distinct salt, then is run through a
26
+ * short xorshift cascade so adjacent seeds (e.g. "g1" vs "g2") diffuse into
27
+ * fully different words rather than differing in only a few low bits.
28
+ */
29
+ const FNV_OFFSET_BASIS = 0x811c9dc5;
30
+ const FNV_PRIME = 0x01000193;
31
+ /** 32-bit FNV-1a over the UTF-8-ish code units of `input`, seeded with `salt`. */
32
+ function fnv1a(input, salt) {
33
+ let hash = (FNV_OFFSET_BASIS ^ salt) >>> 0;
34
+ for (let i = 0; i < input.length; i += 1) {
35
+ const code = input.charCodeAt(i);
36
+ // Fold the full 16-bit code unit in two byte-sized steps so non-ASCII
37
+ // comment-free seeds still contribute every bit.
38
+ hash = (hash ^ (code & 0xff)) >>> 0;
39
+ hash = Math.imul(hash, FNV_PRIME) >>> 0;
40
+ hash = (hash ^ ((code >>> 8) & 0xff)) >>> 0;
41
+ hash = Math.imul(hash, FNV_PRIME) >>> 0;
42
+ }
43
+ return hash >>> 0;
44
+ }
45
+ /** A short xorshift cascade to diffuse a 32-bit word. */
46
+ function xorshift32(value) {
47
+ let x = value >>> 0;
48
+ x ^= x << 13;
49
+ x >>>= 0;
50
+ x ^= x >>> 17;
51
+ x ^= x << 5;
52
+ return x >>> 0;
53
+ }
54
+ /** Left-pad a non-negative 32-bit word to 8 lowercase hex chars. */
55
+ function hex32(value) {
56
+ return (value >>> 0).toString(16).padStart(8, '0');
57
+ }
58
+ /**
59
+ * Stable RFC-4122-shaped UUID derived purely from `seed`.
60
+ *
61
+ * - 8-4-4-4-12 lowercase hex
62
+ * - version nibble fixed to '4'
63
+ * - variant nibble in {8, 9, a, b}
64
+ */
65
+ export function uuidFromSeed(seed) {
66
+ // Four independent 32-bit words, each its own salt then xorshift-mixed.
67
+ const w0 = xorshift32(fnv1a(seed, 0x9e3779b1));
68
+ const w1 = xorshift32(fnv1a(seed, 0x85ebca77));
69
+ const w2 = xorshift32(fnv1a(seed, 0xc2b2ae3d));
70
+ const w3 = xorshift32(fnv1a(seed, 0x27d4eb2f));
71
+ // Cross-mix so each output nibble depends on the whole seed, not one word.
72
+ const a = xorshift32(w0 ^ Math.imul(w3, FNV_PRIME)) >>> 0;
73
+ const b = xorshift32(w1 ^ Math.imul(w0, FNV_PRIME)) >>> 0;
74
+ const c = xorshift32(w2 ^ Math.imul(w1, FNV_PRIME)) >>> 0;
75
+ const d = xorshift32(w3 ^ Math.imul(w2, FNV_PRIME)) >>> 0;
76
+ const hexA = hex32(a);
77
+ const hexB = hex32(b);
78
+ const hexC = hex32(c);
79
+ const hexD = hex32(d);
80
+ // Layout: AAAAAAAA-BBBB-4BBB-VCCC-CCCCDDDDDDDD
81
+ // time_low = hexA (8)
82
+ // time_mid = hexB[0..4) (4)
83
+ // time_hi_ver = '4' + hexB[4..7) (4, version nibble forced to 4)
84
+ // clock_variant = variant + hexC[1..4) (4)
85
+ // node = hexC[4..8) + hexD (12)
86
+ const timeLow = hexA;
87
+ const timeMid = hexB.slice(0, 4);
88
+ const timeHiAndVersion = `4${hexB.slice(4, 7)}`;
89
+ // Variant nibble: high two bits must be '10' -> one of 8, 9, a, b.
90
+ // Derive it from the top nibble of hexC so it is still seed-dependent.
91
+ const variantSource = parseInt(hexC[0], 16);
92
+ const variantNibble = ((variantSource & 0x3) | 0x8).toString(16);
93
+ const clockSeqAndVariant = `${variantNibble}${hexC.slice(1, 4)}`;
94
+ const node = `${hexC.slice(4, 8)}${hexD}`;
95
+ return `${timeLow}-${timeMid}-${timeHiAndVersion}-${clockSeqAndVariant}-${node}`;
96
+ }
97
+ //# sourceMappingURL=deterministic-uuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deterministic-uuid.js","sourceRoot":"","sources":["../src/deterministic-uuid.ts"],"names":[],"mappings":"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"}
@@ -3,9 +3,13 @@
3
3
  * Handles:
4
4
  * - \X2\XXXX\X0\ - Unicode hex encoding (e.g., \X2\00E4\X0\ -> a with umlaut)
5
5
  * - \X4\XXXXXXXX\X0\ - Unicode 4-byte hex for chars outside BMP
6
- * - \X\XX\ - ISO-8859-1 hex encoding
7
- * - \S\X - Extended ASCII with escape
8
- * - \P..\ - Code page switches (supported as directives and removed)
6
+ * - \X\XX\ - ISO-8859-1 hex encoding (NOT code-page dependent: this is always
7
+ * the ISO 10646 row-0 value, per ISO 10303-21 6.4.3)
8
+ * - \S\X - Extended ASCII: code point of X plus 128, mapped through the
9
+ * currently selected \P?\ code page (default ISO 8859-1)
10
+ * - \PA\..\PI\ - Code page selectors (A=ISO 8859-1 .. I=ISO 8859-9); tracked
11
+ * for subsequent \S\ escapes, then the directive itself is dropped. Any
12
+ * other letter is dropped without changing the active page.
9
13
  * - \\ - one literal backslash (ISO 10303-21 doubles the reverse solidus)
10
14
  *
11
15
  * The \\ pair is collapsed AFTER the directive arms: a directive immediately
@@ -19,12 +23,48 @@
19
23
  */
20
24
  export declare function decodeIfcString(str: string): string;
21
25
  /**
22
- * Encode a Unicode string to IFC STEP string escapes.
26
+ * Encode a Unicode string to IFC STEP directive escapes.
23
27
  *
24
- * - Printable ASCII (32..126) is kept as-is.
28
+ * - Printable ASCII (32..126) is kept as-is, with ONE exception: the reverse
29
+ * solidus (`\`, U+005C) is printable ASCII but goes out as `\X\5C`, because
30
+ * a raw `\` in the output is what a reader takes for the start of a
31
+ * directive or of a `\\` pair.
25
32
  * - 8-bit values are encoded as \X\HH.
26
33
  * - BMP values are encoded as \X2\HHHH\X0\.
27
34
  * - Non-BMP values are encoded as \X4\HHHHHHHH\X0\.
35
+ *
36
+ * This is directive encoding only — it does NOT double the apostrophe (`'`,
37
+ * code point 39 is printable ASCII and passes through unchanged). Its output
38
+ * is therefore **not** safe to place directly inside a STEP single-quoted
39
+ * string literal: an undoubled `'` terminates the literal early and produces
40
+ * a file no conformant reader parses as intended (e.g. a name like
41
+ * `O'Brien`). A caller writing into a literal must double `'` itself, or use
42
+ * `escapeStepString` from `@ifc-lite/data`, which handles the full
43
+ * literal-context contract: doubling `'` and `\`, mapping control characters
44
+ * to a space, and encoding non-ASCII —
45
+ * per ISO 10303-21 6.3.3.4. The two functions do not produce the same output
46
+ * for the same input; do not assume they agree. Sweeping U+0000..U+02FF, they
47
+ * disagree on exactly two of the 95 printable ASCII characters: the
48
+ * apostrophe (U+0027; doubled there, passed through here) and the reverse
49
+ * solidus (U+005C; doubled there, `\X\5C` here). They also disagree on all 32
50
+ * C0 controls AND on DEL (U+007F) -- a space there, `\X\HH` here, since
51
+ * `escapeStepString` collapses `/[\x00-\x1F\x7F]/g` to a space -- and on all
52
+ * 128 of U+0080..U+00FF (`\X2\HHHH\X0\` there, `\X\HH` here). That is 163
53
+ * disagreements in all. Above U+00FF they agree on all 512.
54
+ *
55
+ * Kept for round-trip use with {@link decodeIfcString}, within the scope the
56
+ * two functions actually cover: `decodeIfcString(encodeIfcString(s)) === s`
57
+ * for every `s` built from Unicode SCALAR values. That is not the same as
58
+ * every JS string. A JS string can also hold an unpaired surrogate
59
+ * (U+D800..U+DFFF), which is not a scalar value; this encoder writes it as a
60
+ * `\X2\` directive, and {@link decodeIfcString} decodes every lone surrogate
61
+ * to U+FFFD to stay in parity with the Rust decoder's
62
+ * `String::from_utf16_lossy`. Those 2048 code units are the only inputs that
63
+ * do not come back unchanged.
64
+ *
65
+ * Within that scope the guarantee is independent of apostrophe handling,
66
+ * because doubling is a literal-context requirement, not an encoding one.
67
+ * See https://github.com/LTplus-AG/ifc-lite/issues/3445.
28
68
  */
29
69
  export declare function encodeIfcString(str: string): string;
30
70
  //# sourceMappingURL=ifc-string.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc-string.d.ts","sourceRoot":"","sources":["../src/ifc-string.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkHnD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA6BnD"}
1
+ {"version":3,"file":"ifc-string.d.ts","sourceRoot":"","sources":["../src/ifc-string.ts"],"names":[],"mappings":"AAuGA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAyHnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA6BnD"}
@@ -1,14 +1,116 @@
1
1
  /* This Source Code Form is subject to the terms of the Mozilla Public
2
2
  * License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Upper-half (0xA0..0xFF) code-point tables for the ISO 8859 parts a `\P?\`
6
+ * directive can select for a subsequent `\S\` (ISO 10303-21 6.4.3): letters
7
+ * A..I select ISO 8859-1..9 (A=1, the default, needs no table — its upper
8
+ * half is already the Unicode-identity mapping `\S\` used before this
9
+ * change). Index 0 below is codepage 2 (`\PB\`) .. index 7 is codepage 9
10
+ * (`\PI\`). `0000` marks a code position the ISO 8859 part itself leaves
11
+ * unassigned; ISO 10303-21 does not define decoder behaviour there, so
12
+ * {@link resolveExtendedChar} falls back to the raw byte value (the same
13
+ * answer the default page gives) rather than U+FFFD.
14
+ *
15
+ * Source: https://www.unicode.org/Public/MAPPINGS/ISO8859/8859-{2..9}.TXT
16
+ * (verified 2026-08-30). Keep in parity with `CODEPAGE_TABLES` in
17
+ * `rust/core/src/step_encoding.rs` — both are pinned by the codepage cases in
18
+ * `ifc_string_vectors.json`.
19
+ */
20
+ const CODEPAGE_ROWS = [
21
+ // codepage 2: ISO 8859-2 (Central European)
22
+ '00A0 0104 02D8 0141 00A4 013D 015A 00A7 00A8 0160 015E 0164 0179 00AD 017D 017B',
23
+ '00B0 0105 02DB 0142 00B4 013E 015B 02C7 00B8 0161 015F 0165 017A 02DD 017E 017C',
24
+ '0154 00C1 00C2 0102 00C4 0139 0106 00C7 010C 00C9 0118 00CB 011A 00CD 00CE 010E',
25
+ '0110 0143 0147 00D3 00D4 0150 00D6 00D7 0158 016E 00DA 0170 00DC 00DD 0162 00DF',
26
+ '0155 00E1 00E2 0103 00E4 013A 0107 00E7 010D 00E9 0119 00EB 011B 00ED 00EE 010F',
27
+ '0111 0144 0148 00F3 00F4 0151 00F6 00F7 0159 016F 00FA 0171 00FC 00FD 0163 02D9',
28
+ // codepage 3: ISO 8859-3 (South European)
29
+ '00A0 0126 02D8 00A3 00A4 0000 0124 00A7 00A8 0130 015E 011E 0134 00AD 0000 017B',
30
+ '00B0 0127 00B2 00B3 00B4 00B5 0125 00B7 00B8 0131 015F 011F 0135 00BD 0000 017C',
31
+ '00C0 00C1 00C2 0000 00C4 010A 0108 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF',
32
+ '0000 00D1 00D2 00D3 00D4 0120 00D6 00D7 011C 00D9 00DA 00DB 00DC 016C 015C 00DF',
33
+ '00E0 00E1 00E2 0000 00E4 010B 0109 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF',
34
+ '0000 00F1 00F2 00F3 00F4 0121 00F6 00F7 011D 00F9 00FA 00FB 00FC 016D 015D 02D9',
35
+ // codepage 4: ISO 8859-4 (North European)
36
+ '00A0 0104 0138 0156 00A4 0128 013B 00A7 00A8 0160 0112 0122 0166 00AD 017D 00AF',
37
+ '00B0 0105 02DB 0157 00B4 0129 013C 02C7 00B8 0161 0113 0123 0167 014A 017E 014B',
38
+ '0100 00C1 00C2 00C3 00C4 00C5 00C6 012E 010C 00C9 0118 00CB 0116 00CD 00CE 012A',
39
+ '0110 0145 014C 0136 00D4 00D5 00D6 00D7 00D8 0172 00DA 00DB 00DC 0168 016A 00DF',
40
+ '0101 00E1 00E2 00E3 00E4 00E5 00E6 012F 010D 00E9 0119 00EB 0117 00ED 00EE 012B',
41
+ '0111 0146 014D 0137 00F4 00F5 00F6 00F7 00F8 0173 00FA 00FB 00FC 0169 016B 02D9',
42
+ // codepage 5: ISO 8859-5 (Cyrillic)
43
+ '00A0 0401 0402 0403 0404 0405 0406 0407 0408 0409 040A 040B 040C 00AD 040E 040F',
44
+ '0410 0411 0412 0413 0414 0415 0416 0417 0418 0419 041A 041B 041C 041D 041E 041F',
45
+ '0420 0421 0422 0423 0424 0425 0426 0427 0428 0429 042A 042B 042C 042D 042E 042F',
46
+ '0430 0431 0432 0433 0434 0435 0436 0437 0438 0439 043A 043B 043C 043D 043E 043F',
47
+ '0440 0441 0442 0443 0444 0445 0446 0447 0448 0449 044A 044B 044C 044D 044E 044F',
48
+ '2116 0451 0452 0453 0454 0455 0456 0457 0458 0459 045A 045B 045C 00A7 045E 045F',
49
+ // codepage 6: ISO 8859-6 (Arabic)
50
+ '00A0 0000 0000 0000 00A4 0000 0000 0000 0000 0000 0000 0000 060C 00AD 0000 0000',
51
+ '0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 061B 0000 0000 0000 061F',
52
+ '0000 0621 0622 0623 0624 0625 0626 0627 0628 0629 062A 062B 062C 062D 062E 062F',
53
+ '0630 0631 0632 0633 0634 0635 0636 0637 0638 0639 063A 0000 0000 0000 0000 0000',
54
+ '0640 0641 0642 0643 0644 0645 0646 0647 0648 0649 064A 064B 064C 064D 064E 064F',
55
+ '0650 0651 0652 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000',
56
+ // codepage 7: ISO 8859-7 (Greek)
57
+ '00A0 2018 2019 00A3 20AC 20AF 00A6 00A7 00A8 00A9 037A 00AB 00AC 00AD 0000 2015',
58
+ '00B0 00B1 00B2 00B3 0384 0385 0386 00B7 0388 0389 038A 00BB 038C 00BD 038E 038F',
59
+ '0390 0391 0392 0393 0394 0395 0396 0397 0398 0399 039A 039B 039C 039D 039E 039F',
60
+ '03A0 03A1 0000 03A3 03A4 03A5 03A6 03A7 03A8 03A9 03AA 03AB 03AC 03AD 03AE 03AF',
61
+ '03B0 03B1 03B2 03B3 03B4 03B5 03B6 03B7 03B8 03B9 03BA 03BB 03BC 03BD 03BE 03BF',
62
+ '03C0 03C1 03C2 03C3 03C4 03C5 03C6 03C7 03C8 03C9 03CA 03CB 03CC 03CD 03CE 0000',
63
+ // codepage 8: ISO 8859-8 (Hebrew)
64
+ '00A0 0000 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 00D7 00AB 00AC 00AD 00AE 00AF',
65
+ '00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 00F7 00BB 00BC 00BD 00BE 0000',
66
+ '0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000',
67
+ '0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 2017',
68
+ '05D0 05D1 05D2 05D3 05D4 05D5 05D6 05D7 05D8 05D9 05DA 05DB 05DC 05DD 05DE 05DF',
69
+ '05E0 05E1 05E2 05E3 05E4 05E5 05E6 05E7 05E8 05E9 05EA 0000 0000 200E 200F 0000',
70
+ // codepage 9: ISO 8859-9 (Turkish)
71
+ '00A0 00A1 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 00AA 00AB 00AC 00AD 00AE 00AF',
72
+ '00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 00BA 00BB 00BC 00BD 00BE 00BF',
73
+ '00C0 00C1 00C2 00C3 00C4 00C5 00C6 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF',
74
+ '011E 00D1 00D2 00D3 00D4 00D5 00D6 00D7 00D8 00D9 00DA 00DB 00DC 0130 015E 00DF',
75
+ '00E0 00E1 00E2 00E3 00E4 00E5 00E6 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF',
76
+ '011F 00F1 00F2 00F3 00F4 00F5 00F6 00F7 00F8 00F9 00FA 00FB 00FC 0131 015F 00FF',
77
+ ];
78
+ const CODEPAGE_TABLES = (() => {
79
+ const tables = [];
80
+ for (let page = 0; page < 8; page++) {
81
+ const rows = CODEPAGE_ROWS.slice(page * 6, page * 6 + 6);
82
+ tables.push(rows.join(' ').split(' ').map((h) => parseInt(h, 16)));
83
+ }
84
+ return tables;
85
+ })();
86
+ /**
87
+ * Map a `\S\` result code (0x80..0xFF) through the currently selected code
88
+ * page. `codepage` 1 (the default, ISO 8859-1) and any `code` outside
89
+ * 0xA0..0xFF (the C1 control range 0x80..0x9F, or a malformed operand outside
90
+ * a single byte) pass through unchanged, matching the pre-codepage-aware
91
+ * behaviour this decoder had before.
92
+ */
93
+ function resolveExtendedChar(codepage, code) {
94
+ if (codepage <= 1 || code < 0xA0 || code > 0xFF)
95
+ return code;
96
+ const table = CODEPAGE_TABLES[codepage - 2];
97
+ if (!table)
98
+ return code;
99
+ const mapped = table[code - 0xA0];
100
+ return mapped === 0 ? code : mapped;
101
+ }
4
102
  /**
5
103
  * Decode IFC STEP encoded strings.
6
104
  * Handles:
7
105
  * - \X2\XXXX\X0\ - Unicode hex encoding (e.g., \X2\00E4\X0\ -> a with umlaut)
8
106
  * - \X4\XXXXXXXX\X0\ - Unicode 4-byte hex for chars outside BMP
9
- * - \X\XX\ - ISO-8859-1 hex encoding
10
- * - \S\X - Extended ASCII with escape
11
- * - \P..\ - Code page switches (supported as directives and removed)
107
+ * - \X\XX\ - ISO-8859-1 hex encoding (NOT code-page dependent: this is always
108
+ * the ISO 10646 row-0 value, per ISO 10303-21 6.4.3)
109
+ * - \S\X - Extended ASCII: code point of X plus 128, mapped through the
110
+ * currently selected \P?\ code page (default ISO 8859-1)
111
+ * - \PA\..\PI\ - Code page selectors (A=ISO 8859-1 .. I=ISO 8859-9); tracked
112
+ * for subsequent \S\ escapes, then the directive itself is dropped. Any
113
+ * other letter is dropped without changing the active page.
12
114
  * - \\ - one literal backslash (ISO 10303-21 doubles the reverse solidus)
13
115
  *
14
116
  * The \\ pair is collapsed AFTER the directive arms: a directive immediately
@@ -25,24 +127,31 @@ export function decodeIfcString(str) {
25
127
  return str;
26
128
  let result = '';
27
129
  let i = 0;
130
+ let codepage = 1;
28
131
  while (i < str.length) {
29
132
  if (str[i] !== '\\') {
30
133
  result += str[i];
31
134
  i += 1;
32
135
  continue;
33
136
  }
34
- // Handle code page directives like \PA\, \PB\, ... by consuming them.
137
+ // Handle code page directives like \PA\, \PB\, ... Track A..I as
138
+ // codepage 1..9 for subsequent \S\ escapes; any other letter (or an
139
+ // unrecognized custom-page form) is consumed without changing the page.
35
140
  if (str[i + 1] === 'P' && str[i + 3] === '\\') {
141
+ const letter = str[i + 2];
142
+ if (letter >= 'A' && letter <= 'I') {
143
+ codepage = letter.charCodeAt(0) - 0x40;
144
+ }
36
145
  i += 4;
37
146
  continue;
38
147
  }
39
- // Handle \S\X where the value is the code point of X plus 128. Read X as a
40
- // whole code point (advancing past a surrogate pair) so a malformed
41
- // multi-byte X stays in parity with the Rust decoder instead of leaving a
42
- // dangling surrogate.
148
+ // Handle \S\X where the value is the code point of X plus 128, mapped
149
+ // through the active code page. Read X as a whole code point (advancing
150
+ // past a surrogate pair) so a malformed multi-byte X stays in parity
151
+ // with the Rust decoder instead of leaving a dangling surrogate.
43
152
  if (str[i + 1] === 'S' && str[i + 2] === '\\' && i + 3 < str.length) {
44
153
  const cp = str.codePointAt(i + 3);
45
- result += String.fromCodePoint(cp + 128);
154
+ result += String.fromCodePoint(resolveExtendedChar(codepage, cp + 128));
46
155
  i += 3 + (cp > 0xFFFF ? 2 : 1);
47
156
  continue;
48
157
  }
@@ -129,12 +238,48 @@ export function decodeIfcString(str) {
129
238
  return result;
130
239
  }
131
240
  /**
132
- * Encode a Unicode string to IFC STEP string escapes.
241
+ * Encode a Unicode string to IFC STEP directive escapes.
133
242
  *
134
- * - Printable ASCII (32..126) is kept as-is.
243
+ * - Printable ASCII (32..126) is kept as-is, with ONE exception: the reverse
244
+ * solidus (`\`, U+005C) is printable ASCII but goes out as `\X\5C`, because
245
+ * a raw `\` in the output is what a reader takes for the start of a
246
+ * directive or of a `\\` pair.
135
247
  * - 8-bit values are encoded as \X\HH.
136
248
  * - BMP values are encoded as \X2\HHHH\X0\.
137
249
  * - Non-BMP values are encoded as \X4\HHHHHHHH\X0\.
250
+ *
251
+ * This is directive encoding only — it does NOT double the apostrophe (`'`,
252
+ * code point 39 is printable ASCII and passes through unchanged). Its output
253
+ * is therefore **not** safe to place directly inside a STEP single-quoted
254
+ * string literal: an undoubled `'` terminates the literal early and produces
255
+ * a file no conformant reader parses as intended (e.g. a name like
256
+ * `O'Brien`). A caller writing into a literal must double `'` itself, or use
257
+ * `escapeStepString` from `@ifc-lite/data`, which handles the full
258
+ * literal-context contract: doubling `'` and `\`, mapping control characters
259
+ * to a space, and encoding non-ASCII —
260
+ * per ISO 10303-21 6.3.3.4. The two functions do not produce the same output
261
+ * for the same input; do not assume they agree. Sweeping U+0000..U+02FF, they
262
+ * disagree on exactly two of the 95 printable ASCII characters: the
263
+ * apostrophe (U+0027; doubled there, passed through here) and the reverse
264
+ * solidus (U+005C; doubled there, `\X\5C` here). They also disagree on all 32
265
+ * C0 controls AND on DEL (U+007F) -- a space there, `\X\HH` here, since
266
+ * `escapeStepString` collapses `/[\x00-\x1F\x7F]/g` to a space -- and on all
267
+ * 128 of U+0080..U+00FF (`\X2\HHHH\X0\` there, `\X\HH` here). That is 163
268
+ * disagreements in all. Above U+00FF they agree on all 512.
269
+ *
270
+ * Kept for round-trip use with {@link decodeIfcString}, within the scope the
271
+ * two functions actually cover: `decodeIfcString(encodeIfcString(s)) === s`
272
+ * for every `s` built from Unicode SCALAR values. That is not the same as
273
+ * every JS string. A JS string can also hold an unpaired surrogate
274
+ * (U+D800..U+DFFF), which is not a scalar value; this encoder writes it as a
275
+ * `\X2\` directive, and {@link decodeIfcString} decodes every lone surrogate
276
+ * to U+FFFD to stay in parity with the Rust decoder's
277
+ * `String::from_utf16_lossy`. Those 2048 code units are the only inputs that
278
+ * do not come back unchanged.
279
+ *
280
+ * Within that scope the guarantee is independent of apostrophe handling,
281
+ * because doubling is a literal-context requirement, not an encoding one.
282
+ * See https://github.com/LTplus-AG/ifc-lite/issues/3445.
138
283
  */
139
284
  export function encodeIfcString(str) {
140
285
  if (!str || typeof str !== 'string')
@@ -1 +1 @@
1
- {"version":3,"file":"ifc-string.js","sourceRoot":"","sources":["../src/ifc-string.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ifc-string.js","sourceRoot":"","sources":["../src/ifc-string.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,aAAa,GAAsB;IACvC,4CAA4C;IAC5C,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,0CAA0C;IAC1C,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,0CAA0C;IAC1C,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,oCAAoC;IACpC,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,kCAAkC;IAClC,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iCAAiC;IACjC,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,kCAAkC;IAClC,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,mCAAmC;IACnC,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;CAClF,CAAC;AAEF,MAAM,eAAe,GAAwB,CAAC,GAAG,EAAE;IACjD,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC,EAAE,CAAC;AAEL;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,QAAgB,EAAE,IAAY;IACzD,IAAI,QAAQ,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClC,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IAEhD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,iEAAiE;QACjE,oEAAoE;QACpE,wEAAwE;QACxE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBACnC,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACzC,CAAC;YACD,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,sEAAsE;QACtE,wEAAwE;QACxE,qEAAqE;QACrE,iEAAiE;QACjE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YACpE,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;YACnC,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,QAAQ,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;YACxE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,wEAAwE;QACxE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACrE,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACpC,IAAI,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;gBACjD,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QAED,6DAA6D;QAC7D,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;gBAClC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvD,iEAAiE;oBACjE,iEAAiE;oBACjE,mEAAmE;oBACnE,oEAAoE;oBACpE,oEAAoE;oBACpE,yCAAyC;oBACzC,MAAM,KAAK,GAAa,EAAE,CAAC;oBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;oBAChD,CAAC;oBACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBACtC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;wBACnB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM;+BACjD,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;4BACtD,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;4BAC/C,CAAC,IAAI,CAAC,CAAC;wBACT,CAAC;6BAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;4BACtC,MAAM,IAAI,GAAG,CAAC;wBAChB,CAAC;6BAAM,CAAC;4BACN,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;wBACnC,CAAC;oBACH,CAAC;oBACD,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;oBACZ,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;gBAClC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvC,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC7C,6DAA6D;wBAC7D,gEAAgE;wBAChE,kEAAkE;wBAClE,iEAAiE;wBACjE,+DAA+D;wBAC/D,iEAAiE;wBACjE,mEAAmE;wBACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,QAAQ;+BAC7D,CAAC,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,CAAC;wBACrC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;oBACtD,CAAC;oBACD,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;oBACZ,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,IAAI,CAAC;YACf,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,2DAA2D;QAC3D,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IAEhD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,SAAS;QACX,CAAC;QAED,IAAI,SAAS,IAAI,EAAE,IAAI,SAAS,IAAI,GAAG,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACvD,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACX,CAAC;QAED,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;YACtB,OAAO,IAAI,QAAQ,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAC3E,SAAS;QACX,CAAC;QAED,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACxB,OAAO,IAAI,SAAS,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC;YAClF,SAAS;QACX,CAAC;QAED,OAAO,IAAI,SAAS,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC;IACpF,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { decodeIfcString, encodeIfcString } from './ifc-string.js';
2
2
  export { decodeStepStringLiteral } from './step-string-literal.js';
3
3
  export { uuidToIfcGuid, ifcGuidToUuid, generateIfcGuid, generateUuid, isValidIfcGuid, isValidUuid, } from './guid.js';
4
4
  export type { RandomSource } from './guid.js';
5
+ export { uuidFromSeed } from './deterministic-uuid.js';
5
6
  export { isWhollyNumeric } from './numeric-literal.js';
6
7
  export { parsePropertyValue } from './property-value.js';
7
8
  export type { ParsedPropertyValue } from './property-value.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@
4
4
  export { decodeIfcString, encodeIfcString } from './ifc-string.js';
5
5
  export { decodeStepStringLiteral } from './step-string-literal.js';
6
6
  export { uuidToIfcGuid, ifcGuidToUuid, generateIfcGuid, generateUuid, isValidIfcGuid, isValidUuid, } from './guid.js';
7
+ export { uuidFromSeed } from './deterministic-uuid.js';
7
8
  export { isWhollyNumeric } from './numeric-literal.js';
8
9
  export { parsePropertyValue } from './property-value.js';
9
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/encoding",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "IFC string encoding/decoding and property value parsing for IFC-Lite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "typescript": "^6.0.3",
17
- "vitest": "^4.1.10"
17
+ "vitest": "^4.1.11",
18
+ "@ifc-lite/timing-ladder": "^0.1.0"
18
19
  },
19
20
  "license": "MPL-2.0",
20
21
  "author": "Louis True",