yaml 2.3.4 → 2.4.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.
- package/README.md +11 -9
- package/bin.mjs +11 -0
- package/browser/dist/compose/resolve-flow-scalar.js +13 -13
- package/browser/dist/parse/parser.js +4 -1
- package/browser/dist/schema/yaml-1.1/binary.js +1 -1
- package/browser/dist/stringify/foldFlowLines.js +19 -10
- package/browser/dist/stringify/stringifyCollection.js +6 -14
- package/dist/cli.d.ts +9 -0
- package/dist/cli.mjs +195 -0
- package/dist/compose/resolve-flow-scalar.js +13 -13
- package/dist/nodes/Pair.d.ts +1 -1
- package/dist/parse/cst.d.ts +1 -1
- package/dist/parse/parser.js +4 -1
- package/dist/schema/yaml-1.1/binary.js +1 -1
- package/dist/stringify/foldFlowLines.js +19 -10
- package/dist/stringify/stringifyCollection.js +6 -14
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -33,6 +33,8 @@ npm install yaml
|
|
|
33
33
|
The API provided by `yaml` has three layers, depending on how deep you need to go: [Parse & Stringify](https://eemeli.org/yaml/#parse-amp-stringify), [Documents](https://eemeli.org/yaml/#documents), and the underlying [Lexer/Parser/Composer](https://eemeli.org/yaml/#parsing-yaml).
|
|
34
34
|
The first has the simplest API and "just works", the second gets you all the bells and whistles supported by the library along with a decent [AST](https://eemeli.org/yaml/#content-nodes), and the third lets you get progressively closer to YAML source, if that's your thing.
|
|
35
35
|
|
|
36
|
+
A [command-line tool](https://eemeli.org/yaml/#command-line-tool) is also included.
|
|
37
|
+
|
|
36
38
|
```js
|
|
37
39
|
import { parse, stringify } from 'yaml'
|
|
38
40
|
// or
|
|
@@ -55,26 +57,26 @@ const YAML = require('yaml')
|
|
|
55
57
|
- [`#directives`](https://eemeli.org/yaml/#stream-directives)
|
|
56
58
|
- [`#errors`](https://eemeli.org/yaml/#errors)
|
|
57
59
|
- [`#warnings`](https://eemeli.org/yaml/#errors)
|
|
58
|
-
- [`isDocument(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
60
|
+
- [`isDocument(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
59
61
|
- [`parseAllDocuments(str, options?): Document[]`](https://eemeli.org/yaml/#parsing-documents)
|
|
60
62
|
- [`parseDocument(str, options?): Document`](https://eemeli.org/yaml/#parsing-documents)
|
|
61
63
|
|
|
62
64
|
### Content Nodes
|
|
63
65
|
|
|
64
|
-
- [`isAlias(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
65
|
-
- [`isCollection(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
66
|
-
- [`isMap(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
67
|
-
- [`isNode(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
68
|
-
- [`isPair(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
69
|
-
- [`isScalar(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
70
|
-
- [`isSeq(foo): boolean`](https://eemeli.org/yaml/#identifying-
|
|
66
|
+
- [`isAlias(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
67
|
+
- [`isCollection(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
68
|
+
- [`isMap(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
69
|
+
- [`isNode(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
70
|
+
- [`isPair(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
71
|
+
- [`isScalar(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
72
|
+
- [`isSeq(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
71
73
|
- [`new Scalar(value)`](https://eemeli.org/yaml/#scalar-values)
|
|
72
74
|
- [`new YAMLMap()`](https://eemeli.org/yaml/#collections)
|
|
73
75
|
- [`new YAMLSeq()`](https://eemeli.org/yaml/#collections)
|
|
74
76
|
- [`doc.createAlias(node, name?): Alias`](https://eemeli.org/yaml/#working-with-anchors)
|
|
75
77
|
- [`doc.createNode(value, options?): Node`](https://eemeli.org/yaml/#creating-nodes)
|
|
76
78
|
- [`doc.createPair(key, value): Pair`](https://eemeli.org/yaml/#creating-nodes)
|
|
77
|
-
- [`visit(node, visitor)`](https://eemeli.org/yaml/#modifying-nodes)
|
|
79
|
+
- [`visit(node, visitor)`](https://eemeli.org/yaml/#finding-and-modifying-nodes)
|
|
78
80
|
|
|
79
81
|
### Parsing YAML
|
|
80
82
|
|
package/bin.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { UserError, cli, help } from './dist/cli.mjs'
|
|
4
|
+
|
|
5
|
+
cli(process.stdin, error => {
|
|
6
|
+
if (error instanceof UserError) {
|
|
7
|
+
if (error.code === UserError.ARGS) console.error(`${help}\n`)
|
|
8
|
+
console.error(error.message)
|
|
9
|
+
process.exitCode = error.code
|
|
10
|
+
} else if (error) throw error
|
|
11
|
+
})
|
|
@@ -189,19 +189,19 @@ function foldNewline(source, offset) {
|
|
|
189
189
|
return { fold, offset };
|
|
190
190
|
}
|
|
191
191
|
const escapeCodes = {
|
|
192
|
-
'0': '\0',
|
|
193
|
-
a: '\x07',
|
|
194
|
-
b: '\b',
|
|
195
|
-
e: '\x1b',
|
|
196
|
-
f: '\f',
|
|
197
|
-
n: '\n',
|
|
198
|
-
r: '\r',
|
|
199
|
-
t: '\t',
|
|
200
|
-
v: '\v',
|
|
201
|
-
N: '\u0085',
|
|
202
|
-
_: '\u00a0',
|
|
203
|
-
L: '\u2028',
|
|
204
|
-
P: '\u2029',
|
|
192
|
+
'0': '\0', // null character
|
|
193
|
+
a: '\x07', // bell character
|
|
194
|
+
b: '\b', // backspace
|
|
195
|
+
e: '\x1b', // escape character
|
|
196
|
+
f: '\f', // form feed
|
|
197
|
+
n: '\n', // line feed
|
|
198
|
+
r: '\r', // carriage return
|
|
199
|
+
t: '\t', // horizontal tab
|
|
200
|
+
v: '\v', // vertical tab
|
|
201
|
+
N: '\u0085', // Unicode next line
|
|
202
|
+
_: '\u00a0', // Unicode non-breaking space
|
|
203
|
+
L: '\u2028', // Unicode line separator
|
|
204
|
+
P: '\u2029', // Unicode paragraph separator
|
|
205
205
|
' ': ' ',
|
|
206
206
|
'"': '"',
|
|
207
207
|
'/': '/',
|
|
@@ -513,7 +513,10 @@ class Parser {
|
|
|
513
513
|
return;
|
|
514
514
|
}
|
|
515
515
|
if (this.indent >= map.indent) {
|
|
516
|
-
const atNextItem = !this.onKeyLine &&
|
|
516
|
+
const atNextItem = !this.onKeyLine &&
|
|
517
|
+
this.indent === map.indent &&
|
|
518
|
+
it.sep &&
|
|
519
|
+
this.type !== 'seq-item-ind';
|
|
517
520
|
// For empty nodes, assign newline-separated not indented empty tokens to following node
|
|
518
521
|
let start = [];
|
|
519
522
|
if (atNextItem && it.sep && !it.value) {
|
|
@@ -2,7 +2,7 @@ import { Scalar } from '../../nodes/Scalar.js';
|
|
|
2
2
|
import { stringifyString } from '../../stringify/stringifyString.js';
|
|
3
3
|
|
|
4
4
|
const binary = {
|
|
5
|
-
identify: value => value instanceof Uint8Array,
|
|
5
|
+
identify: value => value instanceof Uint8Array, // Buffer inherits from Uint8Array
|
|
6
6
|
default: false,
|
|
7
7
|
tag: 'tag:yaml.org,2002:binary',
|
|
8
8
|
/**
|
|
@@ -28,7 +28,7 @@ function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth =
|
|
|
28
28
|
let escStart = -1;
|
|
29
29
|
let escEnd = -1;
|
|
30
30
|
if (mode === FOLD_BLOCK) {
|
|
31
|
-
i = consumeMoreIndentedLines(text, i);
|
|
31
|
+
i = consumeMoreIndentedLines(text, i, indent.length);
|
|
32
32
|
if (i !== -1)
|
|
33
33
|
end = i + endStep;
|
|
34
34
|
}
|
|
@@ -52,8 +52,8 @@ function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth =
|
|
|
52
52
|
}
|
|
53
53
|
if (ch === '\n') {
|
|
54
54
|
if (mode === FOLD_BLOCK)
|
|
55
|
-
i = consumeMoreIndentedLines(text, i);
|
|
56
|
-
end = i + endStep;
|
|
55
|
+
i = consumeMoreIndentedLines(text, i, indent.length);
|
|
56
|
+
end = i + indent.length + endStep;
|
|
57
57
|
split = undefined;
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
@@ -121,15 +121,24 @@ function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth =
|
|
|
121
121
|
* Presumes `i + 1` is at the start of a line
|
|
122
122
|
* @returns index of last newline in more-indented block
|
|
123
123
|
*/
|
|
124
|
-
function consumeMoreIndentedLines(text, i) {
|
|
125
|
-
let
|
|
124
|
+
function consumeMoreIndentedLines(text, i, indent) {
|
|
125
|
+
let end = i;
|
|
126
|
+
let start = i + 1;
|
|
127
|
+
let ch = text[start];
|
|
126
128
|
while (ch === ' ' || ch === '\t') {
|
|
127
|
-
|
|
128
|
-
ch = text[
|
|
129
|
-
}
|
|
130
|
-
|
|
129
|
+
if (i < start + indent) {
|
|
130
|
+
ch = text[++i];
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
do {
|
|
134
|
+
ch = text[++i];
|
|
135
|
+
} while (ch && ch !== '\n');
|
|
136
|
+
end = i;
|
|
137
|
+
start = i + 1;
|
|
138
|
+
ch = text[start];
|
|
139
|
+
}
|
|
131
140
|
}
|
|
132
|
-
return
|
|
141
|
+
return end;
|
|
133
142
|
}
|
|
134
143
|
|
|
135
144
|
export { FOLD_BLOCK, FOLD_FLOW, FOLD_QUOTED, foldFlowLines };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Collection } from '../nodes/Collection.js';
|
|
2
1
|
import { isNode, isPair } from '../nodes/identity.js';
|
|
3
2
|
import { stringify } from './stringify.js';
|
|
4
3
|
import { lineComment, indentComment } from './stringifyComment.js';
|
|
@@ -59,7 +58,7 @@ function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, fl
|
|
|
59
58
|
onChompKeep();
|
|
60
59
|
return str;
|
|
61
60
|
}
|
|
62
|
-
function stringifyFlowCollection({
|
|
61
|
+
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
63
62
|
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
|
64
63
|
itemIndent += indentStep;
|
|
65
64
|
const itemCtx = Object.assign({}, ctx, {
|
|
@@ -112,32 +111,25 @@ function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemInden
|
|
|
112
111
|
lines.push(str);
|
|
113
112
|
linesAtValue = lines.length;
|
|
114
113
|
}
|
|
115
|
-
let str;
|
|
116
114
|
const { start, end } = flowChars;
|
|
117
115
|
if (lines.length === 0) {
|
|
118
|
-
|
|
116
|
+
return start + end;
|
|
119
117
|
}
|
|
120
118
|
else {
|
|
121
119
|
if (!reqNewline) {
|
|
122
120
|
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
|
|
123
|
-
reqNewline = len >
|
|
121
|
+
reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
|
|
124
122
|
}
|
|
125
123
|
if (reqNewline) {
|
|
126
|
-
str = start;
|
|
124
|
+
let str = start;
|
|
127
125
|
for (const line of lines)
|
|
128
126
|
str += line ? `\n${indentStep}${indent}${line}` : '\n';
|
|
129
|
-
str
|
|
127
|
+
return `${str}\n${indent}${end}`;
|
|
130
128
|
}
|
|
131
129
|
else {
|
|
132
|
-
|
|
130
|
+
return `${start}${fcPadding}${lines.join(' ')}${fcPadding}${end}`;
|
|
133
131
|
}
|
|
134
132
|
}
|
|
135
|
-
if (comment) {
|
|
136
|
-
str += lineComment(str, indent, commentString(comment));
|
|
137
|
-
if (onComment)
|
|
138
|
-
onComment();
|
|
139
|
-
}
|
|
140
|
-
return str;
|
|
141
133
|
}
|
|
142
134
|
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
|
|
143
135
|
if (comment && chompKeep)
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare const help = "yaml: A command-line YAML processor and inspector\n\nReads stdin and writes output to stdout and errors & warnings to stderr.\n\nUsage:\n yaml Process a YAML stream, outputting it as YAML\n yaml cst Parse the CST of a YAML stream\n yaml lex Parse the lexical tokens of a YAML stream\n yaml valid Validate a YAML stream, returning 0 on success\n\nOptions:\n --help, -h Show this message.\n --json, -j Output JSON.\n\nAdditional options for bare \"yaml\" command:\n --doc, -d Output pretty-printed JS Document objects.\n --single, -1 Require the input to consist of a single YAML document.\n --strict, -s Stop on errors.\n --visit, -v Apply a visitor to each document (requires a path to import)\n --yaml 1.1 Set the YAML version. (default: 1.2)";
|
|
3
|
+
export declare class UserError extends Error {
|
|
4
|
+
static ARGS: number;
|
|
5
|
+
static SINGLE: number;
|
|
6
|
+
code: number;
|
|
7
|
+
constructor(code: number, message: string);
|
|
8
|
+
}
|
|
9
|
+
export declare function cli(stdin: NodeJS.ReadableStream, done: (error?: Error) => void, argv?: string[]): Promise<void>;
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { prettyToken } from './parse/cst.js';
|
|
4
|
+
import { Lexer } from './parse/lexer.js';
|
|
5
|
+
import { Parser } from './parse/parser.js';
|
|
6
|
+
import { Composer } from './compose/composer.js';
|
|
7
|
+
import { LineCounter } from './parse/line-counter.js';
|
|
8
|
+
import { prettifyError } from './errors.js';
|
|
9
|
+
import { visit } from './visit.js';
|
|
10
|
+
|
|
11
|
+
const help = `\
|
|
12
|
+
yaml: A command-line YAML processor and inspector
|
|
13
|
+
|
|
14
|
+
Reads stdin and writes output to stdout and errors & warnings to stderr.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
yaml Process a YAML stream, outputting it as YAML
|
|
18
|
+
yaml cst Parse the CST of a YAML stream
|
|
19
|
+
yaml lex Parse the lexical tokens of a YAML stream
|
|
20
|
+
yaml valid Validate a YAML stream, returning 0 on success
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--help, -h Show this message.
|
|
24
|
+
--json, -j Output JSON.
|
|
25
|
+
|
|
26
|
+
Additional options for bare "yaml" command:
|
|
27
|
+
--doc, -d Output pretty-printed JS Document objects.
|
|
28
|
+
--single, -1 Require the input to consist of a single YAML document.
|
|
29
|
+
--strict, -s Stop on errors.
|
|
30
|
+
--visit, -v Apply a visitor to each document (requires a path to import)
|
|
31
|
+
--yaml 1.1 Set the YAML version. (default: 1.2)`;
|
|
32
|
+
class UserError extends Error {
|
|
33
|
+
constructor(code, message) {
|
|
34
|
+
super(`Error: ${message}`);
|
|
35
|
+
this.code = code;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
UserError.ARGS = 2;
|
|
39
|
+
UserError.SINGLE = 3;
|
|
40
|
+
async function cli(stdin, done, argv) {
|
|
41
|
+
let args;
|
|
42
|
+
try {
|
|
43
|
+
args = parseArgs({
|
|
44
|
+
args: argv,
|
|
45
|
+
allowPositionals: true,
|
|
46
|
+
options: {
|
|
47
|
+
doc: { type: 'boolean', short: 'd' },
|
|
48
|
+
help: { type: 'boolean', short: 'h' },
|
|
49
|
+
json: { type: 'boolean', short: 'j' },
|
|
50
|
+
single: { type: 'boolean', short: '1' },
|
|
51
|
+
strict: { type: 'boolean', short: 's' },
|
|
52
|
+
visit: { type: 'string', short: 'v' },
|
|
53
|
+
yaml: { type: 'string', default: '1.2' }
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return done(new UserError(UserError.ARGS, error.message));
|
|
59
|
+
}
|
|
60
|
+
const { positionals: [mode], values: opt } = args;
|
|
61
|
+
stdin.setEncoding('utf-8');
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
63
|
+
switch (opt.help || mode) {
|
|
64
|
+
/* istanbul ignore next */
|
|
65
|
+
case true: // --help
|
|
66
|
+
console.log(help);
|
|
67
|
+
break;
|
|
68
|
+
case 'lex': {
|
|
69
|
+
const lexer = new Lexer();
|
|
70
|
+
const data = [];
|
|
71
|
+
const add = (tok) => {
|
|
72
|
+
if (opt.json)
|
|
73
|
+
data.push(tok);
|
|
74
|
+
else
|
|
75
|
+
console.log(prettyToken(tok));
|
|
76
|
+
};
|
|
77
|
+
stdin.on('data', (chunk) => {
|
|
78
|
+
for (const tok of lexer.lex(chunk, true))
|
|
79
|
+
add(tok);
|
|
80
|
+
});
|
|
81
|
+
stdin.on('end', () => {
|
|
82
|
+
for (const tok of lexer.lex('', false))
|
|
83
|
+
add(tok);
|
|
84
|
+
if (opt.json)
|
|
85
|
+
console.log(JSON.stringify(data));
|
|
86
|
+
done();
|
|
87
|
+
});
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'cst': {
|
|
91
|
+
const parser = new Parser();
|
|
92
|
+
const data = [];
|
|
93
|
+
const add = (tok) => {
|
|
94
|
+
if (opt.json)
|
|
95
|
+
data.push(tok);
|
|
96
|
+
else
|
|
97
|
+
console.dir(tok, { depth: null });
|
|
98
|
+
};
|
|
99
|
+
stdin.on('data', (chunk) => {
|
|
100
|
+
for (const tok of parser.parse(chunk, true))
|
|
101
|
+
add(tok);
|
|
102
|
+
});
|
|
103
|
+
stdin.on('end', () => {
|
|
104
|
+
for (const tok of parser.parse('', false))
|
|
105
|
+
add(tok);
|
|
106
|
+
if (opt.json)
|
|
107
|
+
console.log(JSON.stringify(data));
|
|
108
|
+
done();
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case undefined:
|
|
113
|
+
case 'valid': {
|
|
114
|
+
const lineCounter = new LineCounter();
|
|
115
|
+
const parser = new Parser(lineCounter.addNewLine);
|
|
116
|
+
// @ts-expect-error Version is validated at runtime
|
|
117
|
+
const composer = new Composer({ version: opt.yaml });
|
|
118
|
+
const visitor = opt.visit
|
|
119
|
+
? (await import(resolve(opt.visit))).default
|
|
120
|
+
: null;
|
|
121
|
+
let source = '';
|
|
122
|
+
let hasDoc = false;
|
|
123
|
+
let reqDocEnd = false;
|
|
124
|
+
const data = [];
|
|
125
|
+
const add = (doc) => {
|
|
126
|
+
if (hasDoc && opt.single) {
|
|
127
|
+
return done(new UserError(UserError.SINGLE, 'Input stream contains multiple documents'));
|
|
128
|
+
}
|
|
129
|
+
for (const error of doc.errors) {
|
|
130
|
+
prettifyError(source, lineCounter)(error);
|
|
131
|
+
if (opt.strict || mode === 'valid')
|
|
132
|
+
return done(error);
|
|
133
|
+
console.error(error);
|
|
134
|
+
}
|
|
135
|
+
for (const warning of doc.warnings) {
|
|
136
|
+
prettifyError(source, lineCounter)(warning);
|
|
137
|
+
console.error(warning);
|
|
138
|
+
}
|
|
139
|
+
if (visitor)
|
|
140
|
+
visit(doc, visitor);
|
|
141
|
+
if (mode === 'valid')
|
|
142
|
+
doc.toJS();
|
|
143
|
+
else if (opt.json)
|
|
144
|
+
data.push(doc);
|
|
145
|
+
else if (opt.doc) {
|
|
146
|
+
Object.defineProperties(doc, {
|
|
147
|
+
options: { enumerable: false },
|
|
148
|
+
schema: { enumerable: false }
|
|
149
|
+
});
|
|
150
|
+
console.dir(doc, { depth: null });
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
if (reqDocEnd)
|
|
154
|
+
console.log('...');
|
|
155
|
+
try {
|
|
156
|
+
const str = String(doc);
|
|
157
|
+
console.log(str.endsWith('\n') ? str.slice(0, -1) : str);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
done(error);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
hasDoc = true;
|
|
164
|
+
reqDocEnd = !doc.directives?.docEnd;
|
|
165
|
+
};
|
|
166
|
+
stdin.on('data', (chunk) => {
|
|
167
|
+
source += chunk;
|
|
168
|
+
for (const tok of parser.parse(chunk, true)) {
|
|
169
|
+
for (const doc of composer.next(tok))
|
|
170
|
+
add(doc);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
stdin.on('end', () => {
|
|
174
|
+
for (const tok of parser.parse('', false)) {
|
|
175
|
+
for (const doc of composer.next(tok))
|
|
176
|
+
add(doc);
|
|
177
|
+
}
|
|
178
|
+
for (const doc of composer.end(false))
|
|
179
|
+
add(doc);
|
|
180
|
+
if (opt.single && !hasDoc) {
|
|
181
|
+
return done(new UserError(UserError.SINGLE, 'Input stream contained no documents'));
|
|
182
|
+
}
|
|
183
|
+
if (mode !== 'valid' && opt.json) {
|
|
184
|
+
console.log(JSON.stringify(opt.single ? data[0] : data));
|
|
185
|
+
}
|
|
186
|
+
done();
|
|
187
|
+
});
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
default:
|
|
191
|
+
done(new UserError(UserError.ARGS, `Unknown command: ${JSON.stringify(mode)}`));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export { UserError, cli, help };
|
|
@@ -191,19 +191,19 @@ function foldNewline(source, offset) {
|
|
|
191
191
|
return { fold, offset };
|
|
192
192
|
}
|
|
193
193
|
const escapeCodes = {
|
|
194
|
-
'0': '\0',
|
|
195
|
-
a: '\x07',
|
|
196
|
-
b: '\b',
|
|
197
|
-
e: '\x1b',
|
|
198
|
-
f: '\f',
|
|
199
|
-
n: '\n',
|
|
200
|
-
r: '\r',
|
|
201
|
-
t: '\t',
|
|
202
|
-
v: '\v',
|
|
203
|
-
N: '\u0085',
|
|
204
|
-
_: '\u00a0',
|
|
205
|
-
L: '\u2028',
|
|
206
|
-
P: '\u2029',
|
|
194
|
+
'0': '\0', // null character
|
|
195
|
+
a: '\x07', // bell character
|
|
196
|
+
b: '\b', // backspace
|
|
197
|
+
e: '\x1b', // escape character
|
|
198
|
+
f: '\f', // form feed
|
|
199
|
+
n: '\n', // line feed
|
|
200
|
+
r: '\r', // carriage return
|
|
201
|
+
t: '\t', // horizontal tab
|
|
202
|
+
v: '\v', // vertical tab
|
|
203
|
+
N: '\u0085', // Unicode next line
|
|
204
|
+
_: '\u00a0', // Unicode non-breaking space
|
|
205
|
+
L: '\u2028', // Unicode line separator
|
|
206
|
+
P: '\u2029', // Unicode paragraph separator
|
|
207
207
|
' ': ' ',
|
|
208
208
|
'"': '"',
|
|
209
209
|
'/': '/',
|
package/dist/nodes/Pair.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { StringifyContext } from '../stringify/stringify.js';
|
|
|
5
5
|
import { addPairToJSMap } from './addPairToJSMap.js';
|
|
6
6
|
import { NODE_TYPE } from './identity.js';
|
|
7
7
|
import type { ToJSContext } from './toJS.js';
|
|
8
|
-
export declare function createPair(key: unknown, value: unknown, ctx: CreateNodeContext): Pair<import("./Node.js").Node, import("./
|
|
8
|
+
export declare function createPair(key: unknown, value: unknown, ctx: CreateNodeContext): Pair<import("./Node.js").Node, import("./Alias.js").Alias | import("./Scalar.js").Scalar<unknown> | import("./YAMLMap.js").YAMLMap<unknown, unknown> | import("./YAMLSeq.js").YAMLSeq<unknown>>;
|
|
9
9
|
export declare class Pair<K = unknown, V = unknown> {
|
|
10
10
|
readonly [NODE_TYPE]: symbol;
|
|
11
11
|
/** Always Node or null when parsed, but can be set to anything. */
|
package/dist/parse/cst.d.ts
CHANGED
|
@@ -99,7 +99,7 @@ export declare const SCALAR = "\u001F";
|
|
|
99
99
|
/** @returns `true` if `token` is a flow or block collection */
|
|
100
100
|
export declare const isCollection: (token: Token | null | undefined) => token is BlockMap | BlockSequence | FlowCollection;
|
|
101
101
|
/** @returns `true` if `token` is a flow or block scalar; not an alias */
|
|
102
|
-
export declare const isScalar: (token: Token | null | undefined) => token is
|
|
102
|
+
export declare const isScalar: (token: Token | null | undefined) => token is FlowScalar | BlockScalar;
|
|
103
103
|
/** Get a printable representation of a lexer token */
|
|
104
104
|
export declare function prettyToken(token: string): string;
|
|
105
105
|
/** Identify the type of a lexer token. May return `null` for unknown tokens. */
|
package/dist/parse/parser.js
CHANGED
|
@@ -517,7 +517,10 @@ class Parser {
|
|
|
517
517
|
return;
|
|
518
518
|
}
|
|
519
519
|
if (this.indent >= map.indent) {
|
|
520
|
-
const atNextItem = !this.onKeyLine &&
|
|
520
|
+
const atNextItem = !this.onKeyLine &&
|
|
521
|
+
this.indent === map.indent &&
|
|
522
|
+
it.sep &&
|
|
523
|
+
this.type !== 'seq-item-ind';
|
|
521
524
|
// For empty nodes, assign newline-separated not indented empty tokens to following node
|
|
522
525
|
let start = [];
|
|
523
526
|
if (atNextItem && it.sep && !it.value) {
|
|
@@ -4,7 +4,7 @@ var Scalar = require('../../nodes/Scalar.js');
|
|
|
4
4
|
var stringifyString = require('../../stringify/stringifyString.js');
|
|
5
5
|
|
|
6
6
|
const binary = {
|
|
7
|
-
identify: value => value instanceof Uint8Array,
|
|
7
|
+
identify: value => value instanceof Uint8Array, // Buffer inherits from Uint8Array
|
|
8
8
|
default: false,
|
|
9
9
|
tag: 'tag:yaml.org,2002:binary',
|
|
10
10
|
/**
|
|
@@ -30,7 +30,7 @@ function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth =
|
|
|
30
30
|
let escStart = -1;
|
|
31
31
|
let escEnd = -1;
|
|
32
32
|
if (mode === FOLD_BLOCK) {
|
|
33
|
-
i = consumeMoreIndentedLines(text, i);
|
|
33
|
+
i = consumeMoreIndentedLines(text, i, indent.length);
|
|
34
34
|
if (i !== -1)
|
|
35
35
|
end = i + endStep;
|
|
36
36
|
}
|
|
@@ -54,8 +54,8 @@ function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth =
|
|
|
54
54
|
}
|
|
55
55
|
if (ch === '\n') {
|
|
56
56
|
if (mode === FOLD_BLOCK)
|
|
57
|
-
i = consumeMoreIndentedLines(text, i);
|
|
58
|
-
end = i + endStep;
|
|
57
|
+
i = consumeMoreIndentedLines(text, i, indent.length);
|
|
58
|
+
end = i + indent.length + endStep;
|
|
59
59
|
split = undefined;
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
@@ -123,15 +123,24 @@ function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth =
|
|
|
123
123
|
* Presumes `i + 1` is at the start of a line
|
|
124
124
|
* @returns index of last newline in more-indented block
|
|
125
125
|
*/
|
|
126
|
-
function consumeMoreIndentedLines(text, i) {
|
|
127
|
-
let
|
|
126
|
+
function consumeMoreIndentedLines(text, i, indent) {
|
|
127
|
+
let end = i;
|
|
128
|
+
let start = i + 1;
|
|
129
|
+
let ch = text[start];
|
|
128
130
|
while (ch === ' ' || ch === '\t') {
|
|
129
|
-
|
|
130
|
-
ch = text[
|
|
131
|
-
}
|
|
132
|
-
|
|
131
|
+
if (i < start + indent) {
|
|
132
|
+
ch = text[++i];
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
do {
|
|
136
|
+
ch = text[++i];
|
|
137
|
+
} while (ch && ch !== '\n');
|
|
138
|
+
end = i;
|
|
139
|
+
start = i + 1;
|
|
140
|
+
ch = text[start];
|
|
141
|
+
}
|
|
133
142
|
}
|
|
134
|
-
return
|
|
143
|
+
return end;
|
|
135
144
|
}
|
|
136
145
|
|
|
137
146
|
exports.FOLD_BLOCK = FOLD_BLOCK;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var Collection = require('../nodes/Collection.js');
|
|
4
3
|
var identity = require('../nodes/identity.js');
|
|
5
4
|
var stringify = require('./stringify.js');
|
|
6
5
|
var stringifyComment = require('./stringifyComment.js');
|
|
@@ -61,7 +60,7 @@ function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, fl
|
|
|
61
60
|
onChompKeep();
|
|
62
61
|
return str;
|
|
63
62
|
}
|
|
64
|
-
function stringifyFlowCollection({
|
|
63
|
+
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
65
64
|
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
|
66
65
|
itemIndent += indentStep;
|
|
67
66
|
const itemCtx = Object.assign({}, ctx, {
|
|
@@ -114,32 +113,25 @@ function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemInden
|
|
|
114
113
|
lines.push(str);
|
|
115
114
|
linesAtValue = lines.length;
|
|
116
115
|
}
|
|
117
|
-
let str;
|
|
118
116
|
const { start, end } = flowChars;
|
|
119
117
|
if (lines.length === 0) {
|
|
120
|
-
|
|
118
|
+
return start + end;
|
|
121
119
|
}
|
|
122
120
|
else {
|
|
123
121
|
if (!reqNewline) {
|
|
124
122
|
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
|
|
125
|
-
reqNewline = len >
|
|
123
|
+
reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
|
|
126
124
|
}
|
|
127
125
|
if (reqNewline) {
|
|
128
|
-
str = start;
|
|
126
|
+
let str = start;
|
|
129
127
|
for (const line of lines)
|
|
130
128
|
str += line ? `\n${indentStep}${indent}${line}` : '\n';
|
|
131
|
-
str
|
|
129
|
+
return `${str}\n${indent}${end}`;
|
|
132
130
|
}
|
|
133
131
|
else {
|
|
134
|
-
|
|
132
|
+
return `${start}${fcPadding}${lines.join(' ')}${fcPadding}${end}`;
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
|
-
if (comment) {
|
|
138
|
-
str += stringifyComment.lineComment(str, indent, commentString(comment));
|
|
139
|
-
if (onComment)
|
|
140
|
-
onComment();
|
|
141
|
-
}
|
|
142
|
-
return str;
|
|
143
135
|
}
|
|
144
136
|
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
|
|
145
137
|
if (comment && chompKeep)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaml",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"author": "Eemeli Aro <eemeli@gmail.com>",
|
|
6
6
|
"repository": "github:eemeli/yaml",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"type": "commonjs",
|
|
20
20
|
"main": "./dist/index.js",
|
|
21
|
+
"bin": "./bin.mjs",
|
|
21
22
|
"browser": {
|
|
22
23
|
"./dist/index.js": "./browser/index.js",
|
|
23
24
|
"./dist/util.js": "./browser/dist/util.js",
|
|
@@ -52,7 +53,9 @@
|
|
|
52
53
|
"test:dist:types": "tsc --allowJs --moduleResolution node --noEmit --target es5 dist/index.js",
|
|
53
54
|
"test:types": "tsc --noEmit && tsc --noEmit -p tests/tsconfig.json",
|
|
54
55
|
"docs:install": "cd docs-slate && bundle install",
|
|
56
|
+
"predocs:deploy": "node docs/prepare-docs.mjs",
|
|
55
57
|
"docs:deploy": "cd docs-slate && ./deploy.sh",
|
|
58
|
+
"predocs": "node docs/prepare-docs.mjs",
|
|
56
59
|
"docs": "cd docs-slate && bundle exec middleman server",
|
|
57
60
|
"preversion": "npm test && npm run build",
|
|
58
61
|
"prepublishOnly": "npm run clean && npm test && npm run build"
|
|
@@ -66,17 +69,17 @@
|
|
|
66
69
|
},
|
|
67
70
|
"devDependencies": {
|
|
68
71
|
"@babel/core": "^7.12.10",
|
|
69
|
-
"@babel/plugin-
|
|
70
|
-
"@babel/plugin-
|
|
72
|
+
"@babel/plugin-transform-class-properties": "^7.23.3",
|
|
73
|
+
"@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",
|
|
71
74
|
"@babel/plugin-transform-typescript": "^7.12.17",
|
|
72
75
|
"@babel/preset-env": "^7.12.11",
|
|
73
76
|
"@rollup/plugin-babel": "^6.0.3",
|
|
74
77
|
"@rollup/plugin-replace": "^5.0.2",
|
|
75
78
|
"@rollup/plugin-typescript": "^11.0.0",
|
|
76
79
|
"@types/jest": "^29.2.4",
|
|
77
|
-
"@types/node": "^
|
|
78
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
79
|
-
"@typescript-eslint/parser": "^
|
|
80
|
+
"@types/node": "^20.11.20",
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
|
82
|
+
"@typescript-eslint/parser": "^7.0.2",
|
|
80
83
|
"babel-jest": "^29.0.1",
|
|
81
84
|
"cross-env": "^7.0.3",
|
|
82
85
|
"eslint": "^8.2.0",
|
|
@@ -85,7 +88,7 @@
|
|
|
85
88
|
"jest": "^29.0.1",
|
|
86
89
|
"jest-ts-webcompat-resolver": "^1.0.0",
|
|
87
90
|
"prettier": "^3.0.2",
|
|
88
|
-
"rollup": "^
|
|
91
|
+
"rollup": "^4.12.0",
|
|
89
92
|
"tslib": "^2.1.0",
|
|
90
93
|
"typescript": "^5.0.3"
|
|
91
94
|
},
|