smol-toml 1.7.2 → 1.8.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.
package/README.md CHANGED
@@ -66,7 +66,7 @@ A few notes on the `stringify` function:
66
66
  - By default, floats will be serialized as integers if they don't have a decimal part. See [Integers](#integers)
67
67
  - `stringify(parse('a = 1.0')) === 'a = 1'`
68
68
  - JS `Date` will be serialized as Offset Date Time
69
- - Use the [`TomlDate` object](#dates) for representing other types.
69
+ - Use the [Temporal API] for representing other types (or alternatively the legacy [`TomlDate` object](#dates)).
70
70
 
71
71
  ### Integers
72
72
  When parsing, both integers and floats are read as plain JavaScript numbers, which essentially are floats. This means
@@ -101,8 +101,22 @@ const toml = stringify(obj, { numbersAsFloat: true })
101
101
  ```
102
102
 
103
103
  ### Dates
104
- `smol-toml` uses an extended `Date` object to represent all types of TOML Dates. In the future, `smol-toml` will use
105
- objects from the Temporal proposal, but for now we're stuck with the legacy Date object.
104
+ `smol-toml` uses an extended `Date` object to represent all types of TOML Dates. In the future, `smol-toml` will emit
105
+ objects from the Temporal API, but for now it only supports `Date` when parsing. When stringifying, `smol-toml` does
106
+ support objects from the [Temporal API] and will output the appropriate TOML type.
107
+
108
+ > [!IMPORTANT]
109
+ > If you create a `ZonedDateTime` with a timezone, it will be turned into an offset date-time; losing its precise timezone.
110
+ >
111
+ > For instance, if you create one with the timezone `Europe/Paris`, it'll be turned into an offset date-time `+02:00`
112
+ > or `+01:00`, depending on the offset observed at the instant referred to by the date-time.
113
+ >
114
+ > ```js
115
+ > Temporal.ZonedDateTime.from({ year: 2001, month: 9, day: 21, hour: 10, minute: 17, second: 0, timeZone: 'Europe/Paris' }).toString({ timeZoneName: 'never' })
116
+ > // 2001-09-21T10:17:00+02:00
117
+ > Temporal.ZonedDateTime.from({ year: 2012, month: 3, day: 19, hour: 8, minute: 0, second: 0, timeZone: 'Europe/Paris' }).toString({ timeZoneName: 'never' })
118
+ > // 2012-03-19T08:00:00+01:00
119
+ > ```
106
120
 
107
121
  ```js
108
122
  import { TomlDate } from 'smol-toml'
@@ -400,3 +414,5 @@ summary
400
414
  ```
401
415
 
402
416
  </details>
417
+
418
+ [Temporal API]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Temporal
package/dist/error.d.ts CHANGED
@@ -33,6 +33,6 @@ export declare class TomlError extends Error {
33
33
  line: number;
34
34
  column: number;
35
35
  codeblock: string;
36
- constructor(message: string, /** @internal */ options: TomlErrorOptions);
36
+ constructor(message: string, options: TomlErrorOptions);
37
37
  }
38
38
  export {};
package/dist/error.js CHANGED
@@ -49,15 +49,13 @@ function makeCodeBlock(string, line, column) {
49
49
  return codeblock;
50
50
  }
51
51
  export class TomlError extends Error {
52
- options;
53
52
  line;
54
53
  column;
55
54
  codeblock;
56
- constructor(message, /** @internal */ options) {
55
+ constructor(message, options) {
57
56
  const [line, column] = getLineColFromPtr(options.toml, options.ptr);
58
57
  const codeblock = makeCodeBlock(options.toml, line, column);
59
58
  super(`Invalid TOML document: ${message}\n\n${codeblock}`, options);
60
- this.options = options;
61
59
  this.line = line;
62
60
  this.column = column;
63
61
  this.codeblock = codeblock;
package/dist/index.cjs CHANGED
@@ -137,7 +137,6 @@ function makeCodeBlock(string, line, column) {
137
137
  return codeblock;
138
138
  }
139
139
  var TomlError = class extends Error {
140
- options;
141
140
  line;
142
141
  column;
143
142
  codeblock;
@@ -145,7 +144,6 @@ var TomlError = class extends Error {
145
144
  const [line, column] = getLineColFromPtr(options.toml, options.ptr);
146
145
  const codeblock = makeCodeBlock(options.toml, line, column);
147
146
  super(`Invalid TOML document: ${message}\n\n${codeblock}`, options);
148
- this.options = options;
149
147
  this.line = line;
150
148
  this.column = column;
151
149
  this.codeblock = codeblock;
@@ -619,7 +617,8 @@ function extendedTypeOf(obj) {
619
617
  let type = typeof obj;
620
618
  if (type === "object") {
621
619
  if (Array.isArray(obj)) return "array";
622
- if (obj instanceof Date) return "date";
620
+ if (typeof obj?.getUTCDate === "function" && obj instanceof Date) return "date";
621
+ if (globalThis.Temporal && typeof obj?.since === "function" && (obj instanceof Temporal.Instant || obj instanceof Temporal.PlainDate || obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainTime || obj instanceof Temporal.ZonedDateTime)) return "temporal";
623
622
  }
624
623
  return type;
625
624
  }
@@ -630,23 +629,30 @@ function isArrayOfTables(obj) {
630
629
  function formatString(s) {
631
630
  return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
632
631
  }
632
+ function stringifyTemporal(temporal) {
633
+ return temporal.toString({
634
+ calendarName: "never",
635
+ timeZoneName: "never"
636
+ });
637
+ }
633
638
  function stringifyValue(val, type, depth, numberAsFloat) {
634
639
  if (depth === 0) throw new Error("Could not stringify the object: maximum object depth exceeded");
635
- if (type === "number") {
636
- if (isNaN(val)) return "nan";
637
- if (val === Infinity) return "inf";
638
- if (val === -Infinity) return "-inf";
639
- if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val))) return val.toFixed(1);
640
- return val.toString();
641
- }
642
- if (type === "bigint" || type === "boolean") return val.toString();
643
- if (type === "string") return formatString(val);
644
- if (type === "date") {
645
- if (isNaN(val.getTime())) throw new TypeError("cannot serialize invalid date");
646
- return val.toISOString();
647
- }
648
- if (type === "object") return stringifyInlineTable(val, depth, numberAsFloat);
649
- if (type === "array") return stringifyArray(val, depth, numberAsFloat);
640
+ switch (type) {
641
+ case "number":
642
+ if (isNaN(val)) return "nan";
643
+ if (val === Infinity) return "inf";
644
+ if (val === -Infinity) return "-inf";
645
+ if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val))) return val.toFixed(1);
646
+ case "bigint":
647
+ case "boolean": return val.toString();
648
+ case "string": return formatString(val);
649
+ case "date":
650
+ if (isNaN(val.getTime())) throw new TypeError("cannot serialize invalid date");
651
+ return val.toISOString();
652
+ case "object": return stringifyInlineTable(val, depth, numberAsFloat);
653
+ case "array": return stringifyArray(val, depth, numberAsFloat);
654
+ case "temporal": return stringifyTemporal(val);
655
+ }
650
656
  }
651
657
  function stringifyInlineTable(obj, depth, numberAsFloat) {
652
658
  let keys = Object.keys(obj);
package/dist/stringify.js CHANGED
@@ -31,8 +31,18 @@ function extendedTypeOf(obj) {
31
31
  if (type === 'object') {
32
32
  if (Array.isArray(obj))
33
33
  return 'array';
34
- if (obj instanceof Date)
34
+ if (typeof obj?.getUTCDate === 'function' && obj instanceof Date)
35
35
  return 'date';
36
+ if (globalThis.Temporal &&
37
+ // check for the 'since' property as an early bailout that avoids running all 5 instanceof checks
38
+ typeof obj?.since === 'function' &&
39
+ (obj instanceof Temporal.Instant ||
40
+ obj instanceof Temporal.PlainDate ||
41
+ obj instanceof Temporal.PlainDateTime ||
42
+ obj instanceof Temporal.PlainTime ||
43
+ obj instanceof Temporal.ZonedDateTime)) {
44
+ return 'temporal';
45
+ }
36
46
  }
37
47
  return type;
38
48
  }
@@ -46,38 +56,42 @@ function isArrayOfTables(obj) {
46
56
  function formatString(s) {
47
57
  return JSON.stringify(s).replace(/\x7f/g, '\\u007f');
48
58
  }
59
+ function stringifyTemporal(temporal) {
60
+ return temporal.toString({
61
+ calendarName: 'never',
62
+ timeZoneName: 'never',
63
+ });
64
+ }
49
65
  function stringifyValue(val, type, depth, numberAsFloat) {
50
66
  if (depth === 0) {
51
67
  throw new Error('Could not stringify the object: maximum object depth exceeded');
52
68
  }
53
- if (type === 'number') {
54
- if (isNaN(val))
55
- return 'nan';
56
- if (val === Infinity)
57
- return 'inf';
58
- if (val === -Infinity)
59
- return '-inf';
60
- if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val)))
61
- return val.toFixed(1);
62
- return val.toString();
63
- }
64
- if (type === 'bigint' || type === 'boolean') {
65
- return val.toString();
66
- }
67
- if (type === 'string') {
68
- return formatString(val);
69
- }
70
- if (type === 'date') {
71
- if (isNaN(val.getTime())) {
72
- throw new TypeError('cannot serialize invalid date');
73
- }
74
- return val.toISOString();
75
- }
76
- if (type === 'object') {
77
- return stringifyInlineTable(val, depth, numberAsFloat);
78
- }
79
- if (type === 'array') {
80
- return stringifyArray(val, depth, numberAsFloat);
69
+ switch (type) {
70
+ // @ts-expect-error -- intentional fallthrough case
71
+ case 'number':
72
+ if (isNaN(val))
73
+ return 'nan';
74
+ if (val === Infinity)
75
+ return 'inf';
76
+ if (val === -Infinity)
77
+ return '-inf';
78
+ if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val)))
79
+ return val.toFixed(1);
80
+ case 'bigint':
81
+ case 'boolean':
82
+ return val.toString();
83
+ case 'string':
84
+ return formatString(val);
85
+ case 'date':
86
+ if (isNaN(val.getTime()))
87
+ throw new TypeError('cannot serialize invalid date');
88
+ return val.toISOString();
89
+ case 'object':
90
+ return stringifyInlineTable(val, depth, numberAsFloat);
91
+ case 'array':
92
+ return stringifyArray(val, depth, numberAsFloat);
93
+ case 'temporal':
94
+ return stringifyTemporal(val);
81
95
  }
82
96
  }
83
97
  function stringifyInlineTable(obj, depth, numberAsFloat) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smol-toml",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "A small, fast, and correct TOML parser/serializer",
5
5
  "keywords": [
6
6
  "parser",
@@ -36,6 +36,7 @@
36
36
  "devDependencies": {
37
37
  "@mitata/counters": "^0.0.8",
38
38
  "@tsconfig/node-lts": "^24.0.0",
39
+ "@tsconfig/node-ts": "^23.6.4",
39
40
  "@tsconfig/strictest": "^2.0.8",
40
41
  "@types/node": "^26.2.0",
41
42
  "mitata": "^1.0.34",