@cbortech/cbor 0.24.0 → 0.25.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 (54) hide show
  1. package/README.ja.md +127 -49
  2. package/README.md +128 -49
  3. package/dist/ast/CborAppSeqResult.d.ts +20 -0
  4. package/dist/ast/CborArray.d.ts +3 -3
  5. package/dist/ast/CborBignum.d.ts +5 -5
  6. package/dist/ast/CborByteString.d.ts +2 -2
  7. package/dist/ast/CborEllipsis.d.ts +2 -2
  8. package/dist/ast/CborEmbeddedCBOR.d.ts +3 -3
  9. package/dist/ast/CborFloat.d.ts +8 -2
  10. package/dist/ast/CborIndefiniteByteString.d.ts +3 -3
  11. package/dist/ast/CborIndefiniteTextString.d.ts +3 -3
  12. package/dist/ast/CborItem.d.ts +22 -10
  13. package/dist/ast/CborMap.d.ts +3 -3
  14. package/dist/ast/CborNint.d.ts +2 -2
  15. package/dist/ast/CborSimple.d.ts +2 -2
  16. package/dist/ast/CborTag.d.ts +3 -3
  17. package/dist/ast/CborTextString.d.ts +2 -2
  18. package/dist/ast/CborUint.d.ts +2 -2
  19. package/dist/ast/CborUnresolvedAppExt.d.ts +2 -2
  20. package/dist/ast/index.cjs +1 -1
  21. package/dist/ast/index.js +2 -2
  22. package/dist/cbor.d.ts +44 -26
  23. package/dist/cdn/parser.d.ts +7 -0
  24. package/dist/{edn → cdn}/serialize-utils.d.ts +20 -7
  25. package/dist/cdn/serializer.d.ts +7 -0
  26. package/dist/cdn/test-vectors/runner.d.ts +22 -0
  27. package/dist/{edn → cdn}/tokenizer.d.ts +28 -25
  28. package/dist/extensions/b32.d.ts +5 -0
  29. package/dist/extensions/cri.d.ts +7 -7
  30. package/dist/extensions/dt.d.ts +10 -19
  31. package/dist/extensions/float.d.ts +7 -0
  32. package/dist/extensions/ip.d.ts +8 -8
  33. package/dist/extensions/same.d.ts +7 -0
  34. package/dist/extensions/types.d.ts +30 -8
  35. package/dist/index.cjs +5 -2
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.ts +4 -1
  38. package/dist/index.js +244 -77
  39. package/dist/index.js.map +1 -1
  40. package/dist/mapEntries-BccT62HT.cjs +36 -0
  41. package/dist/mapEntries-BccT62HT.cjs.map +1 -0
  42. package/dist/{mapEntries-D5MWtXqq.js → mapEntries-ZR8QJ0Yj.js} +1157 -853
  43. package/dist/mapEntries-ZR8QJ0Yj.js.map +1 -0
  44. package/dist/simple.d.ts +2 -2
  45. package/dist/tag.d.ts +1 -1
  46. package/dist/types.d.ts +141 -30
  47. package/dist/utils/hexfloat.d.ts +2 -2
  48. package/dist/utils/strip-comments.d.ts +12 -0
  49. package/package.json +13 -11
  50. package/dist/edn/parser.d.ts +0 -7
  51. package/dist/edn/serializer.d.ts +0 -7
  52. package/dist/mapEntries-D5MWtXqq.js.map +0 -1
  53. package/dist/mapEntries-bihZ3yks.cjs +0 -31
  54. package/dist/mapEntries-bihZ3yks.cjs.map +0 -1
package/dist/simple.d.ts CHANGED
@@ -6,12 +6,12 @@
6
6
  * Also serves as a namespace for simple-value utilities.
7
7
  *
8
8
  * @example
9
- * const v = CBOR.fromEDN('simple(19)').toJS();
9
+ * const v = CBOR.fromCDN('simple(19)').toJS();
10
10
  * Simple.is(v); // true
11
11
  * Simple.get(v); // 19
12
12
  *
13
13
  * const node = CBOR.fromJS(new Simple(19));
14
- * node.toEDN(); // "simple(19)"
14
+ * node.toCDN(); // "simple(19)"
15
15
  */
