@cbortech/cbor 0.26.6 → 0.26.7

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 (35) hide show
  1. package/README.ja.md +144 -0
  2. package/README.md +143 -0
  3. package/dist/ast/CborByteString.d.ts +14 -0
  4. package/dist/ast/CborEllipsis.d.ts +94 -2
  5. package/dist/ast/CborFloat.d.ts +10 -0
  6. package/dist/ast/CborItem.d.ts +93 -4
  7. package/dist/ast/CborNint.d.ts +9 -0
  8. package/dist/ast/CborSimple.d.ts +11 -2
  9. package/dist/ast/CborTag.d.ts +8 -0
  10. package/dist/ast/CborTextString.d.ts +20 -0
  11. package/dist/ast/CborUint.d.ts +8 -0
  12. package/dist/ast/index.cjs +1 -1
  13. package/dist/ast/index.js +2 -2
  14. package/dist/cddl/index.cjs +1 -1
  15. package/dist/cddl/index.js +1 -1
  16. package/dist/cdn/serialize-utils.d.ts +186 -8
  17. package/dist/extensions/dt.d.ts +3 -0
  18. package/dist/extensions/types.d.ts +31 -9
  19. package/dist/index.cjs +6 -6
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +61 -98
  22. package/dist/index.js.map +1 -1
  23. package/dist/mapEntries-D2NyeCX3.cjs +17 -0
  24. package/dist/mapEntries-D2NyeCX3.cjs.map +1 -0
  25. package/dist/{mapEntries-Czxt-cmd.js → mapEntries-DxrDre2P.js} +1461 -959
  26. package/dist/mapEntries-DxrDre2P.js.map +1 -0
  27. package/dist/{schema-BxkgvUY6.js → schema-Bofmsptw.js} +247 -247
  28. package/dist/{schema-BxkgvUY6.js.map → schema-Bofmsptw.js.map} +1 -1
  29. package/dist/{schema-BmGsaEaW.cjs → schema-t_bdPk8_.cjs} +5 -5
  30. package/dist/{schema-BmGsaEaW.cjs.map → schema-t_bdPk8_.cjs.map} +1 -1
  31. package/dist/types.d.ts +169 -7
  32. package/package.json +2 -2
  33. package/dist/mapEntries-BhMlCwYo.cjs +0 -15
  34. package/dist/mapEntries-BhMlCwYo.cjs.map +0 -1
  35. package/dist/mapEntries-Czxt-cmd.js.map +0 -1
package/README.ja.md CHANGED
@@ -330,6 +330,46 @@ 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
+ ### 数値リテラルの表記を保持する
353
+
354
+ デフォルトでは、`CBOR.format()` は整数・浮動小数点数リテラルを正規化します。
355
+ 16進数・8進数・2進数の整数(`0xff`、`0o377`、`0b101`)は10進数に変換され、
356
+ 末尾のゼロや冗長なエンコーディング指標のサフィックス(`1.50`、`1.5_1`)は
357
+ 省略されます。`preserveNumberFormat` を指定すると、これらのリテラルを元の
358
+ CDN ソース表記のまま再出力します。`intFormat` / `floatFormat` より優先され
359
+ ます。CDN テキストからパースされたリテラルにのみ効果があり、`CBOR.from()`
360
+ で構築した値や CBOR バイト列からデコードした値には効果がありません(通常
361
+ どおりの整形になります)。
362
+
363
+ ```ts
364
+ import { CBOR } from '@cbortech/cbor';
365
+
366
+ CBOR.format('{"a": 0xff, "b": 1.50}');
367
+ // '{"a":255,"b":1.5}'
368
+
369
+ CBOR.format('{"a": 0xff, "b": 1.50}', { preserveNumberFormat: true });
370
+ // '{"a":0xff,"b":1.50}'
371
+ ```
372
+
333
373
  ### `+` による文字列連結を保持する
334
374
 
335
375
  注意: `+` による文字列連結構文は draft-26 で削除されました。この節は legacy
