.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / remark-parse / lib / tokenize / table.js
1 'use strict';
2
3 var whitespace = require('is-whitespace-character');
4
5 module.exports = table;
6
7 var C_BACKSLASH = '\\';
8 var C_TICK = '`';
9 var C_DASH = '-';
10 var C_PIPE = '|';
11 var C_COLON = ':';
12 var C_SPACE = ' ';
13 var C_NEWLINE = '\n';
14 var C_TAB = '\t';
15
16 var MIN_TABLE_COLUMNS = 1;
17 var MIN_TABLE_ROWS = 2;
18
19 var TABLE_ALIGN_LEFT = 'left';
20 var TABLE_ALIGN_CENTER = 'center';
21 var TABLE_ALIGN_RIGHT = 'right';
22 var TABLE_ALIGN_NONE = null;
23
24 function table(eat, value, silent) {
25   var self = this;
26   var index;
27   var alignments;
28   var alignment;
29   var subvalue;
30   var row;
31   var length;
32   var lines;
33   var queue;
34   var character;
35   var hasDash;
36   var align;
37   var cell;
38   var preamble;
39   var count;
40   var opening;
41   var now;
42   var position;
43   var lineCount;
44   var line;
45   var rows;
46   var table;
47   var lineIndex;
48   var pipeIndex;
49   var first;
50
51   /* Exit when not in gfm-mode. */
52   if (!self.options.gfm) {
53     return;
54   }
55
56   /* Get the rows.
57    * Detecting tables soon is hard, so there are some
58    * checks for performance here, such as the minimum
59    * number of rows, and allowed characters in the
60    * alignment row. */
61   index = 0;
62   lineCount = 0;
63   length = value.length + 1;
64   lines = [];
65
66   while (index < length) {
67     lineIndex = value.indexOf(C_NEWLINE, index);
68     pipeIndex = value.indexOf(C_PIPE, index + 1);
69
70     if (lineIndex === -1) {
71       lineIndex = value.length;
72     }
73
74     if (pipeIndex === -1 || pipeIndex > lineIndex) {
75       if (lineCount < MIN_TABLE_ROWS) {
76         return;
77       }
78
79       break;
80     }
81
82     lines.push(value.slice(index, lineIndex));
83     lineCount++;
84     index = lineIndex + 1;
85   }
86
87   /* Parse the alignment row. */
88   subvalue = lines.join(C_NEWLINE);
89   alignments = lines.splice(1, 1)[0] || [];
90   index = 0;
91   length = alignments.length;
92   lineCount--;
93   alignment = false;
94   align = [];
95
96   while (index < length) {
97     character = alignments.charAt(index);
98
99     if (character === C_PIPE) {
100       hasDash = null;
101
102       if (alignment === false) {
103         if (first === false) {
104           return;
105         }
106       } else {
107         align.push(alignment);
108         alignment = false;
109       }
110
111       first = false;
112     } else if (character === C_DASH) {
113       hasDash = true;
114       alignment = alignment || TABLE_ALIGN_NONE;
115     } else if (character === C_COLON) {
116       if (alignment === TABLE_ALIGN_LEFT) {
117         alignment = TABLE_ALIGN_CENTER;
118       } else if (hasDash && alignment === TABLE_ALIGN_NONE) {
119         alignment = TABLE_ALIGN_RIGHT;
120       } else {
121         alignment = TABLE_ALIGN_LEFT;
122       }
123     } else if (!whitespace(character)) {
124       return;
125     }
126
127     index++;
128   }
129
130   if (alignment !== false) {
131     align.push(alignment);
132   }
133
134   /* Exit when without enough columns. */
135   if (align.length < MIN_TABLE_COLUMNS) {
136     return;
137   }
138
139   /* istanbul ignore if - never used (yet) */
140   if (silent) {
141     return true;
142   }
143
144   /* Parse the rows. */
145   position = -1;
146   rows = [];
147
148   table = eat(subvalue).reset({
149     type: 'table',
150     align: align,
151     children: rows
152   });
153
154   while (++position < lineCount) {
155     line = lines[position];
156     row = {type: 'tableRow', children: []};
157
158     /* Eat a newline character when this is not the
159      * first row. */
160     if (position) {
161       eat(C_NEWLINE);
162     }
163
164     /* Eat the row. */
165     eat(line).reset(row, table);
166
167     length = line.length + 1;
168     index = 0;
169     queue = '';
170     cell = '';
171     preamble = true;
172     count = null;
173     opening = null;
174
175     while (index < length) {
176       character = line.charAt(index);
177
178       if (character === C_TAB || character === C_SPACE) {
179         if (cell) {
180           queue += character;
181         } else {
182           eat(character);
183         }
184
185         index++;
186         continue;
187       }
188
189       if (character === '' || character === C_PIPE) {
190         if (preamble) {
191           eat(character);
192         } else {
193           if (character && opening) {
194             queue += character;
195             index++;
196             continue;
197           }
198
199           if ((cell || character) && !preamble) {
200             subvalue = cell;
201
202             if (queue.length > 1) {
203               if (character) {
204                 subvalue += queue.slice(0, queue.length - 1);
205                 queue = queue.charAt(queue.length - 1);
206               } else {
207                 subvalue += queue;
208                 queue = '';
209               }
210             }
211
212             now = eat.now();
213
214             eat(subvalue)({
215               type: 'tableCell',
216               children: self.tokenizeInline(cell, now)
217             }, row);
218           }
219
220           eat(queue + character);
221
222           queue = '';
223           cell = '';
224         }
225       } else {
226         if (queue) {
227           cell += queue;
228           queue = '';
229         }
230
231         cell += character;
232
233         if (character === C_BACKSLASH && index !== length - 2) {
234           cell += line.charAt(index + 1);
235           index++;
236         }
237
238         if (character === C_TICK) {
239           count = 1;
240
241           while (line.charAt(index + 1) === character) {
242             cell += character;
243             index++;
244             count++;
245           }
246
247           if (!opening) {
248             opening = count;
249           } else if (count >= opening) {
250             opening = 0;
251           }
252         }
253       }
254
255       preamble = false;
256       index++;
257     }
258
259     /* Eat the alignment row. */
260     if (!position) {
261       eat(C_NEWLINE + alignments);
262     }
263   }
264
265   return table;
266 }