| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876 | 'use strict';const Char = {  ANCHOR: '&',  COMMENT: '#',  TAG: '!',  DIRECTIVES_END: '-',  DOCUMENT_END: '.'};const Type = {  ALIAS: 'ALIAS',  BLANK_LINE: 'BLANK_LINE',  BLOCK_FOLDED: 'BLOCK_FOLDED',  BLOCK_LITERAL: 'BLOCK_LITERAL',  COMMENT: 'COMMENT',  DIRECTIVE: 'DIRECTIVE',  DOCUMENT: 'DOCUMENT',  FLOW_MAP: 'FLOW_MAP',  FLOW_SEQ: 'FLOW_SEQ',  MAP: 'MAP',  MAP_KEY: 'MAP_KEY',  MAP_VALUE: 'MAP_VALUE',  PLAIN: 'PLAIN',  QUOTE_DOUBLE: 'QUOTE_DOUBLE',  QUOTE_SINGLE: 'QUOTE_SINGLE',  SEQ: 'SEQ',  SEQ_ITEM: 'SEQ_ITEM'};const defaultTagPrefix = 'tag:yaml.org,2002:';const defaultTags = {  MAP: 'tag:yaml.org,2002:map',  SEQ: 'tag:yaml.org,2002:seq',  STR: 'tag:yaml.org,2002:str'};function findLineStarts(src) {  const ls = [0];  let offset = src.indexOf('\n');  while (offset !== -1) {    offset += 1;    ls.push(offset);    offset = src.indexOf('\n', offset);  }  return ls;}function getSrcInfo(cst) {  let lineStarts, src;  if (typeof cst === 'string') {    lineStarts = findLineStarts(cst);    src = cst;  } else {    if (Array.isArray(cst)) cst = cst[0];    if (cst && cst.context) {      if (!cst.lineStarts) cst.lineStarts = findLineStarts(cst.context.src);      lineStarts = cst.lineStarts;      src = cst.context.src;    }  }  return {    lineStarts,    src  };}/** * @typedef {Object} LinePos - One-indexed position in the source * @property {number} line * @property {number} col *//** * Determine the line/col position matching a character offset. * * Accepts a source string or a CST document as the second parameter. With * the latter, starting indices for lines are cached in the document as * `lineStarts: number[]`. * * Returns a one-indexed `{ line, col }` location if found, or * `undefined` otherwise. * * @param {number} offset * @param {string|Document|Document[]} cst * @returns {?LinePos} */function getLinePos(offset, cst) {  if (typeof offset !== 'number' || offset < 0) return null;  const {    lineStarts,    src  } = getSrcInfo(cst);  if (!lineStarts || !src || offset > src.length) return null;  for (let i = 0; i < lineStarts.length; ++i) {    const start = lineStarts[i];    if (offset < start) {      return {        line: i,        col: offset - lineStarts[i - 1] + 1      };    }    if (offset === start) return {      line: i + 1,      col: 1    };  }  const line = lineStarts.length;  return {    line,    col: offset - lineStarts[line - 1] + 1  };}/** * Get a specified line from the source. * * Accepts a source string or a CST document as the second parameter. With * the latter, starting indices for lines are cached in the document as * `lineStarts: number[]`. * * Returns the line as a string if found, or `null` otherwise. * * @param {number} line One-indexed line number * @param {string|Document|Document[]} cst * @returns {?string} */function getLine(line, cst) {  const {    lineStarts,    src  } = getSrcInfo(cst);  if (!lineStarts || !(line >= 1) || line > lineStarts.length) return null;  const start = lineStarts[line - 1];  let end = lineStarts[line]; // undefined for last line; that's ok for slice()  while (end && end > start && src[end - 1] === '\n') --end;  return src.slice(start, end);}/** * Pretty-print the starting line from the source indicated by the range `pos` * * Trims output to `maxWidth` chars while keeping the starting column visible, * using `…` at either end to indicate dropped characters. * * Returns a two-line string (or `null`) with `\n` as separator; the second line * will hold appropriately indented `^` marks indicating the column range. * * @param {Object} pos * @param {LinePos} pos.start * @param {LinePos} [pos.end] * @param {string|Document|Document[]*} cst * @param {number} [maxWidth=80] * @returns {?string} */function getPrettyContext({  start,  end}, cst, maxWidth = 80) {  let src = getLine(start.line, cst);  if (!src) return null;  let {    col  } = start;  if (src.length > maxWidth) {    if (col <= maxWidth - 10) {      src = src.substr(0, maxWidth - 1) + '…';    } else {      const halfWidth = Math.round(maxWidth / 2);      if (src.length > col + halfWidth) src = src.substr(0, col + halfWidth - 1) + '…';      col -= src.length - maxWidth;      src = '…' + src.substr(1 - maxWidth);    }  }  let errLen = 1;  let errEnd = '';  if (end) {    if (end.line === start.line && col + (end.col - start.col) <= maxWidth + 1) {      errLen = end.col - start.col;    } else {      errLen = Math.min(src.length + 1, maxWidth) - col;      errEnd = '…';    }  }  const offset = col > 1 ? ' '.repeat(col - 1) : '';  const err = '^'.repeat(errLen);  return `${src}\n${offset}${err}${errEnd}`;}class Range {  static copy(orig) {    return new Range(orig.start, orig.end);  }  constructor(start, end) {    this.start = start;    this.end = end || start;  }  isEmpty() {    return typeof this.start !== 'number' || !this.end || this.end <= this.start;  }  /**   * Set `origStart` and `origEnd` to point to the original source range for   * this node, which may differ due to dropped CR characters.   *   * @param {number[]} cr - Positions of dropped CR characters   * @param {number} offset - Starting index of `cr` from the last call   * @returns {number} - The next offset, matching the one found for `origStart`   */  setOrigRange(cr, offset) {    const {      start,      end    } = this;    if (cr.length === 0 || end <= cr[0]) {      this.origStart = start;      this.origEnd = end;      return offset;    }    let i = offset;    while (i < cr.length) {      if (cr[i] > start) break;else ++i;    }    this.origStart = start + i;    const nextOffset = i;    while (i < cr.length) {      // if end was at \n, it should now be at \r      if (cr[i] >= end) break;else ++i;    }    this.origEnd = end + i;    return nextOffset;  }}/** Root class of all nodes */class Node {  static addStringTerminator(src, offset, str) {    if (str[str.length - 1] === '\n') return str;    const next = Node.endOfWhiteSpace(src, offset);    return next >= src.length || src[next] === '\n' ? str + '\n' : str;  } // ^(---|...)  static atDocumentBoundary(src, offset, sep) {    const ch0 = src[offset];    if (!ch0) return true;    const prev = src[offset - 1];    if (prev && prev !== '\n') return false;    if (sep) {      if (ch0 !== sep) return false;    } else {      if (ch0 !== Char.DIRECTIVES_END && ch0 !== Char.DOCUMENT_END) return false;    }    const ch1 = src[offset + 1];    const ch2 = src[offset + 2];    if (ch1 !== ch0 || ch2 !== ch0) return false;    const ch3 = src[offset + 3];    return !ch3 || ch3 === '\n' || ch3 === '\t' || ch3 === ' ';  }  static endOfIdentifier(src, offset) {    let ch = src[offset];    const isVerbatim = ch === '<';    const notOk = isVerbatim ? ['\n', '\t', ' ', '>'] : ['\n', '\t', ' ', '[', ']', '{', '}', ','];    while (ch && notOk.indexOf(ch) === -1) ch = src[offset += 1];    if (isVerbatim && ch === '>') offset += 1;    return offset;  }  static endOfIndent(src, offset) {    let ch = src[offset];    while (ch === ' ') ch = src[offset += 1];    return offset;  }  static endOfLine(src, offset) {    let ch = src[offset];    while (ch && ch !== '\n') ch = src[offset += 1];    return offset;  }  static endOfWhiteSpace(src, offset) {    let ch = src[offset];    while (ch === '\t' || ch === ' ') ch = src[offset += 1];    return offset;  }  static startOfLine(src, offset) {    let ch = src[offset - 1];    if (ch === '\n') return offset;    while (ch && ch !== '\n') ch = src[offset -= 1];    return offset + 1;  }  /**   * End of indentation, or null if the line's indent level is not more   * than `indent`   *   * @param {string} src   * @param {number} indent   * @param {number} lineStart   * @returns {?number}   */  static endOfBlockIndent(src, indent, lineStart) {    const inEnd = Node.endOfIndent(src, lineStart);    if (inEnd > lineStart + indent) {      return inEnd;    } else {      const wsEnd = Node.endOfWhiteSpace(src, inEnd);      const ch = src[wsEnd];      if (!ch || ch === '\n') return wsEnd;    }    return null;  }  static atBlank(src, offset, endAsBlank) {    const ch = src[offset];    return ch === '\n' || ch === '\t' || ch === ' ' || endAsBlank && !ch;  }  static nextNodeIsIndented(ch, indentDiff, indicatorAsIndent) {    if (!ch || indentDiff < 0) return false;    if (indentDiff > 0) return true;    return indicatorAsIndent && ch === '-';  } // should be at line or string end, or at next non-whitespace char  static normalizeOffset(src, offset) {    const ch = src[offset];    return !ch ? offset : ch !== '\n' && src[offset - 1] === '\n' ? offset - 1 : Node.endOfWhiteSpace(src, offset);  } // fold single newline into space, multiple newlines to N - 1 newlines  // presumes src[offset] === '\n'  static foldNewline(src, offset, indent) {    let inCount = 0;    let error = false;    let fold = '';    let ch = src[offset + 1];    while (ch === ' ' || ch === '\t' || ch === '\n') {      switch (ch) {        case '\n':          inCount = 0;          offset += 1;          fold += '\n';          break;        case '\t':          if (inCount <= indent) error = true;          offset = Node.endOfWhiteSpace(src, offset + 2) - 1;          break;        case ' ':          inCount += 1;          offset += 1;          break;      }      ch = src[offset + 1];    }    if (!fold) fold = ' ';    if (ch && inCount <= indent) error = true;    return {      fold,      offset,      error    };  }  constructor(type, props, context) {    Object.defineProperty(this, 'context', {      value: context || null,      writable: true    });    this.error = null;    this.range = null;    this.valueRange = null;    this.props = props || [];    this.type = type;    this.value = null;  }  getPropValue(idx, key, skipKey) {    if (!this.context) return null;    const {      src    } = this.context;    const prop = this.props[idx];    return prop && src[prop.start] === key ? src.slice(prop.start + (skipKey ? 1 : 0), prop.end) : null;  }  get anchor() {    for (let i = 0; i < this.props.length; ++i) {      const anchor = this.getPropValue(i, Char.ANCHOR, true);      if (anchor != null) return anchor;    }    return null;  }  get comment() {    const comments = [];    for (let i = 0; i < this.props.length; ++i) {      const comment = this.getPropValue(i, Char.COMMENT, true);      if (comment != null) comments.push(comment);    }    return comments.length > 0 ? comments.join('\n') : null;  }  commentHasRequiredWhitespace(start) {    const {      src    } = this.context;    if (this.header && start === this.header.end) return false;    if (!this.valueRange) return false;    const {      end    } = this.valueRange;    return start !== end || Node.atBlank(src, end - 1);  }  get hasComment() {    if (this.context) {      const {        src      } = this.context;      for (let i = 0; i < this.props.length; ++i) {        if (src[this.props[i].start] === Char.COMMENT) return true;      }    }    return false;  }  get hasProps() {    if (this.context) {      const {        src      } = this.context;      for (let i = 0; i < this.props.length; ++i) {        if (src[this.props[i].start] !== Char.COMMENT) return true;      }    }    return false;  }  get includesTrailingLines() {    return false;  }  get jsonLike() {    const jsonLikeTypes = [Type.FLOW_MAP, Type.FLOW_SEQ, Type.QUOTE_DOUBLE, Type.QUOTE_SINGLE];    return jsonLikeTypes.indexOf(this.type) !== -1;  }  get rangeAsLinePos() {    if (!this.range || !this.context) return undefined;    const start = getLinePos(this.range.start, this.context.root);    if (!start) return undefined;    const end = getLinePos(this.range.end, this.context.root);    return {      start,      end    };  }  get rawValue() {    if (!this.valueRange || !this.context) return null;    const {      start,      end    } = this.valueRange;    return this.context.src.slice(start, end);  }  get tag() {    for (let i = 0; i < this.props.length; ++i) {      const tag = this.getPropValue(i, Char.TAG, false);      if (tag != null) {        if (tag[1] === '<') {          return {            verbatim: tag.slice(2, -1)          };        } else {          // eslint-disable-next-line no-unused-vars          const [_, handle, suffix] = tag.match(/^(.*!)([^!]*)$/);          return {            handle,            suffix          };        }      }    }    return null;  }  get valueRangeContainsNewline() {    if (!this.valueRange || !this.context) return false;    const {      start,      end    } = this.valueRange;    const {      src    } = this.context;    for (let i = start; i < end; ++i) {      if (src[i] === '\n') return true;    }    return false;  }  parseComment(start) {    const {      src    } = this.context;    if (src[start] === Char.COMMENT) {      const end = Node.endOfLine(src, start + 1);      const commentRange = new Range(start, end);      this.props.push(commentRange);      return end;    }    return start;  }  /**   * Populates the `origStart` and `origEnd` values of all ranges for this   * node. Extended by child classes to handle descendant nodes.   *   * @param {number[]} cr - Positions of dropped CR characters   * @param {number} offset - Starting index of `cr` from the last call   * @returns {number} - The next offset, matching the one found for `origStart`   */  setOrigRanges(cr, offset) {    if (this.range) offset = this.range.setOrigRange(cr, offset);    if (this.valueRange) this.valueRange.setOrigRange(cr, offset);    this.props.forEach(prop => prop.setOrigRange(cr, offset));    return offset;  }  toString() {    const {      context: {        src      },      range,      value    } = this;    if (value != null) return value;    const str = src.slice(range.start, range.end);    return Node.addStringTerminator(src, range.end, str);  }}class YAMLError extends Error {  constructor(name, source, message) {    if (!message || !(source instanceof Node)) throw new Error(`Invalid arguments for new ${name}`);    super();    this.name = name;    this.message = message;    this.source = source;  }  makePretty() {    if (!this.source) return;    this.nodeType = this.source.type;    const cst = this.source.context && this.source.context.root;    if (typeof this.offset === 'number') {      this.range = new Range(this.offset, this.offset + 1);      const start = cst && getLinePos(this.offset, cst);      if (start) {        const end = {          line: start.line,          col: start.col + 1        };        this.linePos = {          start,          end        };      }      delete this.offset;    } else {      this.range = this.source.range;      this.linePos = this.source.rangeAsLinePos;    }    if (this.linePos) {      const {        line,        col      } = this.linePos.start;      this.message += ` at line ${line}, column ${col}`;      const ctx = cst && getPrettyContext(this.linePos, cst);      if (ctx) this.message += `:\n\n${ctx}\n`;    }    delete this.source;  }}class YAMLReferenceError extends YAMLError {  constructor(source, message) {    super('YAMLReferenceError', source, message);  }}class YAMLSemanticError extends YAMLError {  constructor(source, message) {    super('YAMLSemanticError', source, message);  }}class YAMLSyntaxError extends YAMLError {  constructor(source, message) {    super('YAMLSyntaxError', source, message);  }}class YAMLWarning extends YAMLError {  constructor(source, message) {    super('YAMLWarning', source, message);  }}function _defineProperty(obj, key, value) {  if (key in obj) {    Object.defineProperty(obj, key, {      value: value,      enumerable: true,      configurable: true,      writable: true    });  } else {    obj[key] = value;  }  return obj;}class PlainValue extends Node {  static endOfLine(src, start, inFlow) {    let ch = src[start];    let offset = start;    while (ch && ch !== '\n') {      if (inFlow && (ch === '[' || ch === ']' || ch === '{' || ch === '}' || ch === ',')) break;      const next = src[offset + 1];      if (ch === ':' && (!next || next === '\n' || next === '\t' || next === ' ' || inFlow && next === ',')) break;      if ((ch === ' ' || ch === '\t') && next === '#') break;      offset += 1;      ch = next;    }    return offset;  }  get strValue() {    if (!this.valueRange || !this.context) return null;    let {      start,      end    } = this.valueRange;    const {      src    } = this.context;    let ch = src[end - 1];    while (start < end && (ch === '\n' || ch === '\t' || ch === ' ')) ch = src[--end - 1];    let str = '';    for (let i = start; i < end; ++i) {      const ch = src[i];      if (ch === '\n') {        const {          fold,          offset        } = Node.foldNewline(src, i, -1);        str += fold;        i = offset;      } else if (ch === ' ' || ch === '\t') {        // trim trailing whitespace        const wsStart = i;        let next = src[i + 1];        while (i < end && (next === ' ' || next === '\t')) {          i += 1;          next = src[i + 1];        }        if (next !== '\n') str += i > wsStart ? src.slice(wsStart, i + 1) : ch;      } else {        str += ch;      }    }    const ch0 = src[start];    switch (ch0) {      case '\t':        {          const msg = 'Plain value cannot start with a tab character';          const errors = [new YAMLSemanticError(this, msg)];          return {            errors,            str          };        }      case '@':      case '`':        {          const msg = `Plain value cannot start with reserved character ${ch0}`;          const errors = [new YAMLSemanticError(this, msg)];          return {            errors,            str          };        }      default:        return str;    }  }  parseBlockValue(start) {    const {      indent,      inFlow,      src    } = this.context;    let offset = start;    let valueEnd = start;    for (let ch = src[offset]; ch === '\n'; ch = src[offset]) {      if (Node.atDocumentBoundary(src, offset + 1)) break;      const end = Node.endOfBlockIndent(src, indent, offset + 1);      if (end === null || src[end] === '#') break;      if (src[end] === '\n') {        offset = end;      } else {        valueEnd = PlainValue.endOfLine(src, end, inFlow);        offset = valueEnd;      }    }    if (this.valueRange.isEmpty()) this.valueRange.start = start;    this.valueRange.end = valueEnd;    return valueEnd;  }  /**   * Parses a plain value from the source   *   * Accepted forms are:   * ```   * #comment   *   * first line   *   * first line #comment   *   * first line   * block   * lines   *   * #comment   * block   * lines   * ```   * where block lines are empty or have an indent level greater than `indent`.   *   * @param {ParseContext} context   * @param {number} start - Index of first character   * @returns {number} - Index of the character after this scalar, may be `\n`   */  parse(context, start) {    this.context = context;    const {      inFlow,      src    } = context;    let offset = start;    const ch = src[offset];    if (ch && ch !== '#' && ch !== '\n') {      offset = PlainValue.endOfLine(src, start, inFlow);    }    this.valueRange = new Range(start, offset);    offset = Node.endOfWhiteSpace(src, offset);    offset = this.parseComment(offset);    if (!this.hasComment || this.valueRange.isEmpty()) {      offset = this.parseBlockValue(offset);    }    return offset;  }}exports.Char = Char;exports.Node = Node;exports.PlainValue = PlainValue;exports.Range = Range;exports.Type = Type;exports.YAMLError = YAMLError;exports.YAMLReferenceError = YAMLReferenceError;exports.YAMLSemanticError = YAMLSemanticError;exports.YAMLSyntaxError = YAMLSyntaxError;exports.YAMLWarning = YAMLWarning;exports._defineProperty = _defineProperty;exports.defaultTagPrefix = defaultTagPrefix;exports.defaultTags = defaultTags;
 |