@amritk/nish-x86_64-linux 0.24.0 → 0.26.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/bin/nish +0 -0
- package/docs/AI.md +45 -4
- package/package.json +1 -1
- package/runtime/browser.mjs +4 -3
- package/runtime/core/host.d.ts +12 -0
- package/runtime/core/host.mjs +74 -2
- package/runtime/nish.d.ts +148 -0
- package/runtime/nish.h +59 -0
- package/runtime/nish.mjs +25 -0
- package/runtime/node.mjs +136 -6
- package/runtime/runtime-net.c +44 -3
- package/runtime/runtime-os.c +351 -18
- package/scripts/build.sh +13 -3
- package/std/README.md +27 -10
- package/std/cli-args.ts +1216 -0
- package/std/cli-flags.ts +585 -0
- package/std/cli.ts +308 -19
- package/std/compress/checksum.ts +132 -20
- package/std/compress/deflate.ts +638 -248
- package/std/compress/gzip.ts +20 -6
- package/std/crypto/LICENSE-fiat-crypto-p384 +21 -0
- package/std/crypto/p256.ts +63 -1
- package/std/crypto/p384.ts +6044 -0
- package/std/crypto/pki-roots.ts +322 -0
- package/std/crypto/pki.ts +1207 -0
- package/std/crypto/rsa.ts +663 -0
- package/std/crypto/x509.ts +1054 -58
- package/std/net/dns-config.ts +734 -0
- package/std/net/dns-message.ts +517 -0
- package/std/net/dns-resolver.ts +1015 -0
- package/std/net/dns.ts +478 -0
- package/std/net/http1-client.ts +1227 -0
- package/std/net/http1-server.ts +7 -2
- package/std/net/http1.ts +9 -9
- package/std/net/postgres.ts +259 -26
- package/std/net/tls/client.ts +1094 -0
- package/std/net/tls/codec.ts +585 -3
- package/std/net/tls/record-client.ts +1192 -0
- package/std/net/tls/verify.ts +221 -0
- package/std/net/tls-tcp.ts +642 -11
- package/std/net/tls.ts +2 -2
- package/std/net/url.ts +559 -4
- package/std/yaml-write.ts +415 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nish/yaml-write` — a JSON value written as YAML text that `parseYaml` reads
|
|
3
|
+
* back as the same tree.
|
|
4
|
+
*
|
|
5
|
+
* import { JsonDocument } from "nish/json-value"
|
|
6
|
+
* import { JsonLimits } from "nish/json-tokenizer"
|
|
7
|
+
* import { stringifyYaml } from "nish/yaml-write"
|
|
8
|
+
*
|
|
9
|
+
* const doc = new JsonDocument(new JsonLimits())
|
|
10
|
+
* const root = doc.parseText('{"name":"tea","on":"yes","ports":[80,443],"tags":{}}')
|
|
11
|
+
* stringifyYaml(doc, root)
|
|
12
|
+
* // name: tea
|
|
13
|
+
* // "on": "yes"
|
|
14
|
+
* // ports:
|
|
15
|
+
* // - 80
|
|
16
|
+
* // - 443
|
|
17
|
+
* // tags: {}
|
|
18
|
+
*
|
|
19
|
+
* **Block style.** An object is a block map and an array a block sequence,
|
|
20
|
+
* indented two spaces a level, members in their order; an empty one is `{}` or
|
|
21
|
+
* `[]`. A sequence item that is itself a collection starts on the item's line
|
|
22
|
+
* (`- a: 1`). `null`, `true` and `false` are written as themselves and a number
|
|
23
|
+
* as its text, which the core schema reads as an integer or a float. The text
|
|
24
|
+
* ends with a line break.
|
|
25
|
+
*
|
|
26
|
+
* **A string is plain unless it could read as something else.** It is written
|
|
27
|
+
* double-quoted when it is empty; when it reads as null, a boolean or a number
|
|
28
|
+
* under YAML 1.2 or YAML 1.1 (`~`, `null`, `yes`, `on`, `y`, `true` in any
|
|
29
|
+
* case; anything starting with a digit, or a sign or `.` and then a digit;
|
|
30
|
+
* `.inf` and `.nan`, signed or not); when it starts with an indicator (`@`, `` ` ``, `\`, `*`,
|
|
31
|
+
* `&`, `!`, `|`, `>`, `%`, `'`, `"`, `#`, `,`, `[`, `]`, `{`, `}`, or `-`, `?`
|
|
32
|
+
* or `:` before a space or the end) or with `---` or `...`; when it holds
|
|
33
|
+
* `: ` or ` #` or ends in `:`; when it starts or ends with a space; when it
|
|
34
|
+
* holds a control character, a line break, U+2028, U+2029, U+FEFF, U+FFFE or
|
|
35
|
+
* U+FFFF; and, as a key, when it is `<<`, which YAML reads as a merge key.
|
|
36
|
+
* Keys and values follow the same rule. A quoted string escapes `"`, `\` and
|
|
37
|
+
* every character just listed, so it stays on one line. A key whose written
|
|
38
|
+
* form runs past the 1024 bytes YAML allows an implicit key is written as an
|
|
39
|
+
* explicit one, `? key` and then `: value`.
|
|
40
|
+
*
|
|
41
|
+
* **What it answers.** The YAML text, or `""` when `v` names no value or the
|
|
42
|
+
* tree nests deeper than `JSON_WRITER_MAX_DEPTH` collections, the limit
|
|
43
|
+
* `stringify` keeps: a parsed tree never does, and a built one is refused
|
|
44
|
+
* rather than recursed into without bound.
|
|
45
|
+
*
|
|
46
|
+
* A string is written as its UTF-8 bytes. Under Node a string is UTF-16 and
|
|
47
|
+
* each unit is read as a byte, so non-ASCII text differs from the native
|
|
48
|
+
* build, as it does in `nish/json-value`'s builders.
|
|
49
|
+
*/
|
|
50
|
+
import { JSON_WRITER_MAX_DEPTH } from "nish/json"
|
|
51
|
+
import {
|
|
52
|
+
JSON_VALUE_ARRAY,
|
|
53
|
+
JSON_VALUE_BOOLEAN,
|
|
54
|
+
JSON_VALUE_NONE,
|
|
55
|
+
JSON_VALUE_NULL,
|
|
56
|
+
JSON_VALUE_NUMBER,
|
|
57
|
+
JSON_VALUE_OBJECT,
|
|
58
|
+
JsonDocument,
|
|
59
|
+
JsonValue,
|
|
60
|
+
} from "nish/json-value"
|
|
61
|
+
|
|
62
|
+
/** The most bytes an implicit key may run before its `:` (YAML 1.2 §7.4.2). */
|
|
63
|
+
const YAML_WRITE_MAX_KEY_LENGTH: i32 = 1024
|
|
64
|
+
|
|
65
|
+
const YAML_WRITE_HEX: string = "0123456789ABCDEF"
|
|
66
|
+
|
|
67
|
+
/** The bytes the writer puts between scalars. */
|
|
68
|
+
const YAML_WRITE_LF: i32 = 10
|
|
69
|
+
const YAML_WRITE_SPACE: i32 = 32
|
|
70
|
+
const YAML_WRITE_QUOTE: i32 = 34
|
|
71
|
+
const YAML_WRITE_COLON: i32 = 58
|
|
72
|
+
const YAML_WRITE_BACKSLASH: i32 = 92
|
|
73
|
+
|
|
74
|
+
/** Byte `i` of `text`, or `-1` past either end. */
|
|
75
|
+
const yamlWriteByte = (text: string, i: i32): i32 =>
|
|
76
|
+
i >= 0 && i < toI32(text.length) ? toI32(text.charCodeAt(i)) : -1
|
|
77
|
+
|
|
78
|
+
const yamlWriteIsDigit = (c: i32): boolean => c >= 48 && c <= 57
|
|
79
|
+
|
|
80
|
+
/** Whether `c` is an indicator that cannot start a plain scalar, whatever follows it. */
|
|
81
|
+
const yamlWriteIsIndicator = (c: i32): boolean =>
|
|
82
|
+
c === 64 ||
|
|
83
|
+
c === 96 ||
|
|
84
|
+
c === 92 ||
|
|
85
|
+
c === 42 ||
|
|
86
|
+
c === 38 ||
|
|
87
|
+
c === 33 ||
|
|
88
|
+
c === 124 ||
|
|
89
|
+
c === 62 ||
|
|
90
|
+
c === 37 ||
|
|
91
|
+
c === 39 ||
|
|
92
|
+
c === 34 ||
|
|
93
|
+
c === 35 ||
|
|
94
|
+
c === 44 ||
|
|
95
|
+
c === 91 ||
|
|
96
|
+
c === 93 ||
|
|
97
|
+
c === 123 ||
|
|
98
|
+
c === 125
|
|
99
|
+
|
|
100
|
+
/** Whether `text` from byte `from` to its end is `word`, ASCII letters in either case. */
|
|
101
|
+
const yamlWriteMatches = (text: string, from: i32, word: string): boolean => {
|
|
102
|
+
const n: i32 = toI32(word.length)
|
|
103
|
+
if (toI32(text.length) - from !== n) {
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
for (let i: i32 = 0; i < n; i += 1) {
|
|
107
|
+
const c: i32 = yamlWriteByte(text, from + i)
|
|
108
|
+
if ((c >= 65 && c <= 90 ? c + 32 : c) !== yamlWriteByte(word, i)) {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return true
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Whether `text` is one of the words YAML 1.2 or 1.1 reads as null or a boolean. */
|
|
116
|
+
const yamlWriteIsWord = (text: string): boolean =>
|
|
117
|
+
text === "~" ||
|
|
118
|
+
yamlWriteMatches(text, 0, "null") ||
|
|
119
|
+
yamlWriteMatches(text, 0, "true") ||
|
|
120
|
+
yamlWriteMatches(text, 0, "false") ||
|
|
121
|
+
yamlWriteMatches(text, 0, "yes") ||
|
|
122
|
+
yamlWriteMatches(text, 0, "no") ||
|
|
123
|
+
yamlWriteMatches(text, 0, "on") ||
|
|
124
|
+
yamlWriteMatches(text, 0, "off") ||
|
|
125
|
+
yamlWriteMatches(text, 0, "y") ||
|
|
126
|
+
yamlWriteMatches(text, 0, "n")
|
|
127
|
+
|
|
128
|
+
/** Whether `text` could read as a number: a digit first, or a sign or `.` and then a digit, or `.inf` or `.nan`. */
|
|
129
|
+
const yamlWriteIsNumeric = (text: string): boolean => {
|
|
130
|
+
let i: i32 = 0
|
|
131
|
+
const sign: i32 = yamlWriteByte(text, 0)
|
|
132
|
+
if (sign === 43 || sign === 45) {
|
|
133
|
+
i = 1
|
|
134
|
+
}
|
|
135
|
+
const c: i32 = yamlWriteByte(text, i)
|
|
136
|
+
if (yamlWriteIsDigit(c)) {
|
|
137
|
+
return true
|
|
138
|
+
}
|
|
139
|
+
if (c !== 46) {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
if (yamlWriteIsDigit(yamlWriteByte(text, i + 1))) {
|
|
143
|
+
return true
|
|
144
|
+
}
|
|
145
|
+
return yamlWriteMatches(text, i, ".inf") || yamlWriteMatches(text, i, ".nan")
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* How many bytes of `text` from `i` make one character a plain scalar may not
|
|
150
|
+
* hold and a quoted one escapes: a control character, U+0085 and the other C1
|
|
151
|
+
* controls, U+2028, U+2029, U+FEFF, U+FFFE or U+FFFF; `0` for any other.
|
|
152
|
+
*/
|
|
153
|
+
const yamlWriteEscapedLength = (text: string, i: i32): i32 => {
|
|
154
|
+
const c: i32 = yamlWriteByte(text, i)
|
|
155
|
+
if (c < 32 || c === 127) {
|
|
156
|
+
return 1
|
|
157
|
+
}
|
|
158
|
+
const next: i32 = yamlWriteByte(text, i + 1)
|
|
159
|
+
if (c === 194 && next >= 128 && next <= 159) {
|
|
160
|
+
return 2
|
|
161
|
+
}
|
|
162
|
+
const third: i32 = yamlWriteByte(text, i + 2)
|
|
163
|
+
if (c === 226 && next === 128 && (third === 168 || third === 169)) {
|
|
164
|
+
return 3
|
|
165
|
+
}
|
|
166
|
+
if (c === 239 && ((next === 187 && third === 191) || (next === 191 && (third === 190 || third === 191)))) {
|
|
167
|
+
return 3
|
|
168
|
+
}
|
|
169
|
+
return 0
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Whether `text` must be double-quoted to read back as the same string; `key` adds the merge key `<<`. */
|
|
173
|
+
const yamlWriteNeedsQuotes = (text: string, key: boolean): boolean => {
|
|
174
|
+
const n: i32 = toI32(text.length)
|
|
175
|
+
if (n === 0 || yamlWriteIsWord(text) || yamlWriteIsNumeric(text) || (key && text === "<<")) {
|
|
176
|
+
return true
|
|
177
|
+
}
|
|
178
|
+
const first: i32 = yamlWriteByte(text, 0)
|
|
179
|
+
const second: i32 = yamlWriteByte(text, 1)
|
|
180
|
+
if (yamlWriteIsIndicator(first) || first === 32 || yamlWriteByte(text, n - 1) === 32) {
|
|
181
|
+
return true
|
|
182
|
+
}
|
|
183
|
+
if ((first === 45 || first === 63 || first === 58) && (second === 32 || second === -1)) {
|
|
184
|
+
return true
|
|
185
|
+
}
|
|
186
|
+
if (text.startsWith("---") || text.startsWith("...") || yamlWriteByte(text, n - 1) === 58) {
|
|
187
|
+
return true
|
|
188
|
+
}
|
|
189
|
+
for (let i: i32 = 0; i < n; i += 1) {
|
|
190
|
+
const c: i32 = yamlWriteByte(text, i)
|
|
191
|
+
const next: i32 = yamlWriteByte(text, i + 1)
|
|
192
|
+
if ((c === 58 && next === 32) || (c === 32 && next === 35) || yamlWriteEscapedLength(text, i) > 0) {
|
|
193
|
+
return true
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return false
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* How many bytes `text` takes as written: its own, or quoted, two more for the
|
|
201
|
+
* quotes and, for each escape, the bytes it adds to the character it replaces.
|
|
202
|
+
*/
|
|
203
|
+
const yamlWriteLength = (text: string, quoted: boolean): i32 => {
|
|
204
|
+
const n: i32 = toI32(text.length)
|
|
205
|
+
if (!quoted) {
|
|
206
|
+
return n
|
|
207
|
+
}
|
|
208
|
+
let length: i32 = n + 2
|
|
209
|
+
let i: i32 = 0
|
|
210
|
+
while (i < n) {
|
|
211
|
+
const c: i32 = yamlWriteByte(text, i)
|
|
212
|
+
const escaped: i32 = yamlWriteEscapedLength(text, i)
|
|
213
|
+
if (c === 34 || c === 92 || c === 10 || c === 9 || c === 13) {
|
|
214
|
+
length += 1
|
|
215
|
+
} else if (escaped === 1) {
|
|
216
|
+
length += 3
|
|
217
|
+
} else if (escaped > 1) {
|
|
218
|
+
length += escaped
|
|
219
|
+
}
|
|
220
|
+
i += escaped > 1 ? escaped : 1
|
|
221
|
+
}
|
|
222
|
+
return length
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Writes one JSON value as block YAML, byte by byte, into `out`. */
|
|
226
|
+
class YamlWriter {
|
|
227
|
+
doc: JsonDocument
|
|
228
|
+
out: u8[]
|
|
229
|
+
/** Whether a collection nested past `JSON_WRITER_MAX_DEPTH`. */
|
|
230
|
+
tooDeep: boolean = false
|
|
231
|
+
|
|
232
|
+
constructor(doc: JsonDocument) {
|
|
233
|
+
this.doc = doc
|
|
234
|
+
this.out = []
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
byte(c: i32): void {
|
|
238
|
+
this.out.push(toU8(c))
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Writes the bytes of `text` from `from` up to `to`. */
|
|
242
|
+
bytes(text: string, from: i32, to: i32): void {
|
|
243
|
+
for (let i: i32 = from; i < to; i += 1) {
|
|
244
|
+
this.byte(yamlWriteByte(text, i))
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
text(text: string): void {
|
|
249
|
+
const from: i32 = 0
|
|
250
|
+
this.bytes(text, from, toI32(text.length))
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Writes `count` spaces. */
|
|
254
|
+
spaces(count: i32): void {
|
|
255
|
+
for (let i: i32 = 0; i < count; i += 1) {
|
|
256
|
+
this.byte(YAML_WRITE_SPACE)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Writes `\xXX` for byte `c`. */
|
|
261
|
+
hex(c: i32): void {
|
|
262
|
+
this.text("\\x")
|
|
263
|
+
this.byte(yamlWriteByte(YAML_WRITE_HEX, c >> 4))
|
|
264
|
+
this.byte(yamlWriteByte(YAML_WRITE_HEX, c & 15))
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Writes the escape for the `length` bytes at `i`, a character yamlWriteEscapedLength names. */
|
|
268
|
+
escape(text: string, i: i32, length: i32): void {
|
|
269
|
+
const c: i32 = yamlWriteByte(text, i)
|
|
270
|
+
const second: i32 = yamlWriteByte(text, i + 1)
|
|
271
|
+
const third: i32 = yamlWriteByte(text, i + 2)
|
|
272
|
+
if (length === 2) {
|
|
273
|
+
this.hex(second)
|
|
274
|
+
} else if (length === 3 && second === 128) {
|
|
275
|
+
this.text(third === 168 ? "\\u2028" : "\\u2029")
|
|
276
|
+
} else if (length === 3 && second === 187) {
|
|
277
|
+
this.text("\\uFEFF")
|
|
278
|
+
} else if (length === 3) {
|
|
279
|
+
this.text(third === 190 ? "\\uFFFE" : "\\uFFFF")
|
|
280
|
+
} else if (c === 10) {
|
|
281
|
+
this.text("\\n")
|
|
282
|
+
} else if (c === 9) {
|
|
283
|
+
this.text("\\t")
|
|
284
|
+
} else if (c === 13) {
|
|
285
|
+
this.text("\\r")
|
|
286
|
+
} else {
|
|
287
|
+
this.hex(c)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/** Writes `text` as a double-quoted scalar on one line. */
|
|
292
|
+
quoted(text: string): void {
|
|
293
|
+
const n: i32 = toI32(text.length)
|
|
294
|
+
this.byte(YAML_WRITE_QUOTE)
|
|
295
|
+
let i: i32 = 0
|
|
296
|
+
while (i < n) {
|
|
297
|
+
const c: i32 = yamlWriteByte(text, i)
|
|
298
|
+
const length: i32 = yamlWriteEscapedLength(text, i)
|
|
299
|
+
if (c === 34 || c === 92) {
|
|
300
|
+
this.byte(YAML_WRITE_BACKSLASH)
|
|
301
|
+
this.byte(c)
|
|
302
|
+
i += 1
|
|
303
|
+
} else if (length > 0) {
|
|
304
|
+
this.escape(text, i, length)
|
|
305
|
+
i += length
|
|
306
|
+
} else {
|
|
307
|
+
this.byte(c)
|
|
308
|
+
i += 1
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
this.byte(YAML_WRITE_QUOTE)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Writes `text` as a scalar: plain when that reads back as the same string, double-quoted otherwise. */
|
|
315
|
+
string(text: string, quoted: boolean): void {
|
|
316
|
+
if (quoted) {
|
|
317
|
+
this.quoted(text)
|
|
318
|
+
} else {
|
|
319
|
+
this.text(text)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Whether `v` is a collection with members, which takes lines of its own. */
|
|
324
|
+
isBlock(v: JsonValue): boolean {
|
|
325
|
+
const kind: i32 = this.doc.kind(v)
|
|
326
|
+
return (kind === JSON_VALUE_ARRAY || kind === JSON_VALUE_OBJECT) && this.doc.length(v) > 0
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** Writes `v` on one line: a scalar, `{}` or `[]`. */
|
|
330
|
+
inline(v: JsonValue): void {
|
|
331
|
+
const doc: JsonDocument = this.doc
|
|
332
|
+
const kind: i32 = doc.kind(v)
|
|
333
|
+
if (kind === JSON_VALUE_NULL) {
|
|
334
|
+
this.text("null")
|
|
335
|
+
} else if (kind === JSON_VALUE_BOOLEAN) {
|
|
336
|
+
this.text(doc.boolean(v) ? "true" : "false")
|
|
337
|
+
} else if (kind === JSON_VALUE_NUMBER) {
|
|
338
|
+
this.text(doc.numberText(v))
|
|
339
|
+
} else if (kind === JSON_VALUE_ARRAY) {
|
|
340
|
+
this.text("[]")
|
|
341
|
+
} else if (kind === JSON_VALUE_OBJECT) {
|
|
342
|
+
this.text("{}")
|
|
343
|
+
} else {
|
|
344
|
+
const text: string = doc.string(v)
|
|
345
|
+
this.string(text, yamlWriteNeedsQuotes(text, false))
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Writes `v` starting at column `indent`, where the line has already reached
|
|
351
|
+
* it, and ends its last line; `depth` is how many collections hold it.
|
|
352
|
+
*/
|
|
353
|
+
node(v: JsonValue, indent: i32, depth: i32): void {
|
|
354
|
+
const doc: JsonDocument = this.doc
|
|
355
|
+
const kind: i32 = doc.kind(v)
|
|
356
|
+
if ((kind === JSON_VALUE_ARRAY || kind === JSON_VALUE_OBJECT) && depth >= JSON_WRITER_MAX_DEPTH) {
|
|
357
|
+
this.tooDeep = true
|
|
358
|
+
return
|
|
359
|
+
}
|
|
360
|
+
if (!this.isBlock(v)) {
|
|
361
|
+
this.inline(v)
|
|
362
|
+
this.byte(YAML_WRITE_LF)
|
|
363
|
+
return
|
|
364
|
+
}
|
|
365
|
+
const object: boolean = kind === JSON_VALUE_OBJECT
|
|
366
|
+
for (let i: i32 = 0; i < doc.length(v) && !this.tooDeep; i += 1) {
|
|
367
|
+
if (i > 0) {
|
|
368
|
+
this.spaces(indent)
|
|
369
|
+
}
|
|
370
|
+
const member: JsonValue = doc.at(v, i)
|
|
371
|
+
if (!object) {
|
|
372
|
+
this.text("- ")
|
|
373
|
+
this.node(member, indent + 2, depth + 1)
|
|
374
|
+
continue
|
|
375
|
+
}
|
|
376
|
+
const key: string = doc.keyAt(v, i)
|
|
377
|
+
const quoted: boolean = yamlWriteNeedsQuotes(key, true)
|
|
378
|
+
const explicit: boolean = yamlWriteLength(key, quoted) > YAML_WRITE_MAX_KEY_LENGTH
|
|
379
|
+
if (explicit) {
|
|
380
|
+
this.text("? ")
|
|
381
|
+
}
|
|
382
|
+
this.string(key, quoted)
|
|
383
|
+
if (explicit) {
|
|
384
|
+
this.byte(YAML_WRITE_LF)
|
|
385
|
+
this.spaces(indent)
|
|
386
|
+
}
|
|
387
|
+
this.byte(YAML_WRITE_COLON)
|
|
388
|
+
if (this.isBlock(member)) {
|
|
389
|
+
this.byte(YAML_WRITE_LF)
|
|
390
|
+
this.spaces(indent + 2)
|
|
391
|
+
} else {
|
|
392
|
+
this.byte(YAML_WRITE_SPACE)
|
|
393
|
+
}
|
|
394
|
+
this.node(member, indent + 2, depth + 1)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* `v` of `doc` as block YAML text that `parseYaml` reads back as the same
|
|
401
|
+
* tree; `""` when `v` names no value or nests deeper than
|
|
402
|
+
* `JSON_WRITER_MAX_DEPTH` collections. See the module comment for the rule
|
|
403
|
+
* that quotes a string.
|
|
404
|
+
*/
|
|
405
|
+
export const stringifyYaml = (doc: JsonDocument, v: JsonValue): string => {
|
|
406
|
+
if (doc.kind(v) === JSON_VALUE_NONE) {
|
|
407
|
+
return ""
|
|
408
|
+
}
|
|
409
|
+
const writer: YamlWriter = new YamlWriter(doc)
|
|
410
|
+
const indent: i32 = 0
|
|
411
|
+
const depth: i32 = 0
|
|
412
|
+
writer.node(v, indent, depth)
|
|
413
|
+
const from: i32 = 0
|
|
414
|
+
return writer.tooDeep ? "" : String.fromBytes(writer.out, from, toI32(writer.out.length))
|
|
415
|
+
}
|