@effected/yaml 0.7.0 → 0.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 +78 -7
- package/Yaml.js +80 -32
- package/YamlDocument.js +22 -3
- package/YamlFormat.js +170 -19
- package/YamlLint.js +239 -0
- package/YamlLintRule.js +36 -0
- package/YamlNode.js +36 -2
- package/YamlToken.js +139 -0
- package/YamlVisitor.js +40 -5
- package/index.d.ts +439 -12
- package/index.js +4 -1
- package/internal/composer/anchors.js +2 -27
- package/internal/composer/block.js +246 -58
- package/internal/composer/comments.js +187 -0
- package/internal/composer/document.js +49 -12
- package/internal/composer/flow.js +82 -9
- package/internal/composer/scalars.js +48 -11
- package/internal/composer/state.js +16 -2
- package/internal/cst-parser.js +2 -1
- package/internal/diagnostics.js +12 -3
- package/internal/fold.js +22 -10
- package/internal/rules/catalog.js +39 -0
- package/internal/rules/colon-spacing.js +77 -0
- package/internal/rules/comments-spacing.js +68 -0
- package/internal/rules/document-end.js +65 -0
- package/internal/rules/document-start.js +64 -0
- package/internal/rules/empty-lines.js +70 -0
- package/internal/rules/eof-newline.js +33 -0
- package/internal/rules/hyphen-spacing.js +52 -0
- package/internal/rules/indentation.js +103 -0
- package/internal/rules/key-duplicates.js +49 -0
- package/internal/rules/line-length.js +36 -0
- package/internal/rules/parse-validity.js +33 -0
- package/internal/rules/quoted-strings.js +81 -0
- package/internal/rules/trailing-spaces.js +39 -0
- package/internal/rules/truthy.js +84 -0
- package/internal/rules/util.js +92 -0
- package/internal/stringifier.js +266 -54
- package/package.json +3 -2
package/internal/stringifier.js
CHANGED
|
@@ -29,6 +29,27 @@ var StringifyDepthExceeded = class extends Error {
|
|
|
29
29
|
this.name = "StringifyDepthExceeded";
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* YAML 1.2 §8.1.3 caps an implicit block-mapping key: the `:` indicator must
|
|
34
|
+
* appear at most 1024 characters after the start of the key. A key whose
|
|
35
|
+
* RENDERED form (quotes and escapes count, the source scalar does not) is
|
|
36
|
+
* longer than this must spill to explicit-key form (`? key` / `: value`) or
|
|
37
|
+
* strict parsers reject the output. Matches the reference `yaml` package
|
|
38
|
+
* (`stringifyPair`: `str.length > 1024`, block context only — flow contexts
|
|
39
|
+
* never spill): a rendered key of exactly 1024 characters stays implicit.
|
|
40
|
+
*/
|
|
41
|
+
const IMPLICIT_KEY_MAX_LENGTH = 1024;
|
|
42
|
+
/**
|
|
43
|
+
* Continuation-line padding for explicit-key compact notation. Structurally
|
|
44
|
+
* the width of the `? ` / `: ` indicators — two columns — and deliberately
|
|
45
|
+
* NOT `ctx.indent`: compact continuation lines must align with the first
|
|
46
|
+
* item, which always starts two columns in, so any other pad silently
|
|
47
|
+
* re-nests (or corrupts) the value on reparse once `indent !== 2`. This is a
|
|
48
|
+
* recorded divergence from the reference `yaml` package, which pads these
|
|
49
|
+
* lines with the configured indent and emits output its own strict parser
|
|
50
|
+
* misreads or rejects at indent ≠ 2.
|
|
51
|
+
*/
|
|
52
|
+
const EXPLICIT_COMPACT_PAD = " ";
|
|
32
53
|
const NULL_RE = /^(?:null|Null|NULL|~)$/;
|
|
33
54
|
const TRUE_RE = /^(?:true|True|TRUE)$/;
|
|
34
55
|
const FALSE_RE = /^(?:false|False|FALSE)$/;
|
|
@@ -176,7 +197,9 @@ function renderSingleQuoted(s) {
|
|
|
176
197
|
* Block literal and block folded styles are always accepted for single-line
|
|
177
198
|
* strings even though the output is unusual.
|
|
178
199
|
*/
|
|
179
|
-
function renderString(s, style, indent, ignoreType = false, canonical = false, explicitChomp, parentPosition, quoteStyle = "single") {
|
|
200
|
+
function renderString(s, style, indent, ignoreType = false, canonical = false, explicitChomp, parentPosition, quoteStyle = "single", explicitIndent) {
|
|
201
|
+
const fidelity = !canonical;
|
|
202
|
+
const fidelityIndent = fidelity ? explicitIndent : void 0;
|
|
180
203
|
if (s.includes("\n")) {
|
|
181
204
|
let hasControl = false;
|
|
182
205
|
for (let i = 0; i < s.length; i++) {
|
|
@@ -192,14 +215,14 @@ function renderString(s, style, indent, ignoreType = false, canonical = false, e
|
|
|
192
215
|
if (hasInteriorTrailingWhitespace(s)) return renderDoubleQuoted(s, canonical);
|
|
193
216
|
if (hasNewlineSpacesTab(s)) return renderDoubleQuoted(s, canonical);
|
|
194
217
|
}
|
|
195
|
-
if (style === "block-literal") return renderBlockLiteral(s, indent, explicitChomp, parentPosition);
|
|
196
|
-
if (style === "block-folded") return renderBlockFolded(s, indent);
|
|
218
|
+
if (style === "block-literal") return renderBlockLiteral(s, indent, explicitChomp, parentPosition, fidelity, fidelityIndent);
|
|
219
|
+
if (style === "block-folded") return renderBlockFolded(s, indent, fidelity ? explicitChomp : void 0, fidelityIndent);
|
|
197
220
|
if (style === "plain" || style === "single-quoted") {
|
|
198
221
|
if (canonical) {
|
|
199
222
|
const sq = renderSingleQuotedMultiline(s, indent);
|
|
200
223
|
if (sq !== null) return sq;
|
|
201
224
|
}
|
|
202
|
-
return renderBlockLiteral(s, indent, explicitChomp, parentPosition);
|
|
225
|
+
return renderBlockLiteral(s, indent, explicitChomp, parentPosition, fidelity, fidelityIndent);
|
|
203
226
|
}
|
|
204
227
|
return renderDoubleQuoted(s, canonical);
|
|
205
228
|
}
|
|
@@ -215,8 +238,8 @@ function renderString(s, style, indent, ignoreType = false, canonical = false, e
|
|
|
215
238
|
return s;
|
|
216
239
|
case "single-quoted": return renderSingleQuoted(s);
|
|
217
240
|
case "double-quoted": return renderDoubleQuoted(s, canonical);
|
|
218
|
-
case "block-literal": return renderBlockLiteral(s, indent, explicitChomp, parentPosition);
|
|
219
|
-
case "block-folded": return renderBlockFolded(s, indent);
|
|
241
|
+
case "block-literal": return renderBlockLiteral(s, indent, explicitChomp, parentPosition, fidelity, fidelityIndent);
|
|
242
|
+
case "block-folded": return renderBlockFolded(s, indent, fidelity ? explicitChomp : void 0, fidelityIndent);
|
|
220
243
|
}
|
|
221
244
|
}
|
|
222
245
|
/**
|
|
@@ -361,6 +384,18 @@ function stringifyObjectLines(obj, ctx, depth) {
|
|
|
361
384
|
const keyStr = renderKey(k);
|
|
362
385
|
const val = obj[k];
|
|
363
386
|
const valLines = stringifyLines(val, ctx, depth + 1);
|
|
387
|
+
if (keyStr.length > IMPLICIT_KEY_MAX_LENGTH) {
|
|
388
|
+
lines.push(`? ${keyStr}`);
|
|
389
|
+
if (valLines.length === 1) lines.push(`: ${valLines[0]}`);
|
|
390
|
+
else if (valLines[0].startsWith("|") || valLines[0].startsWith(">") || typeof val === "string") {
|
|
391
|
+
lines.push(`: ${valLines[0]}`);
|
|
392
|
+
for (let i = 1; i < valLines.length; i++) lines.push(valLines[i]);
|
|
393
|
+
} else {
|
|
394
|
+
lines.push(`: ${valLines[0]}`);
|
|
395
|
+
for (let i = 1; i < valLines.length; i++) lines.push(valLines[i] === "" ? valLines[i] : `${EXPLICIT_COMPACT_PAD}${valLines[i]}`);
|
|
396
|
+
}
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
364
399
|
if (valLines.length === 1 && !isBlockCollection(val, ctx)) lines.push(`${keyStr}: ${valLines[0]}`);
|
|
365
400
|
else {
|
|
366
401
|
const first = valLines[0];
|
|
@@ -439,8 +474,11 @@ function normalizeNodeTags(node, tagMap) {
|
|
|
439
474
|
style: node.style,
|
|
440
475
|
...node.tag ? { tag: normalizeTag(node.tag, tagMap) } : {},
|
|
441
476
|
...node.anchor !== void 0 ? { anchor: node.anchor } : {},
|
|
477
|
+
...node.commentBefore !== void 0 ? { commentBefore: node.commentBefore } : {},
|
|
442
478
|
...node.comment !== void 0 ? { comment: node.comment } : {},
|
|
479
|
+
...node.spaceBefore !== void 0 ? { spaceBefore: node.spaceBefore } : {},
|
|
443
480
|
...node.chomp !== void 0 ? { chomp: node.chomp } : {},
|
|
481
|
+
...node.blockIndent !== void 0 ? { blockIndent: node.blockIndent } : {},
|
|
444
482
|
...node.raw !== void 0 ? { raw: node.raw } : {},
|
|
445
483
|
...node.sourceMultiline !== void 0 ? { sourceMultiline: node.sourceMultiline } : {},
|
|
446
484
|
offset: node.offset,
|
|
@@ -450,12 +488,16 @@ function normalizeNodeTags(node, tagMap) {
|
|
|
450
488
|
items: node.items.map((pair) => new YamlPair({
|
|
451
489
|
key: normalizeNodeTags(pair.key, tagMap),
|
|
452
490
|
value: pair.value ? normalizeNodeTags(pair.value, tagMap) : null,
|
|
453
|
-
...pair.
|
|
491
|
+
...pair.commentBefore !== void 0 ? { commentBefore: pair.commentBefore } : {},
|
|
492
|
+
...pair.comment !== void 0 ? { comment: pair.comment } : {},
|
|
493
|
+
...pair.spaceBefore !== void 0 ? { spaceBefore: pair.spaceBefore } : {}
|
|
454
494
|
})),
|
|
455
495
|
style: node.style,
|
|
456
496
|
...node.tag ? { tag: normalizeTag(node.tag, tagMap) } : {},
|
|
457
497
|
...node.anchor !== void 0 ? { anchor: node.anchor } : {},
|
|
498
|
+
...node.commentBefore !== void 0 ? { commentBefore: node.commentBefore } : {},
|
|
458
499
|
...node.comment !== void 0 ? { comment: node.comment } : {},
|
|
500
|
+
...node.spaceBefore !== void 0 ? { spaceBefore: node.spaceBefore } : {},
|
|
459
501
|
...node.sourceMultiline !== void 0 ? { sourceMultiline: node.sourceMultiline } : {},
|
|
460
502
|
offset: node.offset,
|
|
461
503
|
length: node.length
|
|
@@ -465,7 +507,9 @@ function normalizeNodeTags(node, tagMap) {
|
|
|
465
507
|
style: node.style,
|
|
466
508
|
...node.tag ? { tag: normalizeTag(node.tag, tagMap) } : {},
|
|
467
509
|
...node.anchor !== void 0 ? { anchor: node.anchor } : {},
|
|
510
|
+
...node.commentBefore !== void 0 ? { commentBefore: node.commentBefore } : {},
|
|
468
511
|
...node.comment !== void 0 ? { comment: node.comment } : {},
|
|
512
|
+
...node.spaceBefore !== void 0 ? { spaceBefore: node.spaceBefore } : {},
|
|
469
513
|
...node.sourceMultiline !== void 0 ? { sourceMultiline: node.sourceMultiline } : {},
|
|
470
514
|
offset: node.offset,
|
|
471
515
|
length: node.length
|
|
@@ -483,6 +527,7 @@ function stripNodeComments(node) {
|
|
|
483
527
|
...node.tag !== void 0 ? { tag: node.tag } : {},
|
|
484
528
|
...node.anchor !== void 0 ? { anchor: node.anchor } : {},
|
|
485
529
|
...node.chomp !== void 0 ? { chomp: node.chomp } : {},
|
|
530
|
+
...node.blockIndent !== void 0 ? { blockIndent: node.blockIndent } : {},
|
|
486
531
|
...node.raw !== void 0 ? { raw: node.raw } : {},
|
|
487
532
|
...node.sourceMultiline !== void 0 ? { sourceMultiline: node.sourceMultiline } : {},
|
|
488
533
|
offset: node.offset,
|
|
@@ -542,7 +587,7 @@ function stringifyScalarNodeLines(node, ctx) {
|
|
|
542
587
|
else lines = ["null"];
|
|
543
588
|
} else if (typeof val === "boolean") lines = [val ? "true" : "false"];
|
|
544
589
|
else if (typeof val === "number") lines = [node.raw !== void 0 ? node.raw : renderNumber(val)];
|
|
545
|
-
else if (typeof val === "string") lines = renderString(val, style, " ".repeat(ctx.indent), !!node.tag, ctx.forceDefaultStyles, node.chomp, ctx.parentPosition, ctx.quoteStyle).split("\n");
|
|
590
|
+
else if (typeof val === "string") lines = renderString(val, style, " ".repeat(ctx.indent), !!node.tag, ctx.forceDefaultStyles, node.chomp, ctx.parentPosition, ctx.quoteStyle, node.blockIndent).split("\n");
|
|
546
591
|
else lines = [renderDoubleQuoted(String(val))];
|
|
547
592
|
if (node.tag) lines[0] = `${node.tag} ${lines[0]}`;
|
|
548
593
|
if (node.anchor) lines[0] = `&${node.anchor} ${lines[0]}`;
|
|
@@ -582,6 +627,79 @@ function stringifyMappingKeyLines(node, ctx, depth) {
|
|
|
582
627
|
return stringifyNodeLines(node, ctx, depth);
|
|
583
628
|
}
|
|
584
629
|
/**
|
|
630
|
+
* Undo the capture-side escape on one stored comment line: a spaces-only
|
|
631
|
+
* slice was stored with one extra trailing space so it cannot collide with
|
|
632
|
+
* `""`, the embedded-blank-line encoding (see `rawCommentText`).
|
|
633
|
+
*/
|
|
634
|
+
function unescapeCommentLine(line) {
|
|
635
|
+
return /^ +$/.test(line) ? line.slice(0, -1) : line;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Render a stored comment block, one output line per stored line. Stored
|
|
639
|
+
* text is the RAW post-`#` slice (reference parity) with spaces-only lines
|
|
640
|
+
* carrying one escape space: `""` is an embedded blank line; any other line
|
|
641
|
+
* renders as `#` + the unescaped slice (`" "` → `#`, `" "` → `# `).
|
|
642
|
+
*/
|
|
643
|
+
function commentBlockLines(comment) {
|
|
644
|
+
return comment.split("\n").map((l) => l === "" ? "" : `#${unescapeCommentLine(l)}`);
|
|
645
|
+
}
|
|
646
|
+
/** Render a trailing comment for appending after content on the same line. */
|
|
647
|
+
function renderTrailingComment(comment) {
|
|
648
|
+
return ` #${comment.split("\n").map(unescapeCommentLine).join(" ")}`;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Emits the `: value` line(s) of an explicit-key block-mapping entry, in
|
|
652
|
+
* compact notation where the value admits it (first line on the colon line,
|
|
653
|
+
* continuation lines indented to align). Shared by the complex-key branch and
|
|
654
|
+
* the implicit-key length spill; `indentSequences` deliberately does not reach
|
|
655
|
+
* this branch (sequence values always align compactly under `: `).
|
|
656
|
+
*
|
|
657
|
+
* Returns the `lines` index that can safely carry the pair's trailing
|
|
658
|
+
* comment (the line where an inline value ends), or `-1` when no line is
|
|
659
|
+
* safe (a compact block collection or a block-scalar header).
|
|
660
|
+
*/
|
|
661
|
+
function pushExplicitKeyValueLines(lines, valNode, ctx, depth, pad) {
|
|
662
|
+
if (!valNode) {
|
|
663
|
+
lines.push(":");
|
|
664
|
+
return lines.length - 1;
|
|
665
|
+
}
|
|
666
|
+
const valLines = stringifyNodeLines(valNode, ctx, depth + 1);
|
|
667
|
+
if (valLines.length === 1) {
|
|
668
|
+
lines.push(`: ${valLines[0]}`);
|
|
669
|
+
return lines.length - 1;
|
|
670
|
+
}
|
|
671
|
+
const first = valLines[0];
|
|
672
|
+
const firstStripped = stripScalarMetadataPrefix(first);
|
|
673
|
+
const isBlockScalarHeader = firstStripped.startsWith("|") || firstStripped.startsWith(">");
|
|
674
|
+
const isInlineQuoted = valNode instanceof YamlScalar && (firstStripped.startsWith("'") || firstStripped.startsWith("\""));
|
|
675
|
+
if (isBlockScalarHeader || isInlineQuoted) {
|
|
676
|
+
const headerIdx = lines.length;
|
|
677
|
+
if (isBlockScalarHeader) {
|
|
678
|
+
const scalarComment = !ctx.forceDefaultStyles && valNode instanceof YamlScalar ? valNode.comment : void 0;
|
|
679
|
+
lines.push(scalarComment !== void 0 ? `: ${first}${renderTrailingComment(scalarComment)}` : `: ${first}`);
|
|
680
|
+
for (let v = 1; v < valLines.length; v++) lines.push(valLines[v]);
|
|
681
|
+
return scalarComment !== void 0 ? -1 : headerIdx;
|
|
682
|
+
}
|
|
683
|
+
lines.push(`: ${first}`);
|
|
684
|
+
for (let v = 1; v < valLines.length; v++) lines.push(valLines[v]);
|
|
685
|
+
return lines.length - 1;
|
|
686
|
+
}
|
|
687
|
+
if (first.startsWith("-")) {
|
|
688
|
+
lines.push(`: ${first}`);
|
|
689
|
+
for (let v = 1; v < valLines.length; v++) lines.push(valLines[v] === "" ? "" : `${EXPLICIT_COMPACT_PAD}${valLines[v]}`);
|
|
690
|
+
return -1;
|
|
691
|
+
}
|
|
692
|
+
if (valNode instanceof YamlMap && valNode.items.length > 0 && (ctx.forceDefaultStyles ? ctx.defaultCollectionStyle : valNode.style ?? ctx.defaultCollectionStyle) === "block") {
|
|
693
|
+
lines.push(`: ${first}`);
|
|
694
|
+
for (let v = 1; v < valLines.length; v++) lines.push(valLines[v] === "" ? "" : `${EXPLICIT_COMPACT_PAD}${valLines[v]}`);
|
|
695
|
+
return -1;
|
|
696
|
+
}
|
|
697
|
+
const colonIdx = lines.length;
|
|
698
|
+
lines.push(":");
|
|
699
|
+
for (const vl of valLines) lines.push(vl === "" ? "" : `${pad}${vl}`);
|
|
700
|
+
return colonIdx;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
585
703
|
* Stringifies a YamlMap node into lines, using the node's collection style.
|
|
586
704
|
*/
|
|
587
705
|
function stringifyMapNodeLines(node, ctx, depth) {
|
|
@@ -599,56 +717,68 @@ function stringifyMapNodeLines(node, ctx, depth) {
|
|
|
599
717
|
return [line];
|
|
600
718
|
}
|
|
601
719
|
if (style === "flow") {
|
|
720
|
+
const flowPrefix = buildMetadataPrefix(node.tag, node.anchor);
|
|
721
|
+
if (!ctx.forceDefaultStyles && (node.comment !== void 0 || items.some((p) => p.commentBefore !== void 0 || p.comment !== void 0 || p.spaceBefore === true))) {
|
|
722
|
+
const flowPad = " ".repeat(ctx.indent);
|
|
723
|
+
const flowLines = [flowPrefix ? `${flowPrefix} {` : "{"];
|
|
724
|
+
for (let fi = 0; fi < items.length; fi++) {
|
|
725
|
+
const pair = items[fi];
|
|
726
|
+
if (pair.spaceBefore === true) flowLines.push("");
|
|
727
|
+
if (pair.commentBefore !== void 0) for (const cl of commentBlockLines(pair.commentBefore)) flowLines.push(cl === "" ? "" : `${flowPad}${cl}`);
|
|
728
|
+
const keyStr = pair.key ? stringifyMappingKeyLines(pair.key, ctx, depth + 1).join(" ") : "null";
|
|
729
|
+
const valStr = pair.value ? stringifyNodeLines(pair.value, ctx, depth + 1).join(" ") : "null";
|
|
730
|
+
const comma = fi < items.length - 1 ? "," : "";
|
|
731
|
+
const trailing = pair.comment !== void 0 ? renderTrailingComment(pair.comment) : "";
|
|
732
|
+
flowLines.push(`${flowPad}${keyStr}: ${valStr}${comma}${trailing}`);
|
|
733
|
+
}
|
|
734
|
+
if (node.comment !== void 0) for (const cl of commentBlockLines(node.comment)) flowLines.push(cl === "" ? "" : `${flowPad}${cl}`);
|
|
735
|
+
flowLines.push("}");
|
|
736
|
+
return flowLines;
|
|
737
|
+
}
|
|
602
738
|
let line = `{${items.map((pair) => {
|
|
603
739
|
return `${pair.key ? stringifyMappingKeyLines(pair.key, ctx, depth + 1).join(" ") : "null"}: ${pair.value ? stringifyNodeLines(pair.value, ctx, depth + 1).join(" ") : "null"}`;
|
|
604
740
|
}).join(", ")}}`;
|
|
605
|
-
const flowPrefix = buildMetadataPrefix(node.tag, node.anchor);
|
|
606
741
|
if (flowPrefix) line = `${flowPrefix} ${line}`;
|
|
607
742
|
return [line];
|
|
608
743
|
}
|
|
609
744
|
const pad = " ".repeat(ctx.indent);
|
|
745
|
+
const emitComments = !ctx.forceDefaultStyles;
|
|
610
746
|
const lines = [];
|
|
747
|
+
/** Append a pair's trailing comment to `lines[idx]` (flattened to one line); `-1` drops it. */
|
|
748
|
+
const appendTrailing = (idx, comment) => {
|
|
749
|
+
if (!emitComments || comment === void 0 || idx < 0 || idx >= lines.length) return;
|
|
750
|
+
lines[idx] = `${lines[idx]}${renderTrailingComment(comment)}`;
|
|
751
|
+
};
|
|
752
|
+
/** A value node's own leading comment block, or undefined. */
|
|
753
|
+
const valueLeading = (valNode) => emitComments && !(valNode instanceof YamlAlias) ? valNode.commentBefore : void 0;
|
|
611
754
|
for (const pair of items) {
|
|
755
|
+
if (emitComments && pair.spaceBefore === true) lines.push("");
|
|
756
|
+
if (emitComments && pair.commentBefore !== void 0) for (const cl of commentBlockLines(pair.commentBefore)) lines.push(cl);
|
|
612
757
|
const keyIsScalarWithNewline = pair.key instanceof YamlScalar && (typeof pair.key.value === "string" && pair.key.value.includes("\n") || pair.key.style === "block-literal" || pair.key.style === "block-folded");
|
|
613
758
|
if ((pair.key instanceof YamlMap || pair.key instanceof YamlSeq) && pair.key.items.length > 0 || keyIsScalarWithNewline) {
|
|
614
759
|
const keyLines = stringifyNodeLines(pair.key, ctx, depth + 1);
|
|
615
760
|
lines.push(`? ${keyLines[0]}`);
|
|
761
|
+
const explicitKeyLineIdx = lines.length - 1;
|
|
616
762
|
const firstTokens = keyLines[0].trim().split(/\s+/).filter(Boolean);
|
|
617
763
|
const firstIsMetaOnly = firstTokens.length > 0 && firstTokens.every((t) => t.startsWith("&") || t.startsWith("!"));
|
|
618
764
|
const keyIsBlockScalar = pair.key instanceof YamlScalar && (pair.key.style === "block-literal" || pair.key.style === "block-folded");
|
|
619
|
-
const contPad = firstIsMetaOnly || keyIsBlockScalar ? "" :
|
|
765
|
+
const contPad = firstIsMetaOnly || keyIsBlockScalar ? "" : EXPLICIT_COMPACT_PAD;
|
|
620
766
|
for (let k = 1; k < keyLines.length; k++) lines.push(`${contPad}${keyLines[k]}`);
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
else {
|
|
624
|
-
const valLines = stringifyNodeLines(valNode, ctx, depth + 1);
|
|
625
|
-
if (valLines.length === 1) lines.push(`: ${valLines[0]}`);
|
|
626
|
-
else {
|
|
627
|
-
const first = valLines[0];
|
|
628
|
-
const firstStripped = stripScalarMetadataPrefix(first);
|
|
629
|
-
const isBlockScalarHeader = firstStripped.startsWith("|") || firstStripped.startsWith(">");
|
|
630
|
-
const isInlineQuoted = valNode instanceof YamlScalar && (firstStripped.startsWith("'") || firstStripped.startsWith("\""));
|
|
631
|
-
if (isBlockScalarHeader || isInlineQuoted) {
|
|
632
|
-
lines.push(`: ${first}`);
|
|
633
|
-
for (let v = 1; v < valLines.length; v++) lines.push(valLines[v]);
|
|
634
|
-
} else if (first.startsWith("-")) {
|
|
635
|
-
lines.push(`: ${first}`);
|
|
636
|
-
for (let v = 1; v < valLines.length; v++) lines.push(`${pad}${valLines[v]}`);
|
|
637
|
-
} else if (valNode instanceof YamlMap && valNode.items.length > 0 && (ctx.forceDefaultStyles ? ctx.defaultCollectionStyle : valNode.style ?? ctx.defaultCollectionStyle) === "block") {
|
|
638
|
-
lines.push(`: ${first}`);
|
|
639
|
-
for (let v = 1; v < valLines.length; v++) lines.push(`${pad}${valLines[v]}`);
|
|
640
|
-
} else {
|
|
641
|
-
lines.push(":");
|
|
642
|
-
for (const vl of valLines) lines.push(`${pad}${vl}`);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
767
|
+
const inlineIdx = pushExplicitKeyValueLines(lines, pair.value, ctx, depth, pad);
|
|
768
|
+
appendTrailing(inlineIdx >= 0 ? inlineIdx : keyLines.length === 1 ? explicitKeyLineIdx : -1, pair.comment);
|
|
646
769
|
continue;
|
|
647
770
|
}
|
|
648
771
|
let resolvedKeyStr;
|
|
649
772
|
if (ctx.forceDefaultStyles && node.style === "flow" && node.sourceMultiline !== true && pair.key instanceof YamlScalar && (pair.key.style === "single-quoted" || pair.key.style === "double-quoted") && typeof pair.key.value === "string" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(pair.key.value)) resolvedKeyStr = pair.key.value;
|
|
650
773
|
else resolvedKeyStr = pair.key ? stringifyMappingKeyLines(pair.key, ctx, depth + 1).join(" ") : "null";
|
|
651
774
|
const keyStr = resolvedKeyStr;
|
|
775
|
+
if (keyStr.length > IMPLICIT_KEY_MAX_LENGTH) {
|
|
776
|
+
lines.push(`? ${keyStr}`);
|
|
777
|
+
const spillKeyLineIdx = lines.length - 1;
|
|
778
|
+
const inlineIdx = pushExplicitKeyValueLines(lines, pair.value, ctx, depth, pad);
|
|
779
|
+
appendTrailing(inlineIdx >= 0 ? inlineIdx : spillKeyLineIdx, pair.comment);
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
652
782
|
const keyIsAnchoredOrTaggedEmpty = pair.key instanceof YamlScalar && pair.key.length === 0 && (pair.key.value === null || pair.key.value === void 0 || pair.key.value === "") && (pair.key.anchor !== void 0 || pair.key.tag !== void 0);
|
|
653
783
|
const sep = pair.key instanceof YamlAlias || keyIsAnchoredOrTaggedEmpty ? " :" : ":";
|
|
654
784
|
const valNode = pair.value;
|
|
@@ -658,16 +788,20 @@ function stringifyMapNodeLines(node, ctx, depth) {
|
|
|
658
788
|
const isRootFlowMap = ctx.parentPosition === void 0 && node.style === "flow" && node.sourceMultiline === true;
|
|
659
789
|
if (ctx.forceDefaultStyles && isRootFlowMap && isPlainKey && keyIsNonEmpty) lines.push(`${keyStr}${sep} null`);
|
|
660
790
|
else lines.push(`${keyStr}${sep}`);
|
|
791
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
661
792
|
continue;
|
|
662
793
|
}
|
|
663
794
|
const valLines = stringifyNodeLines(valNode, {
|
|
664
795
|
...ctx,
|
|
665
796
|
parentPosition: "block-map-value"
|
|
666
797
|
}, depth + 1);
|
|
798
|
+
const valLeading = valueLeading(valNode);
|
|
667
799
|
if (valNode instanceof YamlSeq && valNode.items.length > 0 && (ctx.forceDefaultStyles ? ctx.defaultCollectionStyle : valNode.style ?? ctx.defaultCollectionStyle) === "block") {
|
|
668
800
|
const seqMeta = buildMetadataPrefix(valNode.tag, valNode.anchor);
|
|
669
801
|
const startIdx = seqMeta ? 1 : 0;
|
|
670
802
|
lines.push(seqMeta ? `${keyStr}${sep} ${seqMeta}` : `${keyStr}${sep}`);
|
|
803
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
804
|
+
if (valLeading !== void 0) for (const cl of commentBlockLines(valLeading)) lines.push(ctx.indentSequences ? `${pad}${cl}` : cl);
|
|
671
805
|
for (let i = startIdx; i < valLines.length; i++) {
|
|
672
806
|
const vl = valLines[i];
|
|
673
807
|
lines.push(ctx.indentSequences && vl !== "" ? `${pad}${vl}` : vl);
|
|
@@ -676,28 +810,54 @@ function stringifyMapNodeLines(node, ctx, depth) {
|
|
|
676
810
|
const mapMeta = buildMetadataPrefix(valNode.tag, valNode.anchor);
|
|
677
811
|
const startIdx = mapMeta ? 1 : 0;
|
|
678
812
|
lines.push(mapMeta ? `${keyStr}${sep} ${mapMeta}` : `${keyStr}${sep}`);
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
813
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
814
|
+
if (valLeading !== void 0) for (const cl of commentBlockLines(valLeading)) lines.push(`${pad}${cl}`);
|
|
815
|
+
for (let i = startIdx; i < valLines.length; i++) lines.push(valLines[i] === "" ? "" : `${pad}${valLines[i]}`);
|
|
816
|
+
} else if (valLines.length === 1 && valLeading !== void 0) {
|
|
817
|
+
lines.push(`${keyStr}${sep}`);
|
|
818
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
819
|
+
for (const cl of commentBlockLines(valLeading)) lines.push(`${pad}${cl}`);
|
|
820
|
+
lines.push(valLines[0] === "" ? "" : `${pad}${valLines[0]}`);
|
|
821
|
+
} else if (valLines.length === 1) {
|
|
822
|
+
lines.push(valLines[0] === "" ? `${keyStr}${sep}` : `${keyStr}${sep} ${valLines[0]}`);
|
|
823
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
824
|
+
} else {
|
|
682
825
|
const first = valLines[0];
|
|
683
826
|
const firstStripped = stripScalarMetadataPrefix(first);
|
|
684
827
|
const isBlockScalarHeader = firstStripped.startsWith("|") || firstStripped.startsWith(">");
|
|
685
828
|
const isInlineQuoted = valNode instanceof YamlScalar && (firstStripped.startsWith("'") || firstStripped.startsWith("\""));
|
|
686
829
|
if (isBlockScalarHeader || isInlineQuoted) {
|
|
687
|
-
|
|
688
|
-
|
|
830
|
+
const scalarComment = isBlockScalarHeader && valNode instanceof YamlScalar ? valNode.comment : void 0;
|
|
831
|
+
if (scalarComment !== void 0 && pair.comment !== void 0) {
|
|
832
|
+
lines.push(`${keyStr}${sep}`);
|
|
833
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
834
|
+
const headerIdx = lines.length;
|
|
835
|
+
lines.push(`${pad}${first}`);
|
|
836
|
+
for (let i = 1; i < valLines.length; i++) lines.push(valLines[i]);
|
|
837
|
+
appendTrailing(headerIdx, scalarComment);
|
|
838
|
+
} else {
|
|
839
|
+
const headerIdx = lines.length;
|
|
840
|
+
lines.push(`${keyStr}${sep} ${first}`);
|
|
841
|
+
for (let i = 1; i < valLines.length; i++) lines.push(valLines[i]);
|
|
842
|
+
if (isBlockScalarHeader) appendTrailing(headerIdx, scalarComment ?? pair.comment);
|
|
843
|
+
else appendTrailing(lines.length - 1, pair.comment);
|
|
844
|
+
}
|
|
689
845
|
} else {
|
|
690
846
|
const mapMeta = valNode instanceof YamlMap && (ctx.forceDefaultStyles ? ctx.defaultCollectionStyle : valNode.style ?? ctx.defaultCollectionStyle) === "block" ? buildMetadataPrefix(valNode.tag, valNode.anchor) : void 0;
|
|
691
847
|
if (mapMeta) {
|
|
692
848
|
lines.push(`${keyStr}${sep} ${mapMeta}`);
|
|
693
|
-
|
|
849
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
850
|
+
for (let i = 1; i < valLines.length; i++) lines.push(valLines[i] === "" ? "" : `${pad}${valLines[i]}`);
|
|
694
851
|
} else {
|
|
695
852
|
lines.push(`${keyStr}${sep}`);
|
|
696
|
-
|
|
853
|
+
appendTrailing(lines.length - 1, pair.comment);
|
|
854
|
+
if (valLeading !== void 0) for (const cl of commentBlockLines(valLeading)) lines.push(`${pad}${cl}`);
|
|
855
|
+
for (const vl of valLines) lines.push(vl === "" ? "" : `${pad}${vl}`);
|
|
697
856
|
}
|
|
698
857
|
}
|
|
699
858
|
}
|
|
700
859
|
}
|
|
860
|
+
if (emitComments && node.comment !== void 0) for (const cl of commentBlockLines(node.comment)) lines.push(cl);
|
|
701
861
|
const prefix = buildMetadataPrefix(node.tag, node.anchor);
|
|
702
862
|
if (prefix) lines.unshift(prefix);
|
|
703
863
|
return lines;
|
|
@@ -744,9 +904,32 @@ function stringifySeqNodeLines(node, ctx, depth) {
|
|
|
744
904
|
if (emptyPrefix) line = `${emptyPrefix} ${line}`;
|
|
745
905
|
return [line];
|
|
746
906
|
}
|
|
907
|
+
const emitComments = !ctx.forceDefaultStyles;
|
|
908
|
+
const itemFields = (item) => {
|
|
909
|
+
if (!emitComments || item instanceof YamlAlias) return void 0;
|
|
910
|
+
if (item.commentBefore === void 0 && item.comment === void 0 && item.spaceBefore !== true) return void 0;
|
|
911
|
+
return item;
|
|
912
|
+
};
|
|
747
913
|
if (style === "flow") {
|
|
748
|
-
let line = `[${items.map((item) => stringifyNodeLines(item, ctx, depth + 1).join(" ")).join(", ")}]`;
|
|
749
914
|
const flowPrefix = buildMetadataPrefix(node.tag, node.anchor);
|
|
915
|
+
if (emitComments && (node.comment !== void 0 || items.some((it) => itemFields(it) !== void 0))) {
|
|
916
|
+
const flowPad = " ".repeat(ctx.indent);
|
|
917
|
+
const flowLines = [flowPrefix ? `${flowPrefix} [` : "["];
|
|
918
|
+
for (let fi = 0; fi < items.length; fi++) {
|
|
919
|
+
const item = items[fi];
|
|
920
|
+
const fields = itemFields(item);
|
|
921
|
+
if (fields?.spaceBefore === true) flowLines.push("");
|
|
922
|
+
if (fields?.commentBefore !== void 0) for (const cl of commentBlockLines(fields.commentBefore)) flowLines.push(cl === "" ? "" : `${flowPad}${cl}`);
|
|
923
|
+
const itemStr = stringifyNodeLines(item, ctx, depth + 1).join(" ");
|
|
924
|
+
const comma = fi < items.length - 1 ? "," : "";
|
|
925
|
+
const trailing = fields?.comment !== void 0 ? renderTrailingComment(fields.comment) : "";
|
|
926
|
+
flowLines.push(`${flowPad}${itemStr}${comma}${trailing}`);
|
|
927
|
+
}
|
|
928
|
+
if (node.comment !== void 0) for (const cl of commentBlockLines(node.comment)) flowLines.push(cl === "" ? "" : `${flowPad}${cl}`);
|
|
929
|
+
flowLines.push("]");
|
|
930
|
+
return flowLines;
|
|
931
|
+
}
|
|
932
|
+
let line = `[${items.map((item) => stringifyNodeLines(item, ctx, depth + 1).join(" ")).join(", ")}]`;
|
|
750
933
|
if (flowPrefix) line = `${flowPrefix} ${line}`;
|
|
751
934
|
return [line];
|
|
752
935
|
}
|
|
@@ -757,21 +940,37 @@ function stringifySeqNodeLines(node, ctx, depth) {
|
|
|
757
940
|
parentPosition: "block-seq-item"
|
|
758
941
|
};
|
|
759
942
|
for (const item of items) {
|
|
943
|
+
const fields = itemFields(item);
|
|
944
|
+
if (fields?.spaceBefore === true) lines.push("");
|
|
945
|
+
if (fields?.commentBefore !== void 0) for (const cl of commentBlockLines(fields.commentBefore)) lines.push(cl);
|
|
946
|
+
/** Append the item's trailing comment to `lines[idx]`; `-1` drops it. */
|
|
947
|
+
const appendItemTrailing = (idx) => {
|
|
948
|
+
if (fields?.comment === void 0 || idx < 0 || idx >= lines.length) return;
|
|
949
|
+
lines[idx] = `${lines[idx]}${renderTrailingComment(fields.comment)}`;
|
|
950
|
+
};
|
|
760
951
|
const itemLines = stringifyNodeLines(item, itemCtx, depth + 1);
|
|
761
|
-
if (itemLines.length === 1)
|
|
762
|
-
|
|
952
|
+
if (itemLines.length === 1) {
|
|
953
|
+
lines.push(itemLines[0] === "" ? "-" : `- ${itemLines[0]}`);
|
|
954
|
+
appendItemTrailing(lines.length - 1);
|
|
955
|
+
} else {
|
|
763
956
|
const first = itemLines[0];
|
|
764
957
|
const firstStripped = stripScalarMetadataPrefix(first);
|
|
765
958
|
const itemIsScalar = item instanceof YamlScalar;
|
|
766
|
-
|
|
959
|
+
const isBlockScalarHeader = firstStripped.startsWith("|") || firstStripped.startsWith(">");
|
|
960
|
+
if (isBlockScalarHeader || itemIsScalar && (firstStripped.startsWith("'") || firstStripped.startsWith("\""))) {
|
|
961
|
+
const headerIdx = lines.length;
|
|
767
962
|
lines.push(`- ${first}`);
|
|
768
963
|
for (let i = 1; i < itemLines.length; i++) lines.push(itemLines[i]);
|
|
964
|
+
appendItemTrailing(isBlockScalarHeader ? headerIdx : lines.length - 1);
|
|
769
965
|
} else {
|
|
770
966
|
lines.push(first === "" ? "-" : `- ${first}`);
|
|
771
|
-
|
|
967
|
+
const dashLineIdx = lines.length - 1;
|
|
968
|
+
for (let i = 1; i < itemLines.length; i++) lines.push(itemLines[i] === "" ? "" : `${pad}${itemLines[i]}`);
|
|
969
|
+
appendItemTrailing(dashLineIdx);
|
|
772
970
|
}
|
|
773
971
|
}
|
|
774
972
|
}
|
|
973
|
+
if (emitComments && node.comment !== void 0) for (const cl of commentBlockLines(node.comment)) lines.push(cl);
|
|
775
974
|
const prefix = buildMetadataPrefix(node.tag, node.anchor);
|
|
776
975
|
if (prefix) lines.unshift(prefix);
|
|
777
976
|
return lines;
|
|
@@ -799,7 +998,8 @@ function stringifyDocument(doc, options) {
|
|
|
799
998
|
const ctx = createContext(options);
|
|
800
999
|
const finalNewline = options?.finalNewline ?? true;
|
|
801
1000
|
let contents = doc.contents;
|
|
802
|
-
const
|
|
1001
|
+
const docCommentRaw = ctx.forceDefaultStyles ? void 0 : doc.comment;
|
|
1002
|
+
const docComment = docCommentRaw !== void 0 ? commentBlockLines(docCommentRaw).join("\n") : void 0;
|
|
803
1003
|
if (ctx.forceDefaultStyles && contents) {
|
|
804
1004
|
contents = stripNodeComments(contents);
|
|
805
1005
|
const tagMap = buildTagMap(doc.directives);
|
|
@@ -810,16 +1010,28 @@ function stringifyDocument(doc, options) {
|
|
|
810
1010
|
if (doc.hasDocumentStart) return `---\n${doc.hasDocumentEnd ? "...\n" : ""}`;
|
|
811
1011
|
return "";
|
|
812
1012
|
}
|
|
1013
|
+
if (docComment !== void 0 || doc.commentAfter !== void 0 || doc.hasDocumentStart === true || doc.hasDocumentEnd === true) {
|
|
1014
|
+
const parts = [];
|
|
1015
|
+
if (docComment !== void 0) parts.push(`${docComment}\n`);
|
|
1016
|
+
if (doc.hasDocumentStart) parts.push("---\n");
|
|
1017
|
+
if (doc.hasDocumentEnd) parts.push("...\n");
|
|
1018
|
+
if (doc.commentAfter !== void 0) parts.push(`${commentBlockLines(doc.commentAfter).join("\n")}\n`);
|
|
1019
|
+
const out = parts.join("");
|
|
1020
|
+
return finalNewline ? out : out.replace(/\n$/, "");
|
|
1021
|
+
}
|
|
813
1022
|
return finalNewline ? "null\n" : "null";
|
|
814
1023
|
}
|
|
815
1024
|
const result = stringifyNodeLines(contents, ctx, 0).join("\n");
|
|
816
|
-
const body = finalNewline ? `${result}\n` : result;
|
|
817
1025
|
const needsTerminatorForKeepChomp = ctx.forceDefaultStyles && endsWithKeepChomp(result);
|
|
818
1026
|
const needsTerminatorForAnchoredPlainScalar = ctx.forceDefaultStyles && doc.hasDocumentStart && contents instanceof YamlScalar && contents.style === "plain" && contents.anchor !== void 0 && !contents.tag;
|
|
819
1027
|
const looksLikeDirectiveContinuation = contents instanceof YamlScalar && typeof contents.value === "string" && / %[A-Z]/.test(contents.value);
|
|
820
1028
|
const needsTerminatorForMultilinePlainScalar = ctx.forceDefaultStyles && doc.hasDocumentStart && contents instanceof YamlScalar && contents.style === "plain" && contents.sourceMultiline === true && looksLikeDirectiveContinuation;
|
|
821
1029
|
const needsTerminatorForDocStartTab = ctx.forceDefaultStyles && doc.hasDocumentStartTab === true;
|
|
822
|
-
const
|
|
1030
|
+
const docEndMarker = doc.hasDocumentEnd || needsTerminatorForKeepChomp || needsTerminatorForAnchoredPlainScalar || needsTerminatorForMultilinePlainScalar || needsTerminatorForDocStartTab ? "...\n" : "";
|
|
1031
|
+
const docCommentAfter = ctx.forceDefaultStyles || doc.commentAfter === void 0 ? void 0 : commentBlockLines(doc.commentAfter).join("\n");
|
|
1032
|
+
const docEndFull = docCommentAfter !== void 0 ? `${docEndMarker}${docCommentAfter}\n` : docEndMarker;
|
|
1033
|
+
const body = finalNewline || docEndFull !== "" ? `${result}\n` : result;
|
|
1034
|
+
const docEnd = finalNewline || docEndFull === "" ? docEndFull : docEndFull.replace(/\n$/, "");
|
|
823
1035
|
if (doc.hasDocumentStart) {
|
|
824
1036
|
const rootTag = contents && "tag" in contents ? contents.tag : void 0;
|
|
825
1037
|
const rootAnchor = contents && "anchor" in contents ? contents.anchor : void 0;
|
|
@@ -837,12 +1049,12 @@ function stringifyDocument(doc, options) {
|
|
|
837
1049
|
else if (bodyClean.startsWith(metaInlinePrefix)) bodyClean = bodyClean.slice(metaInlinePrefix.length);
|
|
838
1050
|
const docStart = `--- ${metaStr}`;
|
|
839
1051
|
const sep = isCollection ? "\n" : " ";
|
|
840
|
-
return docComment ?
|
|
1052
|
+
return docComment ? `${docComment}\n${docStart}${sep}${bodyClean}${docEnd}` : `${docStart}${sep}${bodyClean}${docEnd}`;
|
|
841
1053
|
}
|
|
842
|
-
if (isScalar) return docComment ?
|
|
843
|
-
return docComment ?
|
|
1054
|
+
if (isScalar) return docComment ? `${docComment}\n--- ${body}${docEnd}` : `--- ${body}${docEnd}`;
|
|
1055
|
+
return docComment ? `${docComment}\n---\n${body}${docEnd}` : `---\n${body}${docEnd}`;
|
|
844
1056
|
}
|
|
845
|
-
return docComment ?
|
|
1057
|
+
return docComment ? `${docComment}\n${body}${docEnd}` : `${body}${docEnd}`;
|
|
846
1058
|
}
|
|
847
1059
|
|
|
848
1060
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/yaml",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "Zero-dependency YAML parsing, editing and
|
|
5
|
+
"description": "Zero-dependency YAML parsing, editing, formatting and linting as Effect schemas.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"yaml",
|
|
8
8
|
"parser",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"cst",
|
|
13
13
|
"editing",
|
|
14
14
|
"formatting",
|
|
15
|
+
"linting",
|
|
15
16
|
"effected"
|
|
16
17
|
],
|
|
17
18
|
"homepage": "https://github.com/spencerbeggs/effected/tree/main/packages/yaml#readme",
|