"use strict"; exports.Document = void 0; var _constants = require("../constants"); var _errors = require("../errors"); var _BlankLine = require("./BlankLine"); var _Collection = require("./Collection"); var _Comment = require("./Comment"); var _Directive = require("./Directive"); var _Node = require("./Node"); var _Range = require("./Range"); class Document extends _Node.Node { static startCommentOrEndBlankLine(src, start) { const offset = _Node.Node.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.Node.atDocumentBoundary(src, offset, _constants.Char.DIRECTIVES_END)) { offset = Document.startCommentOrEndBlankLine(src, offset); switch (src[offset]) { case '\n': if (atLineStart) { const blankLine = new _BlankLine.BlankLine(); offset = blankLine.parse({ src }, offset); if (offset < src.length) { this.directives.push(blankLine); } } else { offset += 1; atLineStart = true; } break; case '#': { const comment = new _Comment.Comment(); offset = comment.parse({ src }, offset); this.directives.push(comment); atLineStart = false; } break; case '%': { const directive = new _Directive.Directive(); 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.Range(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.Node.endOfWhiteSpace(src, start); let atLineStart = lineStart === start; this.valueRange = new _Range.Range(offset); while (!_Node.Node.atDocumentBoundary(src, offset, _constants.Char.DOCUMENT_END)) { switch (src[offset]) { case '\n': if (atLineStart) { const blankLine = new _BlankLine.BlankLine(); 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.Comment(); offset = comment.parse({ src }, offset); this.contents.push(comment); atLineStart = false; } break; default: { const iEnd = _Node.Node.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.Range(offset, offset + 3); offset += 3; if (src[offset]) { offset = _Node.Node.endOfWhiteSpace(src, offset); if (src[offset] === '#') { const comment = new _Comment.Comment(); 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.Document = Document;