Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ParseContext.js 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _constants = require("../constants");
  7. var _errors = require("../errors");
  8. var _Alias = _interopRequireDefault(require("./Alias"));
  9. var _BlockValue = _interopRequireDefault(require("./BlockValue"));
  10. var _Collection = _interopRequireDefault(require("./Collection"));
  11. var _CollectionItem = _interopRequireDefault(require("./CollectionItem"));
  12. var _FlowCollection = _interopRequireDefault(require("./FlowCollection"));
  13. var _Node = _interopRequireDefault(require("./Node"));
  14. var _PlainValue = _interopRequireDefault(require("./PlainValue"));
  15. var _QuoteDouble = _interopRequireDefault(require("./QuoteDouble"));
  16. var _QuoteSingle = _interopRequireDefault(require("./QuoteSingle"));
  17. var _Range = _interopRequireDefault(require("./Range"));
  18. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  19. 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; }
  20. /**
  21. * @param {boolean} atLineStart - Node starts at beginning of line
  22. * @param {boolean} inFlow - true if currently in a flow context
  23. * @param {boolean} inCollection - true if currently in a collection context
  24. * @param {number} indent - Current level of indentation
  25. * @param {number} lineStart - Start of the current line
  26. * @param {Node} parent - The parent of the node
  27. * @param {string} src - Source of the YAML document
  28. */
  29. class ParseContext {
  30. static parseType(src, offset, inFlow) {
  31. switch (src[offset]) {
  32. case '*':
  33. return _constants.Type.ALIAS;
  34. case '>':
  35. return _constants.Type.BLOCK_FOLDED;
  36. case '|':
  37. return _constants.Type.BLOCK_LITERAL;
  38. case '{':
  39. return _constants.Type.FLOW_MAP;
  40. case '[':
  41. return _constants.Type.FLOW_SEQ;
  42. case '?':
  43. return !inFlow && _Node.default.atBlank(src, offset + 1, true) ? _constants.Type.MAP_KEY : _constants.Type.PLAIN;
  44. case ':':
  45. return !inFlow && _Node.default.atBlank(src, offset + 1, true) ? _constants.Type.MAP_VALUE : _constants.Type.PLAIN;
  46. case '-':
  47. return !inFlow && _Node.default.atBlank(src, offset + 1, true) ? _constants.Type.SEQ_ITEM : _constants.Type.PLAIN;
  48. case '"':
  49. return _constants.Type.QUOTE_DOUBLE;
  50. case "'":
  51. return _constants.Type.QUOTE_SINGLE;
  52. default:
  53. return _constants.Type.PLAIN;
  54. }
  55. }
  56. constructor(orig = {}, {
  57. atLineStart,
  58. inCollection,
  59. inFlow,
  60. indent,
  61. lineStart,
  62. parent
  63. } = {}) {
  64. _defineProperty(this, "parseNode", (overlay, start) => {
  65. if (_Node.default.atDocumentBoundary(this.src, start)) return null;
  66. const context = new ParseContext(this, overlay);
  67. const {
  68. props,
  69. type,
  70. valueStart
  71. } = context.parseProps(start);
  72. let node;
  73. switch (type) {
  74. case _constants.Type.ALIAS:
  75. node = new _Alias.default(type, props);
  76. break;
  77. case _constants.Type.BLOCK_FOLDED:
  78. case _constants.Type.BLOCK_LITERAL:
  79. node = new _BlockValue.default(type, props);
  80. break;
  81. case _constants.Type.FLOW_MAP:
  82. case _constants.Type.FLOW_SEQ:
  83. node = new _FlowCollection.default(type, props);
  84. break;
  85. case _constants.Type.MAP_KEY:
  86. case _constants.Type.MAP_VALUE:
  87. case _constants.Type.SEQ_ITEM:
  88. node = new _CollectionItem.default(type, props);
  89. break;
  90. case _constants.Type.COMMENT:
  91. case _constants.Type.PLAIN:
  92. node = new _PlainValue.default(type, props);
  93. break;
  94. case _constants.Type.QUOTE_DOUBLE:
  95. node = new _QuoteDouble.default(type, props);
  96. break;
  97. case _constants.Type.QUOTE_SINGLE:
  98. node = new _QuoteSingle.default(type, props);
  99. break;
  100. default:
  101. node.error = new _errors.YAMLSyntaxError(node, `Unknown node type: ${JSON.stringify(type)}`);
  102. node.range = new _Range.default(start, start + 1);
  103. return node;
  104. }
  105. let offset = node.parse(context, valueStart);
  106. node.range = new _Range.default(start, offset);
  107. if (offset <= start) {
  108. node.error = new Error(`Node#parse consumed no characters`);
  109. node.error.parseEnd = offset;
  110. node.error.source = node;
  111. node.range.end = start + 1;
  112. }
  113. if (context.nodeStartsCollection(node)) {
  114. if (!node.error && !context.atLineStart && context.parent.type === _constants.Type.DOCUMENT) {
  115. node.error = new _errors.YAMLSyntaxError(node, 'Block collection must not have preceding content here (e.g. directives-end indicator)');
  116. }
  117. const collection = new _Collection.default(node);
  118. offset = collection.parse(new ParseContext(context), offset);
  119. collection.range = new _Range.default(start, offset);
  120. return collection;
  121. }
  122. return node;
  123. });
  124. this.atLineStart = atLineStart != null ? atLineStart : orig.atLineStart || false;
  125. this.inCollection = inCollection != null ? inCollection : orig.inCollection || false;
  126. this.inFlow = inFlow != null ? inFlow : orig.inFlow || false;
  127. this.indent = indent != null ? indent : orig.indent;
  128. this.lineStart = lineStart != null ? lineStart : orig.lineStart;
  129. this.parent = parent != null ? parent : orig.parent || {};
  130. this.root = orig.root;
  131. this.src = orig.src;
  132. } // for logging
  133. get pretty() {
  134. const obj = {
  135. start: `${this.lineStart} + ${this.indent}`,
  136. in: [],
  137. parent: this.parent.type
  138. };
  139. if (!this.atLineStart) obj.start += ' + N';
  140. if (this.inCollection) obj.in.push('collection');
  141. if (this.inFlow) obj.in.push('flow');
  142. return obj;
  143. }
  144. nodeStartsCollection(node) {
  145. const {
  146. inCollection,
  147. inFlow,
  148. src
  149. } = this;
  150. if (inCollection || inFlow) return false;
  151. if (node instanceof _CollectionItem.default) return true; // check for implicit key
  152. let offset = node.range.end;
  153. if (src[offset] === '\n' || src[offset - 1] === '\n') return false;
  154. offset = _Node.default.endOfWhiteSpace(src, offset);
  155. return src[offset] === ':';
  156. } // Anchor and tag are before type, which determines the node implementation
  157. // class; hence this intermediate step.
  158. parseProps(offset) {
  159. const {
  160. inFlow,
  161. parent,
  162. src
  163. } = this;
  164. const props = [];
  165. let lineHasProps = false;
  166. offset = _Node.default.endOfWhiteSpace(src, offset);
  167. let ch = src[offset];
  168. while (ch === _constants.Char.ANCHOR || ch === _constants.Char.COMMENT || ch === _constants.Char.TAG || ch === '\n') {
  169. if (ch === '\n') {
  170. const lineStart = offset + 1;
  171. const inEnd = _Node.default.endOfIndent(src, lineStart);
  172. const indentDiff = inEnd - (lineStart + this.indent);
  173. const noIndicatorAsIndent = parent.type === _constants.Type.SEQ_ITEM && parent.context.atLineStart;
  174. if (!_Node.default.nextNodeIsIndented(src[inEnd], indentDiff, !noIndicatorAsIndent)) break;
  175. this.atLineStart = true;
  176. this.lineStart = lineStart;
  177. lineHasProps = false;
  178. offset = inEnd;
  179. } else if (ch === _constants.Char.COMMENT) {
  180. const end = _Node.default.endOfLine(src, offset + 1);
  181. props.push(new _Range.default(offset, end));
  182. offset = end;
  183. } else {
  184. let end = _Node.default.endOfIdentifier(src, offset + 1);
  185. if (ch === _constants.Char.TAG && src[end] === ',' && /^[a-zA-Z0-9-]+\.[a-zA-Z0-9-]+,\d\d\d\d(-\d\d){0,2}\/\S/.test(src.slice(offset + 1, end + 13))) {
  186. // Let's presume we're dealing with a YAML 1.0 domain tag here, rather
  187. // than an empty but 'foo.bar' private-tagged node in a flow collection
  188. // followed without whitespace by a plain string starting with a year
  189. // or date divided by something.
  190. end = _Node.default.endOfIdentifier(src, end + 5);
  191. }
  192. props.push(new _Range.default(offset, end));
  193. lineHasProps = true;
  194. offset = _Node.default.endOfWhiteSpace(src, end);
  195. }
  196. ch = src[offset];
  197. } // '- &a : b' has an anchor on an empty node
  198. if (lineHasProps && ch === ':' && _Node.default.atBlank(src, offset + 1, true)) offset -= 1;
  199. const type = ParseContext.parseType(src, offset, inFlow);
  200. return {
  201. props,
  202. type,
  203. valueStart: offset
  204. };
  205. }
  206. /**
  207. * Parses a node from the source
  208. * @param {ParseContext} overlay
  209. * @param {number} start - Index of first non-whitespace character for the node
  210. * @returns {?Node} - null if at a document boundary
  211. */
  212. }
  213. exports.default = ParseContext;