@cbortech/cbor 0.26.8 → 0.27.1

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.
Files changed (60) hide show
  1. package/README.ja.md +193 -28
  2. package/README.md +196 -29
  3. package/dist/ast/CborAppSeqResult.d.ts +58 -3
  4. package/dist/ast/CborArray.d.ts +2 -2
  5. package/dist/ast/CborByteString.d.ts +17 -1
  6. package/dist/ast/CborEmbeddedCBOR.d.ts +2 -2
  7. package/dist/ast/CborFloat.d.ts +2 -2
  8. package/dist/ast/CborIndefiniteByteString.d.ts +25 -1
  9. package/dist/ast/CborIndefiniteTextString.d.ts +17 -1
  10. package/dist/ast/CborItem.d.ts +340 -10
  11. package/dist/ast/CborMap.d.ts +2 -2
  12. package/dist/ast/CborNint.d.ts +1 -1
  13. package/dist/ast/CborTag.d.ts +30 -3
  14. package/dist/ast/CborTextString.d.ts +3 -2
  15. package/dist/ast/CborUint.d.ts +1 -1
  16. package/dist/ast/CborUnresolvedAppExt.d.ts +2 -2
  17. package/dist/ast/index.cjs +1 -1
  18. package/dist/ast/index.js +2 -2
  19. package/dist/cddl/index.cjs +1 -1
  20. package/dist/cddl/index.js +1 -1
  21. package/dist/cdn/index.cjs +2 -2
  22. package/dist/cdn/index.cjs.map +1 -1
  23. package/dist/cdn/index.js +18 -18
  24. package/dist/cdn/index.js.map +1 -1
  25. package/dist/cdn/serialize-utils.d.ts +237 -10
  26. package/dist/cdn/tokenizer.d.ts +12 -11
  27. package/dist/extensions/builtins.d.ts +5 -5
  28. package/dist/extensions/cri.d.ts +4 -4
  29. package/dist/extensions/dt.d.ts +4 -4
  30. package/dist/extensions/ip.d.ts +4 -4
  31. package/dist/extensions/types.d.ts +44 -5
  32. package/dist/index.cjs +3 -3
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +158 -158
  36. package/dist/index.js.map +1 -1
  37. package/dist/{mapEntries-Ci_dppP6.js → mapEntries-CCLaJSaJ.js} +1599 -1275
  38. package/dist/mapEntries-CCLaJSaJ.js.map +1 -0
  39. package/dist/mapEntries-CZZJScaj.cjs +13 -0
  40. package/dist/mapEntries-CZZJScaj.cjs.map +1 -0
  41. package/dist/{schema-y8G5mDIS.js → schema-DN9inJny.js} +294 -294
  42. package/dist/{schema-y8G5mDIS.js.map → schema-DN9inJny.js.map} +1 -1
  43. package/dist/schema-zsg5yCPK.cjs +63 -0
  44. package/dist/{schema-DgnkH0P6.cjs.map → schema-zsg5yCPK.cjs.map} +1 -1
  45. package/dist/serialize-utils-DhlW61ZX.cjs +37 -0
  46. package/dist/serialize-utils-DhlW61ZX.cjs.map +1 -0
  47. package/dist/{tokenizer-N-vAvRdj.js → serialize-utils-h-CVB9rg.js} +636 -358
  48. package/dist/serialize-utils-h-CVB9rg.js.map +1 -0
  49. package/dist/types.d.ts +508 -58
  50. package/dist/utils/base64.d.ts +1 -1
  51. package/dist/utils/hexfloat.d.ts +11 -3
  52. package/dist/utils/strip-comments.d.ts +1 -1
  53. package/package.json +13 -12
  54. package/dist/mapEntries-BJzyBUH5.cjs +0 -13
  55. package/dist/mapEntries-BJzyBUH5.cjs.map +0 -1
  56. package/dist/mapEntries-Ci_dppP6.js.map +0 -1
  57. package/dist/schema-DgnkH0P6.cjs +0 -63
  58. package/dist/tokenizer-BD08xbyd.cjs +0 -36
  59. package/dist/tokenizer-BD08xbyd.cjs.map +0 -1
  60. package/dist/tokenizer-N-vAvRdj.js.map +0 -1
