@cbortech/cbor 0.26.7 → 0.27.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.
Files changed (57) hide show
  1. package/README.ja.md +120 -47
  2. package/README.md +121 -48
  3. package/dist/ast/CborAppSeqResult.d.ts +22 -0
  4. package/dist/ast/CborByteString.d.ts +27 -0
  5. package/dist/ast/CborEmbeddedCBOR.d.ts +1 -1
  6. package/dist/ast/CborFloat.d.ts +1 -1
  7. package/dist/ast/CborIndefiniteByteString.d.ts +24 -0
  8. package/dist/ast/CborIndefiniteTextString.d.ts +16 -0
  9. package/dist/ast/CborItem.d.ts +44 -4
  10. package/dist/ast/CborTag.d.ts +27 -0
  11. package/dist/ast/CborTextString.d.ts +18 -1
  12. package/dist/ast/CborUnresolvedAppExt.d.ts +2 -2
  13. package/dist/ast/index.cjs +1 -1
  14. package/dist/ast/index.d.ts +1 -0
  15. package/dist/ast/index.js +2 -2
  16. package/dist/cddl/index.cjs +1 -1
  17. package/dist/cddl/index.js +1 -1
  18. package/dist/cdn/index.cjs +2 -2
  19. package/dist/cdn/index.cjs.map +1 -1
  20. package/dist/cdn/index.d.ts +2 -0
  21. package/dist/cdn/index.js +15 -15
  22. package/dist/cdn/index.js.map +1 -1
  23. package/dist/cdn/serialize-utils.d.ts +241 -21
  24. package/dist/cdn/tokenizer.d.ts +12 -11
  25. package/dist/extensions/builtins.d.ts +5 -5
  26. package/dist/extensions/cri.d.ts +2 -2
  27. package/dist/extensions/ip.d.ts +1 -1
  28. package/dist/extensions/types.d.ts +4 -4
  29. package/dist/index.cjs +3 -3
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.ts +2 -1
  32. package/dist/index.js +158 -158
  33. package/dist/index.js.map +1 -1
  34. package/dist/mapEntries-C1f7G0AM.cjs +13 -0
  35. package/dist/mapEntries-C1f7G0AM.cjs.map +1 -0
  36. package/dist/{mapEntries-DxrDre2P.js → mapEntries-CvLdiN0h.js} +1479 -1558
  37. package/dist/mapEntries-CvLdiN0h.js.map +1 -0
  38. package/dist/{schema-Bofmsptw.js → schema-CNfrVRYp.js} +294 -294
  39. package/dist/{schema-Bofmsptw.js.map → schema-CNfrVRYp.js.map} +1 -1
  40. package/dist/schema-iXpYtKQl.cjs +63 -0
  41. package/dist/{schema-t_bdPk8_.cjs.map → schema-iXpYtKQl.cjs.map} +1 -1
  42. package/dist/{tokenizer-CeuixxXi.js → serialize-utils-BuIZPaUc.js} +634 -30
  43. package/dist/serialize-utils-BuIZPaUc.js.map +1 -0
  44. package/dist/serialize-utils-CjTqQivB.cjs +37 -0
  45. package/dist/serialize-utils-CjTqQivB.cjs.map +1 -0
  46. package/dist/types.d.ts +248 -64
  47. package/dist/utils/base64.d.ts +1 -1
  48. package/dist/utils/hexfloat.d.ts +1 -1
  49. package/dist/utils/strip-comments.d.ts +1 -1
  50. package/package.json +8 -7
  51. package/dist/mapEntries-D2NyeCX3.cjs +0 -17
  52. package/dist/mapEntries-D2NyeCX3.cjs.map +0 -1
  53. package/dist/mapEntries-DxrDre2P.js.map +0 -1
  54. package/dist/schema-t_bdPk8_.cjs +0 -63
  55. package/dist/tokenizer-CeuixxXi.js.map +0 -1
  56. package/dist/tokenizer-EciPlN0n.cjs +0 -30
  57. package/dist/tokenizer-EciPlN0n.cjs.map +0 -1
package/README.ja.md CHANGED
@@ -330,25 +330,6 @@ CBOR.format('`\\d+`', { preserveRawString: true });
330
330
  // '`\\d+`'
