281 lines
7.1 KiB
JavaScript
281 lines
7.1 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _constants = require("../constants");
|
|
|
|
var _errors = require("../errors");
|
|
|
|
var _BlankLine = _interopRequireDefault(require("./BlankLine"));
|
|
|
|
var _Collection = require("./Collection");
|
|
|
|
var _Comment = _interopRequireDefault(require("./Comment"));
|
|
|
|
var _Directive = _interopRequireDefault(require("./Directive"));
|
|
|
|
var _Node = _interopRequireDefault(require("./Node"));
|
|
|
|
var _Range = _interopRequireDefault(require("./Range"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
class Document extends _Node.default {
|
|
static startCommentOrEndBlankLine(src, start) {
|
|
const offset = _Node.default.endOfWhiteSpace(src, start);
|
|
|
|
const ch = src[offset];
|
|
return ch === '#' || ch === '\n' ? offset : start;
|
|
}
|
|
|
|
constructor() {
|
|
super(_constants.Type.DOCUMENT);
|
|
this.directives = null;
|
|
this.contents = null;
|
|
this.directivesEndMarker = null;
|
|
this.documentEndMarker = null;
|
|
}
|
|
|
|
parseDirectives(start) {
|
|
const {
|
|
src
|
|
} = this.context;
|
|
this.directives = [];
|
|
let atLineStart = true;
|
|
let hasDirectives = false;
|
|
let offset = start;
|
|
|
|
while (!_Node.default.atDocumentBoundary(src, offset, _constants.Char.DIRECTIVES_END)) {
|
|
offset = Document.startCommentOrEndBlankLine(src, offset);
|
|
|
|
switch (src[offset]) {
|
|
case '\n':
|
|
if (atLineStart) {
|
|
const blankLine = new _BlankLine.default();
|
|
offset = blankLine.parse({
|
|
src
|
|
}, offset);
|
|
|
|
if (offset < src.length) {
|
|
this.directives.push(blankLine);
|
|
}
|
|
} else {
|
|
offset += 1;
|
|
atLineStart = true;
|
|
}
|
|
|
|
break;
|
|
|
|
case '#':
|
|
{
|
|
const comment = new _Comment.default();
|
|
offset = comment.parse({
|
|
src
|
|
}, offset);
|
|
this.directives.push(comment);
|
|
atLineStart = false;
|
|
}
|
|
break;
|
|
|
|
case '%':
|
|
{
|
|
const directive = new _Directive.default();
|
|
offset = directive.parse({
|
|
parent: this,
|
|
src
|
|
}, offset);
|
|
this.directives.push(directive);
|
|
hasDirectives = true;
|
|
atLineStart = false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (hasDirectives) {
|
|
this.error = new _errors.YAMLSemanticError(this, 'Missing directives-end indicator line');
|
|
} else if (this.directives.length > 0) {
|
|
this.contents = this.directives;
|
|
this.directives = [];
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
}
|
|
|
|
if (src[offset]) {
|
|
this.directivesEndMarker = new _Range.default(offset, offset + 3);
|
|
return offset + 3;
|
|
}
|
|
|
|
if (hasDirectives) {
|
|
this.error = new _errors.YAMLSemanticError(this, 'Missing directives-end indicator line');
|
|
} else if (this.directives.length > 0) {
|
|
this.contents = this.directives;
|
|
this.directives = [];
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
parseContents(start) {
|
|
const {
|
|
parseNode,
|
|
src
|
|
} = this.context;
|
|
if (!this.contents) this.contents = [];
|
|
let lineStart = start;
|
|
|
|
while (src[lineStart - 1] === '-') lineStart -= 1;
|
|
|
|
let offset = _Node.default.endOfWhiteSpace(src, start);
|
|
|
|
let atLineStart = lineStart === start;
|
|
this.valueRange = new _Range.default(offset);
|
|
|
|
while (!_Node.default.atDocumentBoundary(src, offset, _constants.Char.DOCUMENT_END)) {
|
|
switch (src[offset]) {
|
|
case '\n':
|
|
if (atLineStart) {
|
|
const blankLine = new _BlankLine.default();
|
|
offset = blankLine.parse({
|
|
src
|
|
}, offset);
|
|
|
|
if (offset < src.length) {
|
|
this.contents.push(blankLine);
|
|
}
|
|
} else {
|
|
offset += 1;
|
|
atLineStart = true;
|
|
}
|
|
|
|
lineStart = offset;
|
|
break;
|
|
|
|
case '#':
|
|
{
|
|
const comment = new _Comment.default();
|
|
offset = comment.parse({
|
|
src
|
|
}, offset);
|
|
this.contents.push(comment);
|
|
atLineStart = false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
const iEnd = _Node.default.endOfIndent(src, offset);
|
|
|
|
const context = {
|
|
atLineStart,
|
|
indent: -1,
|
|
inFlow: false,
|
|
inCollection: false,
|
|
lineStart,
|
|
parent: this
|
|
};
|
|
const node = parseNode(context, iEnd);
|
|
if (!node) return this.valueRange.end = iEnd; // at next document start
|
|
|
|
this.contents.push(node);
|
|
offset = node.range.end;
|
|
atLineStart = false;
|
|
const ec = (0, _Collection.grabCollectionEndComments)(node);
|
|
if (ec) Array.prototype.push.apply(this.contents, ec);
|
|
}
|
|
}
|
|
|
|
offset = Document.startCommentOrEndBlankLine(src, offset);
|
|
}
|
|
|
|
this.valueRange.end = offset;
|
|
|
|
if (src[offset]) {
|
|
this.documentEndMarker = new _Range.default(offset, offset + 3);
|
|
offset += 3;
|
|
|
|
if (src[offset]) {
|
|
offset = _Node.default.endOfWhiteSpace(src, offset);
|
|
|
|
if (src[offset] === '#') {
|
|
const comment = new _Comment.default();
|
|
offset = comment.parse({
|
|
src
|
|
}, offset);
|
|
this.contents.push(comment);
|
|
}
|
|
|
|
switch (src[offset]) {
|
|
case '\n':
|
|
offset += 1;
|
|
break;
|
|
|
|
case undefined:
|
|
break;
|
|
|
|
default:
|
|
this.error = new _errors.YAMLSyntaxError(this, 'Document end marker line cannot have a non-comment suffix');
|
|
}
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
/**
|
|
* @param {ParseContext} context
|
|
* @param {number} start - Index of first character
|
|
* @returns {number} - Index of the character after this
|
|
*/
|
|
|
|
|
|
parse(context, start) {
|
|
context.root = this;
|
|
this.context = context;
|
|
const {
|
|
src
|
|
} = context;
|
|
let offset = src.charCodeAt(start) === 0xfeff ? start + 1 : start; // skip BOM
|
|
|
|
offset = this.parseDirectives(offset);
|
|
offset = this.parseContents(offset);
|
|
return offset;
|
|
}
|
|
|
|
setOrigRanges(cr, offset) {
|
|
offset = super.setOrigRanges(cr, offset);
|
|
this.directives.forEach(node => {
|
|
offset = node.setOrigRanges(cr, offset);
|
|
});
|
|
if (this.directivesEndMarker) offset = this.directivesEndMarker.setOrigRange(cr, offset);
|
|
this.contents.forEach(node => {
|
|
offset = node.setOrigRanges(cr, offset);
|
|
});
|
|
if (this.documentEndMarker) offset = this.documentEndMarker.setOrigRange(cr, offset);
|
|
return offset;
|
|
}
|
|
|
|
toString() {
|
|
const {
|
|
contents,
|
|
directives,
|
|
value
|
|
} = this;
|
|
if (value != null) return value;
|
|
let str = directives.join('');
|
|
|
|
if (contents.length > 0) {
|
|
if (directives.length > 0 || contents[0].type === _constants.Type.COMMENT) str += '---\n';
|
|
str += contents.join('');
|
|
}
|
|
|
|
if (str[str.length - 1] !== '\n') str += '\n';
|
|
return str;
|
|
}
|
|
|
|
}
|
|
|
|
exports.default = Document; |