mirror of
https://github.com/denoland/std.git
synced 2024-11-21 12:40:03 +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",
|
||||
);
|
||||
}
|
||||
// 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() {
|
||||
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(
|
||||
state: LoaderState,
|
||||
nodeIndent: number,
|
||||
@ -1649,7 +1650,7 @@ function composeNode(
|
||||
hasContent = true;
|
||||
} else {
|
||||
if (
|
||||
(allowBlockScalars && readBlockScalar(state, flowIndent)) ||
|
||||
(allowBlockScalars && state.readBlockScalar(flowIndent)) ||
|
||||
state.readSingleQuotedScalar(flowIndent) ||
|
||||
state.readDoubleQuotedScalar(flowIndent)
|
||||
) {
|
||||
|
Loading…
Reference in New Issue
Block a user