@@ -364,6 +404,110 @@ CBOR.format("h'68' + b64'aQ'", {
364
404
  // b64'aQ'
365
405
  ```
366
406
 
407
+ ### application-string / -sequence 記法を保持する
408
+
409
+ 一部の組み込み拡張(`dt`/`DT`、`ip`/`IP`)は同じ値に対して `prefix'...'`
410
+ (application string)、`` prefix`...` ``(backtick application string)、
411
+ `prefix<<...>>`(application sequence)、生のタグリテラル(`N(...)`)の
412
+ いずれの記法もサポートしていますが、デフォルトでは `CBOR.format()` を呼ぶ
413
+ たびに解決済みの値から `prefix'...'` を再生成します。そのため
414
+ `` DT`1969-07-21T02:56:16Z` `` も `DT<<'1969-07-21T02:56:16Z'>>` も、生の
415
+ タグ記法 `1(1749772800)` さえも、すべて `DT'...'` 記法に正規化され、さら
416
+ に非正規な `DT'...'` の表記(例えば `Z` の代わりに `+00:00` を使った場合
417
+ など)も書き換えられます。`preserveAppSequence` を指定すると、実際に使わ
418
+ れていた表記のまま保持します。`appStrings: false` を同時に指定した場合は
419
+ 効果がありません(どちらにせよ元の表記に関わらず生のタグ記法になるため)。
420
+ これらの記法からパースされていない値にも効果はありません。
421
+
422
+ ```ts
423
+ import { CBOR } from '@cbortech/cbor';
424
+
425
+ CBOR.format('1(1749772800)');
426
+ // "DT'2025-06-13T00:00:00Z'"
427
+
428
+ CBOR.format('1(1749772800)', { preserveAppSequence: true });
429
+ // "1(1749772800)"
430
+
431
+ CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppSequence: true });
432
+ // "DT<<'1969-07-21T02:56:16Z'>>"
433
+
434
+ CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppSequence: true });
435
+ // "DT`1969-07-21T02:56:16Z`"
436
+ ```
437
+
438
+ ### 空行を保持する
439
+
440
+ デフォルトでは、`CBOR.format()` は配列・マップの要素間(および `(_ ...)`
441
+ のチャンク間)の空行を再シリアライズ時に取り除きます。`preserveBlankLines`
442
+ を指定すると、元のソースでその要素の前のどこかに空行があった場合、要素の
443
+ 直前に空行を 1 行だけ再出力します。要素をパラグラフのようにまとめる元の
444
+ 見た目を、フォーマット後も保てます。元の空行が何行連続していても、出力
445
+ されるのは常に 1 行だけです。判定は要素の位置だけに基づいており、
446
+ `preserveComments` は不要で、コメントを出力するかどうかにも影響されません。
447
+ `indent` を指定して整形出力する場合のみ効果があり、空行を保持する
448
+ コンテナは `inlineLeafContainers` が有効でも常に 1 要素 1 行で出力されます。
449
+ `preserveAll` にも含まれます。
450
+
451
+ ```ts
452
+ import { CBOR } from '@cbortech/cbor';
453
+
454
+ const src = `[
455
+ 1,
456
+ 2,
457
+
458
+ 3
459
+ ]`;
460
+
461
+ CBOR.format(src, { indent: 2 });
462
+ // [
463
+ // 1,
464
+ // 2,
465
+ // 3
466
+ // ]
467
+
468
+ CBOR.format(src, { indent: 2, preserveBlankLines: true });
469
+ // [
470
+ // 1,
471
+ // 2,
472
+ //
473
+ // 3
474
+ // ]
475
+ ```
476
+
477
+ ### 変更を最小限にとどめてフォーマットする
478
+
479
+ `preserveAll` を指定すると、すべての `preserve*` 系オプションが一括で
480
+ 有効になります。たとえばエディタの保存時フォーマットのように、空白・
481
+ インデントだけを変更し、ほとんどのリテラルの元の表記には手を加えずに
482
+ CDN テキストを整形できます(bignum だけは例外です。上記の
483
+ `preserveNumberFormat` の説明を参照してください)。個別のオプションを
484
+ 明示的に指定した場合(`false` も含む)は、そちらが `preserveAll` より
485
+ 優先されます。
486
+
487
+ ```ts
488
+ import { CBOR } from '@cbortech/cbor';
489
+
490
+ CBOR.format('{"a":0xff,"b":1.5_1,"c":b64\'aGk=\'}', {
491
+ indent: 2,
492
+ preserveAll: true,
493
+ });
494
+ // {
495
+ // "a": 0xff,
496
+ // "b": 1.5_1,
497
+ // "c": b64'aGk='
498
+ // }
499
+ ```
500
+
501
+ `CBOR.format()` は内部で `fromCDN()` と `toCDN()` の両方に同じオプション
502
+ を渡すため、このオプション一つで済みます。両者を別々に呼び出す場合は、
503
+ コメントはパース時に取り込んでおく必要があるため、`fromCDN()` 側にも
504
+ `preserveAll`(または `preserveComments`)を指定してください。
505
+
506
+ ```ts
507
+ const item = CBOR.fromCDN(text, { preserveAll: true });
508
+ item.toCDN({ preserveAll: true, indent: 2 });
509
+ ```
510
+
367
511
  ### CBOR / CDN / hex dump のバリデーション
368
512
 
369
513
  `validate` は入力の well-formedness と validity を、例外を投げずにチェックします。
package/README.md CHANGED
@@ -336,6 +336,45 @@ 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
+ ### Preserve number literal spelling
359
+
360
+ By default, `CBOR.format()` normalizes integer and floating-point literals:
361
+ hex/octal/binary integers (`0xff`, `0o377`, `0b101`) become decimal, trailing
362
+ zeros and redundant encoding-indicator suffixes (`1.50`, `1.5_1`) are
363
+ dropped. `preserveNumberFormat` re-emits these literals using their original
364
+ CDN source spelling instead, taking precedence over `intFormat` /
365
+ `floatFormat`. It only affects literals parsed from CDN text — values built
366
+ with `CBOR.from()` or decoded from CBOR bytes always use normal formatting.
367
+
368
+ ```ts
369
+ import { CBOR } from '@cbortech/cbor';
370
+
371
+ CBOR.format('{"a": 0xff, "b": 1.50}');
372
+ // '{"a":255,"b":1.5}'
373
+
374
+ CBOR.format('{"a": 0xff, "b": 1.50}', { preserveNumberFormat: true });
375
+ // '{"a":0xff,"b":1.50}'
376
+ ```
377
+
339
378
  ### Preserve `+` string concatenation
340
379
 
341
380
  Note: `+` string concatenation was removed in draft-26. This section is for
@@ -372,6 +411,110 @@ CBOR.format("h'68' + b64'aQ'", {
372
411
  // b64'aQ'
373
412
  ```