331
331
  ```
332
332
 
333
- ### ダブルクォート文字列の表記を保持する
334
-
335
- デフォルトでは、`CBOR.format()` はダブルクォートのテキスト文字列をデコード後の
336
- 値から再エスケープします。そのため `\uXXXX` エスケープはリテラル文字に変換され
337
- ます。`preserveTextString` を指定すると、連結されていない `"..."` リテラルを
338
- 元のソース表記のまま再出力します。(バッククォートの raw 文字列(`` `...` ``)
339
- はこのオプションではなく `preserveRawString` の対象です。`+` 連結を経由した
340
- 文字列は、このオプションを指定していても通常どおり正規化されます。)
341
-
342
- ```ts
343
- import { CBOR } from '@cbortech/cbor';
344
-
345
- CBOR.format('"caf\\u00e9"');
346
- // '"café"'
347
-
348
- CBOR.format('"caf\\u00e9"', { preserveTextString: true });
349
- // '"caf\\u00e9"'
350
- ```
351
-
352
333
  ### 数値リテラルの表記を保持する
353
334
 
354
335
  デフォルトでは、`CBOR.format()` は整数・浮動小数点数リテラルを正規化します。
@@ -404,18 +385,22 @@ CBOR.format("h'68' + b64'aQ'", {
404
385
  // b64'aQ'
405
386
  ```
406
387
 
407
- ### application-string / -sequence 記法を保持する
388
+ 保持した連結を `+` ではなく draft-27 の `t1<<...>>` / `b1<<...>>` 記法で
389
+ 出力するには、[文字列連結と不定長文字列](#文字列連結と不定長文字列) の
390
+ `modernConcat` を参照してください。
391
+
392
+ ### app-string / -sequence 記法を保持する
408
393
 
409
394
  一部の組み込み拡張(`dt`/`DT`、`ip`/`IP`)は同じ値に対して `prefix'...'`
410
- (application string)、`` prefix`...` ``(backtick application string)、
411
- `prefix<<...>>`(application sequence)、生のタグリテラル(`N(...)`)の
395
+ (app-string)、`` prefix`...` ``(backtick app-string)、
396
+ `prefix<<...>>`(app-sequence)、生のタグリテラル(`N(...)`)の
412
397
  いずれの記法もサポートしていますが、デフォルトでは `CBOR.format()` を呼ぶ
413
398
  たびに解決済みの値から `prefix'...'` を再生成します。そのため
414
399
  `` DT`1969-07-21T02:56:16Z` `` も `DT<<'1969-07-21T02:56:16Z'>>` も、生の
415
400
  タグ記法 `1(1749772800)` さえも、すべて `DT'...'` 記法に正規化され、さら
416
401
  に非正規な `DT'...'` の表記(例えば `Z` の代わりに `+00:00` を使った場合
417
- など)も書き換えられます。`preserveAppSequence` を指定すると、実際に使わ
418
- れていた表記のまま保持します。`appStrings: false` を同時に指定した場合は
402
+ など)も書き換えられます。`preserveAppPrefix` を指定すると、実際に使わ
403
+ れていた表記のまま保持します。`appPrefix: false` を同時に指定した場合は
419
404
  効果がありません(どちらにせよ元の表記に関わらず生のタグ記法になるため)。
420
405
  これらの記法からパースされていない値にも効果はありません。
421
406
 
@@ -425,16 +410,50 @@ import { CBOR } from '@cbortech/cbor';
425
410
  CBOR.format('1(1749772800)');
426
411
  // "DT'2025-06-13T00:00:00Z'"
427
412
 
428
- CBOR.format('1(1749772800)', { preserveAppSequence: true });
413
+ CBOR.format('1(1749772800)', { preserveAppPrefix: true });
429
414
  // "1(1749772800)"
430
415
 
431
- CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppSequence: true });
416
+ CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppPrefix: true });
432
417
  // "DT<<'1969-07-21T02:56:16Z'>>"
433
418
 
434
- CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppSequence: true });
419
+ CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppPrefix: true });
435
420
  // "DT`1969-07-21T02:56:16Z`"
436
421
  ```
437
422
 
423
+ ### コメントを保持する
424
+
425
+ デフォルトでは、`CBOR.fromCDN()` はコメントを破棄し、`CBOR.format()` も
426
+ コメントを出力しません。`preserveComments: true` を指定すると、パース時に
427
+ コメントを取り込み、元々書かれていたマーカー(`#`・`//`・`/* */`・`/ /`)の
428
+ まま再出力します。
429
+
430
+ ```ts
431
+ import { CBOR } from '@cbortech/cbor';
432
+
433
+ const text = '{ "a": 1 } # trailing comment';
434
+
435
+ CBOR.format(text, { indent: 2 });
436
+ // '{\n "a": 1\n}'
437
+
438
+ CBOR.format(text, { indent: 2, preserveComments: true });
439
+ // '{\n "a": 1\n} # trailing comment'
440
+ ```
441
+
442
+ 書かれていたマーカーを混在させたまま保持するのではなく、すべてのコメントの
443
+ マーカーを正規化したい場合は `comments` を使います — `'c-style'` は
444
+ `//` と `/* */`、`'cdn-style'` は `#` と `/ /` に正規化します。
445
+ `preserveComments: true` が指定されている場合は効果がありません(verbatim
446
+ が優先されます)。コメントを完全に削除するには `comments: 'strip'` を
447
+ 明示的に指定するか(あるいは両方とも未指定のままにするか)します。
448
+
449
+ ```ts
450
+ CBOR.format(text, { indent: 2, comments: 'c-style' });
451
+ // '{\n "a": 1\n} // trailing comment'
452
+ ```
453
+
454
+ `indent` を指定して整形出力する場合のみ効果があります。1 行出力では改行で
455
+ 終端する必要がある行コメントの性質上、コメントは常に取り除かれます。
456
+
438
457
  ### 空行を保持する