package/README.md CHANGED
@@ -392,19 +392,23 @@ CBOR.format("h'68' + b64'aQ'", {
392
392
  // b64'aQ'
393
393
  ```
394
394
 
395
- ### Preserve application-string/-sequence notation
395
+ To render the preserved concatenation using draft-27's `t1<<...>>` /
396
+ `b1<<...>>` notation instead of `+`, see `modernConcat` in
397
+ [String Concatenation and Indefinite-Length Strings](#string-concatenation-and-indefinite-length-strings).
398
+
399
+ ### Preserve app-string/-sequence notation
396
400
 
397
401
  Some built-in extensions (`dt`/`DT`, `ip`/`IP`) support `prefix'...'`
398
- (application string), `` prefix`...` `` (backtick application string),
399
- `prefix<<...>>` (application sequence), and a raw tag literal (`N(...)`)
402
+ (app-string), `` prefix`...` `` (backtick app-string),
403
+ `prefix<<...>>` (app-sequence), and a raw tag literal (`N(...)`)
400
404
  notation for the same value, and by default regenerate `prefix'...'` from
401
405
  the resolved value on every `CBOR.format()` call — so
402
406
  `` DT`1969-07-21T02:56:16Z` ``, `DT<<'1969-07-21T02:56:16Z'>>`, and even the
403
407
  raw tag form `1(1749772800)` all normalize to `DT'...'` notation, and a
404
408
  non-canonical `DT'...'` spelling (e.g. a `+00:00` offset instead of `Z`)
405
- gets rewritten too. `preserveAppSequence` keeps the original spelling
409
+ gets rewritten too. `preserveAppPrefix` keeps the original spelling
406
410
  instead — whichever form was used. It has no effect when
407
- `appStrings: false` is also set (raw tag notation is used either way
411
+ `appPrefix: false` is also set (raw tag notation is used either way
408
412
  regardless of the original spelling), or on values not parsed from one of
409
413
  these forms.
410
414
 
@@ -414,16 +418,50 @@ import { CBOR } from '@cbortech/cbor';
414
418
  CBOR.format('1(1749772800)');
415
419
  // "DT'2025-06-13T00:00:00Z'"
416
420
 
417
- CBOR.format('1(1749772800)', { preserveAppSequence: true });
421
+ CBOR.format('1(1749772800)', { preserveAppPrefix: true });
418
422
  // "1(1749772800)"
419
423
 
420
- CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppSequence: true });
424
+ CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppPrefix: true });
421
425
  // "DT<<'1969-07-21T02:56:16Z'>>"
422
426
 
423
- CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppSequence: true });
427
+ CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppPrefix: true });
424
428
  // "DT`1969-07-21T02:56:16Z`"
425
429
  ```
426
430
 
431
+ ### Preserve comments
432
+
433
+ By default, `CBOR.fromCDN()` discards comments and `CBOR.format()` emits
434
+ none. `preserveComments: true` captures them while parsing and re-emits each
435
+ comment verbatim, with whichever marker (`#`, `//`, `/* */`, `/ /`) it was
436
+ originally written with.
437
+
438
+ ```ts
439
+ import { CBOR } from '@cbortech/cbor';
440
+
441
+ const text = '{ "a": 1 } # trailing comment';
442
+
443
+ CBOR.format(text, { indent: 2 });
444
+ // '{\n "a": 1\n}'
445
+
446
+ CBOR.format(text, { indent: 2, preserveComments: true });
447
+ // '{\n "a": 1\n} # trailing comment'
448
+ ```
449
+
450
+ To normalize every comment's marker instead of keeping the mix as originally
451
+ written, use `comments` — `'c-style'` for `//` and `/* */`, or
452
+ `'cdn-style'` for `#` and `/ /`. It has no effect when `preserveComments` is
453
+ `true` (verbatim wins); explicitly set `comments: 'strip'` (or leave
454
+ both options unset) to drop comments entirely.
455
+
456
+ ```ts
457
+ CBOR.format(text, { indent: 2, comments: 'c-style' });
458
+ // '{\n "a": 1\n} // trailing comment'
459
+ ```
460
+
461
+ Only effective when `indent` enables pretty-printing: single-line output
462
+ strips all comments regardless, since line comments can only be terminated
463
+ by a newline.
464
+
427
465
  ### Preserve blank lines
428
466
 
429
467
  By default, `CBOR.format()` drops blank lines between array/map entries (and
@@ -681,10 +719,85 @@ console.log(text);
681
719
  // DT'2026-05-06T00:00:00Z'
682
720
  ```
683
721
 
722
+ ### Per-item option overrides
723
+
724
+ `itemOptions` on `toJS()` is called for every node before it is converted, so
725
+ one part of a document can be converted differently from the rest. Return a
726
+ partial options object to override options for that node and its descendants,
727
+ or `undefined` to leave them unchanged. `ctx.path` identifies the node as a
728
+ sequence of array indices and map keys, empty at the root.
729
+
730
+ It can be called more than once for the same node — when a `reviver` is also
731
+ present, arrays and object-mode maps convert each child at least twice: once
732
+ to build a value visible to an earlier sibling's own `reviver` call, and once
733
+ more for the value that's actually kept. Write it as a pure function of
734
+ `node`/`ctx`, not relying on how many times it runs.
735
+
736
+ ```ts
737
+ import { CBOR } from '@cbortech/cbor';
738
+
739
+ const item = CBOR.fromCDN(
740
+ `{"date1": DT'2026-08-23T00:00:00Z', "date2": DT'2026-08-23T00:00:00Z'}`
741
+ );
742
+
743
+ const value = item.toJS({
744
+ stripTags: true,
745
+ itemOptions: (_node, ctx) =>
746
+ ctx.path.length === 1 && ctx.path[0] === 'date1'
747
+ ? { extensions: [CBOR.dt_as_Date] }
748
+ : undefined,
749
+ });
750
+
751
+ console.log(value);
752
+ // { date1: Date(...), date2: 1787443200 }
753
+ ```
754
+
755
+ `extensions` on `ToJSOptions` also works on its own, without `itemOptions`, to
756
+ reinterpret an entire tree: a value parsed with the default `dt` extension can
757
+ still be converted with `dt_as_Date` (or vice versa) by passing `extensions`
758
+ directly to `toJS()`.
759
+
760
+ `ctx.options` carries the options already in effect for the node — the root
761
+ options merged with whatever an ancestor's `itemOptions` already returned —
762
+ so a callback can build on the current value of an option instead of
763
+ overriding it outright:
764
+
765
+ ```ts
766
+ itemOptions: (_node, ctx) => ({
767
+ extensions: [...(ctx.options.extensions ?? []), CBOR.dt_as_Date],
768
+ });
769
+ ```
770
+
771
+ `toCDN()` takes the same `itemOptions` option, formatting one part of a
772
+ document differently from the rest:
773
+
774
+ ```ts
775
+ import { CBOR } from '@cbortech/cbor';
776
+
777
+ const item = CBOR.fromCDN('{"raw": 255, "count": 255}');
778
+
779
+ const text = item.toCDN({
780
+ itemOptions: (_node, ctx) =>
781
+ ctx.path.length === 1 && ctx.path[0] === 'raw'
782
+ ? { intFormat: 'hex' }
783
+ : undefined,
784
+ });
785
+
786
+ console.log(text);
787
+ // {"raw":0xff,"count":255}
788
+ ```
789
+
790
+ There is no `reviver` for `toCDN()`, so it can't be called more than once for
791
+ that reason — but it can still be called more than once for a node that's
792
+ also a `toCDN()` layout decision (`inlineLeafContainers`'s one-line collapse
793
+ check, or a tag/app-sequence value's own multi-word check re-render an entry
794
+ purely to answer that question before the real render). Write it as a pure
795
+ function here too.
796
+
684
797
  ## String Concatenation and Indefinite-Length Strings
685
798
 
686
- The `t1` / `b1` / `ilbs` / `ilts` application extensions from
687
- draft-ietf-cbor-edn-literals-26 (§3.4 / §3.5) are enabled by default.
799
+ The `t1` / `b1` / `ilbs` / `ilts` app-extensions from
800
+ draft-ietf-cbor-edn-literals-27 (§3.5 / §3.6) are enabled by default.
688
801
 
689
802
  `t1<<...>>` and `b1<<...>>` join (text or byte) string arguments from left to
690
803
  right into a single text string (`t1`) or byte string (`b1`). Arguments may
@@ -694,11 +807,11 @@ also be ellipses (`...`) to elide parts of a string.
694
807
  import { CBOR } from '@cbortech/cbor';
695
808
 
696
809
  const text = CBOR.fromCDN('t1<<"Hello ", "world">>');
697
- console.log(text.toCDN({ appStrings: false }));
810
+ console.log(text.toCDN({ appPrefix: false }));
698
811
  // "Hello world"
699
812
 
700
813
  const bytes = CBOR.fromCDN("b1<<'Hello ', h'776f726c64'>>");
701
- console.log(bytes.toCDN({ appStrings: false }));
814
+ console.log(bytes.toCDN({ appPrefix: false }));
702
815
  // 'Hello world'
703
816
  ```
704
817
 
@@ -711,29 +824,81 @@ documents; this library keeps accepting the legacy syntax on input.
711
824
  import { CBOR } from '@cbortech/cbor';
712
825
 
713
826
  const v = CBOR.fromCDN("ilbs<<'Hello ', 'world'>>");
714
- console.log(v.toCDN({ appStrings: false }));
827
+ console.log(v.toCDN({ appPrefix: false }));
715
828
  // (_ 'Hello ','world')
716
829
  ```
717
830
 
831
+ ### Emitting `t1`/`b1`/`ilbs`/`ilts` notation
832
+
833
+ Parsing already accepts `t1`/`b1`/`ilbs`/`ilts` notation, but by default
834
+ `toCDN()`/`CBOR.format()` never emit it on their own: a preserved
835
+ concatenation (`preserveConcatenation`) still renders as `+`, and an
836
+ indefinite-length string still renders as the legacy `(_ ...)` streamstring
837
+ form. `modernConcat` and `modernStreamSyntax` opt into emitting the draft-27
838
+ notation instead — both default to `false` (the legacy syntax), and both fall
839
+ back to it when `appPrefix` is `false`.
840
+
841
+ ```ts
842
+ import { CBOR } from '@cbortech/cbor';
843
+
844
+ CBOR.format('"a" + "b"', {
845
+ indent: 2,
846
+ preserveConcatenation: true,
847
+ modernConcat: true,
848
+ });
849
+ // t1<<"a", "b">>
850
+
851
+ CBOR.format('(_ "a", "b")', { modernStreamSyntax: true });
852
+ // ilts<<"a","b">>
853
+ ```
854
+
855
+ `modernConcat` also applies within a `...` elision chain (§5.2), rendering
856
+ `"a" + ... + "b"` as `t1<<"a", ..., "b">>` — unlike plain concatenation, this
857
+ happens regardless of `preserveConcatenation`, since an elision chain has no
858
+ single-literal collapsed form to fall back to in the first place.
859
+
860
+ > [!NOTE]
861
+ > Neither option converts `t1`/`b1`/`ilbs`/`ilts` source back to the
862
+ > legacy notation: a value parsed from `t1<<...>>` (or `ilbs<<...>>`, etc.)
863
+ > keeps that exact spelling on output regardless of `modernConcat` /
864
+ > `modernStreamSyntax` — as long as `appPrefix` is not `false`,
865
+ > `encodingIndicators` is `'auto'` (both defaults), and the source is either
866
+ > single-line or being rendered with `indent` enabled. `encodingIndicators:
867
+ 'always'`/`'never'` or `appPrefix: false` still normalize it like any
868
+ > other app-string value (e.g. `t1<<"a", "b">>` becomes `"ab"_i`
869
+ > under `encodingIndicators: 'always'`), and a multi-line source falls back
870
+ > to normalized output in single-line mode (that layout can't be reproduced
871
+ > without `indent`):
872
+ >
873
+ > ```ts
874
+ > CBOR.format('t1<<\n "a",\n "b"\n>>');
875
+ > // '"ab"' — falls back: multi-line source, no `indent`
876
+ > CBOR.format('t1<<\n "a",\n "b"\n>>', { indent: 2 });
877
+ > // 't1<<\n "a",\n "b"\n>>' — kept verbatim
878
+ > ```
879
+ >
880
+ > Both options only affect how a value reconstructed from a `+` chain or a
881
+ > `(_ ...)` chunk list is _newly_ rendered.
882
+
718
883
  > [!NOTE]
719
- > The identifiers `t1` and `b1` are explicitly provisional in draft-26 and
884
+ > The identifiers `t1` and `b1` are explicitly provisional in draft-27 and
720
885
  > may be renamed by the CBOR working group.
721
886
 
722
887
  ## float
723
888
 
724
889
  Interprets a hex bit-pattern as an IEEE 754 floating-point value
725
- (draft-ietf-cbor-edn-literals-26 §3.7). Enabled by default.
890
+ (draft-ietf-cbor-edn-literals-27 §3.8). Enabled by default.
726
891
 
727
892
  ```ts
728
893
  import { CBOR } from '@cbortech/cbor';
729
894
 
730
895
  const v = CBOR.fromCDN("float'7e00'");
731
- console.log(v.toCDN({ appStrings: false }));
896
+ console.log(v.toCDN({ appPrefix: false }));
732
897
  // NaN
733
898
 
734
899
  // Interpret bytes as float bits
735
900
  const v2 = CBOR.fromCDN("float<<h'3f800000'>>");
736
- console.log(v2.toCDN({ appStrings: false }));
901
+ console.log(v2.toCDN({ appPrefix: false }));
737
902
  // 1.0_2
738
903
  ```
739
904
 
@@ -747,7 +912,7 @@ default. Import what you need and pass it through the `extensions` option.
747
912
  Byte-string literals using [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648)
748
913
  Base32 encoding. These prefixes are described in §8 of
749
914
  [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) and also mentioned in
750
- [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/).
915
+ [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/).
751
916
 
752
917
  - `b32` — §6 Base32 (`A–Z 2–7` alphabet)
753
918
  - `h32` — §7 Base32Hex (`0–9 A–V` alphabet)
@@ -756,11 +921,11 @@ Base32 encoding. These prefixes are described in §8 of
756
921
  import { CBOR, b32, h32 } from '@cbortech/cbor';
757
922
 
758
923
  const v1 = CBOR.fromCDN("b32'AEBAGBA'", { extensions: [b32] });
759
- console.log(v1.toCDN({ appStrings: false }));
924
+ console.log(v1.toCDN({ appPrefix: false }));
760
925
  // h'01020304'
761
926
 
762
927
  const v2 = CBOR.fromCDN("h32'00P00'", { extensions: [h32] });
763
- console.log(v2.toCDN({ appStrings: false }));
928
+ console.log(v2.toCDN({ appPrefix: false }));
764
929
  // h'003200'
765
930
  ```
766
931
 
@@ -774,24 +939,24 @@ identical CBOR bytes and returns the first item. This extension is described in
774
939
  import { CBOR, same } from '@cbortech/cbor';
775
940
 
776
941
  const v = CBOR.fromCDN("same<<h'0102', h'0102'>>", { extensions: [same] });
777
- console.log(v.toCDN({ appStrings: false }));
942
+ console.log(v.toCDN({ appPrefix: false }));
778
943
  // h'0102'
779
944
 
780
945
  // A single-item sequence always passes
781
946
  const v2 = CBOR.fromCDN('same<<42>>', { extensions: [same] });
782
- console.log(v2.toCDN({ appStrings: false }));
947
+ console.log(v2.toCDN({ appPrefix: false }));
783
948
  // 42
784
949
  ```
785
950
 
786
951
  ---
787
952
 
788
- Additional application extensions are published as separate packages. Install
953
+ Additional app-extensions are published as separate packages. Install
789
954
  the ones you need and pass them through the `extensions` option.
790
955
 
791
956
  ### hash
792
957
 
793
- `hash` is an application extension defined in §3.3 of
794
- [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/).
958
+ `hash` is an app-extension defined in §3.4 of
959
+ [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/).
795
960
  It represents cryptographic hash values in the form `hash'algorithm:value'`.
796
961
  Because it requires an external cryptographic library, it is provided separately
797
962
  as [@cbortech/hash-extension](https://www.npmjs.com/package/@cbortech/hash-extension).
@@ -816,7 +981,7 @@ const digest = cbor.parse(
816
981
 
817
982
  ### uuid
818
983
 
819
- `uuid` is a library-specific application extension, provided separately as
984
+ `uuid` is a library-specific app-extension, provided separately as
820
985
  [@cbortech/uuid-extension](https://www.npmjs.com/package/@cbortech/uuid-extension).
821
986
 
822
987
  ```bash
@@ -835,7 +1000,7 @@ const id = cbor.parse("uuid'550e8400-e29b-41d4-a716-446655440000'");
835
1000
 
836
1001
  ### set / map
837
1002
 
838
- `SET` and `MAP` are library-specific application extensions for tagged Set and
1003
+ `SET` and `MAP` are library-specific app-extensions for tagged Set and
839
1004
  Map values. They are provided together as
840
1005
  [@cbortech/set-map-extensions](https://www.npmjs.com/package/@cbortech/set-map-extensions).
841
1006
  `SET<<[...]>>` produces CBOR tag 258 over an array, and `MAP<<{...}>>` produces
@@ -1093,9 +1258,11 @@ types).
1093
1258
 
1094
1259
  - CBOR
1095
1260
  - [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)
1261
+ - CBOR Sequences
1262
+ - [RFC 8742](https://www.rfc-editor.org/rfc/rfc8742)
1096
1263
  - CDN (CBOR-EDN)
1097
1264
  - [draft-ietf-cbor-edn-literals-25](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/)
1098
- - [draft-ietf-cbor-edn-literals-26](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/26/)
1265
+ - [draft-ietf-cbor-edn-literals-27](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/)
1099
1266
  - CDDL
1100
1267
  - [RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)
1101
1268
  - [RFC 9682](https://www.rfc-editor.org/rfc/rfc9682)
@@ -1103,7 +1270,7 @@ types).
1103
1270
 
1104
1271
  Implementation notes:
1105
1272
 
1106
- - CDN follows draft-26 while retaining draft-25's `(_ ...)` streamstring syntax
1273
+ - CDN follows draft-27 while retaining draft-25's `(_ ...)` streamstring syntax
1107
1274
  and `+` string-concatenation syntax.
1108
1275
  - CDDL implements every RFC 8610 control operator, plus RFC 9165's `.plus`,
1109
1276
  `.cat`, and `.feature`.
@@ -1,5 +1,5 @@
1
1
  import { ToCDNOptions, ToCBOROptions, ToJSOptions } from '../types';
2
- import { CborItem } from './CborItem';
2
+ import { CborItem, Occurrence } from './CborItem';
3
3
  import { CborWriter } from '../cbor/encode';
4
4
  /**
5
5
  * Wraps a resolved app-sequence result and preserves the original EDN source
@@ -13,6 +13,39 @@ import { CborWriter } from '../cbor/encode';
13
13
  * lines also delegates to the inner item, since it cannot be re-emitted
14
14
  * without breaking the single-line guarantee.
15
15
  *
16
+ * When `toCDN()`'s `itemOptions` is configured (see `needsCdnItemDispatch`),
17
+ * the verbatim `ednSource` fast path alone can't be trusted: it was produced
18
+ * without ever visiting `this.inner`'s own descendants, so an override
19
+ * targeting one of them (e.g. one chunk of an `ilbs<<...>>`) would otherwise
20
+ * never even be offered the chance to apply. But merely *having* `itemOptions`
21
+ * configured must not by itself change the output — many callers set it
22
+ * without it ever matching anything in this particular subtree, and
23
+ * `itemOptions` returning `undefined` everywhere is documented to mean "no
24
+ * change" (see `CdnItemContext`). So this renders through the normal
25
+ * recursive path while tracking, via `CDN_OVERRIDE_TRACKER` (an out-of-band
26
+ * symbol key, *not* a wrapped `itemOptions` — wrapping it would make
27
+ * `ctx.options.itemOptions` a different function for every descendant here
28
+ * than everywhere else in the tree, observable even to a pure callback),
29
+ * whether any call in the subtree actually returned an override, and only
30
+ * swaps in that freshly rendered text when one did; otherwise the exact
31
+ * preserved `ednSource` is still returned.
32
+ *
33
+ * Each `_toCDN()` call installs its *own fresh* tracker box before
34
+ * recursing, rather than reusing whatever tracker it was handed — reusing
35
+ * one directly would let an override applied by some unrelated part of the
36
+ * tree that merely happens to share the same ambient `options` object (a
37
+ * later sibling reached through the same `itemOptions`, say) falsely mark
38
+ * *this* wrapper's own verbatim source as stale. But a genuinely *nested*
39
+ * app-sequence (e.g. a custom `wrap<<ilbs<<h'61'>>>>` extension wrapping an
40
+ * `ilbs<<...>>` result) must still have its own outer verbatim source
41
+ * abandoned when the inner wrapper's own tracked render found something to
42
+ * apply — an inner override changes what the outer source would need to
43
+ * embed too. So once this call's own local tracker comes back `applied`,
44
+ * that fact is additionally bubbled up to whichever ancestor tracker (if
45
+ * any) this call itself received via `options` — the exact wrapper this
46
+ * call is nested inside, never a sibling reached only through shared
47
+ * top-level `options`.
48
+ *
16
49
  * CBOR encoding and JS conversion always delegate to the inner item so the
17
50
  * wrapper is fully transparent for those operations.
18
51
  */
@@ -21,7 +54,29 @@ export declare class CborAppSeqResult extends CborItem {
21
54
  readonly ednSource: string;
22
55
  constructor(inner: CborItem, ednSource: string);
23
56
  get _containsCdnContainer(): boolean;
57
+ /**
58
+ * Same approach as `CborTag`: tokenize this wrapper's own `_toCDN()`
59
+ * output rather than delegating to `this.inner._isMultiWordText()`.
60
+ * Delegating to `this.inner` was tried and found wrong: for
61
+ * `ilbs<<h'68656c6c6f20776f726c64'>>`, the chunk's raw bytes decode to
62
+ * printable "hello world", so `this.inner`'s own semantic check reports
63
+ * it as multi-word — but the *actual* rendering is the preserved
64
+ * `ilbs<<...>>` app-sequence spelling, where that chunk appears as a
65
+ * `h'...'` literal, never as decoded text; the semantic prediction and
66
+ * the real output disagree. Tokenizing `this._toCDN()` directly sees
67
+ * whichever one actually happens: the preserved `ednSource` verbatim
68
+ * (`isMultiWordRenderedLiteral` peels the `prefix<<...>>` wrapper and
69
+ * checks each item under the loose rule, same as `<<...>>` — a
70
+ * multi-word text item like `ilts<<"two words">>` still always counts,
71
+ * a prefixed-literal item like `ilbs<<h'00'>>` does not) or, in the
72
+ * 'always'/'never' `encodingIndicators` modes, a pure passthrough to
73
+ * `this.inner._toCDN()` with no extra wrapping (any node needing that to
74
+ * be caught, like a self-disqualifying `CborIndefiniteByteString`, has
75
+ * already produced a `\n` in that string, which the caller's own
76
+ * `s.includes('\n')` check picks up independently either way).
77
+ */
78
+ _isMultiWordText(options: ToCDNOptions | undefined, strict?: boolean, path?: readonly unknown[]): boolean;
24
79
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
25
- _toCDN(options: ToCDNOptions | undefined, depth: number): string;
26
- _toJS(options?: ToJSOptions): unknown;
80
+ _toCDN(options: ToCDNOptions | undefined, depth: number, path?: readonly unknown[]): string;
81
+ _toJS(options?: ToJSOptions, path?: readonly unknown[], occurrence?: Occurrence): unknown;
27
82
  }
@@ -12,7 +12,7 @@ export declare class CborArray extends CborItem {
12
12
  });
13
13
  get _containsCdnContainer(): boolean;
14
14
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
15
- _toCDN(options: ToCDNOptions | undefined, depth: number): string;
15
+ _toCDN(options: ToCDNOptions | undefined, depth: number, path?: readonly unknown[]): string;
16
16
  _toHexDump(depth: number, options?: ToCDNOptions): AnnotatedLine[];
17
- _toJS(options?: ToJSOptions): unknown;
17
+ _toJS(options?: ToJSOptions, path?: readonly unknown[], occurrence?: readonly unknown[]): unknown;
18
18
  }
@@ -48,7 +48,23 @@ export declare class CborByteString extends CborItem {
48
48
  ednCommentSyntax?: ByteCommentSyntax;
49
49
  ednParts?: readonly CborByteStringPart[];
50
50
  });
51
+ /**
52
+ * Only the "bare sqstr text with 2+ words" case — the "is this a
53
+ * prefixed literal" question is deliberately *not* predicted here from
54
+ * raw bytes at all (a subclass like `CborIpExt` might override `_toCDN()`
55
+ * to render something else entirely, e.g. a preserved
56
+ * `ip<<'192.0.2.42'>>` app-sequence spelling, that raw-byte prediction
57
+ * knows nothing about — see `isMultiWordByteString`'s doc). That
58
+ * question is instead answered from the *actual rendering*: for a bare
59
+ * entry, `serializeContainer`'s own `isPrefixedLiteralText(s)` check
60
+ * already covers it (this node's render *is* `s`, unobscured); for one
61
+ * wrapped in a `CborTag`, `CborTag._isMultiWordText`'s
62
+ * `isMultiWordRenderedLiteral` check covers it instead. `strict` isn't
63
+ * needed here at all now — it's accepted purely for interface
64
+ * consistency with the base class.
65
+ */
66
+ _isMultiWordText(options: ToCDNOptions | undefined, _strict?: boolean, _path?: readonly unknown[]): boolean;
51
67
  _encodeTo(writer: CborWriter, _options?: ToCBOROptions): void;
52
- _toCDN(options: ToCDNOptions | undefined, _depth: number): string;
68
+ _toCDN(options: ToCDNOptions | undefined, _depth: number, _path?: readonly unknown[]): string;
53
69
  _toJS(_options?: ToJSOptions): unknown;
54
70
  }