374
413
 
414
+ ### Preserve application-string/-sequence notation
415
+
416
+ 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(...)`)
419
+ notation for the same value, and by default regenerate `prefix'...'` from
420
+ the resolved value on every `CBOR.format()` call — so
421
+ `` DT`1969-07-21T02:56:16Z` ``, `DT<<'1969-07-21T02:56:16Z'>>`, and even the
422
+ raw tag form `1(1749772800)` all normalize to `DT'...'` notation, and a
423
+ non-canonical `DT'...'` spelling (e.g. a `+00:00` offset instead of `Z`)
424
+ gets rewritten too. `preserveAppSequence` keeps the original spelling
425
+ instead — whichever form was used. It has no effect when
426
+ `appStrings: false` is also set (raw tag notation is used either way
427
+ regardless of the original spelling), or on values not parsed from one of
428
+ these forms.
429
+
430
+ ```ts
431
+ import { CBOR } from '@cbortech/cbor';
432
+
433
+ CBOR.format('1(1749772800)');
434
+ // "DT'2025-06-13T00:00:00Z'"
435
+
436
+ CBOR.format('1(1749772800)', { preserveAppSequence: true });
437
+ // "1(1749772800)"
438
+
439
+ CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppSequence: true });
440
+ // "DT<<'1969-07-21T02:56:16Z'>>"
441
+
442
+ CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppSequence: true });
443
+ // "DT`1969-07-21T02:56:16Z`"
444
+ ```
445
+
446
+ ### Preserve blank lines
447
+
448
+ By default, `CBOR.format()` drops blank lines between array/map entries (and
449
+ `(_ ...)` chunks) when re-serializing. `preserveBlankLines` re-emits a single
450
+ blank line above an entry that had one anywhere before it in the source, so
451
+ paragraph-like groupings of entries survive a reformat — at most one blank
452
+ line per gap, regardless of how many were originally there. Detection is
453
+ based on entry positions alone: it does not require `preserveComments` and is
454
+ unaffected by whether comments are emitted. Only effective when `indent`
455
+ enables pretty-printing; a container with a preserved blank line is always
456
+ rendered one entry per line, even under `inlineLeafContainers`. Included in
457
+ `preserveAll`.
458
+
459
+ ```ts
460
+ import { CBOR } from '@cbortech/cbor';
461
+
462
+ const src = `[
463
+ 1,
464
+ 2,
465
+
466
+ 3
467
+ ]`;
468
+
469
+ CBOR.format(src, { indent: 2 });
470
+ // [
471
+ // 1,
472
+ // 2,
473
+ // 3
474
+ // ]
475
+
476
+ CBOR.format(src, { indent: 2, preserveBlankLines: true });
477
+ // [
478
+ // 1,
479
+ // 2,
480
+ //
481
+ // 3
482
+ // ]
483
+ ```
484
+
485
+ ### Format with minimal changes
486
+
487
+ `preserveAll` turns on every `preserve*` option at once, to reformat CDN
488
+ text — e.g. when reformatting on save in an editor — touching only
489
+ whitespace/indentation and leaving most literals' original spelling
490
+ untouched (bignums are the one exception; see `preserveNumberFormat`
491
+ above). An explicitly-set individual option (including `false`) still wins
492
+ over `preserveAll`.
493
+
494
+ ```ts
495
+ import { CBOR } from '@cbortech/cbor';
496
+
497
+ CBOR.format('{"a":0xff,"b":1.5_1,"c":b64\'aGk=\'}', {
498
+ indent: 2,
499
+ preserveAll: true,
500
+ });
501
+ // {
502
+ // "a": 0xff,
503
+ // "b": 1.5_1,
504
+ // "c": b64'aGk='
505
+ // }
506
+ ```
507
+
508
+ `CBOR.format()` passes the same options to both `fromCDN()` and `toCDN()`
509
+ internally, so this one option is enough. Calling them separately needs
510
+ `preserveAll` (or `preserveComments`) on the `fromCDN()` side too, since
511
+ comments must be captured while parsing to be re-emittable later:
512
+
513
+ ```ts
514
+ const item = CBOR.fromCDN(text, { preserveAll: true });
515
+ item.toCDN({ preserveAll: true, indent: 2 });
516
+ ```
517
+
375
518
  ### Validate CBOR / CDN / hex dump
376
519
 
377
520
  `validate` checks input for well-formedness and validity without throwing.
@@ -1,11 +1,14 @@
1
1
  import { ToCDNOptions, ToJSOptions, ToCBOROptions } from '../types';
2
2
  import { CborItem } from './CborItem';
3
3
  import { CborWriter, EncodingWidth } from '../cbor/encode';
4
+ import { ByteCommentSyntax } from '../cdn/serialize-utils';
4
5
  /** One part of a byte string parsed from a CDN `+` concatenation chain. */
5
6
  export interface CborByteStringPart {
6
7
  bytes: Uint8Array;
7
8
  /** Original literal source text, when the part came from a byte string token. */
8
9
  source?: string;
10
+ /** Which comment syntax `source` recognizes, if any — see `ednCommentSyntax`. */
11
+ commentSyntax?: ByteCommentSyntax;
9
12
  }
10
13
  /** CBOR Major Type 2 — definite-length byte string. */
11
14
  export declare class CborByteString extends CborItem {
@@ -15,12 +18,23 @@ export declare class CborByteString extends CborItem {
15
18
  readonly ednEncoding: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex';
16
19
  encodingWidth: EncodingWidth | undefined;
17
20
  readonly ednSource: string | undefined;
21
+ /**
22
+ * Which comment syntax `ednSource` recognizes, if any — set once at parse
23
+ * time by whoever actually knows the literal's real origin (see
24
+ * `ByteCommentSyntax`), never re-derived later from its prefix string:
25
+ * a user extension can register under any prefix, including one a
26
+ * built-in (`b32`/`h32`) also uses, so the prefix string alone can't say
27
+ * which comment rules (if any) actually apply. `undefined` when
28
+ * `ednSource` has no comment syntax, or its extension's isn't known.
29
+ */
30
+ readonly ednCommentSyntax: ByteCommentSyntax | undefined;
18
31
  /** Part boundaries of the original `+` concatenation chain, if any. */
19
32
  readonly ednParts: readonly CborByteStringPart[] | undefined;
20
33
  constructor(value: Uint8Array, options?: {
21
34
  ednEncoding?: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex';
22
35
  encodingWidth?: EncodingWidth;
23
36
  ednSource?: string;
37
+ ednCommentSyntax?: ByteCommentSyntax;
24
38
  ednParts?: readonly CborByteStringPart[];
25
39
  });
26
40
  _encodeTo(writer: CborWriter, _options?: ToCBOROptions): void;
@@ -3,9 +3,101 @@ import { CborTag } from './CborTag';
3
3
  import { CborItem } from './CborItem';
4
4
  export declare const CPA888_TAG = 888n;
5
5
  export declare class CborEllipsis extends CborTag {
6
+ /**
7
+ * For the array (string/bytes elision) form: `realBoundary[i]` is `true`
8
+ * when a genuine `+` from the source precedes `items[i]` — as opposed to
9
+ * `items[i]` sitting *inside* a single `h'xx...yy'` literal's own `...`
10
+ * notation (index 0's value is never consulted — there is nothing before
11
+ * the first item). `preserveConcatenation` uses this to show only the
12
+ * real boundaries and fuse everything else, exactly as each source
13
+ * literal was spelled.
14
+ *
15
+ * `undefined` means no boundary information is available at all (e.g.
16
+ * reconstructed from raw CBOR bytes, which carry no notion of "was there
17
+ * a `+` here" to begin with) — `preserveConcatenation` then has no effect,
18
+ * the same as for a value that didn't originate from CDN source.
19
+ */
20
+ readonly realBoundary: readonly boolean[] | undefined;
21
+ /**
22
+ * For a subtree-elision placeholder (`888(null)`, i.e. `content
23
+ * instanceof CborSimple`) that sits *inside* another `CborEllipsis`'s
24
+ * items: `true` when it came from a `h'xx...yy'`-family literal's own
25
+ * `...` notation — even a fully-elided `h'...'` with no hex digits at all
26
+ * — as opposed to a bare standalone `...` token. Only consulted when this
27
+ * placeholder ends up isolated as its own preserved fragment (nothing to
28
+ * fuse it with on either side), to pick the right spelling: `h'...'` vs
29
+ * plain `...`.
30
+ */
31
+ readonly fromByteLiteral: boolean;
32
+ /**
33
+ * When `fromByteLiteral` is `true`: that `h'xx...yy'`-family literal's own
34
+ * raw source text (e.g. `h'AB...CD'` verbatim — case, interior whitespace,
35
+ * and any `/ ... /`/`# ...` comments included), for `preserveByteString`
36
+ * to round-trip instead of re-emitting a freshly lower-cased, comment-free
37
+ * `h'...'` literal. `undefined` when `fromByteLiteral` is `false`.
38
+ */
39
+ readonly literalSource: string | undefined;
6
40
  /** Subtree elision: 888(null) */