439
458
 
440
459
  デフォルトでは、`CBOR.format()` は配列・マップの要素間(および `(_ ...)`
@@ -691,7 +710,7 @@ console.log(text);
691
710
 
692
711
  ## 文字列連結と不定長文字列
693
712
 
694
- draft-ietf-cbor-edn-literals-26(§3.4 / §3.5)の application extension
713
+ draft-ietf-cbor-edn-literals-27(§3.5 / §3.6)の app-extension
695
714
  `t1` / `b1` / `ilbs` / `ilts` は、デフォルトで有効です。
696
715
 
697
716
  `t1<<...>>` と `b1<<...>>` は、(テキストまたはバイト)文字列の引数を左から
@@ -702,11 +721,11 @@ draft-ietf-cbor-edn-literals-26(§3.4 / §3.5)の application extension
702
721
  import { CBOR } from '@cbortech/cbor';
703
722
 
704
723
  const text = CBOR.fromCDN('t1<<"Hello ", "world">>');
705
- console.log(text.toCDN({ appStrings: false }));
724
+ console.log(text.toCDN({ appPrefix: false }));
706
725
  // "Hello world"
707
726
 
708
727
  const bytes = CBOR.fromCDN("b1<<'Hello ', h'776f726c64'>>");
709
- console.log(bytes.toCDN({ appStrings: false }));
728
+ console.log(bytes.toCDN({ appPrefix: false }));
710
729
  // 'Hello world'
711
730
  ```
712
731
 
@@ -720,29 +739,82 @@ streamstring 構文の置き換えですが、本ライブラリは従来構文
720
739
  import { CBOR } from '@cbortech/cbor';
721
740
 
722
741
  const v = CBOR.fromCDN("ilbs<<'Hello ', 'world'>>");
723
- console.log(v.toCDN({ appStrings: false }));
742
+ console.log(v.toCDN({ appPrefix: false }));
724
743
  // (_ 'Hello ','world')
725
744
  ```
726
745
 
746
+ ### `t1`/`b1`/`ilbs`/`ilts` 記法を出力する
747
+
748
+ パース側はすでに `t1`/`b1`/`ilbs`/`ilts` 記法を受理しますが、`toCDN()` /
749
+ `CBOR.format()` はデフォルトではこれらを自ら出力しません。保持した連結
750
+ (`preserveConcatenation`)は従来どおり `+` で、不定長文字列は従来どおり
751
+ `(_ ...)` streamstring 形式でレンダリングされます。`modernConcat` と
752
+ `modernStreamSyntax` を `true` にすると draft-27 の記法での出力を選択でき
753
+ ます。どちらもデフォルトは `false`(従来構文)で、`appPrefix` が `false`
754
+ の場合は従来構文にフォールバックします。
755
+
756
+ ```ts
757
+ import { CBOR } from '@cbortech/cbor';
758
+
759
+ CBOR.format('"a" + "b"', {
760
+ indent: 2,
761
+ preserveConcatenation: true,
762
+ modernConcat: true,
763
+ });
764
+ // t1<<"a", "b">>
765
+
766
+ CBOR.format('(_ "a", "b")', { modernStreamSyntax: true });
767
+ // ilts<<"a","b">>
768
+ ```
769
+
770
+ `modernConcat` は `...` による省略連結(§5.2)にも適用され、
771
+ `"a" + ... + "b"` は `t1<<"a", ..., "b">>` としてレンダリングされます。
772
+ 通常の連結と異なり、これは `preserveConcatenation` の値に関わらず適用され
773
+ ます — 省略連結にはそもそも1つのリテラルに畳み込んだ状態が存在しないため
774
+ です。
775
+
776
+ > [!NOTE]
777
+ > どちらのオプションも `t1`/`b1`/`ilbs`/`ilts` のソースを従来記法に
778
+ > 変換するものではありません。`t1<<...>>`(や `ilbs<<...>>` など)
779
+ > からパースされた値は、`appPrefix` が `false` でなく、
780
+ > `encodingIndicators` が `'auto'`(どちらもデフォルト)であり、かつ
781
+ > ソースが単一行、または `indent` 指定時であれば、`modernConcat` /
782
+ > `modernStreamSyntax` の値に関わらずそのままの記法で出力されます。
783
+ > `encodingIndicators: 'always'`/`'never'` や `appPrefix: false` を指定
784
+ > した場合は、他の app-string 値と同様に正規化されます(例:
785
+ > `encodingIndicators: 'always'` では `t1<<"a", "b">>` が `"ab"_i` に
786
+ > なります)。また、複数行のソースは `indent` 未指定(1行出力)の場合、
787
+ > そのレイアウトを再現できないため正規化されます:
788
+ >
789
+ > ```ts
790
+ > CBOR.format('t1<<\n "a",\n "b"\n>>');
791
+ > // '"ab"' — indent未指定のため正規化される
792
+ > CBOR.format('t1<<\n "a",\n "b"\n>>', { indent: 2 });
793
+ > // 't1<<\n "a",\n "b"\n>>' — そのまま保持される
794
+ > ```
795
+ >
796
+ > 両オプションが影響するのは `+` チェーンや `(_ ...)` チャンク列から
797
+ > 再構築された値の出力のみです。
798
+
727
799
  > [!NOTE]
728
- > `t1` / `b1` という識別子は draft-26 で暫定(provisional)と明記されて
800
+ > `t1` / `b1` という識別子は draft-27 でも暫定(provisional)と明記されて
729
801
  > おり、CBOR ワーキンググループにより改名される可能性があります。
730
802
 
731
803
  ## float
732
804
 
733
805
  16 進数のビットパターンを IEEE 754 浮動小数点値として解釈します
734
- (draft-ietf-cbor-edn-literals-26 §3.7)。デフォルトで有効です。
806
+ (draft-ietf-cbor-edn-literals-27 §3.8)。デフォルトで有効です。
735
807
 
736
808
  ```ts
737
809
  import { CBOR } from '@cbortech/cbor';
738
810
 
739
811
  const v = CBOR.fromCDN("float'7e00'");
740
- console.log(v.toCDN({ appStrings: false }));
812
+ console.log(v.toCDN({ appPrefix: false }));
741
813
  // NaN
742
814
 
743
815
  // バイト列から解釈する場合
744
816
  const v2 = CBOR.fromCDN("float<<h'3f800000'>>");
745
- console.log(v2.toCDN({ appStrings: false }));
817
+ console.log(v2.toCDN({ appPrefix: false }));
746
818
  // 1.0_2
747
819
  ```
748
820
 
@@ -755,7 +827,7 @@ extension があります。必要なものを `import` し、
755
827
  ### b32 / h32
756
828
 
757
829
  [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648) の Base32 エンコードによるバイト列リテラルです。
758
- [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) §8 に記載があり、[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/) でも触れられています。
830
+ [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) §8 に記載があり、[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/) でも触れられています。
759
831
 
760
832
  - `b32` — §6 Base32(`A–Z 2–7` アルファベット)
761
833
  - `h32` — §7 Base32Hex(`0–9 A–V` アルファベット)
@@ -764,11 +836,11 @@ extension があります。必要なものを `import` し、
764
836
  import { CBOR, b32, h32 } from '@cbortech/cbor';
765
837
 
766
838
  const v1 = CBOR.fromCDN("b32'AEBAGBA'", { extensions: [b32] });
767
- console.log(v1.toCDN({ appStrings: false }));
839
+ console.log(v1.toCDN({ appPrefix: false }));
768
840
  // h'01020304'
769
841
 
770
842
  const v2 = CBOR.fromCDN("h32'00P00'", { extensions: [h32] });
771
- console.log(v2.toCDN({ appStrings: false }));
843
+ console.log(v2.toCDN({ appPrefix: false }));
772
844
  // h'003200'
773
845
  ```
774
846
 
@@ -782,25 +854,24 @@ console.log(v2.toCDN({ appStrings: false }));
782
854
  ```ts
783
855
  import { CBOR, same } from '@cbortech/cbor';
784
856
 
785
- // すべての要素が同じバイト列かを検証し、最初の要素を返す
786
857
  const v = CBOR.fromCDN("same<<h'0102', h'0102'>>", { extensions: [same] });
787
- console.log(v.toCDN({ appStrings: false }));
858
+ console.log(v.toCDN({ appPrefix: false }));
788
859
  // h'0102'
789
860
 
790
861
  // 要素が 1 つでも有効(常にパスする)
791
862
  const v2 = CBOR.fromCDN('same<<42>>', { extensions: [same] });
792
- console.log(v2.toCDN({ appStrings: false }));
863
+ console.log(v2.toCDN({ appPrefix: false }));
793
864
  // 42
794
865
  ```
795
866
 
796
867
  ---
797
868
 
798
- 追加の application extension は別パッケージとして公開されています。必要なものを
869
+ 追加の app-extension は別パッケージとして公開されています。必要なものを
799
870
  インストールし、`extensions` オプションに渡して使います。
800
871
 
801
872
  ### hash
802
873
 
803
- `hash` は [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/) §3.3 で定義された標準の application extension です。
874
+ `hash` は [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/) §3.4 で定義された標準の app-extension です。
804
875
  ハッシュアルゴリズムと値を `hash'algorithm:value'` の形式で表現します。
805
876
  実装には外部の暗号ライブラリが必要なため、[@cbortech/hash-extension](https://www.npmjs.com/package/@cbortech/hash-extension) として
806
877
  別パッケージで提供しています。
@@ -825,7 +896,7 @@ const digest = cbor.parse(
825
896
 
826
897
  ### uuid
827
898
 
828
- `uuid` はこのライブラリ独自の application extension です。
899
+ `uuid` はこのライブラリ独自の app-extension です。
829
900
  [@cbortech/uuid-extension](https://www.npmjs.com/package/@cbortech/uuid-extension) として別パッケージで提供しています。
830
901
 
831
902
  ```bash
@@ -845,7 +916,7 @@ const id = cbor.parse("uuid'550e8400-e29b-41d4-a716-446655440000'");
845
916
  ### set / map
846
917
 
847
918
  `SET` と `MAP` は、タグ付きの Set / Map 値を扱うための、このライブラリ独自の
848
- application extension です。
919
+ app-extension です。
849
920
  [@cbortech/set-map-extensions](https://www.npmjs.com/package/@cbortech/set-map-extensions)
850
921
  としてまとめて別パッケージで提供しています。`SET<<[...]>>` は配列に CBOR tag
851
922
  258 を付けた値、`MAP<<{...}>>` は map に CBOR tag 259 を付けた値を生成します。
@@ -1102,9 +1173,11 @@ CDDL コンパイラは `@cbortech/cbor/cddl`
1102
1173
 
1103
1174
  - CBOR
1104
1175
  - [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)
1176
+ - CBOR Sequences
1177
+ - [RFC 8742](https://www.rfc-editor.org/rfc/rfc8742)
1105
1178
  - CDN (CBOR-EDN)
1106
1179
  - [draft-ietf-cbor-edn-literals-25](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/)
1107
- - [draft-ietf-cbor-edn-literals-26](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/26/)
1180
+ - [draft-ietf-cbor-edn-literals-27](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/)
1108
1181
  - CDDL
1109
1182
  - [RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)
1110
1183
  - [RFC 9682](https://www.rfc-editor.org/rfc/rfc9682)
@@ -1112,7 +1185,7 @@ CDDL コンパイラは `@cbortech/cbor/cddl`
1112
1185
 
1113
1186
  補足:
1114
1187
 
1115
- - CDN は draft-26 に準拠しつつ、draft-25 の `(_ ...)` streamstring 構文と
1188
+ - CDN は draft-27 に準拠しつつ、draft-25 の `(_ ...)` streamstring 構文と
1116
1189
  `+` による文字列連結構文も引き続きサポートしています。
1117
1190
  - CDDL は RFC 8610 のすべての control operator と、RFC 9165 の `.plus`、
1118
1191
  `.cat`、`.feature` をサポートしています。
package/README.md CHANGED
@@ -336,25 +336,6 @@ CBOR.format('`\\d+`', { preserveRawString: true });
336
336
  // '`\\d+`'
337
337
  ```
338
338
 
339
- ### Preserve double-quoted string spelling
340
-
341
- By default, `CBOR.format()` re-escapes double-quoted text strings from their
342
- decoded value, so e.g. a `\uXXXX` escape becomes the literal character.
343
- `preserveTextString` re-emits a non-concatenated `"..."` literal using its
344
- original source spelling instead. (Raw backtick literals such as `` `...` ``
345
- are covered by `preserveRawString`, not this option; a string reached via
346
- `+` concatenation is normalised as usual regardless of this option.)
347
-
348
- ```ts
349
- import { CBOR } from '@cbortech/cbor';
350
-
351
- CBOR.format('"caf\\u00e9"');
352
- // '"café"'
353
-
354
- CBOR.format('"caf\\u00e9"', { preserveTextString: true });
355
- // '"caf\\u00e9"'
356
- ```
357
-
358
339
  ### Preserve number literal spelling
359
340
 
360
341
  By default, `CBOR.format()` normalizes integer and floating-point literals:
@@ -411,19 +392,23 @@ CBOR.format("h'68' + b64'aQ'", {
411
392
  // b64'aQ'
412
393
  ```
413
394
 
414
- ### 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
415
400
 
416
401
  Some built-in extensions (`dt`/`DT`, `ip`/`IP`) support `prefix'...'`
417
- (application string), `` prefix`...` `` (backtick application string),
418
- `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(...)`)
419
404
  notation for the same value, and by default regenerate `prefix'...'` from
420
405
  the resolved value on every `CBOR.format()` call — so
421
406
  `` DT`1969-07-21T02:56:16Z` ``, `DT<<'1969-07-21T02:56:16Z'>>`, and even the
422
407
  raw tag form `1(1749772800)` all normalize to `DT'...'` notation, and a
423
408
  non-canonical `DT'...'` spelling (e.g. a `+00:00` offset instead of `Z`)
424
- gets rewritten too. `preserveAppSequence` keeps the original spelling
409
+ gets rewritten too. `preserveAppPrefix` keeps the original spelling
425
410
  instead — whichever form was used. It has no effect when
426
- `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
427
412
  regardless of the original spelling), or on values not parsed from one of
428
413
  these forms.
429
414
 
@@ -433,16 +418,50 @@ import { CBOR } from '@cbortech/cbor';
433
418
  CBOR.format('1(1749772800)');
434
419
  // "DT'2025-06-13T00:00:00Z'"
435
420
 
436
- CBOR.format('1(1749772800)', { preserveAppSequence: true });
421
+ CBOR.format('1(1749772800)', { preserveAppPrefix: true });
437
422
  // "1(1749772800)"
438
423
 
439
- CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppSequence: true });
424
+ CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppPrefix: true });
440
425
  // "DT<<'1969-07-21T02:56:16Z'>>"
441
426
 
442
- CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppSequence: true });
427
+ CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppPrefix: true });
443
428
  // "DT`1969-07-21T02:56:16Z`"
444
429
  ```
445
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
+
446
465
  ### Preserve blank lines
447
466
 
448
467
  By default, `CBOR.format()` drops blank lines between array/map entries (and
@@ -702,8 +721,8 @@ console.log(text);
702
721
 
703
722
  ## String Concatenation and Indefinite-Length Strings
704
723
 
705
- The `t1` / `b1` / `ilbs` / `ilts` application extensions from
706
- draft-ietf-cbor-edn-literals-26 (§3.4 / §3.5) are enabled by default.
724
+ The `t1` / `b1` / `ilbs` / `ilts` app-extensions from
725
+ draft-ietf-cbor-edn-literals-27 (§3.5 / §3.6) are enabled by default.
707
726
 
708
727
  `t1<<...>>` and `b1<<...>>` join (text or byte) string arguments from left to
709
728
  right into a single text string (`t1`) or byte string (`b1`). Arguments may
@@ -713,11 +732,11 @@ also be ellipses (`...`) to elide parts of a string.
713
732
  import { CBOR } from '@cbortech/cbor';
714
733
 
715
734
  const text = CBOR.fromCDN('t1<<"Hello ", "world">>');
716
- console.log(text.toCDN({ appStrings: false }));
735
+ console.log(text.toCDN({ appPrefix: false }));
717
736
  // "Hello world"
718
737
 
719
738
  const bytes = CBOR.fromCDN("b1<<'Hello ', h'776f726c64'>>");
720
- console.log(bytes.toCDN({ appStrings: false }));
739
+ console.log(bytes.toCDN({ appPrefix: false }));
721
740
  // 'Hello world'
722
741
  ```
723
742
 
@@ -730,29 +749,81 @@ documents; this library keeps accepting the legacy syntax on input.
730
749
  import { CBOR } from '@cbortech/cbor';
731
750
 
732
751
  const v = CBOR.fromCDN("ilbs<<'Hello ', 'world'>>");
733
- console.log(v.toCDN({ appStrings: false }));
752
+ console.log(v.toCDN({ appPrefix: false }));
734
753
  // (_ 'Hello ','world')
735
754
  ```
736
755
 
756
+ ### Emitting `t1`/`b1`/`ilbs`/`ilts` notation
757
+
758
+ Parsing already accepts `t1`/`b1`/`ilbs`/`ilts` notation, but by default
759
+ `toCDN()`/`CBOR.format()` never emit it on their own: a preserved
760
+ concatenation (`preserveConcatenation`) still renders as `+`, and an
761
+ indefinite-length string still renders as the legacy `(_ ...)` streamstring
762
+ form. `modernConcat` and `modernStreamSyntax` opt into emitting the draft-27
763
+ notation instead — both default to `false` (the legacy syntax), and both fall
764
+ back to it when `appPrefix` is `false`.
765
+
766
+ ```ts
767
+ import { CBOR } from '@cbortech/cbor';
768
+
769
+ CBOR.format('"a" + "b"', {
770
+ indent: 2,
771
+ preserveConcatenation: true,
772
+ modernConcat: true,
773
+ });
774
+ // t1<<"a", "b">>
775
+
776
+ CBOR.format('(_ "a", "b")', { modernStreamSyntax: true });
777
+ // ilts<<"a","b">>
778
+ ```
779
+
780
+ `modernConcat` also applies within a `...` elision chain (§5.2), rendering
781
+ `"a" + ... + "b"` as `t1<<"a", ..., "b">>` — unlike plain concatenation, this
782
+ happens regardless of `preserveConcatenation`, since an elision chain has no
783
+ single-literal collapsed form to fall back to in the first place.
784
+
785
+ > [!NOTE]
786
+ > Neither option converts `t1`/`b1`/`ilbs`/`ilts` source back to the
787
+ > legacy notation: a value parsed from `t1<<...>>` (or `ilbs<<...>>`, etc.)
788
+ > keeps that exact spelling on output regardless of `modernConcat` /
789
+ > `modernStreamSyntax` — as long as `appPrefix` is not `false`,
790
+ > `encodingIndicators` is `'auto'` (both defaults), and the source is either
791
+ > single-line or being rendered with `indent` enabled. `encodingIndicators:
792
+ 'always'`/`'never'` or `appPrefix: false` still normalize it like any
793
+ > other app-string value (e.g. `t1<<"a", "b">>` becomes `"ab"_i`
794
+ > under `encodingIndicators: 'always'`), and a multi-line source falls back
795
+ > to normalized output in single-line mode (that layout can't be reproduced
796
+ > without `indent`):
797
+ >
798
+ > ```ts
799
+ > CBOR.format('t1<<\n "a",\n "b"\n>>');
800
+ > // '"ab"' — falls back: multi-line source, no `indent`
801
+ > CBOR.format('t1<<\n "a",\n "b"\n>>', { indent: 2 });
802
+ > // 't1<<\n "a",\n "b"\n>>' — kept verbatim
803
+ > ```
804
+ >
805
+ > Both options only affect how a value reconstructed from a `+` chain or a
806
+ > `(_ ...)` chunk list is _newly_ rendered.
807
+
737
808
  > [!NOTE]
738
- > The identifiers `t1` and `b1` are explicitly provisional in draft-26 and
809
+ > The identifiers `t1` and `b1` are explicitly provisional in draft-27 and
739
810
  > may be renamed by the CBOR working group.
740
811
 
741
812
  ## float
742
813
 
743
814
  Interprets a hex bit-pattern as an IEEE 754 floating-point value
744
- (draft-ietf-cbor-edn-literals-26 §3.7). Enabled by default.
815
+ (draft-ietf-cbor-edn-literals-27 §3.8). Enabled by default.
745
816
 
746
817
  ```ts
747
818
  import { CBOR } from '@cbortech/cbor';
748
819
 
749
820
  const v = CBOR.fromCDN("float'7e00'");
750
- console.log(v.toCDN({ appStrings: false }));
821
+ console.log(v.toCDN({ appPrefix: false }));
751
822
  // NaN
752
823
 
753
824
  // Interpret bytes as float bits
754
825
  const v2 = CBOR.fromCDN("float<<h'3f800000'>>");
755
- console.log(v2.toCDN({ appStrings: false }));
826
+ console.log(v2.toCDN({ appPrefix: false }));
756
827
  // 1.0_2
757
828
  ```
758
829
 
@@ -766,7 +837,7 @@ default. Import what you need and pass it through the `extensions` option.
766
837
  Byte-string literals using [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648)
767
838
  Base32 encoding. These prefixes are described in §8 of
768
839
  [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) and also mentioned in
769
- [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/).
840
+ [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/).
770
841
 
771
842
  - `b32` — §6 Base32 (`A–Z 2–7` alphabet)
772
843
  - `h32` — §7 Base32Hex (`0–9 A–V` alphabet)
@@ -775,11 +846,11 @@ Base32 encoding. These prefixes are described in §8 of
775
846
  import { CBOR, b32, h32 } from '@cbortech/cbor';
776
847
 
777
848
  const v1 = CBOR.fromCDN("b32'AEBAGBA'", { extensions: [b32] });
778
- console.log(v1.toCDN({ appStrings: false }));
849
+ console.log(v1.toCDN({ appPrefix: false }));
779
850
  // h'01020304'
780
851
 
781
852
  const v2 = CBOR.fromCDN("h32'00P00'", { extensions: [h32] });
782
- console.log(v2.toCDN({ appStrings: false }));
853
+ console.log(v2.toCDN({ appPrefix: false }));
783
854
  // h'003200'
784
855
  ```
785
856
 
@@ -793,24 +864,24 @@ identical CBOR bytes and returns the first item. This extension is described in
793
864
  import { CBOR, same } from '@cbortech/cbor';
794
865
 
795
866
  const v = CBOR.fromCDN("same<<h'0102', h'0102'>>", { extensions: [same] });
796
- console.log(v.toCDN({ appStrings: false }));
867
+ console.log(v.toCDN({ appPrefix: false }));
797
868
  // h'0102'
798
869
 
799
870
  // A single-item sequence always passes
800
871
  const v2 = CBOR.fromCDN('same<<42>>', { extensions: [same] });
801
- console.log(v2.toCDN({ appStrings: false }));
872
+ console.log(v2.toCDN({ appPrefix: false }));
802
873
  // 42
803
874
  ```
804
875
 
805
876
  ---
806
877
 
807
- Additional application extensions are published as separate packages. Install
878
+ Additional app-extensions are published as separate packages. Install
808
879
  the ones you need and pass them through the `extensions` option.
809
880
 
810
881
  ### hash
811
882
 
812
- `hash` is an application extension defined in §3.3 of
813
- [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/).
883
+ `hash` is an app-extension defined in §3.4 of
884
+ [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/).
814
885
  It represents cryptographic hash values in the form `hash'algorithm:value'`.
815
886
  Because it requires an external cryptographic library, it is provided separately
816
887
  as [@cbortech/hash-extension](https://www.npmjs.com/package/@cbortech/hash-extension).
@@ -835,7 +906,7 @@ const digest = cbor.parse(
835
906
 
836
907
  ### uuid
837
908
 
838
- `uuid` is a library-specific application extension, provided separately as
909
+ `uuid` is a library-specific app-extension, provided separately as
839
910
  [@cbortech/uuid-extension](https://www.npmjs.com/package/@cbortech/uuid-extension).
840
911
 
841
912
  ```bash
@@ -854,7 +925,7 @@ const id = cbor.parse("uuid'550e8400-e29b-41d4-a716-446655440000'");
854
925
 
855
926
  ### set / map
856
927
 
857
- `SET` and `MAP` are library-specific application extensions for tagged Set and
928
+ `SET` and `MAP` are library-specific app-extensions for tagged Set and
858
929
  Map values. They are provided together as
859
930
  [@cbortech/set-map-extensions](https://www.npmjs.com/package/@cbortech/set-map-extensions).
860
931
  `SET<<[...]>>` produces CBOR tag 258 over an array, and `MAP<<{...}>>` produces
@@ -1112,9 +1183,11 @@ types).
1112
1183
 
1113
1184
  - CBOR
1114
1185
  - [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)
1186
+ - CBOR Sequences
1187
+ - [RFC 8742](https://www.rfc-editor.org/rfc/rfc8742)
1115
1188
  - CDN (CBOR-EDN)
1116
1189
  - [draft-ietf-cbor-edn-literals-25](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/)
1117
- - [draft-ietf-cbor-edn-literals-26](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/26/)
1190
+ - [draft-ietf-cbor-edn-literals-27](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/)
1118
1191
  - CDDL
1119
1192
  - [RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)
1120
1193
  - [RFC 9682](https://www.rfc-editor.org/rfc/rfc9682)
@@ -1122,7 +1195,7 @@ types).
1122
1195
 
1123
1196
  Implementation notes:
1124
1197
 
1125
- - CDN follows draft-26 while retaining draft-25's `(_ ...)` streamstring syntax
1198
+ - CDN follows draft-27 while retaining draft-25's `(_ ...)` streamstring syntax
1126
1199
  and `+` string-concatenation syntax.
1127
1200
  - CDDL implements every RFC 8610 control operator, plus RFC 9165's `.plus`,
1128
1201
  `.cat`, and `.feature`.
@@ -21,6 +21,28 @@ export declare class CborAppSeqResult extends CborItem {
21
21
  readonly ednSource: string;
22
22
  constructor(inner: CborItem, ednSource: string);
23
23
  get _containsCdnContainer(): boolean;
24
+ /**
25
+ * Same approach as `CborTag`: tokenize this wrapper's own `_toCDN()`
26
+ * output rather than delegating to `this.inner._isMultiWordText()`.
27
+ * Delegating to `this.inner` was tried and found wrong: for
28
+ * `ilbs<<h'68656c6c6f20776f726c64'>>`, the chunk's raw bytes decode to
29
+ * printable "hello world", so `this.inner`'s own semantic check reports
30
+ * it as multi-word — but the *actual* rendering is the preserved
31
+ * `ilbs<<...>>` app-sequence spelling, where that chunk appears as a
32
+ * `h'...'` literal, never as decoded text; the semantic prediction and
33
+ * the real output disagree. Tokenizing `this._toCDN()` directly sees
34
+ * whichever one actually happens: the preserved `ednSource` verbatim
35
+ * (`isMultiWordRenderedLiteral` peels the `prefix<<...>>` wrapper and
36
+ * checks each item under the loose rule, same as `<<...>>` — a
37
+ * multi-word text item like `ilts<<"two words">>` still always counts,
38
+ * a prefixed-literal item like `ilbs<<h'00'>>` does not) or, in the
39
+ * 'always'/'never' `encodingIndicators` modes, a pure passthrough to
40
+ * `this.inner._toCDN()` with no extra wrapping (any node needing that to
41
+ * be caught, like a self-disqualifying `CborIndefiniteByteString`, has
42
+ * already produced a `\n` in that string, which the caller's own
43
+ * `s.includes('\n')` check picks up independently either way).
44
+ */
45
+ _isMultiWordText(options: ToCDNOptions | undefined, strict?: boolean): boolean;
24
46
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
25
47
  _toCDN(options: ToCDNOptions | undefined, depth: number): string;
26
48
  _toJS(options?: ToJSOptions): unknown;