@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/index.js
CHANGED
|
@@ -4,6 +4,9 @@ import { Yaml, YamlParseError, YamlParseOptions, YamlStringifyError, YamlStringi
|
|
|
4
4
|
import { YamlDirective, YamlDocument } from "./YamlDocument.js";
|
|
5
5
|
import { YamlEdit, YamlRange } from "./YamlEdit.js";
|
|
6
6
|
import { YamlFormat, YamlFormattingOptions, YamlModificationError } from "./YamlFormat.js";
|
|
7
|
+
import { YamlLintDiagnostic, YamlLintSeverity } from "./YamlLintRule.js";
|
|
8
|
+
import { YamlToken, YamlTokenKind, YamlTokens } from "./YamlToken.js";
|
|
9
|
+
import { YamlLint, YamlLintConfig, YamlLintRuleSetting } from "./YamlLint.js";
|
|
7
10
|
import { YamlVisitor, YamlVisitorEvent } from "./YamlVisitor.js";
|
|
8
11
|
|
|
9
|
-
export { CollectionStyle, QuoteStyle, ScalarChomp, ScalarStyle, Yaml, YamlAlias, YamlComposerErrorCode, YamlDiagnostic, YamlDirective, YamlDocument, YamlEdit, YamlErrorCode, YamlFormat, YamlFormattingOptions, YamlLexErrorCode, YamlMap, YamlModificationError, YamlModifyErrorCode, YamlNode, YamlPair, YamlParseError, YamlParseErrorCode, YamlParseOptions, YamlRange, YamlScalar, YamlSeq, YamlStringifyError, YamlStringifyErrorCode, YamlStringifyOptions, YamlVisitor, YamlVisitorEvent };
|
|
12
|
+
export { CollectionStyle, QuoteStyle, ScalarChomp, ScalarStyle, Yaml, YamlAlias, YamlComposerErrorCode, YamlDiagnostic, YamlDirective, YamlDocument, YamlEdit, YamlErrorCode, YamlFormat, YamlFormattingOptions, YamlLexErrorCode, YamlLint, YamlLintConfig, YamlLintDiagnostic, YamlLintRuleSetting, YamlLintSeverity, YamlMap, YamlModificationError, YamlModifyErrorCode, YamlNode, YamlPair, YamlParseError, YamlParseErrorCode, YamlParseOptions, YamlRange, YamlScalar, YamlSeq, YamlStringifyError, YamlStringifyErrorCode, YamlStringifyOptions, YamlToken, YamlTokenKind, YamlTokens, YamlVisitor, YamlVisitorEvent };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { YamlAlias
|
|
1
|
+
import { YamlAlias } from "../../YamlNode.js";
|
|
2
2
|
|
|
3
3
|
//#region src/internal/composer/anchors.ts
|
|
4
4
|
/**
|
|
@@ -67,31 +67,6 @@ function scanName(text, start) {
|
|
|
67
67
|
}
|
|
68
68
|
return text.slice(start, end);
|
|
69
69
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Build an anchor map by walking the AST, collecting nodes that have anchors.
|
|
72
|
-
* Used to resolve aliases when extracting plain JavaScript values from
|
|
73
|
-
* parsed YAML documents.
|
|
74
|
-
*/
|
|
75
|
-
function buildAnchorMap(node) {
|
|
76
|
-
const anchors = /* @__PURE__ */ new Map();
|
|
77
|
-
collectAnchors(node, anchors);
|
|
78
|
-
return anchors;
|
|
79
|
-
}
|
|
80
|
-
function collectAnchors(node, anchors) {
|
|
81
|
-
if (node === null) return;
|
|
82
|
-
if (node instanceof YamlScalar) {
|
|
83
|
-
if (node.anchor !== void 0) anchors.set(node.anchor, node);
|
|
84
|
-
} else if (node instanceof YamlMap) {
|
|
85
|
-
if (node.anchor !== void 0) anchors.set(node.anchor, node);
|
|
86
|
-
for (const pair of node.items) {
|
|
87
|
-
collectAnchors(pair.key, anchors);
|
|
88
|
-
collectAnchors(pair.value, anchors);
|
|
89
|
-
}
|
|
90
|
-
} else if (node instanceof YamlSeq) {
|
|
91
|
-
if (node.anchor !== void 0) anchors.set(node.anchor, node);
|
|
92
|
-
for (const item of node.items) collectAnchors(item, anchors);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
70
|
|
|
96
71
|
//#endregion
|
|
97
|
-
export {
|
|
72
|
+
export { checkAnchorOnAlias, getAliasName, getAnchorName, makeAlias, registerAnchor, scanName };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { YamlMap, YamlPair, YamlScalar, YamlSeq } from "../../YamlNode.js";
|
|
2
2
|
import { checkAnchorOnAlias, getAnchorName, makeAlias, registerAnchor } from "./anchors.js";
|
|
3
|
+
import { blankAboveIsKeepChompContent, columnAt, hasBlankLineAbove, isOwnLineAt, joinComments, rawCommentText, sameLineSpan, withCommentFields } from "./comments.js";
|
|
3
4
|
import { enterNesting, exitNesting, hasMeta, hasNonWhitespaceBeforeOnLine, lineCol, lineIndentColumn, sameLine } from "./state.js";
|
|
4
5
|
import { blockMapStartsWithValueSep, classifyPlainNumeric, collectMultilineKey, collectMultilinePlainScalar, findFirstContent, findLastContent, findNextContentInList, findNextSignificantChild, findValueSepOffset, getScalarStyle, hasValueSepAfterInList, hasValueSepBetween, hasValueSepThroughPlainScalars, makeScalar, resolveScalar, shouldPreserveRaw } from "./scalars.js";
|
|
5
6
|
|
|
@@ -35,11 +36,12 @@ function composeBlockMapInner(blockMapCst, state, externalFirstKey, meta) {
|
|
|
35
36
|
kind: "key",
|
|
36
37
|
node: externalFirstKey
|
|
37
38
|
});
|
|
38
|
-
buildPairs(items, pairs, state.text);
|
|
39
|
+
const trailingComment = buildPairs(items, pairs, state.text, state.escapedComments);
|
|
39
40
|
if (state.options.uniqueKeys) checkDuplicateKeys(pairs, state);
|
|
40
41
|
checkMultilineImplicitKeys(pairs, state);
|
|
41
42
|
const offset = externalFirstKey ? "offset" in externalFirstKey ? externalFirstKey.offset : blockMapCst.offset : blockMapCst.offset;
|
|
42
43
|
const length = blockMapCst.offset + blockMapCst.length - offset;
|
|
44
|
+
const mapComment = meta?.comment !== void 0 ? trailingComment !== void 0 ? `${meta.comment}\n${trailingComment}` : meta.comment : trailingComment;
|
|
43
45
|
const map = new YamlMap({
|
|
44
46
|
items: pairs,
|
|
45
47
|
style: "block",
|
|
@@ -47,7 +49,7 @@ function composeBlockMapInner(blockMapCst, state, externalFirstKey, meta) {
|
|
|
47
49
|
length,
|
|
48
50
|
...meta?.tag !== void 0 ? { tag: meta.tag } : {},
|
|
49
51
|
...meta?.anchor !== void 0 ? { anchor: meta.anchor } : {},
|
|
50
|
-
...
|
|
52
|
+
...mapComment !== void 0 ? { comment: mapComment } : {}
|
|
51
53
|
});
|
|
52
54
|
if (meta?.anchor) registerAnchor(map, meta.anchor, state, offset);
|
|
53
55
|
return map;
|
|
@@ -104,6 +106,14 @@ function flattenBlockMapChildren(children, state, externalKeyColumn, externalKey
|
|
|
104
106
|
kind: "node",
|
|
105
107
|
node
|
|
106
108
|
});
|
|
109
|
+
if (state.escapedComments.length > 0) {
|
|
110
|
+
for (const ec of state.escapedComments) items.push({
|
|
111
|
+
kind: "comment",
|
|
112
|
+
comment: ec.text,
|
|
113
|
+
offset: ec.offset
|
|
114
|
+
});
|
|
115
|
+
state.escapedComments.length = 0;
|
|
116
|
+
}
|
|
107
117
|
afterValueSep = false;
|
|
108
118
|
}
|
|
109
119
|
for (let i = 0; i < children.length; i++) {
|
|
@@ -132,7 +142,7 @@ function flattenBlockMapChildren(children, state, externalKeyColumn, externalKey
|
|
|
132
142
|
const sliceChildren = children.slice(i + 1, lookahead.endIdx);
|
|
133
143
|
const innerItems = flattenBlockMapChildren(sliceChildren, state);
|
|
134
144
|
const innerPairs = [];
|
|
135
|
-
buildPairs(innerItems, innerPairs, state.text);
|
|
145
|
+
const innerTrailing = buildPairs(innerItems, innerPairs, state.text);
|
|
136
146
|
const firstC = findFirstContent(sliceChildren);
|
|
137
147
|
const lastC = findLastContent(sliceChildren);
|
|
138
148
|
const innerOffset = firstC ? firstC.offset : child.offset;
|
|
@@ -141,7 +151,8 @@ function flattenBlockMapChildren(children, state, externalKeyColumn, externalKey
|
|
|
141
151
|
items: innerPairs,
|
|
142
152
|
style: "block",
|
|
143
153
|
offset: innerOffset,
|
|
144
|
-
length: innerEnd - innerOffset
|
|
154
|
+
length: innerEnd - innerOffset,
|
|
155
|
+
...innerTrailing !== void 0 ? { comment: innerTrailing } : {}
|
|
145
156
|
}), innerOffset);
|
|
146
157
|
i = lookahead.endIdx - 1;
|
|
147
158
|
continue;
|
|
@@ -187,10 +198,10 @@ function flattenBlockMapChildren(children, state, externalKeyColumn, externalKey
|
|
|
187
198
|
continue;
|
|
188
199
|
}
|
|
189
200
|
if (child.type === "comment") {
|
|
190
|
-
const text = child.source.startsWith("#") ? child.source.slice(1).trim() : child.source;
|
|
191
201
|
items.push({
|
|
192
202
|
kind: "comment",
|
|
193
|
-
comment:
|
|
203
|
+
comment: rawCommentText(child.source),
|
|
204
|
+
offset: child.offset
|
|
194
205
|
});
|
|
195
206
|
continue;
|
|
196
207
|
}
|
|
@@ -479,9 +490,51 @@ function flattenBlockMapChildren(children, state, externalKeyColumn, externalKey
|
|
|
479
490
|
* Pattern: node, value-sep, node produces a key:value pair.
|
|
480
491
|
* Pattern: node, value-sep (no node) produces a key:null pair.
|
|
481
492
|
* Pattern: value-sep, node produces a null:value pair.
|
|
493
|
+
*
|
|
494
|
+
* Comment attribution (#127): a comment on the same line as the end of the
|
|
495
|
+
* previous pair attaches to it as the trailing `comment`; an own-line
|
|
496
|
+
* comment attaches FORWARD to the next pair as `commentBefore` (consecutive
|
|
497
|
+
* lines join with `\n`); a blank line before a pair (or before its
|
|
498
|
+
* `commentBefore` block) sets `spaceBefore`. Own-line comments left over
|
|
499
|
+
* after the last pair are returned so the caller can attach them as the
|
|
500
|
+
* containing collection's trailing `comment`.
|
|
482
501
|
*/
|
|
483
|
-
function buildPairs(items, pairs, text) {
|
|
502
|
+
function buildPairs(items, pairs, text, escaped) {
|
|
484
503
|
let i = 0;
|
|
504
|
+
let pending = [];
|
|
505
|
+
let pendingSpace = false;
|
|
506
|
+
let lastEnd = -1;
|
|
507
|
+
let lastNode;
|
|
508
|
+
let contentColumn = -1;
|
|
509
|
+
const nodeEnd = (n) => n.offset + n.length;
|
|
510
|
+
const noteContentColumn = (offset) => {
|
|
511
|
+
if (contentColumn < 0 && offset >= 0) contentColumn = columnAt(text, offset);
|
|
512
|
+
};
|
|
513
|
+
/** Join pending parts: `\n` between lines, an extra `\n` per embedded blank. */
|
|
514
|
+
const joinPending = (parts) => {
|
|
515
|
+
if (parts.length === 0) return void 0;
|
|
516
|
+
let out = parts[0].text;
|
|
517
|
+
for (let k = 1; k < parts.length; k++) {
|
|
518
|
+
const part = parts[k];
|
|
519
|
+
out += part.blankAbove ? `\n\n${part.text}` : `\n${part.text}`;
|
|
520
|
+
}
|
|
521
|
+
return out;
|
|
522
|
+
};
|
|
523
|
+
/** The pending comment fields for the pair being constructed, then reset. */
|
|
524
|
+
const takePendingFields = (anchorOffset) => {
|
|
525
|
+
let commentBefore = joinPending(pending);
|
|
526
|
+
if (anchorOffset >= 0 && hasBlankLineAbove(text, anchorOffset)) {
|
|
527
|
+
if (commentBefore !== void 0) commentBefore = `${commentBefore}\n`;
|
|
528
|
+
else if (!pendingSpace && lastEnd >= 0 && !blankAboveIsKeepChompContent(text, anchorOffset, lastNode)) pendingSpace = true;
|
|
529
|
+
}
|
|
530
|
+
const fields = {
|
|
531
|
+
...commentBefore !== void 0 ? { commentBefore } : {},
|
|
532
|
+
...pendingSpace ? { spaceBefore: true } : {}
|
|
533
|
+
};
|
|
534
|
+
pending = [];
|
|
535
|
+
pendingSpace = false;
|
|
536
|
+
return fields;
|
|
537
|
+
};
|
|
485
538
|
while (i < items.length) {
|
|
486
539
|
const item = items[i];
|
|
487
540
|
if (!item) {
|
|
@@ -489,12 +542,24 @@ function buildPairs(items, pairs, text) {
|
|
|
489
542
|
continue;
|
|
490
543
|
}
|
|
491
544
|
if (item.kind === "comment") {
|
|
492
|
-
|
|
545
|
+
const cOff = item.offset ?? -1;
|
|
546
|
+
const cText = item.comment ?? "";
|
|
547
|
+
if (!(cOff < 0 ? true : isOwnLineAt(text, cOff)) && pairs.length > 0) {
|
|
493
548
|
const last = pairs[pairs.length - 1];
|
|
494
549
|
if (last) pairs[pairs.length - 1] = new YamlPair({
|
|
495
550
|
key: last.key,
|
|
496
551
|
value: last.value,
|
|
497
|
-
...
|
|
552
|
+
...last.commentBefore !== void 0 ? { commentBefore: last.commentBefore } : {},
|
|
553
|
+
comment: last.comment !== void 0 ? `${last.comment}\n${cText}` : cText,
|
|
554
|
+
...last.spaceBefore !== void 0 ? { spaceBefore: last.spaceBefore } : {}
|
|
555
|
+
});
|
|
556
|
+
} else {
|
|
557
|
+
const blankAbove = cOff >= 0 && hasBlankLineAbove(text, cOff) && !blankAboveIsKeepChompContent(text, cOff, lastNode);
|
|
558
|
+
if (blankAbove && pending.length === 0 && lastEnd >= 0) pendingSpace = true;
|
|
559
|
+
pending.push({
|
|
560
|
+
text: cText,
|
|
561
|
+
offset: cOff,
|
|
562
|
+
blankAbove: blankAbove && pending.length > 0
|
|
498
563
|
});
|
|
499
564
|
}
|
|
500
565
|
i++;
|
|
@@ -503,30 +568,32 @@ function buildPairs(items, pairs, text) {
|
|
|
503
568
|
if (item.kind === "value-sep") {
|
|
504
569
|
const valueSepOffset = item.offset ?? 0;
|
|
505
570
|
i++;
|
|
571
|
+
const pendingFields = takePendingFields(valueSepOffset);
|
|
572
|
+
noteContentColumn(valueSepOffset);
|
|
506
573
|
const valueNode = consumeValueNodeForNullKey(items, i, text, valueSepOffset);
|
|
574
|
+
const nullKey = new YamlScalar({
|
|
575
|
+
value: null,
|
|
576
|
+
style: "plain",
|
|
577
|
+
offset: valueSepOffset,
|
|
578
|
+
length: 0
|
|
579
|
+
});
|
|
507
580
|
if (valueNode) {
|
|
508
|
-
const nullKey = new YamlScalar({
|
|
509
|
-
value: null,
|
|
510
|
-
style: "plain",
|
|
511
|
-
offset: valueSepOffset,
|
|
512
|
-
length: 0
|
|
513
|
-
});
|
|
514
581
|
pairs.push(new YamlPair({
|
|
515
582
|
key: nullKey,
|
|
516
|
-
value: valueNode.node ?? null
|
|
583
|
+
value: valueNode.node ?? null,
|
|
584
|
+
...pendingFields
|
|
517
585
|
}));
|
|
518
586
|
i = valueNode.nextIdx;
|
|
587
|
+
lastEnd = valueNode.node ? nodeEnd(valueNode.node) : valueSepOffset + 1;
|
|
588
|
+
lastNode = valueNode.node ?? void 0;
|
|
519
589
|
} else {
|
|
520
|
-
const nullKey = new YamlScalar({
|
|
521
|
-
value: null,
|
|
522
|
-
style: "plain",
|
|
523
|
-
offset: valueSepOffset,
|
|
524
|
-
length: 0
|
|
525
|
-
});
|
|
526
590
|
pairs.push(new YamlPair({
|
|
527
591
|
key: nullKey,
|
|
528
|
-
value: null
|
|
592
|
+
value: null,
|
|
593
|
+
...pendingFields
|
|
529
594
|
}));
|
|
595
|
+
lastEnd = valueSepOffset + 1;
|
|
596
|
+
lastNode = void 0;
|
|
530
597
|
}
|
|
531
598
|
continue;
|
|
532
599
|
}
|
|
@@ -540,62 +607,109 @@ function buildPairs(items, pairs, text) {
|
|
|
540
607
|
i++;
|
|
541
608
|
}
|
|
542
609
|
}
|
|
543
|
-
|
|
610
|
+
if (keyNode) noteContentColumn(keyNode.offset);
|
|
611
|
+
const pendingFields = takePendingFields(keyNode ? keyNode.offset : -1);
|
|
612
|
+
let pairTrailing;
|
|
613
|
+
while (i < items.length && items[i]?.kind === "comment") {
|
|
614
|
+
const c = items[i]?.comment;
|
|
615
|
+
if (c !== void 0) pairTrailing = joinComments(pairTrailing, c);
|
|
616
|
+
i++;
|
|
617
|
+
}
|
|
618
|
+
const keyOrNull = () => keyNode ?? new YamlScalar({
|
|
619
|
+
value: null,
|
|
620
|
+
style: "plain",
|
|
621
|
+
offset: 0,
|
|
622
|
+
length: 0
|
|
623
|
+
});
|
|
544
624
|
if (i < items.length && items[i]?.kind === "value-sep") {
|
|
625
|
+
const sepOffset = items[i]?.offset ?? (keyNode ? nodeEnd(keyNode) : 0);
|
|
545
626
|
i++;
|
|
546
|
-
const valueResult = consumeValueNode(items, i);
|
|
627
|
+
const valueResult = consumeValueNode(items, i, text, sepOffset);
|
|
547
628
|
if (valueResult) {
|
|
629
|
+
for (const c of valueResult.sameLineComments) pairTrailing = joinComments(pairTrailing, c);
|
|
630
|
+
let valNode = valueResult.node;
|
|
631
|
+
if (valNode !== null && valueResult.leadingComments.length > 0) valNode = withCommentFields(valNode, { commentBefore: valueResult.leadingComments.join("\n") });
|
|
548
632
|
pairs.push(new YamlPair({
|
|
549
|
-
key:
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
length: 0
|
|
554
|
-
}),
|
|
555
|
-
value: valueResult.node ?? null
|
|
633
|
+
key: keyOrNull(),
|
|
634
|
+
value: valNode,
|
|
635
|
+
...pendingFields,
|
|
636
|
+
...pairTrailing !== void 0 ? { comment: pairTrailing } : {}
|
|
556
637
|
}));
|
|
557
638
|
i = valueResult.nextIdx;
|
|
558
|
-
|
|
559
|
-
|
|
639
|
+
lastEnd = valNode ? nodeEnd(valNode) : sepOffset + 1;
|
|
640
|
+
lastNode = valNode ?? void 0;
|
|
641
|
+
} else {
|
|
642
|
+
pairs.push(new YamlPair({
|
|
643
|
+
key: keyOrNull(),
|
|
560
644
|
value: null,
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
} else
|
|
568
|
-
|
|
645
|
+
...pendingFields,
|
|
646
|
+
...pairTrailing !== void 0 ? { comment: pairTrailing } : {}
|
|
647
|
+
}));
|
|
648
|
+
lastEnd = sepOffset + 1;
|
|
649
|
+
lastNode = void 0;
|
|
650
|
+
}
|
|
651
|
+
} else {
|
|
652
|
+
pairs.push(new YamlPair({
|
|
653
|
+
key: keyOrNull(),
|
|
569
654
|
value: null,
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
}
|
|
655
|
+
...pendingFields,
|
|
656
|
+
...pairTrailing !== void 0 ? { comment: pairTrailing } : {}
|
|
657
|
+
}));
|
|
658
|
+
lastEnd = keyNode ? nodeEnd(keyNode) : lastEnd;
|
|
659
|
+
if (keyNode) lastNode = keyNode;
|
|
660
|
+
}
|
|
576
661
|
continue;
|
|
577
662
|
}
|
|
578
663
|
i++;
|
|
579
664
|
}
|
|
665
|
+
if (pending.length === 0) return void 0;
|
|
666
|
+
const withLeadingBlank = (parts) => {
|
|
667
|
+
const joined = joinPending(parts);
|
|
668
|
+
const first = parts[0];
|
|
669
|
+
return joined !== void 0 && first !== void 0 && lastEnd >= 0 && first.offset >= 0 && hasBlankLineAbove(text, first.offset) && !blankAboveIsKeepChompContent(text, first.offset, lastNode) ? `\n${joined}` : joined;
|
|
670
|
+
};
|
|
671
|
+
if (escaped !== void 0 && contentColumn > 0) {
|
|
672
|
+
const kept = [];
|
|
673
|
+
for (const part of pending) if (part.offset >= 0 && columnAt(text, part.offset) < contentColumn) escaped.push({
|
|
674
|
+
text: part.text,
|
|
675
|
+
offset: part.offset
|
|
676
|
+
});
|
|
677
|
+
else kept.push(part);
|
|
678
|
+
return withLeadingBlank(kept);
|
|
679
|
+
}
|
|
680
|
+
return withLeadingBlank(pending);
|
|
580
681
|
}
|
|
581
|
-
function consumeValueNode(items, startIdx) {
|
|
682
|
+
function consumeValueNode(items, startIdx, text, sepOffset) {
|
|
683
|
+
let peek = startIdx;
|
|
684
|
+
while (peek < items.length && items[peek]?.kind === "comment") peek++;
|
|
685
|
+
const candidate = peek < items.length ? items[peek] : void 0;
|
|
686
|
+
if (candidate?.kind === "node" && peek + 1 < items.length && items[peek + 1]?.kind === "value-sep" && candidate.node !== void 0 && text.slice(sepOffset, candidate.node.offset).includes("\n")) return null;
|
|
582
687
|
let i = startIdx;
|
|
688
|
+
const sameLineComments = [];
|
|
689
|
+
const leadingComments = [];
|
|
583
690
|
while (i < items.length) {
|
|
584
691
|
const item = items[i];
|
|
585
692
|
if (!item) break;
|
|
586
693
|
if (item.kind === "comment") {
|
|
694
|
+
const cText = item.comment ?? "";
|
|
695
|
+
if (item.offset !== void 0 && sameLineSpan(text, sepOffset, item.offset)) sameLineComments.push(cText);
|
|
696
|
+
else leadingComments.push(cText);
|
|
587
697
|
i++;
|
|
588
698
|
continue;
|
|
589
699
|
}
|
|
590
700
|
if (item.kind === "node") return {
|
|
591
701
|
node: item.node ?? null,
|
|
592
|
-
nextIdx: i + 1
|
|
702
|
+
nextIdx: i + 1,
|
|
703
|
+
sameLineComments,
|
|
704
|
+
leadingComments
|
|
593
705
|
};
|
|
594
706
|
break;
|
|
595
707
|
}
|
|
596
708
|
return i > startIdx ? {
|
|
597
709
|
node: null,
|
|
598
|
-
nextIdx: i
|
|
710
|
+
nextIdx: i,
|
|
711
|
+
sameLineComments,
|
|
712
|
+
leadingComments
|
|
599
713
|
} : null;
|
|
600
714
|
}
|
|
601
715
|
/**
|
|
@@ -950,11 +1064,59 @@ function composeBlockSeq(cst, state, meta) {
|
|
|
950
1064
|
}
|
|
951
1065
|
function composeBlockSeqInner(cst, state, meta) {
|
|
952
1066
|
const children = cst.children ?? [];
|
|
953
|
-
const
|
|
1067
|
+
const rawItems = [];
|
|
954
1068
|
let pendingMeta = {};
|
|
955
1069
|
let sawEntry = false;
|
|
956
1070
|
const seqIndent = lineIndentColumn(state.text, cst.offset);
|
|
957
1071
|
let sawNewlineSincePending = false;
|
|
1072
|
+
let pending = [];
|
|
1073
|
+
let pendingSpace = false;
|
|
1074
|
+
let lastItemEnd = -1;
|
|
1075
|
+
let lastItemNode;
|
|
1076
|
+
const joinPending = (parts) => {
|
|
1077
|
+
if (parts.length === 0) return void 0;
|
|
1078
|
+
let out = parts[0].text;
|
|
1079
|
+
for (let k = 1; k < parts.length; k++) {
|
|
1080
|
+
const part = parts[k];
|
|
1081
|
+
out += part.blankAbove ? `\n\n${part.text}` : `\n${part.text}`;
|
|
1082
|
+
}
|
|
1083
|
+
return out;
|
|
1084
|
+
};
|
|
1085
|
+
const acceptOwnLineComment = (cText, cOff) => {
|
|
1086
|
+
const blankAbove = cOff >= 0 && hasBlankLineAbove(state.text, cOff) && !blankAboveIsKeepChompContent(state.text, cOff, lastItemNode);
|
|
1087
|
+
if (blankAbove && pending.length === 0 && lastItemEnd >= 0) pendingSpace = true;
|
|
1088
|
+
pending.push({
|
|
1089
|
+
text: cText,
|
|
1090
|
+
offset: cOff,
|
|
1091
|
+
blankAbove: blankAbove && pending.length > 0
|
|
1092
|
+
});
|
|
1093
|
+
};
|
|
1094
|
+
const items = {
|
|
1095
|
+
get length() {
|
|
1096
|
+
return rawItems.length;
|
|
1097
|
+
},
|
|
1098
|
+
push(node) {
|
|
1099
|
+
let commentBefore = joinPending(pending);
|
|
1100
|
+
if (node.length > 0 && hasBlankLineAbove(state.text, node.offset)) {
|
|
1101
|
+
if (commentBefore !== void 0) commentBefore = `${commentBefore}\n`;
|
|
1102
|
+
else if (!pendingSpace && lastItemEnd >= 0 && !blankAboveIsKeepChompContent(state.text, node.offset, lastItemNode)) pendingSpace = true;
|
|
1103
|
+
}
|
|
1104
|
+
let decorated = node;
|
|
1105
|
+
if (commentBefore !== void 0 || pendingSpace) decorated = withCommentFields(node, {
|
|
1106
|
+
...commentBefore !== void 0 ? { commentBefore } : {},
|
|
1107
|
+
...pendingSpace ? { spaceBefore: true } : {}
|
|
1108
|
+
});
|
|
1109
|
+
pending = [];
|
|
1110
|
+
pendingSpace = false;
|
|
1111
|
+
rawItems.push(decorated);
|
|
1112
|
+
lastItemEnd = node.offset + node.length;
|
|
1113
|
+
lastItemNode = node;
|
|
1114
|
+
if (state.escapedComments.length > 0) {
|
|
1115
|
+
for (const ec of state.escapedComments) acceptOwnLineComment(ec.text, ec.offset);
|
|
1116
|
+
state.escapedComments.length = 0;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
958
1120
|
for (let ci = 0; ci < children.length; ci++) {
|
|
959
1121
|
const child = children[ci];
|
|
960
1122
|
if (!child) continue;
|
|
@@ -962,7 +1124,14 @@ function composeBlockSeqInner(cst, state, meta) {
|
|
|
962
1124
|
if (hasMeta(pendingMeta)) sawNewlineSincePending = true;
|
|
963
1125
|
continue;
|
|
964
1126
|
}
|
|
965
|
-
if (child.type === "comment")
|
|
1127
|
+
if (child.type === "comment") {
|
|
1128
|
+
const cText = rawCommentText(child.source);
|
|
1129
|
+
if (rawItems.length > 0 && !isOwnLineAt(state.text, child.offset)) {
|
|
1130
|
+
const prev = rawItems[rawItems.length - 1];
|
|
1131
|
+
if (prev) rawItems[rawItems.length - 1] = withCommentFields(prev, { comment: cText });
|
|
1132
|
+
} else acceptOwnLineComment(cText, child.offset);
|
|
1133
|
+
continue;
|
|
1134
|
+
}
|
|
966
1135
|
if (child.type === "whitespace") {
|
|
967
1136
|
if (child.source.trim() === "-") {
|
|
968
1137
|
if (sawEntry) {
|
|
@@ -1121,14 +1290,32 @@ function composeBlockSeqInner(cst, state, meta) {
|
|
|
1121
1290
|
if (pendingMeta.anchor) registerAnchor(scalar, pendingMeta.anchor, state, 0);
|
|
1122
1291
|
items.push(scalar);
|
|
1123
1292
|
}
|
|
1293
|
+
const withLeadingBlank = (parts) => {
|
|
1294
|
+
const joined = joinPending(parts);
|
|
1295
|
+
const first = parts[0];
|
|
1296
|
+
return joined !== void 0 && first !== void 0 && lastItemEnd >= 0 && first.offset >= 0 && hasBlankLineAbove(state.text, first.offset) && !blankAboveIsKeepChompContent(state.text, first.offset, lastItemNode) ? `\n${joined}` : joined;
|
|
1297
|
+
};
|
|
1298
|
+
let seqTrailing;
|
|
1299
|
+
if (pending.length > 0) {
|
|
1300
|
+
if (seqIndent > 0) {
|
|
1301
|
+
const kept = [];
|
|
1302
|
+
for (const part of pending) if (part.offset >= 0 && columnAt(state.text, part.offset) < seqIndent) state.escapedComments.push({
|
|
1303
|
+
text: part.text,
|
|
1304
|
+
offset: part.offset
|
|
1305
|
+
});
|
|
1306
|
+
else kept.push(part);
|
|
1307
|
+
seqTrailing = withLeadingBlank(kept);
|
|
1308
|
+
} else seqTrailing = withLeadingBlank(pending);
|
|
1309
|
+
}
|
|
1310
|
+
const seqComment = meta?.comment !== void 0 ? seqTrailing !== void 0 ? `${meta.comment}\n${seqTrailing}` : meta.comment : seqTrailing;
|
|
1124
1311
|
const seq = new YamlSeq({
|
|
1125
|
-
items,
|
|
1312
|
+
items: rawItems,
|
|
1126
1313
|
style: "block",
|
|
1127
1314
|
offset: cst.offset,
|
|
1128
1315
|
length: cst.length,
|
|
1129
1316
|
...meta?.tag !== void 0 ? { tag: meta.tag } : {},
|
|
1130
1317
|
...meta?.anchor !== void 0 ? { anchor: meta.anchor } : {},
|
|
1131
|
-
...
|
|
1318
|
+
...seqComment !== void 0 ? { comment: seqComment } : {}
|
|
1132
1319
|
});
|
|
1133
1320
|
if (meta?.anchor) registerAnchor(seq, meta.anchor, state, cst.offset);
|
|
1134
1321
|
return seq;
|
|
@@ -1144,11 +1331,12 @@ function composeFlatBlockMap(children, startIdx, parentCst, state, externalFirst
|
|
|
1144
1331
|
node: externalFirstKey
|
|
1145
1332
|
});
|
|
1146
1333
|
const pairs = [];
|
|
1147
|
-
buildPairs(items, pairs, state.text);
|
|
1334
|
+
const trailingComment = buildPairs(items, pairs, state.text, state.escapedComments);
|
|
1148
1335
|
if (state.options.uniqueKeys) checkDuplicateKeys(pairs, state);
|
|
1149
1336
|
checkMultilineImplicitKeys(pairs, state);
|
|
1150
1337
|
const offset = "offset" in externalFirstKey ? externalFirstKey.offset : parentCst.offset;
|
|
1151
1338
|
const end = parentCst.offset + parentCst.length;
|
|
1339
|
+
const mapComment = meta?.comment !== void 0 ? trailingComment !== void 0 ? `${meta.comment}\n${trailingComment}` : meta.comment : trailingComment;
|
|
1152
1340
|
const map = new YamlMap({
|
|
1153
1341
|
items: pairs,
|
|
1154
1342
|
style: "block",
|
|
@@ -1156,11 +1344,11 @@ function composeFlatBlockMap(children, startIdx, parentCst, state, externalFirst
|
|
|
1156
1344
|
length: end - offset,
|
|
1157
1345
|
...meta?.tag !== void 0 ? { tag: meta.tag } : {},
|
|
1158
1346
|
...meta?.anchor !== void 0 ? { anchor: meta.anchor } : {},
|
|
1159
|
-
...
|
|
1347
|
+
...mapComment !== void 0 ? { comment: mapComment } : {}
|
|
1160
1348
|
});
|
|
1161
1349
|
if (meta?.anchor) registerAnchor(map, meta.anchor, state, offset);
|
|
1162
1350
|
return map;
|
|
1163
1351
|
}
|
|
1164
1352
|
|
|
1165
1353
|
//#endregion
|
|
1166
|
-
export { buildPairs, checkDuplicateKeys, checkMultilineImplicitKeys, checkTrailingContentOnSameLine, composeBlockMap, composeBlockSeq, composeFlatBlockMap, flattenBlockMapChildren };
|
|
1354
|
+
export { buildPairs, checkDuplicateKeys, checkMultilineImplicitKeys, checkTrailingContentOnSameLine, composeBlockMap, composeBlockSeq, composeFlatBlockMap, flattenBlockMapChildren, keyIdentity };
|