7
- constructor();
41
+ constructor(fromByteLiteral?: boolean, literalSource?: string);
8
42
  /** String/bytes elision: 888([items...]) */
9
- constructor(items: CborItem[]);
43
+ constructor(items: CborItem[], realBoundary?: readonly boolean[]);
10
44
  _toCDN(options: ToCDNOptions | undefined, depth: number): string;
45
+ /**
46
+ * `true` when this bytes elision has at least one real `+` boundary
47
+ * somewhere — as opposed to being a single `h'xx...yy'` literal's own
48
+ * `...` notation, which is not "produced by + concatenation" (see
49
+ * `preserveByteString`'s own docs) and so has its spelling preserved by
50
+ * `preserveByteString` alone, the same as a non-elided `h'...'` literal.
51
+ *
52
+ * A real boundary can hide two ways: as `realBoundary[i]` (`i > 0`) on the
53
+ * items array itself, or *inside* a merged `CborByteString` whose
54
+ * `ednParts.length > 1` — two `+`-joined literals that sat next to each
55
+ * other with no ellipsis between them (e.g. `h'AB' + h'CD...EF'`) merge
56
+ * into one item during parsing, so their boundary doesn't show up in
57
+ * `realBoundary` at that item's own index.
58
+ */
59
+ private _hasRealConcatenation;
60
+ /**
61
+ * Render one elision fragment as it should appear under
62
+ * `preserveConcatenation`: a merged multi-part `CborTextString` (see the
63
+ * parser's `currentParts` consolidation) is expanded back into its
64
+ * original `+`-joined literals, single-line, honoring `preserveRawString`
65
+ * per part. Anything else (a single-part fragment, or a nested
66
+ * `CborEllipsis`) renders normally.
67
+ *
68
+ * Only reached for text elision (or anything not shaped like a pure bytes
69
+ * elision, or a bytes elision with no `realBoundary` information) —
70
+ * `_renderPreservedBytesElision` handles the bytes case that has that
71
+ * information, since it needs to see all the fragments together to know
72
+ * which `...`s are real `+`-joined ellipses and which are internal to one
73
+ * `h'...'` literal.
74
+ */
75
+ private _renderFragment;
76
+ /**
77
+ * Re-emit a `888([...])` bytes elision as a single `h'xx...yy'` literal
78
+ * when every item is either a plain `CborByteString` fragment or a
79
+ * subtree-elision placeholder (`888(null)`) — i.e. exactly what
80
+ * `h'xx...yy'` parses into. Returns `undefined` when the items don't
81
+ * match that shape (e.g. text-string elision, or a fragment that isn't a
82
+ * plain byte string), so the caller falls back to the `frag + ... + frag`
83
+ * form.
84
+ */
85
+ private _compactHexElided;
86
+ /**
87
+ * `preserveConcatenation` rendering for a bytes elision. Groups the
88
+ * fragments at every *real* boundary (`realBoundary[i]`) and renders each
89
+ * group as one unit — fusing together whatever sits between real
90
+ * boundaries, including any `h'xx...yy'` literal's own internal `...`
91
+ * (wherever it's positioned — leading, trailing, or in the middle) and
92
+ * the fragments on either side of it, exactly as that literal was
93
+ * written. Within a group, a `CborByteString` that itself merged several
94
+ * `+`-joined literals (`ednParts.length > 1`, always a real boundary
95
+ * internally — see the parser) is further split at each of those parts.
96
+ *
97
+ * Returns `undefined` when there's no `realBoundary` to work from, or an
98
+ * item isn't a plain `CborByteString` or subtree-elision placeholder
99
+ * (e.g. text elision), so the caller falls back to the compact literal or
100
+ * the simpler per-fragment `frag + ... + frag` rendering.
101
+ */
102
+ private _renderPreservedBytesElision;
11
103
  }
