soml-lang 0.0.1 → 0.0.3

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.
@@ -0,0 +1,56 @@
1
+ import { type StringifyOptions } from './stringify.ts';
2
+ /**
3
+ Options for `edit()`, which writes the new value as `stringify()` does.
4
+ */
5
+ export type EditOptions = StringifyOptions;
6
+ /**
7
+ A key in an object or an index in an array.
8
+ */
9
+ export type PathSegment = string | number;
10
+ /**
11
+ Change one value in a document, and keep everything else as it is written: comments, member order, layout, and the spelling of every other value. For tools that update a config file, such as a dependency bumper or a `set` command.
12
+
13
+ The value at `path` is replaced, or added when it does not exist yet, and an `undefined` value removes it. Only the changed part of the text is rewritten, and an edit to a formatted document leaves it formatted.
14
+
15
+ - A new value is written as `stringify()` writes it, at the indentation of its line. So `0xFF` that is replaced by `255n` becomes `255`, and `8080` becomes `8080.0` unless you pass `8080n` or the `integers: 'number'` option. The members of a new object keep their order, unless you pass the `canonical: true` option. In a container that is on one line, it is written on one line too, so `[1, 2]` with a new item `{a: 3n}` becomes `[1, 2, {a: 3}]`.
16
+ - A new member goes after the last member of its object, or after the last member that shares its dotted prefix, as `postgres.port` after `postgres.host`. Missing objects on the way are created.
17
+ - A new item can be added at the end of an array, with the index that is its length.
18
+ - A new member or item goes on its own line without a comma, after the comments that the one before it owns (see below), and the commas of the other members and items stay as they are. When something follows the member or item before it on the same line, such as the closing bracket of the one-line container `{a: 1}`, it goes on that line after a comma, as in `{a: 1, b: 2}`. In an empty `[]` or `{}`, it goes on a line of its own, unless that container is inside a container on one line, so `a: [1, []]` becomes `a: [1, [2]]`.
19
+ - A removed member or item takes the comments it owns, which are the ones that `format()` keeps with it: the comments after it on its line, also after its comma when nothing else follows there, and the block comments before it on its line, after the comma or bracket before it. So removing `2` from `[1, /* note *\/ 2]` gives `[1]`. A comment on a line of its own belongs to no member or item, so it stays. A removed member or item also removes its lines when nothing else is on them. A line that a block comment after it continues onto counts as one of its lines. Removing every item of a container closes it up to `[]` or `{}`, unless a comment is left inside.
20
+ - A removed member or item takes its comma with it. When the removed items are the last ones and have no comma after them, they take the comma directly before them instead, when only spaces, tabs, and the comments they own are between, so `[1, 2]` becomes `[1]`.
21
+ - Removing the last member under a dotted prefix, such as `a.b` when it is the only member that starts with `a.`, leaves `a: {}`, because the object `a` still exists. Removing the only member of a document without braces leaves `{}`.
22
+
23
+ Comments inside a value that is replaced or removed are removed with it. In a layout that `format()` never writes, an edit can leave odd spacing, such as a new item after a closing block string delimiter on its line that is indented differently from its neighbors. The document is always valid and has the right value. Removing a value that does not exist changes nothing and is not an error: a missing member, a missing object or array on the way, or an index at or past the end of its array. So removing the same path twice is safe, and `edit(text, path, undefined) === text` tells whether something was removed.
24
+
25
+ The result is parsed before it is returned, so a bug in `edit()` throws an `Error` rather than returning a broken document.
26
+
27
+ @param text - The document.
28
+ @param path - The keys and array indexes that lead to the value, such as `['servers', 0, 'port']`. A dotted key is followed like the objects it builds, so `['postgres', 'host']` finds `postgres.host: 'db'`.
29
+ @param value - The new value, of the types that `stringify()` accepts, or `undefined` to remove the value.
30
+ @param options - How an int is represented in `value`, and whether to sort its members, as for `stringify()`.
31
+ @returns The changed document.
32
+ @throws {ParseError} When `text` is not a valid document.
33
+ @throws {TypeError} When `text` is not a string, when `path` is not a non-empty array of keys and array indexes, when it leads through a value that is not an object or an array, or when it has a key where an array is or an index where an object is. Also when `value` cannot be represented, or `options` is invalid, as for `stringify()`.
34
+ @throws {RangeError} When a value is set at an index past the end of its array, or at an index under a value that does not exist, or when the change would nest the document more than 100 levels deep. Also when `value` is out of range, as for `stringify()`.
35
+
36
+ @example
37
+ ```
38
+ import {edit} from 'soml-lang';
39
+
40
+ edit('name: \'api\' # The service\nport: 8080\n', ['port'], 9090n);
41
+ //=> "name: 'api' # The service\nport: 9090\n"
42
+
43
+ edit('postgres.host: \'db\'\n', ['postgres', 'port'], 5432n);
44
+ //=> "postgres.host: 'db'\npostgres.port: 5432\n"
45
+
46
+ edit('a: 1\nb: 2\n', ['a'], undefined);
47
+ //=> 'b: 2\n'
48
+
49
+ edit('port: 8080', ['port'], 9090, {integers: 'number'});
50
+ //=> 'port: 9090'
51
+
52
+ edit('a: 1\n', ['b'], {y: 1n, x: 2n}, {canonical: true});
53
+ //=> 'a: 1\nb: {\n\tx: 2\n\ty: 1\n}\n'
54
+ ```
55
+ */
56
+ export declare function edit(text: string, path: readonly PathSegment[], value: unknown, options?: EditOptions): string;