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.

BlockValue.js 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = exports.Chomp = void 0;
  6. var _constants = require("../constants");
  7. var _Node = _interopRequireDefault(require("./Node"));
  8. var _Range = _interopRequireDefault(require("./Range"));
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10. const Chomp = {
  11. CLIP: 'CLIP',
  12. KEEP: 'KEEP',
  13. STRIP: 'STRIP'
  14. };
  15. exports.Chomp = Chomp;
  16. class BlockValue extends _Node.default {
  17. constructor(type, props) {
  18. super(type, props);
  19. this.blockIndent = null;
  20. this.chomping = Chomp.CLIP;
  21. this.header = null;
  22. }
  23. get includesTrailingLines() {
  24. return this.chomping === Chomp.KEEP;
  25. }
  26. get strValue() {
  27. if (!this.valueRange || !this.context) return null;
  28. let {
  29. start,
  30. end
  31. } = this.valueRange;
  32. const {
  33. indent,
  34. src
  35. } = this.context;
  36. if (this.valueRange.isEmpty()) return '';
  37. let lastNewLine = null;
  38. let ch = src[end - 1];
  39. while (ch === '\n' || ch === '\t' || ch === ' ') {
  40. end -= 1;
  41. if (end <= start) {
  42. if (this.chomping === Chomp.KEEP) break;else return '';
  43. }
  44. if (ch === '\n') lastNewLine = end;
  45. ch = src[end - 1];
  46. }
  47. let keepStart = end + 1;
  48. if (lastNewLine) {
  49. if (this.chomping === Chomp.KEEP) {
  50. keepStart = lastNewLine;
  51. end = this.valueRange.end;
  52. } else {
  53. end = lastNewLine;
  54. }
  55. }
  56. const bi = indent + this.blockIndent;
  57. const folded = this.type === _constants.Type.BLOCK_FOLDED;
  58. let atStart = true;
  59. let str = '';
  60. let sep = '';
  61. let prevMoreIndented = false;
  62. for (let i = start; i < end; ++i) {
  63. for (let j = 0; j < bi; ++j) {
  64. if (src[i] !== ' ') break;
  65. i += 1;
  66. }
  67. const ch = src[i];
  68. if (ch === '\n') {
  69. if (sep === '\n') str += '\n';else sep = '\n';
  70. } else {
  71. const lineEnd = _Node.default.endOfLine(src, i);
  72. const line = src.slice(i, lineEnd);
  73. i = lineEnd;
  74. if (folded && (ch === ' ' || ch === '\t') && i < keepStart) {
  75. if (sep === ' ') sep = '\n';else if (!prevMoreIndented && !atStart && sep === '\n') sep = '\n\n';
  76. str += sep + line; //+ ((lineEnd < end && src[lineEnd]) || '')
  77. sep = lineEnd < end && src[lineEnd] || '';
  78. prevMoreIndented = true;
  79. } else {
  80. str += sep + line;
  81. sep = folded && i < keepStart ? ' ' : '\n';
  82. prevMoreIndented = false;
  83. }
  84. if (atStart && line !== '') atStart = false;
  85. }
  86. }
  87. return this.chomping === Chomp.STRIP ? str : str + '\n';
  88. }
  89. parseBlockHeader(start) {
  90. const {
  91. src
  92. } = this.context;
  93. let offset = start + 1;
  94. let bi = '';
  95. while (true) {
  96. const ch = src[offset];
  97. switch (ch) {
  98. case '-':
  99. this.chomping = Chomp.STRIP;
  100. break;
  101. case '+':
  102. this.chomping = Chomp.KEEP;
  103. break;
  104. case '0':
  105. case '1':
  106. case '2':
  107. case '3':
  108. case '4':
  109. case '5':
  110. case '6':
  111. case '7':
  112. case '8':
  113. case '9':
  114. bi += ch;
  115. break;
  116. default:
  117. this.blockIndent = Number(bi) || null;
  118. this.header = new _Range.default(start, offset);
  119. return offset;
  120. }
  121. offset += 1;
  122. }
  123. }
  124. parseBlockValue(start) {
  125. const {
  126. indent,
  127. src
  128. } = this.context;
  129. let offset = start;
  130. let valueEnd = start;
  131. let bi = this.blockIndent ? indent + this.blockIndent - 1 : indent;
  132. let minBlockIndent = 1;
  133. for (let ch = src[offset]; ch === '\n'; ch = src[offset]) {
  134. offset += 1;
  135. if (_Node.default.atDocumentBoundary(src, offset)) break;
  136. const end = _Node.default.endOfBlockIndent(src, bi, offset); // should not include tab?
  137. if (end === null) break;
  138. if (!this.blockIndent) {
  139. // no explicit block indent, none yet detected
  140. const lineIndent = end - (offset + indent);
  141. if (src[end] !== '\n') {
  142. // first line with non-whitespace content
  143. if (lineIndent < minBlockIndent) {
  144. offset -= 1;
  145. break;
  146. }
  147. this.blockIndent = lineIndent;
  148. bi = indent + this.blockIndent - 1;
  149. } else if (lineIndent > minBlockIndent) {
  150. // empty line with more whitespace
  151. minBlockIndent = lineIndent;
  152. }
  153. }
  154. if (src[end] === '\n') {
  155. offset = end;
  156. } else {
  157. offset = valueEnd = _Node.default.endOfLine(src, end);
  158. }
  159. }
  160. if (this.chomping !== Chomp.KEEP) {
  161. offset = src[valueEnd] ? valueEnd + 1 : valueEnd;
  162. }
  163. this.valueRange = new _Range.default(start + 1, offset);
  164. return offset;
  165. }
  166. /**
  167. * Parses a block value from the source
  168. *
  169. * Accepted forms are:
  170. * ```
  171. * BS
  172. * block
  173. * lines
  174. *
  175. * BS #comment
  176. * block
  177. * lines
  178. * ```
  179. * where the block style BS matches the regexp `[|>][-+1-9]*` and block lines
  180. * are empty or have an indent level greater than `indent`.
  181. *
  182. * @param {ParseContext} context
  183. * @param {number} start - Index of first character
  184. * @returns {number} - Index of the character after this block
  185. */
  186. parse(context, start) {
  187. this.context = context;
  188. const {
  189. src
  190. } = context;
  191. let offset = this.parseBlockHeader(start);
  192. offset = _Node.default.endOfWhiteSpace(src, offset);
  193. offset = this.parseComment(offset);
  194. offset = this.parseBlockValue(offset);
  195. return offset;
  196. }
  197. setOrigRanges(cr, offset) {
  198. offset = super.setOrigRanges(cr, offset);
  199. return this.header ? this.header.setOrigRange(cr, offset) : offset;
  200. }
  201. }
  202. exports.default = BlockValue;