@@ -25,6 +25,15 @@ export declare class CborFloat extends CborItem {
25
25
  * to round-trip the literal when `appStrings` is not false.
26
26
  */
27
27
  ednSource?: string;
28
+ /**
29
+ * Original CDN literal source text (e.g. `1.50`, `1.5_1`, `0x1.8p+0_1`),
30
+ * set by the parser when this float came from a plain CDN float literal
31
+ * (as opposed to a `float'...'` app-string, which uses `ednSource`
32
+ * above). Used by `_toCDN()` to round-trip the literal's exact spelling,
33
+ * including its encoding-indicator suffix, when `preserveNumberFormat`
34
+ * is set.
35
+ */
36
+ literalSource?: string;
28
37
  /**
29
38
  * Original encoded payload bytes (big-endian, without the initial byte),
30
39
  * set by the decoder when the value is NaN so that NaN payloads survive a
@@ -36,6 +45,7 @@ export declare class CborFloat extends CborItem {
36
45
  constructor(value: number, options?: {
37
46
  precision?: FloatPrecision;
38
47
  rawBits?: Uint8Array;
48
+ literalSource?: string;
39
49
  });
40
50
  _encodeTo(writer: CborWriter, _options?: ToCBOROptions): void;
41
51
  _toCDN(options: ToCDNOptions | undefined, _depth: number): string;
@@ -1,4 +1,4 @@
1
- import { CBOROptions, ToCDNOptions, ToJSOptions, ToHexDumpOptions, ToCBOROptions, CborComments, DecodeWarning, ParseWarning } from '../types';
1
+ import { CBOROptions, ToCDNOptions, ToJSOptions, ToHexDumpOptions, ToCBOROptions, CborComment, CborComments, DecodeWarning, ParseWarning } from '../types';
2
2
  import { CborWriter } from '../cbor/encode';
3
3
  /** @internal One line of an annotated hex dump. */
4
4
  export interface AnnotatedLine {
@@ -6,6 +6,27 @@ export interface AnnotatedLine {
6
6
  hex: string;
7
7
  comment: string;
8
8
  }
9
+ export interface AppSeqEncodingEdit {
10
+ /** Start/end offsets within appSeqSource of an existing indicator. */
11
+ start: number;
12
+ end: number;
13
+ /** Replacement used by encodingIndicators: 'always'. */
14
+ always: string;
15
+ /** Replacement used by encodingIndicators: 'never'. */
16
+ never: string;
17
+ }
18
+ /**
19
+ * Original literal features used by the sole item inside a preserved
20
+ * `prefix<<item>>` source. They let serialization honour an explicitly
21
+ * disabled sibling `preserve*` option instead of replaying that literal
22
+ * verbatim through `preserveAppSequence`.
23
+ */
24
+ export interface AppSeqSourceFeatures {
25
+ byteString?: boolean;
26
+ textString?: boolean;
27
+ rawString?: boolean;
28
+ concatenation?: boolean;
29
+ }
9
30
  /**
10
31
  * Abstract base class for all CBOR AST nodes.
11
32
  *
@@ -31,6 +52,71 @@ export declare abstract class CborItem {
31
52
  * They do not affect CBOR bytes or JS conversion.
32
53
  */
33
54
  comments?: CborComments;
55
+ /**
56
+ * `true` when this node is an array/map entry (or indefinite-length
57
+ * string chunk) immediately preceded by a blank line in the parsed CDN
58
+ * source — set unconditionally by the parser, regardless of any
59
+ * `preserve*` option, mirroring `start`/`end`. Only consulted by
60
+ * `toCDN()` when `ToCDNOptions.preserveBlankLines` is set; otherwise
61
+ * ignored. Left `undefined` for nodes not parsed as a container entry, or
62
+ * with no blank line before them.
63
+ */
64
+ blankLineBefore?: boolean;
65
+ /**
66
+ * Original application-string/-sequence source text — `prefix'...'`,
67
+ * `` prefix`...` ``, or `prefix<<...>>` — set by the parser when the
68
+ * resolving extension declares `preserveAppSeqSource: 'optional'`. A
69
+ * subclass's own `_toCDN()` override may check this (gated behind
70
+ * `ToCDNOptions.preserveAppSequence`) to round-trip the exact original
71
+ * spelling instead of always regenerating `prefix'...'` notation from the
72
+ * resolved value. Left `undefined` for nodes not parsed from one of these
73
+ * forms.
74
+ */
75
+ appSeqSource?: string;
76
+ /**
77
+ * Comments contained within `appSeqSource`, with `start`/`end` offsets
78
+ * relative to that string. These spans allow comment markers to be
79
+ * converted (or comments to be removed) without regenerating and thereby
80
+ * losing the original application-string/-sequence notation.
81
+ */
82
+ appSeqComments?: CborComment[];
83
+ /**
84
+ * Source edits for encoding indicators contained in a raw-tag
85
+ * `appSeqSource`. Includes zero-width edits where an indicator was absent
86
+ * so `encodingIndicators: 'always'` can insert one without regenerating
87
+ * the surrounding source.
88
+ */
89
+ appSeqEncodingEdits?: AppSeqEncodingEdit[];
90
+ /**
91
+ * `false` when `appSeqEncodingEdits` does not cover every encoding
92
+ * indicator nested inside a raw-tag `appSeqSource` — i.e. its content
93
+ * contains a node type `collectContentEncodingEdits` doesn't know how to
94
+ * edit (e.g. a `CborMap`, `CborTag`, or indefinite-length string inside an
95
+ * `ip` array). Left `undefined` (treated as complete) when coverage is
96
+ * exhaustive, which holds for every tag content type `dt` accepts and for
97
+ * most content `ip` accepts. When `false`, `decideTaggedAppSeqRendering`
98
+ * must not choose the `'source'` decision under `encodingIndicators !==
99
+ * 'auto'`, since surgical span edits would silently leave the uncovered
100
+ * node's indicator unchanged; it falls back to `'structural'` instead.
101
+ */
102
+ appSeqEncodingEditsComplete?: boolean;
103
+ /**
104
+ * For an `appSeqSource` parsed from `prefix<<item>>` notation: the offset
105
+ * within `appSeqSource`, relative to its own start, where the sole inner
106
+ * item's own consumption ends — i.e. right after its own encoding
107
+ * indicator, if it had one. Lets `adjustAppSeqIndicator` locate and strip
108
+ * that inner indicator exactly, regardless of what (whitespace, a
109
+ * trailing comma, a comment) separates it from the closing `>>`, rather
110
+ * than pattern-matching text near `>>`. `undefined` when `appSeqSource`
111
+ * isn't `<<...>>` notation, or wasn't captured with a single inner item.
112
+ */
113
+ appSeqInnerEnd?: number;
114
+ /**
115
+ * Literal-preservation features present in the sole item of a captured
116
+ * `prefix<<item>>` source. Used to resolve explicitly disabled
117
+ * `preserve*` options without treating unrelated options as conflicts.
118
+ */
119
+ appSeqSourceFeatures?: AppSeqSourceFeatures;
34
120
  /**
35
121
  * Validity violations detected while decoding or parsing this node.
36
122
  * Populated when `strict: false` is set in `FromCBOROptions` or
@@ -46,9 +132,12 @@ export declare abstract class CborItem {
46
132
  /**
47
133
  * @internal
48
134
  * True when this node is, or contains through wrapper nodes (tags,
49
- * embedded CBOR, app-sequence results), an array or map.
50
- * `inlineLeafContainers` never inlines a container whose entries contain
51
- * another container, even one that renders on a single line.
135
+ * app-sequence results), an array or map. `inlineLeafContainers` never
136
+ * inlines a container whose entries contain another container, even one
137
+ * that renders on a single line. `CborEmbeddedCBOR` (`<<...>>`) is the one
138
+ * exception: it inlines its own entries based purely on whether they
139
+ * render without a line break, regardless of this flag — see its
140
+ * `_toCDN()`, which omits `entryIsLeaf` for that reason.
52
141
  */
53
142
  get _containsCdnContainer(): boolean;
54
143
  /** Serialize this node to CBOR binary. */
@@ -16,8 +16,17 @@ export declare class CborNint extends CborItem {
16
16
  /** CBOR raw argument n, where actual value = −1 − n. */
17
17
  readonly argument: bigint;
18
18
  encodingWidth: EncodingWidth | undefined;
19
+ /**
20
+ * Original CDN digit spelling (sign + base + digits, without the
21
+ * encoding-indicator suffix), set by the parser when this value came
22
+ * from CDN text. Used by `_toCDN()` to round-trip the literal's base
23
+ * (`-0xff`, `-0o377`, `-0b101`, decimal) when `preserveNumberFormat` is
24
+ * set.
25
+ */
26
+ readonly ednSource?: string;
19
27
  constructor(value: number | bigint, options?: {
20
28
  encodingWidth?: EncodingWidth;
29
+ ednSource?: string;
21
30
  });
22
31
  /** The actual decoded negative value (−1 − argument). */
23
32
  get value(): bigint;
@@ -12,12 +12,21 @@ import { CborWriter } from '../cbor/encode';
12
12
  */
13
13
  export declare class CborSimple extends CborItem {
14
14
  readonly value: number;
15
- constructor(value: number);
15
+ /**
16
+ * Original CDN digit spelling of the argument to `simple(...)` (base +
17
+ * digits), set by the parser when this value came from CDN text. Used by
18
+ * `_toCDN()` to round-trip the argument's base (`0x10`, decimal, …) when
19
+ * `preserveNumberFormat` is set.
20
+ */
21
+ readonly ednSource?: string;
22
+ constructor(value: number, options?: {
23
+ ednSource?: string;
24
+ });
16
25
  static readonly FALSE: CborSimple;
17
26
  static readonly TRUE: CborSimple;
18
27
  static readonly NULL: CborSimple;
19
28
  static readonly UNDEFINED: CborSimple;
20
29
  _encodeTo(writer: CborWriter, _options?: ToCBOROptions): void;
21
- _toCDN(_options: ToCDNOptions | undefined, _depth: number): string;
30
+ _toCDN(options: ToCDNOptions | undefined, _depth: number): string;
22
31
  _toJS(_options?: ToJSOptions): unknown;
23
32
  }
@@ -6,8 +6,16 @@ export declare class CborTag extends CborItem {
6
6
  readonly tag: bigint;
7
7
  readonly content: CborItem;
8
8
  encodingWidth: EncodingWidth | undefined;
9
+ /**
10
+ * Original CDN digit spelling of the tag number (base + digits, without
11
+ * the encoding-indicator suffix), set by the parser when this tag came
12
+ * from CDN text. Used by `_toCDN()` to round-trip the tag number's base
13
+ * (`0x3e7`, decimal, …) when `preserveNumberFormat` is set.
14
+ */
15
+ ednSource?: string;
9
16
  constructor(tag: number | bigint, content: CborItem, options?: {
10
17
  encodingWidth?: EncodingWidth;
18
+ ednSource?: string;
11
19
  });
12
20
  get _containsCdnContainer(): boolean;
13
21
  _encodeTo(writer: CborWriter, options?: ToCBOROptions): void;