@@ -2,7 +2,7 @@ import { ToCDNOptions, ToJSOptions, ToCBOROptions } from '../types';
2
2
  import { CborItem, AnnotatedLine } from './CborItem';
3
3
  import { CborWriter, EncodingWidth } from '../cbor/encode';
4
4
  /**
5
- * CBOR Sequence Literal (§2.5.6) — `<<item, item, ...>>`.
5
+ * CBOR Sequence Literal (§2.3.4) — `<<item, item, ...>>`.
6
6
  *
7
7
  * Encodes as a definite-length byte string whose value is the concatenation
8
8
  * of the CBOR encodings of the contained items.
@@ -21,7 +21,7 @@ export declare class CborEmbeddedCBOR extends CborItem {
21
21
  /** The raw concatenated CBOR bytes of all contained items. */
22
22
  private _content;
23
23
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
24
- _toCDN(options: ToCDNOptions | undefined, depth: number): string;
24
+ _toCDN(options: ToCDNOptions | undefined, depth: number, path?: readonly unknown[]): string;
25
25
  _toHexDump(depth: number, options?: ToCDNOptions): AnnotatedLine[];
26
26
  _toJS(_options?: ToJSOptions): unknown;
27
27
  }
@@ -22,7 +22,7 @@ export declare class CborFloat extends CborItem {
22
22
  /**
23
23
  * Original app-string source (e.g. `float'7e00'`), set by the parser when
24
24
  * this float is the result of a `float'...'` app-string. Used by toCDN()
25
- * to round-trip the literal when `appStrings` is not false.
25
+ * to round-trip the literal when `appPrefix` is not false.
26
26
  */
27
27
  ednSource?: string;
28
28
  /**
@@ -48,6 +48,6 @@ export declare class CborFloat extends CborItem {
48
48
  literalSource?: string;
49
49
  });
50
50
  _encodeTo(writer: CborWriter, _options?: ToCBOROptions): void;
51
- _toCDN(options: ToCDNOptions | undefined, _depth: number): string;
51
+ _toCDN(options: ToCDNOptions | undefined, _depth: number, _path?: readonly unknown[]): string;
52
52
  _toJS(_options?: ToJSOptions): unknown;
53
53
  }
@@ -8,7 +8,31 @@ export declare class CborIndefiniteByteString extends CborItem {
8
8
  readonly chunks: CborByteString[];
9
9
  constructor(chunks: CborByteString[]);
10
10
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
11
- _toCDN(options: ToCDNOptions | undefined, depth: number): string;
11
+ /**
12
+ * True when any chunk's own decoded content, if it renders as bare sqstr
13
+ * text, has two or more words. Reachable when this node is a *direct*
14
+ * entry of another container (`[(_ "two words")]`) — though even then,
15
+ * its own `_toCDN()` already self-disqualifies internally in that case
16
+ * (a multi-word chunk forces a multi-line self-render), which the
17
+ * ordinary "entry's own rendering has a line break" check would catch
18
+ * regardless of what this method answers, so this mostly exists for
19
+ * robustness/consistency with `CborTextString`/`CborByteString` rather
20
+ * than because some case is otherwise unreachable.
21
+ *
22
+ * `CborAppSeqResult`, which wraps this node for results like
23
+ * `ilbs<<...>>`, does *not* delegate to this method — it tokenizes its
24
+ * own rendered output directly instead (`isMultiWordRenderedLiteral`),
25
+ * which is exactly why `ilbs<<h'00'>>` stays an ordinary leaf (checked
26
+ * under the loose rule, matching `<<...>>`) while `[h'00']`/`(_ h'00')`
27
+ * still always disqualify — this method's own `_strict` (always `true`,
28
+ * matching how a chunk renders when this container *is* regenerated
29
+ * directly) plays no part in that distinction anymore, and a byte string
30
+ * chunk's own `_isMultiWordText` doesn't consult `strict` at all
31
+ * regardless (see `CborByteString`'s doc — its "prefixed literal" case
32
+ * was removed there too).
33
+ */
34
+ _isMultiWordText(options: ToCDNOptions | undefined, _strict?: boolean): boolean;
35
+ _toCDN(options: ToCDNOptions | undefined, depth: number, path?: readonly unknown[]): string;
12
36
  _toHexDump(depth: number, options?: ToCDNOptions): AnnotatedLine[];
13
37
  _toJS(_options?: ToJSOptions): unknown;
14
38
  }
