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.

source-utils.js 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.getLinePos = getLinePos;
  6. exports.getLine = getLine;
  7. exports.getPrettyContext = getPrettyContext;
  8. function findLineStarts(src) {
  9. var ls = [0];
  10. var offset = src.indexOf('\n');
  11. while (offset !== -1) {
  12. offset += 1;
  13. ls.push(offset);
  14. offset = src.indexOf('\n', offset);
  15. }
  16. return ls;
  17. }
  18. function getSrcInfo(cst) {
  19. var lineStarts, src;
  20. if (typeof cst === 'string') {
  21. lineStarts = findLineStarts(cst);
  22. src = cst;
  23. } else {
  24. if (Array.isArray(cst)) cst = cst[0];
  25. if (cst && cst.context) {
  26. if (!cst.lineStarts) cst.lineStarts = findLineStarts(cst.context.src);
  27. lineStarts = cst.lineStarts;
  28. src = cst.context.src;
  29. }
  30. }
  31. return {
  32. lineStarts: lineStarts,
  33. src: src
  34. };
  35. }
  36. /**
  37. * @typedef {Object} LinePos - One-indexed position in the source
  38. * @property {number} line
  39. * @property {number} col
  40. */
  41. /**
  42. * Determine the line/col position matching a character offset.
  43. *
  44. * Accepts a source string or a CST document as the second parameter. With
  45. * the latter, starting indices for lines are cached in the document as
  46. * `lineStarts: number[]`.
  47. *
  48. * Returns a one-indexed `{ line, col }` location if found, or
  49. * `undefined` otherwise.
  50. *
  51. * @param {number} offset
  52. * @param {string|Document|Document[]} cst
  53. * @returns {?LinePos}
  54. */
  55. function getLinePos(offset, cst) {
  56. if (typeof offset !== 'number' || offset < 0) return null;
  57. var _getSrcInfo = getSrcInfo(cst),
  58. lineStarts = _getSrcInfo.lineStarts,
  59. src = _getSrcInfo.src;
  60. if (!lineStarts || !src || offset > src.length) return null;
  61. for (var i = 0; i < lineStarts.length; ++i) {
  62. var start = lineStarts[i];
  63. if (offset < start) {
  64. return {
  65. line: i,
  66. col: offset - lineStarts[i - 1] + 1
  67. };
  68. }
  69. if (offset === start) return {
  70. line: i + 1,
  71. col: 1
  72. };
  73. }
  74. var line = lineStarts.length;
  75. return {
  76. line: line,
  77. col: offset - lineStarts[line - 1] + 1
  78. };
  79. }
  80. /**
  81. * Get a specified line from the source.
  82. *
  83. * Accepts a source string or a CST document as the second parameter. With
  84. * the latter, starting indices for lines are cached in the document as
  85. * `lineStarts: number[]`.
  86. *
  87. * Returns the line as a string if found, or `null` otherwise.
  88. *
  89. * @param {number} line One-indexed line number
  90. * @param {string|Document|Document[]} cst
  91. * @returns {?string}
  92. */
  93. function getLine(line, cst) {
  94. var _getSrcInfo2 = getSrcInfo(cst),
  95. lineStarts = _getSrcInfo2.lineStarts,
  96. src = _getSrcInfo2.src;
  97. if (!lineStarts || !(line >= 1) || line > lineStarts.length) return null;
  98. var start = lineStarts[line - 1];
  99. var end = lineStarts[line]; // undefined for last line; that's ok for slice()
  100. while (end && end > start && src[end - 1] === '\n') {
  101. --end;
  102. }
  103. return src.slice(start, end);
  104. }
  105. /**
  106. * Pretty-print the starting line from the source indicated by the range `pos`
  107. *
  108. * Trims output to `maxWidth` chars while keeping the starting column visible,
  109. * using `…` at either end to indicate dropped characters.
  110. *
  111. * Returns a two-line string (or `null`) with `\n` as separator; the second line
  112. * will hold appropriately indented `^` marks indicating the column range.
  113. *
  114. * @param {Object} pos
  115. * @param {LinePos} pos.start
  116. * @param {LinePos} [pos.end]
  117. * @param {string|Document|Document[]*} cst
  118. * @param {number} [maxWidth=80]
  119. * @returns {?string}
  120. */
  121. function getPrettyContext(_ref, cst) {
  122. var start = _ref.start,
  123. end = _ref.end;
  124. var maxWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 80;
  125. var src = getLine(start.line, cst);
  126. if (!src) return null;
  127. var col = start.col;
  128. if (src.length > maxWidth) {
  129. if (col <= maxWidth - 10) {
  130. src = src.substr(0, maxWidth - 1) + '…';
  131. } else {
  132. var halfWidth = Math.round(maxWidth / 2);
  133. if (src.length > col + halfWidth) src = src.substr(0, col + halfWidth - 1) + '…';
  134. col -= src.length - maxWidth;
  135. src = '…' + src.substr(1 - maxWidth);
  136. }
  137. }
  138. var errLen = 1;
  139. var errEnd = '';
  140. if (end) {
  141. if (end.line === start.line && col + (end.col - start.col) <= maxWidth + 1) {
  142. errLen = end.col - start.col;
  143. } else {
  144. errLen = Math.min(src.length + 1, maxWidth) - col;
  145. errEnd = '…';
  146. }
  147. }
  148. var offset = col > 1 ? ' '.repeat(col - 1) : '';
  149. var err = '^'.repeat(errLen);
  150. return "".concat(src, "\n").concat(offset).concat(err).concat(errEnd);
  151. }