.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / remark-parse / lib / tokenize / link.js
1 'use strict';
2
3 var whitespace = require('is-whitespace-character');
4 var locate = require('../locate/link');
5
6 module.exports = link;
7 link.locator = locate;
8
9 var own = {}.hasOwnProperty;
10
11 var C_BACKSLASH = '\\';
12 var C_BRACKET_OPEN = '[';
13 var C_BRACKET_CLOSE = ']';
14 var C_PAREN_OPEN = '(';
15 var C_PAREN_CLOSE = ')';
16 var C_LT = '<';
17 var C_GT = '>';
18 var C_TICK = '`';
19 var C_DOUBLE_QUOTE = '"';
20 var C_SINGLE_QUOTE = '\'';
21
22 /* Map of characters, which can be used to mark link
23  * and image titles. */
24 var LINK_MARKERS = {};
25
26 LINK_MARKERS[C_DOUBLE_QUOTE] = C_DOUBLE_QUOTE;
27 LINK_MARKERS[C_SINGLE_QUOTE] = C_SINGLE_QUOTE;
28
29 /* Map of characters, which can be used to mark link
30  * and image titles in commonmark-mode. */
31 var COMMONMARK_LINK_MARKERS = {};
32
33 COMMONMARK_LINK_MARKERS[C_DOUBLE_QUOTE] = C_DOUBLE_QUOTE;
34 COMMONMARK_LINK_MARKERS[C_SINGLE_QUOTE] = C_SINGLE_QUOTE;
35 COMMONMARK_LINK_MARKERS[C_PAREN_OPEN] = C_PAREN_CLOSE;
36
37 function link(eat, value, silent) {
38   var self = this;
39   var subvalue = '';
40   var index = 0;
41   var character = value.charAt(0);
42   var pedantic = self.options.pedantic;
43   var commonmark = self.options.commonmark;
44   var gfm = self.options.gfm;
45   var closed;
46   var count;
47   var opening;
48   var beforeURL;
49   var beforeTitle;
50   var subqueue;
51   var hasMarker;
52   var markers;
53   var isImage;
54   var content;
55   var marker;
56   var length;
57   var title;
58   var depth;
59   var queue;
60   var url;
61   var now;
62   var exit;
63   var node;
64
65   /* Detect whether this is an image. */
66   if (character === '!') {
67     isImage = true;
68     subvalue = character;
69     character = value.charAt(++index);
70   }
71
72   /* Eat the opening. */
73   if (character !== C_BRACKET_OPEN) {
74     return;
75   }
76
77   /* Exit when this is a link and we’re already inside
78    * a link. */
79   if (!isImage && self.inLink) {
80     return;
81   }
82
83   subvalue += character;
84   queue = '';
85   index++;
86
87   /* Eat the content. */
88   length = value.length;
89   now = eat.now();
90   depth = 0;
91
92   now.column += index;
93   now.offset += index;
94
95   while (index < length) {
96     character = value.charAt(index);
97     subqueue = character;
98
99     if (character === C_TICK) {
100       /* Inline-code in link content. */
101       count = 1;
102
103       while (value.charAt(index + 1) === C_TICK) {
104         subqueue += character;
105         index++;
106         count++;
107       }
108
109       if (!opening) {
110         opening = count;
111       } else if (count >= opening) {
112         opening = 0;
113       }
114     } else if (character === C_BACKSLASH) {
115       /* Allow brackets to be escaped. */
116       index++;
117       subqueue += value.charAt(index);
118     /* In GFM mode, brackets in code still count.
119      * In all other modes, they don’t.  This empty
120      * block prevents the next statements are
121      * entered. */
122     } else if ((!opening || gfm) && character === C_BRACKET_OPEN) {
123       depth++;
124     } else if ((!opening || gfm) && character === C_BRACKET_CLOSE) {
125       if (depth) {
126         depth--;
127       } else {
128         /* Allow white-space between content and
129          * url in GFM mode. */
130         if (!pedantic) {
131           while (index < length) {
132             character = value.charAt(index + 1);
133
134             if (!whitespace(character)) {
135               break;
136             }
137
138             subqueue += character;
139             index++;
140           }
141         }
142
143         if (value.charAt(index + 1) !== C_PAREN_OPEN) {
144           return;
145         }
146
147         subqueue += C_PAREN_OPEN;
148         closed = true;
149         index++;
150
151         break;
152       }
153     }
154
155     queue += subqueue;
156     subqueue = '';
157     index++;
158   }
159
160   /* Eat the content closing. */
161   if (!closed) {
162     return;
163   }
164
165   content = queue;
166   subvalue += queue + subqueue;
167   index++;
168
169   /* Eat white-space. */
170   while (index < length) {
171     character = value.charAt(index);
172
173     if (!whitespace(character)) {
174       break;
175     }
176
177     subvalue += character;
178     index++;
179   }
180
181   /* Eat the URL. */
182   character = value.charAt(index);
183   markers = commonmark ? COMMONMARK_LINK_MARKERS : LINK_MARKERS;
184   queue = '';
185   beforeURL = subvalue;
186
187   if (character === C_LT) {
188     index++;
189     beforeURL += C_LT;
190
191     while (index < length) {
192       character = value.charAt(index);
193
194       if (character === C_GT) {
195         break;
196       }
197
198       if (commonmark && character === '\n') {
199         return;
200       }
201
202       queue += character;
203       index++;
204     }
205
206     if (value.charAt(index) !== C_GT) {
207       return;
208     }
209
210     subvalue += C_LT + queue + C_GT;
211     url = queue;
212     index++;
213   } else {
214     character = null;
215     subqueue = '';
216
217     while (index < length) {
218       character = value.charAt(index);
219
220       if (subqueue && own.call(markers, character)) {
221         break;
222       }
223
224       if (whitespace(character)) {
225         if (!pedantic) {
226           break;
227         }
228
229         subqueue += character;
230       } else {
231         if (character === C_PAREN_OPEN) {
232           depth++;
233         } else if (character === C_PAREN_CLOSE) {
234           if (depth === 0) {
235             break;
236           }
237
238           depth--;
239         }
240
241         queue += subqueue;
242         subqueue = '';
243
244         if (character === C_BACKSLASH) {
245           queue += C_BACKSLASH;
246           character = value.charAt(++index);
247         }
248
249         queue += character;
250       }
251
252       index++;
253     }
254
255     subvalue += queue;
256     url = queue;
257     index = subvalue.length;
258   }
259
260   /* Eat white-space. */
261   queue = '';
262
263   while (index < length) {
264     character = value.charAt(index);
265
266     if (!whitespace(character)) {
267       break;
268     }
269
270     queue += character;
271     index++;
272   }
273
274   character = value.charAt(index);
275   subvalue += queue;
276
277   /* Eat the title. */
278   if (queue && own.call(markers, character)) {
279     index++;
280     subvalue += character;
281     queue = '';
282     marker = markers[character];
283     beforeTitle = subvalue;
284
285     /* In commonmark-mode, things are pretty easy: the
286      * marker cannot occur inside the title.
287      *
288      * Non-commonmark does, however, support nested
289      * delimiters. */
290     if (commonmark) {
291       while (index < length) {
292         character = value.charAt(index);
293
294         if (character === marker) {
295           break;
296         }
297
298         if (character === C_BACKSLASH) {
299           queue += C_BACKSLASH;
300           character = value.charAt(++index);
301         }
302
303         index++;
304         queue += character;
305       }
306
307       character = value.charAt(index);
308
309       if (character !== marker) {
310         return;
311       }
312
313       title = queue;
314       subvalue += queue + character;
315       index++;
316
317       while (index < length) {
318         character = value.charAt(index);
319
320         if (!whitespace(character)) {
321           break;
322         }
323
324         subvalue += character;
325         index++;
326       }
327     } else {
328       subqueue = '';
329
330       while (index < length) {
331         character = value.charAt(index);
332
333         if (character === marker) {
334           if (hasMarker) {
335             queue += marker + subqueue;
336             subqueue = '';
337           }
338
339           hasMarker = true;
340         } else if (!hasMarker) {
341           queue += character;
342         } else if (character === C_PAREN_CLOSE) {
343           subvalue += queue + marker + subqueue;
344           title = queue;
345           break;
346         } else if (whitespace(character)) {
347           subqueue += character;
348         } else {
349           queue += marker + subqueue + character;
350           subqueue = '';
351           hasMarker = false;
352         }
353
354         index++;
355       }
356     }
357   }
358
359   if (value.charAt(index) !== C_PAREN_CLOSE) {
360     return;
361   }
362
363   /* istanbul ignore if - never used (yet) */
364   if (silent) {
365     return true;
366   }
367
368   subvalue += C_PAREN_CLOSE;
369
370   url = self.decode.raw(self.unescape(url), eat(beforeURL).test().end);
371
372   if (title) {
373     beforeTitle = eat(beforeTitle).test().end;
374     title = self.decode.raw(self.unescape(title), beforeTitle);
375   }
376
377   node = {
378     type: isImage ? 'image' : 'link',
379     title: title || null,
380     url: url
381   };
382
383   if (isImage) {
384     node.alt = self.decode.raw(self.unescape(content), now) || null;
385   } else {
386     exit = self.enterLink();
387     node.children = self.tokenizeInline(content, now);
388     exit();
389   }
390
391   return eat(subvalue)(node);
392 }