16
16
  export declare class Simple {
17
17
  readonly value: number;
package/dist/tag.d.ts CHANGED
@@ -19,7 +19,7 @@ export declare function getCborTaggedValue(value: unknown): unknown;
19
19
  * Namespace for CBOR tag annotation utilities.
20
20
  *
21
21
  * @example
22
- * const v = CBOR.fromEDN('42("hello")').toJS();
22
+ * const v = CBOR.fromCDN('42("hello")').toJS();
23
23
  * Tag.get(v); // 42n
24
24
  * Tag.getValue(v); // "hello"
25
25
  *
package/dist/types.d.ts CHANGED
@@ -40,7 +40,7 @@ export interface ToJSOptions {
40
40
  * - `'object'`: always `Record<string, unknown>` — non-string keys are
41
41
  * converted via `String()`. Duplicate keys are overwritten (last wins).
42
42
  * - `'entries'`: always `MapEntries` (a typed `Array` subclass) — preserves all
43
- * entries including duplicate keys (§2.6.2 of draft-ietf-cbor-edn-literals-20).
43
+ * entries including duplicate keys (§2.6.3 of draft-ietf-cbor-edn-literals-25).
44
44
  * `fromJS()` recognises `MapEntries` instances and converts them back to `CborMap`.
45
45
  * @default 'auto'
46
46
  */
@@ -80,6 +80,28 @@ export interface ToJSOptions {
80
80
  }
81
81
  export interface ToCBOROptions {
82
82
  }
83
+ /**
84
+ * A CBOR validity violation detected during decoding.
85
+ */
86
+ export interface DecodeWarning {
87
+ /** Human-readable description of the violation. */
88
+ message: string;
89
+ /** Byte offset within the decoded input where the violation was detected. */
90
+ offset: number;
91
+ }
92
+ /**
93
+ * A CDN/EDN validity violation detected during parsing.
94
+ */
95
+ export interface ParseWarning {
96
+ /** Human-readable description of the violation. */
97
+ message: string;
98
+ /** Character offset within the input text where the violation was detected. */
99
+ offset?: number;
100
+ /** Line number (1-based) where the violation was detected. */
101
+ line?: number;
102
+ /** Column number (1-based) where the violation was detected. */
103
+ column?: number;
104
+ }
83
105
  export interface FromCBOROptions {
84
106
  /**
85
107
  * Byte offset within the supplied input at which CBOR decoding starts.
@@ -110,6 +132,39 @@ export interface FromCBOROptions {
110
132
  * `CborTag` node.
111
133
  */
112
134
  extensions?: CborExtension[];
135
+ /**
136
+ * Controls how CBOR validity violations are handled.
137
+ *
138
+ * - `true` (default): violations call `onWarning` and then throw, stopping
139
+ * decoding immediately.
140
+ * - `false`: recoverable violations call `onWarning` and decoding continues
141
+ * with a best-effort interpretation of the data.
142
+ *
143
+ * Truly malformed data (e.g. truncated input, reserved AI values) always
144
+ * throws regardless of this setting.
145
+ *
146
+ * @default true
147
+ */
148
+ strict?: boolean;
149
+ /**
150
+ * Callback invoked when a CBOR validity violation is detected.
151
+ *
152
+ * In strict mode (the default), this is called before the error is thrown.
153
+ * In non-strict mode (`strict: false`), this is called and decoding
154
+ * continues.
155
+ *
156
+ * If not supplied and `silent` is not `true`, violations are reported via
157
+ * `console.warn`.
158
+ */
159
+ onWarning?: (warning: DecodeWarning) => void;
160
+ /**
161
+ * When `true`, suppresses the default `console.warn` output for validity
162
+ * violations. An explicit `onWarning` callback is still invoked even when
163
+ * `silent` is `true`.
164
+ *
165
+ * @default false
166
+ */
167
+ silent?: boolean;
113
168
  }
114
169
  /**
115
170
  * Options for parsing an annotated hex dump.
@@ -122,9 +177,9 @@ export interface FromHexDumpOptions {
122
177
  */
123
178
  extensions?: CborExtension[];
124
179
  }
125
- export interface FromEDNOptions {
180
+ export interface FromCDNOptions {
126
181
  /**
127
- * Character offset within the supplied text at which CBOR-EDN parsing starts.
182
+ * Character offset within the supplied text at which CDN parsing starts.
128
183
  * Leading whitespace/comments at or after this offset are skipped as usual.
129
184
  *
130
185
  * @default 0
@@ -135,22 +190,22 @@ export interface FromEDNOptions {
135
190
  *
136
191
  * When `false`, parsing still requires the item to consume the remaining
137
192
  * input, preserving the historical single-item behaviour. Set this to `true`
138
- * when using `CborItem.end` to continue parsing a CBOR-EDN sequence.
139
- * Top-level comma separators are not skipped by `fromEDN()` itself; handle
193
+ * when using `CborItem.end` to continue parsing a CDN sequence.
194
+ * Top-level comma separators are not skipped by `fromCDN()` itself; handle
140
195
  * them in sequence-level code before passing the next `offset`. For example,
141
196
  * after parsing `1, 2`, the first item's `end` points just before the comma;
142
197
  * advance past that comma before parsing the next item.
143
198
  *
144
199
  * @example
145
200
  * // Read two whitespace-separated items, validating that the second is last.
146
- * const first = CBOR.fromEDN(text, { allowTrailing: true });
147
- * const second = CBOR.fromEDN(text, { offset: first.end });
201
+ * const first = CBOR.fromCDN(text, { allowTrailing: true });
202
+ * const second = CBOR.fromCDN(text, { offset: first.end });
148
203
  *
149
204
  * @default false
150
205
  */
151
206
  allowTrailing?: boolean;
152
207
  /**
153
- * Extension plugins for EDN parsing.
208
+ * Extension plugins for CDN parsing.
154
209
  * Each extension declares which app-string prefixes (and, in future, tag
155
210
  * numbers) it handles via `appStringPrefixes` / `tagNumbers`, and provides
156
211
  * callback methods that return `CborItem`-subclassed objects controlling
@@ -162,11 +217,11 @@ export interface FromEDNOptions {
162
217
  extensions?: CborExtension[];
163
218
  /**
164
219
  * How to handle unrecognised application-extension identifiers
165
- * (§4.1 draft-ietf-cbor-edn-literals-20).
220
+ * (§4.1 of draft-ietf-cbor-edn-literals-25).
166
221
  *
167
222
  * - `'cpa999'`: wrap the literal in a `CPA999` tag
168
223
  * (`CborUnresolvedAppExt`) instead of failing. The resulting node
169
- * round-trips through `toEDN()` back to the original notation.
224
+ * round-trips through `toCDN()` back to the original notation.
170
225
  * - `'error'`: throw `SyntaxError` for unknown prefixes.
171
226
  * @default 'cpa999'
172
227
  */
@@ -184,16 +239,56 @@ export interface FromEDNOptions {
184
239
  */
185
240
  allowInvalidUtf8?: boolean;
186
241
  /**
187
- * Preserve comments found between CBOR-EDN values and attach them to the AST.
242
+ * Preserve comments found between CDN values and attach them to the AST.
188
243
  *
189
244
  * Comments are metadata only: they are ignored by CBOR binary encoding and
190
- * JavaScript conversion. Use together with `ToEDNOptions.preserveComments`
191
- * to include them when formatting back to EDN.
245
+ * JavaScript conversion. Use together with `ToCDNOptions.preserveComments`
246
+ * to include them when formatting back to CDN.
247
+ *
248
+ * The string values `'c-style'` and `'cdn-style'` are treated as `true`
249
+ * for parsing purposes; they become meaningful when passed to `toCDN()`.
192
250
  *
193
251
  * @default false
194
252
  */
195
- preserveComments?: boolean;
253
+ preserveComments?: boolean | 'c-style' | 'cdn-style';
254
+ /**
255
+ * Controls how CDN/EDN validity violations are handled.
256
+ *
257
+ * - `true` (default): recoverable violations call `onWarning` and then throw.
258
+ * - `false`: recoverable violations call `onWarning` and parsing continues
259
+ * with a best-effort interpretation of the input.
260
+ *
261
+ * Hard syntax errors (e.g. unterminated strings, unexpected tokens) always
262
+ * throw regardless of this setting.
263
+ *
264
+ * @default true
265
+ */
266
+ strict?: boolean;
267
+ /**
268
+ * Callback invoked when a CDN/EDN validity violation is detected.
269
+ *
270
+ * In strict mode (the default), this is called before the error is thrown.
271
+ * In non-strict mode (`strict: false`), this is called and parsing continues.
272
+ *
273
+ * If not supplied and `silent` is not `true`, violations are reported via
274
+ * `console.warn`.
275
+ */
276
+ onWarning?: (warning: ParseWarning) => void;
277
+ /**
278
+ * When `true`, suppresses the default `console.warn` output for validity
279
+ * violations. An explicit `onWarning` callback is still invoked even when
280
+ * `silent` is `true`.
281
+ *
282
+ * @default false
283
+ */
284
+ silent?: boolean;
196
285
  }
286
+ /**
287
+ * Options for parsing Concise Diagnostic Notation (CDN).
288
+ *
289
+ * @deprecated Use `FromCDNOptions` instead.
290
+ */
291
+ export type FromEDNOptions = FromCDNOptions;
197
292
  export interface FromJSOptions {
198
293
  /**
199
294
  * Extension plugins applied during `fromJS()`.
@@ -238,7 +333,7 @@ export interface FromJSOptions {
238
333
  */
239
334
  undefinedOmits?: boolean;
240
335
  }
241
- export interface ToEDNOptions {
336
+ export interface ToCDNOptions {
242
337
  /**
243
338
  * Indentation for pretty-printing.
244
339
  * - `number`: number of spaces
@@ -247,16 +342,25 @@ export interface ToEDNOptions {
247
342
  */
248
343
  indent?: number | string;
249
344
  /**
250
- * Emit comments previously captured by `FromEDNOptions.preserveComments`.
345
+ * Emit comments previously captured by `FromCDNOptions.preserveComments`.
346
+ *
347
+ * - `true`: emit comments with their original markers.
348
+ * - `'c-style'`: emit comments, normalising line comments to `//` and block
349
+ * comments to `/* … *\/`.
350
+ * - `'cdn-style'`: emit comments, normalising line comments to `#` and block
351
+ * comments to `/ … /`. When a `/* … *\/` comment's content contains `/`
352
+ * (which cannot be represented inside `/ … /`), the `/* … *\/` form is
353
+ * kept as-is.
354
+ * - `false` / omitted: strip all comments from the output.
251
355
  *
252
356
  * When enabled for containers, comment-bearing arrays/maps are emitted in
253
357
  * multi-line form even if `indent` is omitted.
254
358
  *
255
359
  * @default false
256
360
  */
257
- preserveComments?: boolean;
361
+ preserveComments?: boolean | 'c-style' | 'cdn-style';
258
362
  /**
259
- * Re-emit byte string literals parsed from EDN using their original source
363
+ * Re-emit byte string literals parsed from CDN using their original source
260
364
  * text when available.
261
365
  *
262
366
  * This preserves the spelling and interior layout of non-concatenated
@@ -278,17 +382,14 @@ export interface ToEDNOptions {
278
382
  * @default 'comma'
279
383
  */
280
384
  commas?: 'comma' | 'none' | 'trailing';
281
- /**
282
385
  /**
283
386
  * Fallback binary encoding for byte string literals when sqstr is not applicable.
284
387
  * - `'hex'`: `h'...'`
285
388
  * - `'base64'`: `b64'...'`
286
389
  * - `'base64url'`: `b64'...'` (base64url alphabet)
287
- * - `'base32'`: `b32'...'`
288
- * - `'base32hex'`: `h32'...'`
289
390
  * @default 'hex'
290
391
  */
291
- bstrEncoding?: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex';
392
+ bstrEncoding?: 'hex' | 'base64' | 'base64url';
292
393
  /**
293
394
  * Whether to prefer single-quoted string form (`sqstr`) for byte strings.
294
395
  * - `'printable-string'`: emit `'...'` when the bytes are valid UTF-8 and
@@ -308,7 +409,7 @@ export interface ToEDNOptions {
308
409
  */
309
410
  appStrings?: boolean;
310
411
  /**
311
- * Numeric format for integer values in EDN output.
412
+ * Numeric format for integer values in CDN output.
312
413
  * - `'decimal'`: standard decimal notation (e.g. `42`, `-14159024`)
313
414
  * - `'hex'`: hexadecimal notation (e.g. `0x2a`, `-0xd83130`)
314
415
  * - `'octal'`: octal notation (e.g. `0o52`, `-0o67061560`)
@@ -317,25 +418,35 @@ export interface ToEDNOptions {
317
418
  */
318
419
  intFormat?: 'decimal' | 'hex' | 'octal' | 'binary';
319
420
  /**
320
- * Numeric format for floating-point values in EDN output.
421
+ * Numeric format for floating-point values in CDN output.
321
422
  * - `'decimal'`: standard decimal notation (e.g. `1.5`, `145544.0_3`)
322
423
  * - `'hex'`: C99-style hex float notation (e.g. `0x1.8p+0`, `0x1.1c54p+17_3`)
323
424
  * @default 'decimal'
324
425
  */
325
426
  floatFormat?: 'decimal' | 'hex';
326
427
  /**
327
- * Split long text strings using EDN string concatenation syntax (`"a" + "b"`).
428
+ * Split long text strings using CDN string concatenation syntax (`"a" + "b"`).
328
429
  * Only effective when `indent` is specified.
329
430
  *
330
431
  * - `'newline'`: split at newline characters
331
- * - `'cboredn'`: split according to CBOR-EDN structure when the string content
332
- * is parseable as CBOR-EDN (JSON superset)
432
+ * - `'cdn'`: split according to CDN structure when the string content
433
+ * is parseable as CDN (JSON superset)
434
+ * - `'cboredn'`: deprecated alias for `'cdn'`
333
435
  *
334
- * When both are specified, CBOR-EDN structure split points are combined with
436
+ * When both are specified, CDN structure split points are combined with
335
437
  * newline split points.
336
438
  */
337
- textStringFormat?: ('newline' | 'cboredn')[];
439
+ textStringFormat?: TextStringFormat[];
338
440
  }
441
+ export type TextStringFormat = 'newline' | 'cdn' | DeprecatedTextStringFormat;
442
+ /** @deprecated Use `'cdn'` instead. */
443
+ export type DeprecatedTextStringFormat = 'cboredn';
444
+ /**
445
+ * Options for serializing Concise Diagnostic Notation (CDN).
446
+ *
447
+ * @deprecated Use `ToCDNOptions` instead.
448
+ */
449
+ export type ToEDNOptions = ToCDNOptions;
339
450
  export interface CborComment {
340
451
  kind: 'line' | 'block';
341
452
  marker: '#' | '//' | '/*' | '/';
@@ -359,4 +470,4 @@ export interface CborComments {
359
470
  * Note: `encodeIntegerAs` (from {@link FromJSOptions}) and `integerAs` (from
360
471
  * {@link ToJSOptions}) are distinct fields and do not conflict.
361
472
  */
362
- export type CBOROptions = FromEDNOptions & FromJSOptions & ToCBOROptions & ToEDNOptions & ToJSOptions & ToHexDumpOptions;
473
+ export type CBOROptions = FromCDNOptions & FromJSOptions & ToCBOROptions & ToCDNOptions & ToJSOptions & ToHexDumpOptions;
@@ -4,7 +4,7 @@
4
4
  * Hex float format:
5
5
  * [-] 0x [hex digits] [. [hex digits]] p [+-] [decimal exponent]
6
6
  *
7
- * This notation appears in CBOR-EDN (draft-ietf-cbor-edn-literals) as an
7
+ * This notation appears in CDN (draft-ietf-cbor-edn-literals-25) as an
8
8
  * alternative representation for floating-point values (major type 7).
9
9
  */
10
10
  /**
@@ -17,7 +17,7 @@
17
17
  export declare function parseHexFloat(s: string): number;
18
18
  /**
19
19
  * Convert a JS number to a normalized hex float string compatible with
20
- * CBOR-EDN diagnostic notation.
20
+ * CDN diagnostic notation.
21
21
  *
22
22
  * - Normal values: `0x1.[hex fraction]p[+-][exp]` (e.g. `0x1.8p+0` for 1.5)
23
23
  * - Subnormal values: `0x0.[hex fraction]p-1022`
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Strip whitespace and EDN §2.2 comments from app-string content.
3
+ *
4
+ * Used by extensions whose content allows the same comment syntax as byte
5
+ * string literals (b32, h32, float, …):
6
+ * SP / LF / CR — whitespace, skipped
7
+ * # … LF — line comment
8
+ * // … LF — line comment
9
+ * /* … *\/ — block comment (unterminated → SyntaxError)
10
+ * / … / — block comment (unterminated → SyntaxError)
11
+ */
12
+ export declare function stripComments(str: string): string;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@cbortech/cbor",
3
- "version": "0.24.0",
4
- "description": "Convert between CBOR, CBOR-EDN, and JavaScript values",
3
+ "version": "0.25.1",
4
+ "description": "Convert between CBOR, CDN, and JavaScript values",
5
5
  "keywords": [
6
6
  "cbor",
7
+ "cdn",
7
8
  "cbor-edn",
8
- "edn",
9
9
  "diagnostic-notation",
10
10
  "json",
11
11
  "jsonc",
@@ -67,9 +67,11 @@
67
67
  "start": "node dist/index.js",
68
68
  "dev": "npm run build && npm start",
69
69
  "clean": "node -e \"['dist','coverage'].forEach(d=>require('fs').rmSync(d,{recursive:true,force:true}))\"",
70
- "test": "vitest run",
70
+ "test": "vitest run --exclude src/cdn/edn-test-vectors.test.ts --exclude src/cdn/edn-abnf-vectors.test.ts",
71
71
  "test:exports": "npm run build && node scripts/check-package-exports.mjs",
72
- "test:node": "vitest run",
72
+ "test:node": "vitest run --exclude src/cdn/edn-test-vectors.test.ts --exclude src/cdn/edn-abnf-vectors.test.ts",
73
+ "test:edn-vectors": "vitest run src/cdn/edn-test-vectors.test.ts",
74
+ "test:edn-abnf": "vitest run src/cdn/edn-abnf-vectors.test.ts",
73
75
  "test:chromium": "cross-env BROWSER=chromium vitest run --config vitest.browser.config.ts",
74
76
  "test:firefox": "cross-env BROWSER=firefox vitest run --config vitest.browser.config.ts",
75
77
  "test:webkit": "cross-env BROWSER=webkit vitest run --config vitest.browser.config.ts",
@@ -82,16 +84,16 @@
82
84
  },
83
85
  "devDependencies": {
84
86
  "@types/node": "^24.12.4",
85
- "@vitest/browser": "^4.1.6",
86
- "@vitest/browser-playwright": "^4.1.6",
87
- "@vitest/coverage-v8": "^4.1.6",
88
- "@vitest/ui": "^4.1.6",
87
+ "@vitest/browser": "^4.1.8",
88
+ "@vitest/browser-playwright": "^4.1.8",
89
+ "@vitest/coverage-v8": "^4.1.8",
90
+ "@vitest/ui": "^4.1.8",
89
91
  "cross-env": "^10.1.0",
90
92
  "playwright": "^1.60.0",
91
93
  "prettier": "^3.8.3",
92
94
  "typescript": "^5.9.3",
93
- "vite": "^8.0.12",
95
+ "vite": "^8.0.16",
94
96
  "vite-plugin-dts": "^4.5.4",
95
- "vitest": "^4.1.6"
97
+ "vitest": "^4.1.8"
96
98
  }
97
99
  }
@@ -1,7 +0,0 @@
1
- import { CborItem } from '../ast/CborItem';
2
- import { FromEDNOptions } from '../types';
3
- /**
4
- * Parse a CBOR-EDN diagnostic notation string into a CborItem AST node.
5
- * Throws SyntaxError on invalid input.
6
- */
7
- export declare function parseEDN(text: string, options?: FromEDNOptions): CborItem;
@@ -1,7 +0,0 @@
1
- import { CborItem } from '../ast/CborItem';
2
- import { ToEDNOptions } from '../types';
3
- /**
4
- * Serialize a CborItem AST node to CBOR-EDN diagnostic notation.
5
- * Equivalent to calling value.toEDN(options) directly.
6
- */
7
- export declare function toEDN(value: CborItem, options?: ToEDNOptions): string;