@effected/yaml 0.10.0 → 0.12.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 +43 -7
- package/Yaml.js +32 -3
- package/YamlDocument.js +2 -0
- package/YamlFormat.js +77 -9
- package/YamlLint.js +0 -0
- package/YamlLintRule.js +50 -1
- package/YamlNode.js +16 -1
- package/index.d.ts +300 -7
- package/index.js +4 -4
- package/internal/requote.js +48 -0
- package/internal/rules/comments-spacing.js +48 -9
- package/internal/rules/document-end.js +48 -18
- package/internal/rules/document-start.js +31 -5
- package/internal/rules/empty-lines.js +21 -1
- package/internal/rules/indentation.js +76 -23
- package/internal/rules/line-length.js +9 -1
- package/internal/rules/quoted-strings.js +29 -11
- package/internal/stringifier.js +30 -7
- package/package.json +1 -1
- package/tsdoc-metadata.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { YamlEdit } from "../../YamlEdit.js";
|
|
2
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
2
|
+
import { StyleVote, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
3
3
|
import { Schema } from "effect";
|
|
4
4
|
|
|
5
5
|
//#region src/internal/rules/document-start.ts
|
|
@@ -15,13 +15,17 @@ const TRIVIA = /* @__PURE__ */ new Set([
|
|
|
15
15
|
"byte-order-mark",
|
|
16
16
|
"directive"
|
|
17
17
|
]);
|
|
18
|
+
/** True when the stream carries `%YAML`/`%TAG` directives — which REQUIRE `---`. */
|
|
19
|
+
const hasDirectives = (ctx) => ctx.tokens.some((t) => t.kind === "directive");
|
|
20
|
+
/** The first non-trivia token: it decides whether the stream is headed by `---`. */
|
|
21
|
+
const headToken = (ctx) => ctx.tokens.find((t) => !TRIVIA.has(t.kind));
|
|
18
22
|
/** The `---` marker at the head of the stream. */
|
|
19
23
|
const documentStart = {
|
|
20
24
|
id: "document-start",
|
|
21
25
|
check: (ctx, options) => {
|
|
22
26
|
const present = options?.present ?? true;
|
|
23
|
-
const
|
|
24
|
-
const first = ctx
|
|
27
|
+
const directives = hasDirectives(ctx);
|
|
28
|
+
const first = headToken(ctx);
|
|
25
29
|
const headed = first?.kind === "document-start";
|
|
26
30
|
if (present && !headed && ctx.text.trim() !== "") return [new YamlLintDiagnostic({
|
|
27
31
|
rule: "document-start",
|
|
@@ -31,7 +35,7 @@ const documentStart = {
|
|
|
31
35
|
length: 0,
|
|
32
36
|
line: 0,
|
|
33
37
|
character: 0,
|
|
34
|
-
...
|
|
38
|
+
...directives ? {} : { fix: YamlEdit.make({
|
|
35
39
|
offset: 0,
|
|
36
40
|
length: 0,
|
|
37
41
|
content: "---\n"
|
|
@@ -39,7 +43,7 @@ const documentStart = {
|
|
|
39
43
|
})];
|
|
40
44
|
if (!present && headed && first !== void 0) {
|
|
41
45
|
const lineText = ctx.lines[first.line]?.text ?? "";
|
|
42
|
-
const alone = !
|
|
46
|
+
const alone = !directives && lineText.trim() === "---";
|
|
43
47
|
const terminator = ctx.text.startsWith("\r\n", first.offset + first.length) ? 2 : 1;
|
|
44
48
|
return [new YamlLintDiagnostic({
|
|
45
49
|
rule: "document-start",
|
|
@@ -57,6 +61,28 @@ const documentStart = {
|
|
|
57
61
|
})];
|
|
58
62
|
}
|
|
59
63
|
return [];
|
|
64
|
+
},
|
|
65
|
+
infer: (ctx) => {
|
|
66
|
+
if (ctx.text.trim() === "") return [];
|
|
67
|
+
const first = headToken(ctx);
|
|
68
|
+
if (first === void 0) return [];
|
|
69
|
+
const headed = first.kind === "document-start";
|
|
70
|
+
if (!headed && hasDirectives(ctx)) return [];
|
|
71
|
+
return [StyleVote.make(headed ? {
|
|
72
|
+
dimension: "present",
|
|
73
|
+
value: true,
|
|
74
|
+
offset: first.offset,
|
|
75
|
+
length: first.length,
|
|
76
|
+
line: first.line,
|
|
77
|
+
character: first.character
|
|
78
|
+
} : {
|
|
79
|
+
dimension: "present",
|
|
80
|
+
value: false,
|
|
81
|
+
offset: 0,
|
|
82
|
+
length: 0,
|
|
83
|
+
line: 0,
|
|
84
|
+
character: 0
|
|
85
|
+
})];
|
|
60
86
|
}
|
|
61
87
|
};
|
|
62
88
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { YamlEdit } from "../../YamlEdit.js";
|
|
2
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
2
|
+
import { StyleFloor, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
3
3
|
import { insideScalarSpan, nonNegativeIntegerOption } from "./util.js";
|
|
4
4
|
import { Schema } from "effect";
|
|
5
5
|
|
|
@@ -63,6 +63,26 @@ const emptyLines = {
|
|
|
63
63
|
i = end;
|
|
64
64
|
}
|
|
65
65
|
return out;
|
|
66
|
+
},
|
|
67
|
+
infer: (ctx) => {
|
|
68
|
+
let longest = 0;
|
|
69
|
+
const lines = ctx.lines;
|
|
70
|
+
let i = 0;
|
|
71
|
+
while (i < lines.length) {
|
|
72
|
+
const line = lines[i];
|
|
73
|
+
if (line === void 0 || line.text !== "" || insideScalarSpan(ctx.tokens, line.offset)) {
|
|
74
|
+
i++;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
let end = i;
|
|
78
|
+
while (end < lines.length && (lines[end]?.text ?? "x") === "") end++;
|
|
79
|
+
if (i !== 0 && end !== lines.length && end - i > longest) longest = end - i;
|
|
80
|
+
i = end;
|
|
81
|
+
}
|
|
82
|
+
return longest > 0 ? [StyleFloor.make({
|
|
83
|
+
dimension: "max",
|
|
84
|
+
value: longest
|
|
85
|
+
})] : [];
|
|
66
86
|
}
|
|
67
87
|
};
|
|
68
88
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
1
|
+
import { StyleVote, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
2
2
|
import { coveringToken, isScalarContinuationLine, nonNegativeIntegerOption } from "./util.js";
|
|
3
3
|
import { Schema } from "effect";
|
|
4
4
|
|
|
@@ -30,6 +30,44 @@ const flowDepthAtLineStarts = (ctx) => {
|
|
|
30
30
|
}
|
|
31
31
|
return depths;
|
|
32
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* The content lines block structure speaks about — shared by the check and
|
|
35
|
+
* the inference hook so the two read the same lines. Skips blanks, comment
|
|
36
|
+
* lines, directives, tab-indented lines (the parser's error), lines inside
|
|
37
|
+
* flow collections, scalar continuations and document markers.
|
|
38
|
+
*/
|
|
39
|
+
const contentLines = (ctx) => {
|
|
40
|
+
const flowDepths = flowDepthAtLineStarts(ctx);
|
|
41
|
+
const content = [];
|
|
42
|
+
for (const line of ctx.lines) {
|
|
43
|
+
const indent = line.text.length - line.text.trimStart().length;
|
|
44
|
+
const firstChar = line.text[indent];
|
|
45
|
+
if (firstChar === void 0) continue;
|
|
46
|
+
if (firstChar === "#") continue;
|
|
47
|
+
if (firstChar === "%") continue;
|
|
48
|
+
if (line.text.slice(0, indent).includes(" ")) continue;
|
|
49
|
+
if ((flowDepths[line.number] ?? 0) > 0) continue;
|
|
50
|
+
if (isScalarContinuationLine(ctx.tokens, line.offset, line.offset + indent)) continue;
|
|
51
|
+
if (line.text.slice(indent).startsWith("---") || line.text.slice(indent).startsWith("...")) continue;
|
|
52
|
+
content.push({
|
|
53
|
+
line,
|
|
54
|
+
indent,
|
|
55
|
+
firstChar
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return content;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* True when consecutive content lines `prev` → `curr` are a mapping key
|
|
62
|
+
* followed by a sequence entry — the pair the `indentSequences` policy is
|
|
63
|
+
* about. Shared by the check and the inference hook.
|
|
64
|
+
*/
|
|
65
|
+
const isKeyThenSeqEntry = (ctx, prev, curr, unit) => {
|
|
66
|
+
if (curr.firstChar !== "-") return false;
|
|
67
|
+
if (coveringToken(ctx.tokens, curr.line.offset + curr.indent)?.kind !== "block-seq-entry") return false;
|
|
68
|
+
if (!prev.line.text.replace(/ #.*$/, "").trimEnd().endsWith(":")) return false;
|
|
69
|
+
return curr.indent === prev.indent || curr.indent === prev.indent + (unit ?? curr.indent - prev.indent);
|
|
70
|
+
};
|
|
33
71
|
/** Block-structure indent style. */
|
|
34
72
|
const indentation = {
|
|
35
73
|
id: "indentation",
|
|
@@ -38,24 +76,7 @@ const indentation = {
|
|
|
38
76
|
const spacesOpt = opts.spaces ?? "consistent";
|
|
39
77
|
const seqOpt = opts.indentSequences ?? "consistent";
|
|
40
78
|
const out = [];
|
|
41
|
-
const
|
|
42
|
-
const content = [];
|
|
43
|
-
for (const line of ctx.lines) {
|
|
44
|
-
const indent = line.text.length - line.text.trimStart().length;
|
|
45
|
-
const firstChar = line.text[indent];
|
|
46
|
-
if (firstChar === void 0) continue;
|
|
47
|
-
if (firstChar === "#") continue;
|
|
48
|
-
if (firstChar === "%") continue;
|
|
49
|
-
if (line.text.slice(0, indent).includes(" ")) continue;
|
|
50
|
-
if ((flowDepths[line.number] ?? 0) > 0) continue;
|
|
51
|
-
if (isScalarContinuationLine(ctx.tokens, line.offset, line.offset + indent)) continue;
|
|
52
|
-
if (line.text.slice(indent).startsWith("---") || line.text.slice(indent).startsWith("...")) continue;
|
|
53
|
-
content.push({
|
|
54
|
-
line,
|
|
55
|
-
indent,
|
|
56
|
-
firstChar
|
|
57
|
-
});
|
|
58
|
-
}
|
|
79
|
+
const content = contentLines(ctx);
|
|
59
80
|
let unit = typeof spacesOpt === "number" ? spacesOpt : void 0;
|
|
60
81
|
const stack = [0];
|
|
61
82
|
for (const { line, indent } of content) {
|
|
@@ -79,10 +100,7 @@ const indentation = {
|
|
|
79
100
|
for (let i = 1; i < content.length; i++) {
|
|
80
101
|
const prev = content[i - 1];
|
|
81
102
|
const curr = content[i];
|
|
82
|
-
if (curr
|
|
83
|
-
if (coveringToken(ctx.tokens, curr.line.offset + curr.indent)?.kind !== "block-seq-entry") continue;
|
|
84
|
-
if (!prev.line.text.replace(/ #.*$/, "").trimEnd().endsWith(":")) continue;
|
|
85
|
-
if (curr.indent !== prev.indent && curr.indent !== prev.indent + (unit ?? curr.indent - prev.indent)) continue;
|
|
103
|
+
if (!isKeyThenSeqEntry(ctx, prev, curr, unit)) continue;
|
|
86
104
|
const indented = curr.indent > prev.indent;
|
|
87
105
|
if (seqIndented === void 0) seqIndented = indented;
|
|
88
106
|
else if (indented !== seqIndented) out.push(new YamlLintDiagnostic({
|
|
@@ -96,6 +114,41 @@ const indentation = {
|
|
|
96
114
|
}));
|
|
97
115
|
}
|
|
98
116
|
return out;
|
|
117
|
+
},
|
|
118
|
+
infer: (ctx) => {
|
|
119
|
+
const out = [];
|
|
120
|
+
const content = contentLines(ctx);
|
|
121
|
+
let unit;
|
|
122
|
+
const stack = [0];
|
|
123
|
+
for (const { line, indent } of content) {
|
|
124
|
+
const top = stack[stack.length - 1];
|
|
125
|
+
if (indent > top) {
|
|
126
|
+
out.push(StyleVote.make({
|
|
127
|
+
dimension: "spaces",
|
|
128
|
+
value: indent - top,
|
|
129
|
+
offset: line.offset,
|
|
130
|
+
length: indent,
|
|
131
|
+
line: line.number,
|
|
132
|
+
character: 0
|
|
133
|
+
}));
|
|
134
|
+
if (unit === void 0) unit = indent - top;
|
|
135
|
+
stack.push(indent);
|
|
136
|
+
} else if (indent < top) while (stack.length > 1 && stack[stack.length - 1] > indent) stack.pop();
|
|
137
|
+
}
|
|
138
|
+
for (let i = 1; i < content.length; i++) {
|
|
139
|
+
const prev = content[i - 1];
|
|
140
|
+
const curr = content[i];
|
|
141
|
+
if (!isKeyThenSeqEntry(ctx, prev, curr, unit)) continue;
|
|
142
|
+
out.push(StyleVote.make({
|
|
143
|
+
dimension: "indentSequences",
|
|
144
|
+
value: curr.indent > prev.indent,
|
|
145
|
+
offset: curr.line.offset,
|
|
146
|
+
length: curr.indent,
|
|
147
|
+
line: curr.line.number,
|
|
148
|
+
character: 0
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
99
152
|
}
|
|
100
153
|
};
|
|
101
154
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
1
|
+
import { StyleFloor, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
2
2
|
import { nonNegativeIntegerOption } from "./util.js";
|
|
3
3
|
import { Schema } from "effect";
|
|
4
4
|
|
|
@@ -29,6 +29,14 @@ const lineLength = {
|
|
|
29
29
|
character: max
|
|
30
30
|
}));
|
|
31
31
|
return out;
|
|
32
|
+
},
|
|
33
|
+
infer: (ctx) => {
|
|
34
|
+
let longest = 0;
|
|
35
|
+
for (const line of ctx.lines) if (line.text.length > longest) longest = line.text.length;
|
|
36
|
+
return longest > 0 ? [StyleFloor.make({
|
|
37
|
+
dimension: "max",
|
|
38
|
+
value: longest
|
|
39
|
+
})] : [];
|
|
32
40
|
}
|
|
33
41
|
};
|
|
34
42
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { YamlEdit } from "../../YamlEdit.js";
|
|
2
|
-
import {
|
|
2
|
+
import { requoteScalarText } from "../requote.js";
|
|
3
|
+
import { StyleVote, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
3
4
|
import { positionAt, walkScalars } from "./util.js";
|
|
4
5
|
import { Schema } from "effect";
|
|
5
6
|
|
|
@@ -14,20 +15,19 @@ const quotedStringsOptions = Schema.Struct({
|
|
|
14
15
|
quoteType: Schema.optionalKey(Schema.Literals(["single", "double"])),
|
|
15
16
|
required: Schema.optionalKey(Schema.Boolean)
|
|
16
17
|
});
|
|
17
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* A value-preserving requote/wrap edit, or undefined when none is safe.
|
|
20
|
+
* Delegates to the shared helper's CONSERVATIVE mode (#347) — the shipped
|
|
21
|
+
* fix behavior stays exactly as released; the escaping-capable mode belongs
|
|
22
|
+
* to the format path's opt-in `requoteScalars`, not the lint fix.
|
|
23
|
+
*/
|
|
18
24
|
const safeQuoteFix = (ctx, scalar, quote) => {
|
|
19
|
-
|
|
20
|
-
if (
|
|
21
|
-
const raw = ctx.text.slice(scalar.offset, scalar.offset + scalar.length);
|
|
22
|
-
if (raw.includes("\n")) return void 0;
|
|
23
|
-
const inner = scalar.style === "plain" ? raw : raw.slice(1, -1);
|
|
24
|
-
if (inner !== scalar.value) return void 0;
|
|
25
|
-
if (inner.includes(quote)) return void 0;
|
|
26
|
-
if (quote === "\"" && inner.includes("\\")) return void 0;
|
|
25
|
+
const content = requoteScalarText(ctx.text, scalar, quote, "conservative");
|
|
26
|
+
if (content === void 0) return void 0;
|
|
27
27
|
return YamlEdit.make({
|
|
28
28
|
offset: scalar.offset,
|
|
29
29
|
length: scalar.length,
|
|
30
|
-
content
|
|
30
|
+
content
|
|
31
31
|
});
|
|
32
32
|
};
|
|
33
33
|
/** Quote-style policy for string value scalars. */
|
|
@@ -74,6 +74,24 @@ const quotedStrings = {
|
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
76
|
return out;
|
|
77
|
+
},
|
|
78
|
+
infer: (ctx) => {
|
|
79
|
+
const out = [];
|
|
80
|
+
walkScalars(ctx.document.contents, "root", (scalar, role) => {
|
|
81
|
+
if (role === "key") return;
|
|
82
|
+
if (typeof scalar.value !== "string") return;
|
|
83
|
+
if (scalar.style !== "single-quoted" && scalar.style !== "double-quoted") return;
|
|
84
|
+
const pos = positionAt(ctx.lines, scalar.offset);
|
|
85
|
+
out.push(StyleVote.make({
|
|
86
|
+
dimension: "quoteType",
|
|
87
|
+
value: scalar.style === "single-quoted" ? "single" : "double",
|
|
88
|
+
offset: scalar.offset,
|
|
89
|
+
length: scalar.length,
|
|
90
|
+
line: pos.line,
|
|
91
|
+
character: pos.character
|
|
92
|
+
}));
|
|
93
|
+
});
|
|
94
|
+
return out;
|
|
77
95
|
}
|
|
78
96
|
};
|
|
79
97
|
|
package/internal/stringifier.js
CHANGED
|
@@ -105,6 +105,23 @@ function wouldBeResolved(s) {
|
|
|
105
105
|
if (FLOAT_RE.test(s)) return true;
|
|
106
106
|
return false;
|
|
107
107
|
}
|
|
108
|
+
const BOOL_11_RE = /^(?:y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$/;
|
|
109
|
+
const INT_11_RE = /^[-+]?(?:0b[0-1_]+|0o?[0-7_]+|[0-9][0-9_]*|0x[0-9a-fA-F_]+|[1-9][0-9_]*(?::[0-5]?[0-9])+)$/;
|
|
110
|
+
const FLOAT_11_RE = /^[-+]?(?:[0-9][0-9_]*(?:\.[0-9_]*(?:[eE][-+]?[0-9]+)?|[eE][-+]?[0-9]+)|\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*)$/;
|
|
111
|
+
const TIMESTAMP_11_RE = /^[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::?[0-9][0-9])?))?)?$/;
|
|
112
|
+
/**
|
|
113
|
+
* Returns true if a string value would be resolved as a non-string type by a
|
|
114
|
+
* YAML 1.1 parser. The delta over {@link wouldBeResolved}: null spellings are
|
|
115
|
+
* identical in both editions (and already covered), so only the boolean,
|
|
116
|
+
* integer, float and timestamp families are tested here.
|
|
117
|
+
*/
|
|
118
|
+
function wouldBeResolved11(s) {
|
|
119
|
+
if (BOOL_11_RE.test(s)) return true;
|
|
120
|
+
if (INT_11_RE.test(s)) return true;
|
|
121
|
+
if (FLOAT_11_RE.test(s)) return true;
|
|
122
|
+
if (TIMESTAMP_11_RE.test(s)) return true;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
108
125
|
/**
|
|
109
126
|
* Returns true if a string requires quoting to be safely represented as a plain scalar.
|
|
110
127
|
*
|
|
@@ -112,11 +129,16 @@ function wouldBeResolved(s) {
|
|
|
112
129
|
* embedded newlines, leading indicator characters or whitespace, and inline
|
|
113
130
|
* comment/mapping-value patterns (`: `, ` #`). This is the single gate that
|
|
114
131
|
* decides whether a plain scalar is safe or must be wrapped in quotes.
|
|
132
|
+
*
|
|
133
|
+
* `quoteCompat` is strictly additive: `"yaml-1.1"` additionally quotes
|
|
134
|
+
* strings a YAML 1.1 parser would coerce ({@link wouldBeResolved11}) and can
|
|
135
|
+
* never un-quote anything the 1.2 rules require quoted.
|
|
115
136
|
*/
|
|
116
|
-
function requiresQuoting(s, ignoreType = false) {
|
|
137
|
+
function requiresQuoting(s, ignoreType = false, quoteCompat) {
|
|
117
138
|
if (s === "") return true;
|
|
118
139
|
if (s.includes("\n")) return true;
|
|
119
140
|
if (!ignoreType && wouldBeResolved(s)) return true;
|
|
141
|
+
if (!ignoreType && quoteCompat === "yaml-1.1" && wouldBeResolved11(s)) return true;
|
|
120
142
|
const first = s[0];
|
|
121
143
|
if (first === " " || first === " ") return true;
|
|
122
144
|
if (first !== void 0 && INDICATOR_CHARS.has(first)) {
|
|
@@ -197,7 +219,7 @@ function renderSingleQuoted(s) {
|
|
|
197
219
|
* Block literal and block folded styles are always accepted for single-line
|
|
198
220
|
* strings even though the output is unusual.
|
|
199
221
|
*/
|
|
200
|
-
function renderString(s, style, indent, ignoreType = false, canonical = false, explicitChomp, parentPosition, quoteStyle = "single", explicitIndent) {
|
|
222
|
+
function renderString(s, style, indent, ignoreType = false, canonical = false, explicitChomp, parentPosition, quoteStyle = "single", explicitIndent, quoteCompat) {
|
|
201
223
|
const fidelity = !canonical;
|
|
202
224
|
const fidelityIndent = fidelity ? explicitIndent : void 0;
|
|
203
225
|
if (s.includes("\n")) {
|
|
@@ -230,7 +252,7 @@ function renderString(s, style, indent, ignoreType = false, canonical = false, e
|
|
|
230
252
|
if (s === "" && (style === "block-literal" || style === "block-folded")) return renderDoubleQuoted(s, canonical);
|
|
231
253
|
switch (style) {
|
|
232
254
|
case "plain":
|
|
233
|
-
if (requiresQuoting(s, ignoreType)) {
|
|
255
|
+
if (requiresQuoting(s, ignoreType, quoteCompat)) {
|
|
234
256
|
if (s.includes(" ") || s.includes("\r")) return renderDoubleQuoted(s, canonical);
|
|
235
257
|
for (let i = 0; i < s.length; i++) if (isControlChar(s.charCodeAt(i))) return renderDoubleQuoted(s, canonical);
|
|
236
258
|
return quoteStyle === "double" ? renderDoubleQuoted(s, canonical) : renderSingleQuoted(s);
|
|
@@ -289,6 +311,7 @@ function createContext(options) {
|
|
|
289
311
|
sortKeys: options?.sortKeys ?? false,
|
|
290
312
|
indentSequences: options?.indentSequences ?? false,
|
|
291
313
|
quoteStyle: options?.quoteStyle ?? "single",
|
|
314
|
+
quoteCompat: options?.quoteCompat,
|
|
292
315
|
forceDefaultStyles: options?.forceDefaultStyles ?? false,
|
|
293
316
|
seen: /* @__PURE__ */ new Set()
|
|
294
317
|
};
|
|
@@ -308,7 +331,7 @@ function stringifyLines(value, ctx, depth, allowFold = true) {
|
|
|
308
331
|
if (typeof value === "bigint") return [value.toString()];
|
|
309
332
|
if (typeof value === "string") {
|
|
310
333
|
const indentStr = " ".repeat(ctx.indent);
|
|
311
|
-
const rendered = renderString(value, ctx.defaultScalarStyle, indentStr, false, ctx.forceDefaultStyles, void 0, void 0, ctx.quoteStyle);
|
|
334
|
+
const rendered = renderString(value, ctx.defaultScalarStyle, indentStr, false, ctx.forceDefaultStyles, void 0, void 0, ctx.quoteStyle, void 0, ctx.quoteCompat);
|
|
312
335
|
return (allowFold && ctx.lineWidth > 0 ? foldRenderedScalar(rendered, indentStr, ctx.lineWidth) : rendered).split("\n");
|
|
313
336
|
}
|
|
314
337
|
if (Array.isArray(value)) {
|
|
@@ -373,7 +396,7 @@ function stringifyObjectLines(obj, ctx, depth) {
|
|
|
373
396
|
const keys = Object.keys(obj);
|
|
374
397
|
if (keys.length === 0) return ["{}"];
|
|
375
398
|
if (ctx.sortKeys) keys.sort();
|
|
376
|
-
const renderPlainKey = (k) => renderString(k, "plain", "", false, false, void 0, void 0, ctx.quoteStyle);
|
|
399
|
+
const renderPlainKey = (k) => renderString(k, "plain", "", false, false, void 0, void 0, ctx.quoteStyle, void 0, ctx.quoteCompat);
|
|
377
400
|
if (ctx.defaultCollectionStyle === "flow") return [`{${keys.map((k) => {
|
|
378
401
|
return `${renderPlainKey(k)}: ${stringifyLines(obj[k], ctx, depth + 1, false).join(" ")}`;
|
|
379
402
|
}).join(", ")}}`];
|
|
@@ -584,7 +607,7 @@ function stringifyScalarNodeLines(node, ctx) {
|
|
|
584
607
|
else lines = ["null"];
|
|
585
608
|
} else if (typeof val === "boolean") lines = [val ? "true" : "false"];
|
|
586
609
|
else if (typeof val === "number") lines = [node.raw !== void 0 ? node.raw : renderNumber(val)];
|
|
587
|
-
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");
|
|
610
|
+
else if (typeof val === "string") lines = renderString(val, style, " ".repeat(ctx.indent), !!node.tag, ctx.forceDefaultStyles, node.chomp, ctx.parentPosition, ctx.quoteStyle, node.blockIndent, ctx.quoteCompat).split("\n");
|
|
588
611
|
else lines = [renderDoubleQuoted(String(val))];
|
|
589
612
|
if (node.tag) lines[0] = `${node.tag} ${lines[0]}`;
|
|
590
613
|
if (node.anchor) lines[0] = `&${node.anchor} ${lines[0]}`;
|
|
@@ -1134,4 +1157,4 @@ function stringifyDocument(doc, options) {
|
|
|
1134
1157
|
}
|
|
1135
1158
|
|
|
1136
1159
|
//#endregion
|
|
1137
|
-
export { StringifyDepthExceeded, StringifyFailure, stringifyDocument, stringifyValue, stripNodeComments };
|
|
1160
|
+
export { StringifyDepthExceeded, StringifyFailure, renderDoubleQuoted, renderSingleQuoted, stringifyDocument, stringifyValue, stripNodeComments };
|
package/package.json
CHANGED