marked 7.0.0 → 7.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Lexer.ts DELETED
@@ -1,517 +0,0 @@
1
- import { _Tokenizer } from './Tokenizer.ts';
2
- import { _defaults } from './defaults.ts';
3
- import { block, inline } from './rules.ts';
4
- import type { Token, TokensList } from './Tokens.ts';
5
- import type { MarkedOptions, TokenizerExtension } from './MarkedOptions.ts';
6
- import type { Rules } from './rules.ts';
7
-
8
- /**
9
- * smartypants text replacement
10
- */
11
- function smartypants(text: string) {
12
- return text
13
- // em-dashes
14
- .replace(/---/g, '\u2014')
15
- // en-dashes
16
- .replace(/--/g, '\u2013')
17
- // opening singles
18
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
19
- // closing singles & apostrophes
20
- .replace(/'/g, '\u2019')
21
- // opening doubles
22
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
23
- // closing doubles
24
- .replace(/"/g, '\u201d')
25
- // ellipses
26
- .replace(/\.{3}/g, '\u2026');
27
- }
28
-
29
- /**
30
- * mangle email addresses
31
- */
32
- function mangle(text: string) {
33
- let out = '',
34
- i,
35
- ch;
36
-
37
- const l = text.length;
38
- for (i = 0; i < l; i++) {
39
- ch = text.charCodeAt(i);
40
- if (Math.random() > 0.5) {
41
- ch = 'x' + ch.toString(16);
42
- }
43
- out += '&#' + ch + ';';
44
- }
45
-
46
- return out;
47
- }
48
-
49
- /**
50
- * Block Lexer
51
- */
52
- export class _Lexer {
53
- tokens: TokensList;
54
- options: MarkedOptions;
55
- state: {
56
- inLink: boolean;
57
- inRawBlock: boolean;
58
- top: boolean;
59
- };
60
-
61
- private tokenizer: _Tokenizer;
62
- private inlineQueue: {src: string, tokens: Token[]}[];
63
-
64
- constructor(options?: MarkedOptions) {
65
- // TokenList cannot be created in one go
66
- // @ts-expect-error
67
- this.tokens = [];
68
- this.tokens.links = Object.create(null);
69
- this.options = options || _defaults;
70
- this.options.tokenizer = this.options.tokenizer || new _Tokenizer();
71
- this.tokenizer = this.options.tokenizer;
72
- this.tokenizer.options = this.options;
73
- this.tokenizer.lexer = this;
74
- this.inlineQueue = [];
75
- this.state = {
76
- inLink: false,
77
- inRawBlock: false,
78
- top: true
79
- };
80
-
81
- const rules = {
82
- block: block.normal,
83
- inline: inline.normal
84
- };
85
-
86
- if (this.options.pedantic) {
87
- rules.block = block.pedantic;
88
- rules.inline = inline.pedantic;
89
- } else if (this.options.gfm) {
90
- rules.block = block.gfm;
91
- if (this.options.breaks) {
92
- rules.inline = inline.breaks;
93
- } else {
94
- rules.inline = inline.gfm;
95
- }
96
- }
97
- this.tokenizer.rules = rules;
98
- }
99
-
100
- /**
101
- * Expose Rules
102
- */
103
- static get rules(): Rules {
104
- return {
105
- block,
106
- inline
107
- };
108
- }
109
-
110
- /**
111
- * Static Lex Method
112
- */
113
- static lex(src: string, options?: MarkedOptions) {
114
- const lexer = new _Lexer(options);
115
- return lexer.lex(src);
116
- }
117
-
118
- /**
119
- * Static Lex Inline Method
120
- */
121
- static lexInline(src: string, options?: MarkedOptions) {
122
- const lexer = new _Lexer(options);
123
- return lexer.inlineTokens(src);
124
- }
125
-
126
- /**
127
- * Preprocessing
128
- */
129
- lex(src: string) {
130
- src = src
131
- .replace(/\r\n|\r/g, '\n');
132
-
133
- this.blockTokens(src, this.tokens);
134
-
135
- let next;
136
- while (next = this.inlineQueue.shift()) {
137
- this.inlineTokens(next.src, next.tokens);
138
- }
139
-
140
- return this.tokens;
141
- }
142
-
143
- /**
144
- * Lexing
145
- */
146
- blockTokens(src: string, tokens?: Token[]): Token[];
147
- blockTokens(src: string, tokens?: TokensList): TokensList;
148
- blockTokens(src: string, tokens: Token[] = []) {
149
- if (this.options.pedantic) {
150
- src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
151
- } else {
152
- src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
153
- return leading + ' '.repeat(tabs.length);
154
- });
155
- }
156
-
157
- let token, lastToken, cutSrc, lastParagraphClipped;
158
-
159
- while (src) {
160
- if (this.options.extensions
161
- && this.options.extensions.block
162
- && this.options.extensions.block.some((extTokenizer: TokenizerExtension['tokenizer']) => {
163
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
164
- src = src.substring(token.raw.length);
165
- tokens.push(token);
166
- return true;
167
- }
168
- return false;
169
- })) {
170
- continue;
171
- }
172
-
173
- // newline
174
- if (token = this.tokenizer.space(src)) {
175
- src = src.substring(token.raw.length);
176
- if (token.raw.length === 1 && tokens.length > 0) {
177
- // if there's a single \n as a spacer, it's terminating the last line,
178
- // so move it there so that we don't get unecessary paragraph tags
179
- tokens[tokens.length - 1].raw += '\n';
180
- } else {
181
- tokens.push(token);
182
- }
183
- continue;
184
- }
185
-
186
- // code
187
- if (token = this.tokenizer.code(src)) {
188
- src = src.substring(token.raw.length);
189
- lastToken = tokens[tokens.length - 1];
190
- // An indented code block cannot interrupt a paragraph.
191
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
192
- lastToken.raw += '\n' + token.raw;
193
- lastToken.text += '\n' + token.text;
194
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
195
- } else {
196
- tokens.push(token);
197
- }
198
- continue;
199
- }
200
-
201
- // fences
202
- if (token = this.tokenizer.fences(src)) {
203
- src = src.substring(token.raw.length);
204
- tokens.push(token);
205
- continue;
206
- }
207
-
208
- // heading
209
- if (token = this.tokenizer.heading(src)) {
210
- src = src.substring(token.raw.length);
211
- tokens.push(token);
212
- continue;
213
- }
214
-
215
- // hr
216
- if (token = this.tokenizer.hr(src)) {
217
- src = src.substring(token.raw.length);
218
- tokens.push(token);
219
- continue;
220
- }
221
-
222
- // blockquote
223
- if (token = this.tokenizer.blockquote(src)) {
224
- src = src.substring(token.raw.length);
225
- tokens.push(token);
226
- continue;
227
- }
228
-
229
- // list
230
- if (token = this.tokenizer.list(src)) {
231
- src = src.substring(token.raw.length);
232
- tokens.push(token);
233
- continue;
234
- }
235
-
236
- // html
237
- if (token = this.tokenizer.html(src)) {
238
- src = src.substring(token.raw.length);
239
- tokens.push(token);
240
- continue;
241
- }
242
-
243
- // def
244
- if (token = this.tokenizer.def(src)) {
245
- src = src.substring(token.raw.length);
246
- lastToken = tokens[tokens.length - 1];
247
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
248
- lastToken.raw += '\n' + token.raw;
249
- lastToken.text += '\n' + token.raw;
250
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
251
- } else if (!this.tokens.links[token.tag]) {
252
- this.tokens.links[token.tag] = {
253
- href: token.href,
254
- title: token.title
255
- };
256
- }
257
- continue;
258
- }
259
-
260
- // table (gfm)
261
- if (token = this.tokenizer.table(src)) {
262
- src = src.substring(token.raw.length);
263
- tokens.push(token);
264
- continue;
265
- }
266
-
267
- // lheading
268
- if (token = this.tokenizer.lheading(src)) {
269
- src = src.substring(token.raw.length);
270
- tokens.push(token);
271
- continue;
272
- }
273
-
274
- // top-level paragraph
275
- // prevent paragraph consuming extensions by clipping 'src' to extension start
276
- cutSrc = src;
277
- if (this.options.extensions && this.options.extensions.startBlock) {
278
- let startIndex = Infinity;
279
- const tempSrc = src.slice(1);
280
- let tempStart;
281
- this.options.extensions.startBlock.forEach((getStartIndex) => {
282
- tempStart = getStartIndex.call({ lexer: this }, tempSrc);
283
- if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
284
- });
285
- if (startIndex < Infinity && startIndex >= 0) {
286
- cutSrc = src.substring(0, startIndex + 1);
287
- }
288
- }
289
- if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
290
- lastToken = tokens[tokens.length - 1];
291
- if (lastParagraphClipped && lastToken.type === 'paragraph') {
292
- lastToken.raw += '\n' + token.raw;
293
- lastToken.text += '\n' + token.text;
294
- this.inlineQueue.pop();
295
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
296
- } else {
297
- tokens.push(token);
298
- }
299
- lastParagraphClipped = (cutSrc.length !== src.length);
300
- src = src.substring(token.raw.length);
301
- continue;
302
- }
303
-
304
- // text
305
- if (token = this.tokenizer.text(src)) {
306
- src = src.substring(token.raw.length);
307
- lastToken = tokens[tokens.length - 1];
308
- if (lastToken && lastToken.type === 'text') {
309
- lastToken.raw += '\n' + token.raw;
310
- lastToken.text += '\n' + token.text;
311
- this.inlineQueue.pop();
312
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
313
- } else {
314
- tokens.push(token);
315
- }
316
- continue;
317
- }
318
-
319
- if (src) {
320
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
321
- if (this.options.silent) {
322
- console.error(errMsg);
323
- break;
324
- } else {
325
- throw new Error(errMsg);
326
- }
327
- }
328
- }
329
-
330
- this.state.top = true;
331
- return tokens;
332
- }
333
-
334
- inline(src: string, tokens: Token[] = []) {
335
- this.inlineQueue.push({ src, tokens });
336
- return tokens;
337
- }
338
-
339
- /**
340
- * Lexing/Compiling
341
- */
342
- inlineTokens(src: string, tokens: Token[] = []): Token[] {
343
- let token, lastToken, cutSrc;
344
-
345
- // String with links masked to avoid interference with em and strong
346
- let maskedSrc = src;
347
- let match;
348
- let keepPrevChar, prevChar;
349
-
350
- // Mask out reflinks
351
- if (this.tokens.links) {
352
- const links = Object.keys(this.tokens.links);
353
- if (links.length > 0) {
354
- while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
355
- if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
356
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
357
- }
358
- }
359
- }
360
- }
361
- // Mask out other blocks
362
- while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
363
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
364
- }
365
-
366
- // Mask out escaped characters
367
- while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
368
- maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
369
- }
370
-
371
- while (src) {
372
- if (!keepPrevChar) {
373
- prevChar = '';
374
- }
375
- keepPrevChar = false;
376
-
377
- // extensions
378
- if (this.options.extensions
379
- && this.options.extensions.inline
380
- && this.options.extensions.inline.some((extTokenizer) => {
381
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
382
- src = src.substring(token.raw.length);
383
- tokens.push(token);
384
- return true;
385
- }
386
- return false;
387
- })) {
388
- continue;
389
- }
390
-
391
- // escape
392
- if (token = this.tokenizer.escape(src)) {
393
- src = src.substring(token.raw.length);
394
- tokens.push(token);
395
- continue;
396
- }
397
-
398
- // tag
399
- if (token = this.tokenizer.tag(src)) {
400
- src = src.substring(token.raw.length);
401
- lastToken = tokens[tokens.length - 1];
402
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
403
- lastToken.raw += token.raw;
404
- lastToken.text += token.text;
405
- } else {
406
- tokens.push(token);
407
- }
408
- continue;
409
- }
410
-
411
- // link
412
- if (token = this.tokenizer.link(src)) {
413
- src = src.substring(token.raw.length);
414
- tokens.push(token);
415
- continue;
416
- }
417
-
418
- // reflink, nolink
419
- if (token = this.tokenizer.reflink(src, this.tokens.links)) {
420
- src = src.substring(token.raw.length);
421
- lastToken = tokens[tokens.length - 1];
422
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
423
- lastToken.raw += token.raw;
424
- lastToken.text += token.text;
425
- } else {
426
- tokens.push(token);
427
- }
428
- continue;
429
- }
430
-
431
- // em & strong
432
- if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
433
- src = src.substring(token.raw.length);
434
- tokens.push(token);
435
- continue;
436
- }
437
-
438
- // code
439
- if (token = this.tokenizer.codespan(src)) {
440
- src = src.substring(token.raw.length);
441
- tokens.push(token);
442
- continue;
443
- }
444
-
445
- // br
446
- if (token = this.tokenizer.br(src)) {
447
- src = src.substring(token.raw.length);
448
- tokens.push(token);
449
- continue;
450
- }
451
-
452
- // del (gfm)
453
- if (token = this.tokenizer.del(src)) {
454
- src = src.substring(token.raw.length);
455
- tokens.push(token);
456
- continue;
457
- }
458
-
459
- // autolink
460
- if (token = this.tokenizer.autolink(src, mangle)) {
461
- src = src.substring(token.raw.length);
462
- tokens.push(token);
463
- continue;
464
- }
465
-
466
- // url (gfm)
467
- if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
468
- src = src.substring(token.raw.length);
469
- tokens.push(token);
470
- continue;
471
- }
472
-
473
- // text
474
- // prevent inlineText consuming extensions by clipping 'src' to extension start
475
- cutSrc = src;
476
- if (this.options.extensions && this.options.extensions.startInline) {
477
- let startIndex = Infinity;
478
- const tempSrc = src.slice(1);
479
- let tempStart;
480
- this.options.extensions.startInline.forEach((getStartIndex) => {
481
- tempStart = getStartIndex.call({ lexer: this }, tempSrc);
482
- if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
483
- });
484
- if (startIndex < Infinity && startIndex >= 0) {
485
- cutSrc = src.substring(0, startIndex + 1);
486
- }
487
- }
488
- if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
489
- src = src.substring(token.raw.length);
490
- if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
491
- prevChar = token.raw.slice(-1);
492
- }
493
- keepPrevChar = true;
494
- lastToken = tokens[tokens.length - 1];
495
- if (lastToken && lastToken.type === 'text') {
496
- lastToken.raw += token.raw;
497
- lastToken.text += token.text;
498
- } else {
499
- tokens.push(token);
500
- }
501
- continue;
502
- }
503
-
504
- if (src) {
505
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
506
- if (this.options.silent) {
507
- console.error(errMsg);
508
- break;
509
- } else {
510
- throw new Error(errMsg);
511
- }
512
- }
513
- }
514
-
515
- return tokens;
516
- }
517
- }