in lib/src/scanner.dart [1100:1225]
Token _scanBlockScalar({bool literal = false}) {
var start = _scanner.state;
// Eat the indicator '|' or '>'.
_scanner.readChar();
// Check for a chomping indicator.
var chomping = _Chomping.clip;
var increment = 0;
var char = _scanner.peekChar();
if (char == PLUS || char == HYPHEN) {
chomping = char == PLUS ? _Chomping.keep : _Chomping.strip;
_scanner.readChar();
// Check for an indentation indicator.
if (_isDigit) {
// Check that the indentation is greater than 0.
if (_scanner.peekChar() == NUMBER_0) {
throw YamlException('0 may not be used as an indentation indicator.',
_scanner.spanFrom(start));
}
increment = _scanner.readChar() - NUMBER_0;
}
} else if (_isDigit) {
// Do the same as above, but in the opposite order.
if (_scanner.peekChar() == NUMBER_0) {
throw YamlException('0 may not be used as an indentation indicator.',
_scanner.spanFrom(start));
}
increment = _scanner.readChar() - NUMBER_0;
char = _scanner.peekChar();
if (char == PLUS || char == HYPHEN) {
chomping = char == PLUS ? _Chomping.keep : _Chomping.strip;
_scanner.readChar();
}
}
// Eat whitespace and comments to the end of the line.
_skipBlanks();
_skipComment();
// Check if we're at the end of the line.
if (!_isBreakOrEnd) {
throw YamlException(
'Expected comment or line break.', _scanner.emptySpan);
}
_skipLine();
// If the block scalar has an explicit indentation indicator, add that to
// the current indentation to get the indentation level for the scalar's
// contents.
var indent = 0;
if (increment != 0) {
indent = _indent >= 0 ? _indent + increment : increment;
}
// Scan the leading line breaks to determine the indentation level if
// needed.
var pair = _scanBlockScalarBreaks(indent);
indent = pair.first;
var trailingBreaks = pair.last;
// Scan the block scalar contents.
var buffer = StringBuffer();
var leadingBreak = '';
var leadingBlank = false;
var trailingBlank = false;
var end = _scanner.state;
while (_scanner.column == indent && !_scanner.isDone) {
// Check for a document indicator. libyaml doesn't do this, but the spec
// mandates it. See example 9.5:
// http://yaml.org/spec/1.2/spec.html#id2801606.
if (_isDocumentIndicator) break;
// We are at the beginning of a non-empty line.
// Is there trailing whitespace?
trailingBlank = _isBlank;
// Check if we need to fold the leading line break.
if (!literal &&
leadingBreak.isNotEmpty &&
!leadingBlank &&
!trailingBlank) {
// Do we need to join the lines with a space?
if (trailingBreaks.isEmpty) buffer.writeCharCode(SP);
} else {
buffer.write(leadingBreak);
}
leadingBreak = '';
// Append the remaining line breaks.
buffer.write(trailingBreaks);
// Is there leading whitespace?
leadingBlank = _isBlank;
var startPosition = _scanner.position;
while (!_isBreakOrEnd) {
_scanner.readChar();
}
buffer.write(_scanner.substring(startPosition));
end = _scanner.state;
// libyaml always reads a line here, but this breaks on block scalars at
// the end of the document that end without newlines. See example 8.1:
// http://yaml.org/spec/1.2/spec.html#id2793888.
if (!_scanner.isDone) leadingBreak = _readLine();
// Eat the following indentation and spaces.
var pair = _scanBlockScalarBreaks(indent);
indent = pair.first;
trailingBreaks = pair.last;
}
// Chomp the tail.
if (chomping != _Chomping.strip) buffer.write(leadingBreak);
if (chomping == _Chomping.keep) buffer.write(trailingBreaks);
return ScalarToken(_scanner.spanFrom(start, end), buffer.toString(),
literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED);
}