.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / remark-parse / lib / tokenize / list.js
1 'use strict';
2
3 /* eslint-disable max-params */
4
5 var trim = require('trim');
6 var repeat = require('repeat-string');
7 var decimal = require('is-decimal');
8 var getIndent = require('../util/get-indentation');
9 var removeIndent = require('../util/remove-indentation');
10 var interrupt = require('../util/interrupt');
11
12 module.exports = list;
13
14 var C_ASTERISK = '*';
15 var C_UNDERSCORE = '_';
16 var C_PLUS = '+';
17 var C_DASH = '-';
18 var C_DOT = '.';
19 var C_SPACE = ' ';
20 var C_NEWLINE = '\n';
21 var C_TAB = '\t';
22 var C_PAREN_CLOSE = ')';
23 var C_X_LOWER = 'x';
24
25 var TAB_SIZE = 4;
26 var EXPRESSION_LOOSE_LIST_ITEM = /\n\n(?!\s*$)/;
27 var EXPRESSION_TASK_ITEM = /^\[([ \t]|x|X)][ \t]/;
28 var EXPRESSION_BULLET = /^([ \t]*)([*+-]|\d+[.)])( {1,4}(?! )| |\t|$|(?=\n))([^\n]*)/;
29 var EXPRESSION_PEDANTIC_BULLET = /^([ \t]*)([*+-]|\d+[.)])([ \t]+)/;
30 var EXPRESSION_INITIAL_INDENT = /^( {1,4}|\t)?/gm;
31
32 /* Map of characters which can be used to mark
33  * list-items. */
34 var LIST_UNORDERED_MARKERS = {};
35
36 LIST_UNORDERED_MARKERS[C_ASTERISK] = true;
37 LIST_UNORDERED_MARKERS[C_PLUS] = true;
38 LIST_UNORDERED_MARKERS[C_DASH] = true;
39
40 /* Map of characters which can be used to mark
41  * list-items after a digit. */
42 var LIST_ORDERED_MARKERS = {};
43
44 LIST_ORDERED_MARKERS[C_DOT] = true;
45
46 /* Map of characters which can be used to mark
47  * list-items after a digit. */
48 var LIST_ORDERED_COMMONMARK_MARKERS = {};
49
50 LIST_ORDERED_COMMONMARK_MARKERS[C_DOT] = true;
51 LIST_ORDERED_COMMONMARK_MARKERS[C_PAREN_CLOSE] = true;
52
53 function list(eat, value, silent) {
54   var self = this;
55   var commonmark = self.options.commonmark;
56   var pedantic = self.options.pedantic;
57   var tokenizers = self.blockTokenizers;
58   var interuptors = self.interruptList;
59   var markers;
60   var index = 0;
61   var length = value.length;
62   var start = null;
63   var size = 0;
64   var queue;
65   var ordered;
66   var character;
67   var marker;
68   var nextIndex;
69   var startIndex;
70   var prefixed;
71   var currentMarker;
72   var content;
73   var line;
74   var prevEmpty;
75   var empty;
76   var items;
77   var allLines;
78   var emptyLines;
79   var item;
80   var enterTop;
81   var exitBlockquote;
82   var isLoose;
83   var node;
84   var now;
85   var end;
86   var indented;
87
88   while (index < length) {
89     character = value.charAt(index);
90
91     if (character === C_TAB) {
92       size += TAB_SIZE - (size % TAB_SIZE);
93     } else if (character === C_SPACE) {
94       size++;
95     } else {
96       break;
97     }
98
99     index++;
100   }
101
102   if (size >= TAB_SIZE) {
103     return;
104   }
105
106   character = value.charAt(index);
107
108   markers = commonmark ?
109     LIST_ORDERED_COMMONMARK_MARKERS :
110     LIST_ORDERED_MARKERS;
111
112   if (LIST_UNORDERED_MARKERS[character] === true) {
113     marker = character;
114     ordered = false;
115   } else {
116     ordered = true;
117     queue = '';
118
119     while (index < length) {
120       character = value.charAt(index);
121
122       if (!decimal(character)) {
123         break;
124       }
125
126       queue += character;
127       index++;
128     }
129
130     character = value.charAt(index);
131
132     if (!queue || markers[character] !== true) {
133       return;
134     }
135
136     start = parseInt(queue, 10);
137     marker = character;
138   }
139
140   character = value.charAt(++index);
141
142   if (character !== C_SPACE && character !== C_TAB) {
143     return;
144   }
145
146   if (silent) {
147     return true;
148   }
149
150   index = 0;
151   items = [];
152   allLines = [];
153   emptyLines = [];
154
155   while (index < length) {
156     nextIndex = value.indexOf(C_NEWLINE, index);
157     startIndex = index;
158     prefixed = false;
159     indented = false;
160
161     if (nextIndex === -1) {
162       nextIndex = length;
163     }
164
165     end = index + TAB_SIZE;
166     size = 0;
167
168     while (index < length) {
169       character = value.charAt(index);
170
171       if (character === C_TAB) {
172         size += TAB_SIZE - (size % TAB_SIZE);
173       } else if (character === C_SPACE) {
174         size++;
175       } else {
176         break;
177       }
178
179       index++;
180     }
181
182     if (size >= TAB_SIZE) {
183       indented = true;
184     }
185
186     if (item && size >= item.indent) {
187       indented = true;
188     }
189
190     character = value.charAt(index);
191     currentMarker = null;
192
193     if (!indented) {
194       if (LIST_UNORDERED_MARKERS[character] === true) {
195         currentMarker = character;
196         index++;
197         size++;
198       } else {
199         queue = '';
200
201         while (index < length) {
202           character = value.charAt(index);
203
204           if (!decimal(character)) {
205             break;
206           }
207
208           queue += character;
209           index++;
210         }
211
212         character = value.charAt(index);
213         index++;
214
215         if (queue && markers[character] === true) {
216           currentMarker = character;
217           size += queue.length + 1;
218         }
219       }
220
221       if (currentMarker) {
222         character = value.charAt(index);
223
224         if (character === C_TAB) {
225           size += TAB_SIZE - (size % TAB_SIZE);
226           index++;
227         } else if (character === C_SPACE) {
228           end = index + TAB_SIZE;
229
230           while (index < end) {
231             if (value.charAt(index) !== C_SPACE) {
232               break;
233             }
234
235             index++;
236             size++;
237           }
238
239           if (index === end && value.charAt(index) === C_SPACE) {
240             index -= TAB_SIZE - 1;
241             size -= TAB_SIZE - 1;
242           }
243         } else if (character !== C_NEWLINE && character !== '') {
244           currentMarker = null;
245         }
246       }
247     }
248
249     if (currentMarker) {
250       if (!pedantic && marker !== currentMarker) {
251         break;
252       }
253
254       prefixed = true;
255     } else {
256       if (!commonmark && !indented && value.charAt(startIndex) === C_SPACE) {
257         indented = true;
258       } else if (commonmark && item) {
259         indented = size >= item.indent || size > TAB_SIZE;
260       }
261
262       prefixed = false;
263       index = startIndex;
264     }
265
266     line = value.slice(startIndex, nextIndex);
267     content = startIndex === index ? line : value.slice(index, nextIndex);
268
269     if (
270       currentMarker === C_ASTERISK ||
271       currentMarker === C_UNDERSCORE ||
272       currentMarker === C_DASH
273     ) {
274       if (tokenizers.thematicBreak.call(self, eat, line, true)) {
275         break;
276       }
277     }
278
279     prevEmpty = empty;
280     empty = !trim(content).length;
281
282     if (indented && item) {
283       item.value = item.value.concat(emptyLines, line);
284       allLines = allLines.concat(emptyLines, line);
285       emptyLines = [];
286     } else if (prefixed) {
287       if (emptyLines.length !== 0) {
288         item.value.push('');
289         item.trail = emptyLines.concat();
290       }
291
292       item = {
293         value: [line],
294         indent: size,
295         trail: []
296       };
297
298       items.push(item);
299       allLines = allLines.concat(emptyLines, line);
300       emptyLines = [];
301     } else if (empty) {
302       if (prevEmpty) {
303         break;
304       }
305
306       emptyLines.push(line);
307     } else {
308       if (prevEmpty) {
309         break;
310       }
311
312       if (interrupt(interuptors, tokenizers, self, [eat, line, true])) {
313         break;
314       }
315
316       item.value = item.value.concat(emptyLines, line);
317       allLines = allLines.concat(emptyLines, line);
318       emptyLines = [];
319     }
320
321     index = nextIndex + 1;
322   }
323
324   node = eat(allLines.join(C_NEWLINE)).reset({
325     type: 'list',
326     ordered: ordered,
327     start: start,
328     loose: null,
329     children: []
330   });
331
332   enterTop = self.enterList();
333   exitBlockquote = self.enterBlock();
334   isLoose = false;
335   index = -1;
336   length = items.length;
337
338   while (++index < length) {
339     item = items[index].value.join(C_NEWLINE);
340     now = eat.now();
341
342     item = eat(item)(listItem(self, item, now), node);
343
344     if (item.loose) {
345       isLoose = true;
346     }
347
348     item = items[index].trail.join(C_NEWLINE);
349
350     if (index !== length - 1) {
351       item += C_NEWLINE;
352     }
353
354     eat(item);
355   }
356
357   enterTop();
358   exitBlockquote();
359
360   node.loose = isLoose;
361
362   return node;
363 }
364
365 function listItem(ctx, value, position) {
366   var offsets = ctx.offset;
367   var fn = ctx.options.pedantic ? pedanticListItem : normalListItem;
368   var checked = null;
369   var task;
370   var indent;
371
372   value = fn.apply(null, arguments);
373
374   if (ctx.options.gfm) {
375     task = value.match(EXPRESSION_TASK_ITEM);
376
377     if (task) {
378       indent = task[0].length;
379       checked = task[1].toLowerCase() === C_X_LOWER;
380       offsets[position.line] += indent;
381       value = value.slice(indent);
382     }
383   }
384
385   return {
386     type: 'listItem',
387     loose: EXPRESSION_LOOSE_LIST_ITEM.test(value) ||
388       value.charAt(value.length - 1) === C_NEWLINE,
389     checked: checked,
390     children: ctx.tokenizeBlock(value, position)
391   };
392 }
393
394 /* Create a list-item using overly simple mechanics. */
395 function pedanticListItem(ctx, value, position) {
396   var offsets = ctx.offset;
397   var line = position.line;
398
399   /* Remove the list-item’s bullet. */
400   value = value.replace(EXPRESSION_PEDANTIC_BULLET, replacer);
401
402   /* The initial line was also matched by the below, so
403    * we reset the `line`. */
404   line = position.line;
405
406   return value.replace(EXPRESSION_INITIAL_INDENT, replacer);
407
408   /* A simple replacer which removed all matches,
409    * and adds their length to `offset`. */
410   function replacer($0) {
411     offsets[line] = (offsets[line] || 0) + $0.length;
412     line++;
413
414     return '';
415   }
416 }
417
418 /* Create a list-item using sane mechanics. */
419 function normalListItem(ctx, value, position) {
420   var offsets = ctx.offset;
421   var line = position.line;
422   var max;
423   var bullet;
424   var rest;
425   var lines;
426   var trimmedLines;
427   var index;
428   var length;
429
430   /* Remove the list-item’s bullet. */
431   value = value.replace(EXPRESSION_BULLET, replacer);
432
433   lines = value.split(C_NEWLINE);
434
435   trimmedLines = removeIndent(value, getIndent(max).indent).split(C_NEWLINE);
436
437   /* We replaced the initial bullet with something
438    * else above, which was used to trick
439    * `removeIndentation` into removing some more
440    * characters when possible.  However, that could
441    * result in the initial line to be stripped more
442    * than it should be. */
443   trimmedLines[0] = rest;
444
445   offsets[line] = (offsets[line] || 0) + bullet.length;
446   line++;
447
448   index = 0;
449   length = lines.length;
450
451   while (++index < length) {
452     offsets[line] = (offsets[line] || 0) +
453       lines[index].length - trimmedLines[index].length;
454     line++;
455   }
456
457   return trimmedLines.join(C_NEWLINE);
458
459   function replacer($0, $1, $2, $3, $4) {
460     bullet = $1 + $2 + $3;
461     rest = $4;
462
463     /* Make sure that the first nine numbered list items
464      * can indent with an extra space.  That is, when
465      * the bullet did not receive an extra final space. */
466     if (Number($2) < 10 && bullet.length % 2 === 1) {
467       $2 = C_SPACE + $2;
468     }
469
470     max = $1 + repeat(C_SPACE, $2.length) + $3;
471
472     return max + rest;
473   }
474 }