mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
refactor(yaml): inline readBlockScalar()
(#5841)
This commit is contained in:
parent
baa5086dff
commit
cde346da13
@ -943,6 +943,162 @@ export class LoaderState {
|
|||||||
"Cannot read flow collection: unexpected end of the stream within a flow collection",
|
"Cannot read flow collection: unexpected end of the stream within a flow collection",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Handles block scaler styles: e.g. '|', '>', '|-' and '>-'.
|
||||||
|
// https://yaml.org/spec/1.2.2/#81-block-scalar-styles
|
||||||
|
readBlockScalar(nodeIndent: number): boolean {
|
||||||
|
let chomping = CHOMPING_CLIP;
|
||||||
|
let didReadContent = false;
|
||||||
|
let detectedIndent = false;
|
||||||
|
let textIndent = nodeIndent;
|
||||||
|
let emptyLines = 0;
|
||||||
|
let atMoreIndented = false;
|
||||||
|
|
||||||
|
let ch = this.peek();
|
||||||
|
|
||||||
|
let folding = false;
|
||||||
|
if (ch === VERTICAL_LINE) {
|
||||||
|
folding = false;
|
||||||
|
} else if (ch === GREATER_THAN) {
|
||||||
|
folding = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.kind = "scalar";
|
||||||
|
this.result = "";
|
||||||
|
|
||||||
|
let tmp = 0;
|
||||||
|
while (ch !== 0) {
|
||||||
|
ch = this.next();
|
||||||
|
|
||||||
|
if (ch === PLUS || ch === MINUS) {
|
||||||
|
if (CHOMPING_CLIP === chomping) {
|
||||||
|
chomping = ch === PLUS ? CHOMPING_KEEP : CHOMPING_STRIP;
|
||||||
|
} else {
|
||||||
|
return this.throwError(
|
||||||
|
"Cannot read block: chomping mode identifier repeated",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if ((tmp = decimalCharCodeToNumber(ch)) >= 0) {
|
||||||
|
if (tmp === 0) {
|
||||||
|
return this.throwError(
|
||||||
|
"Cannot read block: indentation width must be greater than 0",
|
||||||
|
);
|
||||||
|
} else if (!detectedIndent) {
|
||||||
|
textIndent = nodeIndent + tmp - 1;
|
||||||
|
detectedIndent = true;
|
||||||
|
} else {
|
||||||
|
return this.throwError(
|
||||||
|
"Cannot read block: indentation width identifier repeated",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWhiteSpace(ch)) {
|
||||||
|
do {
|
||||||
|
ch = this.next();
|
||||||
|
} while (isWhiteSpace(ch));
|
||||||
|
|
||||||
|
if (ch === SHARP) {
|
||||||
|
do {
|
||||||
|
ch = this.next();
|
||||||
|
} while (!isEOL(ch) && ch !== 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ch !== 0) {
|
||||||
|
this.readLineBreak();
|
||||||
|
this.lineIndent = 0;
|
||||||
|
|
||||||
|
ch = this.peek();
|
||||||
|
|
||||||
|
while (
|
||||||
|
(!detectedIndent || this.lineIndent < textIndent) &&
|
||||||
|
ch === SPACE
|
||||||
|
) {
|
||||||
|
this.lineIndent++;
|
||||||
|
ch = this.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!detectedIndent && this.lineIndent > textIndent) {
|
||||||
|
textIndent = this.lineIndent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEOL(ch)) {
|
||||||
|
emptyLines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of the scalar.
|
||||||
|
if (this.lineIndent < textIndent) {
|
||||||
|
// Perform the chomping.
|
||||||
|
if (chomping === CHOMPING_KEEP) {
|
||||||
|
this.result += "\n".repeat(
|
||||||
|
didReadContent ? 1 + emptyLines : emptyLines,
|
||||||
|
);
|
||||||
|
} else if (chomping === CHOMPING_CLIP) {
|
||||||
|
if (didReadContent) {
|
||||||
|
// i.e. only if the scalar is not empty.
|
||||||
|
this.result += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break this `while` cycle and go to the function's epilogue.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Folded style: use fancy rules to handle line breaks.
|
||||||
|
if (folding) {
|
||||||
|
// Lines starting with white space characters (more-indented lines) are not folded.
|
||||||
|
if (isWhiteSpace(ch)) {
|
||||||
|
atMoreIndented = true;
|
||||||
|
// except for the first content line (cf. Example 8.1)
|
||||||
|
this.result += "\n".repeat(
|
||||||
|
didReadContent ? 1 + emptyLines : emptyLines,
|
||||||
|
);
|
||||||
|
|
||||||
|
// End of more-indented block.
|
||||||
|
} else if (atMoreIndented) {
|
||||||
|
atMoreIndented = false;
|
||||||
|
this.result += "\n".repeat(emptyLines + 1);
|
||||||
|
|
||||||
|
// Just one line break - perceive as the same line.
|
||||||
|
} else if (emptyLines === 0) {
|
||||||
|
if (didReadContent) {
|
||||||
|
// i.e. only if we have already read some scalar content.
|
||||||
|
this.result += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Several line breaks - perceive as different lines.
|
||||||
|
} else {
|
||||||
|
this.result += "\n".repeat(emptyLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Literal style: just add exact number of line breaks between content lines.
|
||||||
|
} else {
|
||||||
|
// Keep all line breaks except the header line break.
|
||||||
|
this.result += "\n".repeat(
|
||||||
|
didReadContent ? 1 + emptyLines : emptyLines,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
didReadContent = true;
|
||||||
|
detectedIndent = true;
|
||||||
|
emptyLines = 0;
|
||||||
|
const captureStart = this.position;
|
||||||
|
|
||||||
|
while (!isEOL(ch) && ch !== 0) {
|
||||||
|
ch = this.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.captureSegment(captureStart, this.position, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
readDocument() {
|
readDocument() {
|
||||||
const documentStart = this.position;
|
const documentStart = this.position;
|
||||||
@ -1072,161 +1228,6 @@ export class LoaderState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles block scaler styles: e.g. '|', '>', '|-' and '>-'.
|
|
||||||
// https://yaml.org/spec/1.2.2/#81-block-scalar-styles
|
|
||||||
function readBlockScalar(state: LoaderState, nodeIndent: number): boolean {
|
|
||||||
let chomping = CHOMPING_CLIP;
|
|
||||||
let didReadContent = false;
|
|
||||||
let detectedIndent = false;
|
|
||||||
let textIndent = nodeIndent;
|
|
||||||
let emptyLines = 0;
|
|
||||||
let atMoreIndented = false;
|
|
||||||
|
|
||||||
let ch = state.peek();
|
|
||||||
|
|
||||||
let folding = false;
|
|
||||||
if (ch === VERTICAL_LINE) {
|
|
||||||
folding = false;
|
|
||||||
} else if (ch === GREATER_THAN) {
|
|
||||||
folding = true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.kind = "scalar";
|
|
||||||
state.result = "";
|
|
||||||
|
|
||||||
let tmp = 0;
|
|
||||||
while (ch !== 0) {
|
|
||||||
ch = state.next();
|
|
||||||
|
|
||||||
if (ch === PLUS || ch === MINUS) {
|
|
||||||
if (CHOMPING_CLIP === chomping) {
|
|
||||||
chomping = ch === PLUS ? CHOMPING_KEEP : CHOMPING_STRIP;
|
|
||||||
} else {
|
|
||||||
return state.throwError(
|
|
||||||
"Cannot read block: chomping mode identifier repeated",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if ((tmp = decimalCharCodeToNumber(ch)) >= 0) {
|
|
||||||
if (tmp === 0) {
|
|
||||||
return state.throwError(
|
|
||||||
"Cannot read block: indentation width must be greater than 0",
|
|
||||||
);
|
|
||||||
} else if (!detectedIndent) {
|
|
||||||
textIndent = nodeIndent + tmp - 1;
|
|
||||||
detectedIndent = true;
|
|
||||||
} else {
|
|
||||||
return state.throwError(
|
|
||||||
"Cannot read block: indentation width identifier repeated",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isWhiteSpace(ch)) {
|
|
||||||
do {
|
|
||||||
ch = state.next();
|
|
||||||
} while (isWhiteSpace(ch));
|
|
||||||
|
|
||||||
if (ch === SHARP) {
|
|
||||||
do {
|
|
||||||
ch = state.next();
|
|
||||||
} while (!isEOL(ch) && ch !== 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ch !== 0) {
|
|
||||||
state.readLineBreak();
|
|
||||||
state.lineIndent = 0;
|
|
||||||
|
|
||||||
ch = state.peek();
|
|
||||||
|
|
||||||
while (
|
|
||||||
(!detectedIndent || state.lineIndent < textIndent) &&
|
|
||||||
ch === SPACE
|
|
||||||
) {
|
|
||||||
state.lineIndent++;
|
|
||||||
ch = state.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!detectedIndent && state.lineIndent > textIndent) {
|
|
||||||
textIndent = state.lineIndent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isEOL(ch)) {
|
|
||||||
emptyLines++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of the scalar.
|
|
||||||
if (state.lineIndent < textIndent) {
|
|
||||||
// Perform the chomping.
|
|
||||||
if (chomping === CHOMPING_KEEP) {
|
|
||||||
state.result += "\n".repeat(
|
|
||||||
didReadContent ? 1 + emptyLines : emptyLines,
|
|
||||||
);
|
|
||||||
} else if (chomping === CHOMPING_CLIP) {
|
|
||||||
if (didReadContent) {
|
|
||||||
// i.e. only if the scalar is not empty.
|
|
||||||
state.result += "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Break this `while` cycle and go to the function's epilogue.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Folded style: use fancy rules to handle line breaks.
|
|
||||||
if (folding) {
|
|
||||||
// Lines starting with white space characters (more-indented lines) are not folded.
|
|
||||||
if (isWhiteSpace(ch)) {
|
|
||||||
atMoreIndented = true;
|
|
||||||
// except for the first content line (cf. Example 8.1)
|
|
||||||
state.result += "\n".repeat(
|
|
||||||
didReadContent ? 1 + emptyLines : emptyLines,
|
|
||||||
);
|
|
||||||
|
|
||||||
// End of more-indented block.
|
|
||||||
} else if (atMoreIndented) {
|
|
||||||
atMoreIndented = false;
|
|
||||||
state.result += "\n".repeat(emptyLines + 1);
|
|
||||||
|
|
||||||
// Just one line break - perceive as the same line.
|
|
||||||
} else if (emptyLines === 0) {
|
|
||||||
if (didReadContent) {
|
|
||||||
// i.e. only if we have already read some scalar content.
|
|
||||||
state.result += " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Several line breaks - perceive as different lines.
|
|
||||||
} else {
|
|
||||||
state.result += "\n".repeat(emptyLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Literal style: just add exact number of line breaks between content lines.
|
|
||||||
} else {
|
|
||||||
// Keep all line breaks except the header line break.
|
|
||||||
state.result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
didReadContent = true;
|
|
||||||
detectedIndent = true;
|
|
||||||
emptyLines = 0;
|
|
||||||
const captureStart = state.position;
|
|
||||||
|
|
||||||
while (!isEOL(ch) && ch !== 0) {
|
|
||||||
ch = state.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.captureSegment(captureStart, state.position, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function readBlockMapping(
|
function readBlockMapping(
|
||||||
state: LoaderState,
|
state: LoaderState,
|
||||||
nodeIndent: number,
|
nodeIndent: number,
|
||||||
@ -1649,7 +1650,7 @@ function composeNode(
|
|||||||
hasContent = true;
|
hasContent = true;
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
(allowBlockScalars && readBlockScalar(state, flowIndent)) ||
|
(allowBlockScalars && state.readBlockScalar(flowIndent)) ||
|
||||||
state.readSingleQuotedScalar(flowIndent) ||
|
state.readSingleQuotedScalar(flowIndent) ||
|
||||||
state.readDoubleQuotedScalar(flowIndent)
|
state.readDoubleQuotedScalar(flowIndent)
|
||||||
) {
|
) {
|
||||||
|
Loading…
Reference in New Issue
Block a user