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.

Node.js 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _constants = require("../constants");
  7. var _sourceUtils = require("./source-utils");
  8. var _Range = _interopRequireDefault(require("./Range"));
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10. /** Root class of all nodes */
  11. class Node {
  12. static addStringTerminator(src, offset, str) {
  13. if (str[str.length - 1] === '\n') return str;
  14. const next = Node.endOfWhiteSpace(src, offset);
  15. return next >= src.length || src[next] === '\n' ? str + '\n' : str;
  16. } // ^(---|...)
  17. static atDocumentBoundary(src, offset, sep) {
  18. const ch0 = src[offset];
  19. if (!ch0) return true;
  20. const prev = src[offset - 1];
  21. if (prev && prev !== '\n') return false;
  22. if (sep) {
  23. if (ch0 !== sep) return false;
  24. } else {
  25. if (ch0 !== _constants.Char.DIRECTIVES_END && ch0 !== _constants.Char.DOCUMENT_END) return false;
  26. }
  27. const ch1 = src[offset + 1];
  28. const ch2 = src[offset + 2];
  29. if (ch1 !== ch0 || ch2 !== ch0) return false;
  30. const ch3 = src[offset + 3];
  31. return !ch3 || ch3 === '\n' || ch3 === '\t' || ch3 === ' ';
  32. }
  33. static endOfIdentifier(src, offset) {
  34. let ch = src[offset];
  35. const isVerbatim = ch === '<';
  36. const notOk = isVerbatim ? ['\n', '\t', ' ', '>'] : ['\n', '\t', ' ', '[', ']', '{', '}', ','];
  37. while (ch && notOk.indexOf(ch) === -1) ch = src[offset += 1];
  38. if (isVerbatim && ch === '>') offset += 1;
  39. return offset;
  40. }
  41. static endOfIndent(src, offset) {
  42. let ch = src[offset];
  43. while (ch === ' ') ch = src[offset += 1];
  44. return offset;
  45. }
  46. static endOfLine(src, offset) {
  47. let ch = src[offset];
  48. while (ch && ch !== '\n') ch = src[offset += 1];
  49. return offset;
  50. }
  51. static endOfWhiteSpace(src, offset) {
  52. let ch = src[offset];
  53. while (ch === '\t' || ch === ' ') ch = src[offset += 1];
  54. return offset;
  55. }
  56. static startOfLine(src, offset) {
  57. let ch = src[offset - 1];
  58. if (ch === '\n') return offset;
  59. while (ch && ch !== '\n') ch = src[offset -= 1];
  60. return offset + 1;
  61. }
  62. /**
  63. * End of indentation, or null if the line's indent level is not more
  64. * than `indent`
  65. *
  66. * @param {string} src
  67. * @param {number} indent
  68. * @param {number} lineStart
  69. * @returns {?number}
  70. */
  71. static endOfBlockIndent(src, indent, lineStart) {
  72. const inEnd = Node.endOfIndent(src, lineStart);
  73. if (inEnd > lineStart + indent) {
  74. return inEnd;
  75. } else {
  76. const wsEnd = Node.endOfWhiteSpace(src, inEnd);
  77. const ch = src[wsEnd];
  78. if (!ch || ch === '\n') return wsEnd;
  79. }
  80. return null;
  81. }
  82. static atBlank(src, offset, endAsBlank) {
  83. const ch = src[offset];
  84. return ch === '\n' || ch === '\t' || ch === ' ' || endAsBlank && !ch;
  85. }
  86. static atCollectionItem(src, offset) {
  87. const ch = src[offset];
  88. return (ch === '?' || ch === ':' || ch === '-') && Node.atBlank(src, offset + 1, true);
  89. }
  90. static nextNodeIsIndented(ch, indentDiff, indicatorAsIndent) {
  91. if (!ch || indentDiff < 0) return false;
  92. if (indentDiff > 0) return true;
  93. return indicatorAsIndent && ch === '-';
  94. } // should be at line or string end, or at next non-whitespace char
  95. static normalizeOffset(src, offset) {
  96. const ch = src[offset];
  97. return !ch ? offset : ch !== '\n' && src[offset - 1] === '\n' ? offset - 1 : Node.endOfWhiteSpace(src, offset);
  98. } // fold single newline into space, multiple newlines to N - 1 newlines
  99. // presumes src[offset] === '\n'
  100. static foldNewline(src, offset, indent) {
  101. let inCount = 0;
  102. let error = false;
  103. let fold = '';
  104. let ch = src[offset + 1];
  105. while (ch === ' ' || ch === '\t' || ch === '\n') {
  106. switch (ch) {
  107. case '\n':
  108. inCount = 0;
  109. offset += 1;
  110. fold += '\n';
  111. break;
  112. case '\t':
  113. if (inCount <= indent) error = true;
  114. offset = Node.endOfWhiteSpace(src, offset + 2) - 1;
  115. break;
  116. case ' ':
  117. inCount += 1;
  118. offset += 1;
  119. break;
  120. }
  121. ch = src[offset + 1];
  122. }
  123. if (!fold) fold = ' ';
  124. if (ch && inCount <= indent) error = true;
  125. return {
  126. fold,
  127. offset,
  128. error
  129. };
  130. }
  131. constructor(type, props, context) {
  132. Object.defineProperty(this, 'context', {
  133. value: context || null,
  134. writable: true
  135. });
  136. this.error = null;
  137. this.range = null;
  138. this.valueRange = null;
  139. this.props = props || [];
  140. this.type = type;
  141. this.value = null;
  142. }
  143. getPropValue(idx, key, skipKey) {
  144. if (!this.context) return null;
  145. const {
  146. src
  147. } = this.context;
  148. const prop = this.props[idx];
  149. return prop && src[prop.start] === key ? src.slice(prop.start + (skipKey ? 1 : 0), prop.end) : null;
  150. }
  151. get anchor() {
  152. for (let i = 0; i < this.props.length; ++i) {
  153. const anchor = this.getPropValue(i, _constants.Char.ANCHOR, true);
  154. if (anchor != null) return anchor;
  155. }
  156. return null;
  157. }
  158. get comment() {
  159. const comments = [];
  160. for (let i = 0; i < this.props.length; ++i) {
  161. const comment = this.getPropValue(i, _constants.Char.COMMENT, true);
  162. if (comment != null) comments.push(comment);
  163. }
  164. return comments.length > 0 ? comments.join('\n') : null;
  165. }
  166. commentHasRequiredWhitespace(start) {
  167. const {
  168. src
  169. } = this.context;
  170. if (this.header && start === this.header.end) return false;
  171. if (!this.valueRange) return false;
  172. const {
  173. end
  174. } = this.valueRange;
  175. return start !== end || Node.atBlank(src, end - 1);
  176. }
  177. get hasComment() {
  178. if (this.context) {
  179. const {
  180. src
  181. } = this.context;
  182. for (let i = 0; i < this.props.length; ++i) {
  183. if (src[this.props[i].start] === _constants.Char.COMMENT) return true;
  184. }
  185. }
  186. return false;
  187. }
  188. get hasProps() {
  189. if (this.context) {
  190. const {
  191. src
  192. } = this.context;
  193. for (let i = 0; i < this.props.length; ++i) {
  194. if (src[this.props[i].start] !== _constants.Char.COMMENT) return true;
  195. }
  196. }
  197. return false;
  198. }
  199. get includesTrailingLines() {
  200. return false;
  201. }
  202. get jsonLike() {
  203. const jsonLikeTypes = [_constants.Type.FLOW_MAP, _constants.Type.FLOW_SEQ, _constants.Type.QUOTE_DOUBLE, _constants.Type.QUOTE_SINGLE];
  204. return jsonLikeTypes.indexOf(this.type) !== -1;
  205. }
  206. get rangeAsLinePos() {
  207. if (!this.range || !this.context) return undefined;
  208. const start = (0, _sourceUtils.getLinePos)(this.range.start, this.context.root);
  209. if (!start) return undefined;
  210. const end = (0, _sourceUtils.getLinePos)(this.range.end, this.context.root);
  211. return {
  212. start,
  213. end
  214. };
  215. }
  216. get rawValue() {
  217. if (!this.valueRange || !this.context) return null;
  218. const {
  219. start,
  220. end
  221. } = this.valueRange;
  222. return this.context.src.slice(start, end);
  223. }
  224. get tag() {
  225. for (let i = 0; i < this.props.length; ++i) {
  226. const tag = this.getPropValue(i, _constants.Char.TAG, false);
  227. if (tag != null) {
  228. if (tag[1] === '<') {
  229. return {
  230. verbatim: tag.slice(2, -1)
  231. };
  232. } else {
  233. // eslint-disable-next-line no-unused-vars
  234. const [_, handle, suffix] = tag.match(/^(.*!)([^!]*)$/);
  235. return {
  236. handle,
  237. suffix
  238. };
  239. }
  240. }
  241. }
  242. return null;
  243. }
  244. get valueRangeContainsNewline() {
  245. if (!this.valueRange || !this.context) return false;
  246. const {
  247. start,
  248. end
  249. } = this.valueRange;
  250. const {
  251. src
  252. } = this.context;
  253. for (let i = start; i < end; ++i) {
  254. if (src[i] === '\n') return true;
  255. }
  256. return false;
  257. }
  258. parseComment(start) {
  259. const {
  260. src
  261. } = this.context;
  262. if (src[start] === _constants.Char.COMMENT) {
  263. const end = Node.endOfLine(src, start + 1);
  264. const commentRange = new _Range.default(start, end);
  265. this.props.push(commentRange);
  266. return end;
  267. }
  268. return start;
  269. }
  270. /**
  271. * Populates the `origStart` and `origEnd` values of all ranges for this
  272. * node. Extended by child classes to handle descendant nodes.
  273. *
  274. * @param {number[]} cr - Positions of dropped CR characters
  275. * @param {number} offset - Starting index of `cr` from the last call
  276. * @returns {number} - The next offset, matching the one found for `origStart`
  277. */
  278. setOrigRanges(cr, offset) {
  279. if (this.range) offset = this.range.setOrigRange(cr, offset);
  280. if (this.valueRange) this.valueRange.setOrigRange(cr, offset);
  281. this.props.forEach(prop => prop.setOrigRange(cr, offset));
  282. return offset;
  283. }
  284. toString() {
  285. const {
  286. context: {
  287. src
  288. },
  289. range,
  290. value
  291. } = this;
  292. if (value != null) return value;
  293. const str = src.slice(range.start, range.end);
  294. return Node.addStringTerminator(src, range.end, str);
  295. }
  296. }
  297. exports.default = Node;