@@ -8,7 +8,23 @@ export declare class CborIndefiniteTextString extends CborItem {
8
8
  readonly chunks: CborTextString[];
9
9
  constructor(chunks: CborTextString[]);
10
10
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
11
- _toCDN(options: ToCDNOptions | undefined, depth: number): string;
11
+ /**
12
+ * True when any chunk is multi-word. Reachable when this node is a
13
+ * *direct* entry of another container (`[(_ "two words")]`) — though even
14
+ * then, its own `_toCDN()` already self-disqualifies internally in that
15
+ * case, producing a multi-line self-render that the ordinary "entry's own
16
+ * rendering has a line break" check would catch regardless of what this
17
+ * method answers, so this mostly exists for robustness/consistency with
18
+ * `CborTextString`/`CborByteString` rather than because some case is
19
+ * otherwise unreachable. (`CborAppSeqResult`, which wraps this node for
20
+ * results like `ilts<<...>>`, does *not* delegate to this method — it
21
+ * tokenizes its own rendered output directly instead; see its doc for
22
+ * why that turned out to be necessary.) `_strict` is intentionally
23
+ * unused: a chunk is always CborTextString, whose own word count doesn't
24
+ * depend on it.
25
+ */
26
+ _isMultiWordText(options: ToCDNOptions | undefined, _strict?: boolean): boolean;
27
+ _toCDN(options: ToCDNOptions | undefined, depth: number, path?: readonly unknown[]): string;
12
28
  _toHexDump(depth: number, options?: ToCDNOptions): AnnotatedLine[];
13
29
  _toJS(_options?: ToJSOptions): unknown;
14
30
  }