marked 4.0.2 → 4.0.6
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/README.md +7 -0
- package/bin/marked.js +11 -5
- package/lib/marked.cjs +43 -45
- package/lib/marked.esm.js +48 -40
- package/lib/marked.umd.js +43 -45
- package/marked.min.js +1 -1
- package/package.json +12 -12
- package/src/Tokenizer.js +35 -39
- package/src/rules.js +13 -1
- package/lib/marked.js +0 -2914
package/README.md
CHANGED
|
@@ -47,7 +47,9 @@ Also read about:
|
|
|
47
47
|
|
|
48
48
|
**CLI**
|
|
49
49
|
|
|
50
|
+
|
|
50
51
|
``` bash
|
|
52
|
+
# Example with stdin input
|
|
51
53
|
$ marked -o hello.html
|
|
52
54
|
hello world
|
|
53
55
|
^D
|
|
@@ -55,6 +57,11 @@ $ cat hello.html
|
|
|
55
57
|
<p>hello world</p>
|
|
56
58
|
```
|
|
57
59
|
|
|
60
|
+
```bash
|
|
61
|
+
# Print all options
|
|
62
|
+
$ marked --help
|
|
63
|
+
```
|
|
64
|
+
|
|
58
65
|
**Browser**
|
|
59
66
|
|
|
60
67
|
```html
|
package/bin/marked.js
CHANGED
|
@@ -27,10 +27,16 @@ async function help() {
|
|
|
27
27
|
const { dirname, resolve } = await import('path');
|
|
28
28
|
const { fileURLToPath } = await import('url');
|
|
29
29
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
const helpText = await readFile(resolve(__dirname, '../man/marked.1.txt'), 'utf8');
|
|
31
|
+
|
|
32
|
+
// eslint-disable-next-line promise/param-names
|
|
33
|
+
await new Promise(res => {
|
|
34
|
+
spawn('man', [resolve(__dirname, '../man/marked.1')], options)
|
|
35
|
+
.on('error', () => {
|
|
36
|
+
console.log(helpText);
|
|
37
|
+
})
|
|
38
|
+
.on('close', res);
|
|
39
|
+
});
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
async function version() {
|
|
@@ -149,7 +155,7 @@ async function main(argv) {
|
|
|
149
155
|
: marked(data, options);
|
|
150
156
|
|
|
151
157
|
if (output) {
|
|
152
|
-
return await writeFile(output,
|
|
158
|
+
return await writeFile(output, html);
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
process.stdout.write(html + '\n');
|
package/lib/marked.cjs
CHANGED
|
@@ -533,7 +533,7 @@ var Tokenizer = /*#__PURE__*/function () {
|
|
|
533
533
|
var cap = this.rules.block.list.exec(src);
|
|
534
534
|
|
|
535
535
|
if (cap) {
|
|
536
|
-
var raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line,
|
|
536
|
+
var raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line, nextLine, rawLine, itemContents;
|
|
537
537
|
var bull = cap[1].trim();
|
|
538
538
|
var isordered = bull.length > 1;
|
|
539
539
|
var list = {
|
|
@@ -551,83 +551,77 @@ var Tokenizer = /*#__PURE__*/function () {
|
|
|
551
551
|
} // Get next list item
|
|
552
552
|
|
|
553
553
|
|
|
554
|
-
var itemRegex = new RegExp("^( {0,3}" + bull + ")((?: [^\\n]
|
|
554
|
+
var itemRegex = new RegExp("^( {0,3}" + bull + ")((?: [^\\n]*)?(?:\\n|$))"); // Check if current bullet point can start a new List Item
|
|
555
555
|
|
|
556
556
|
while (src) {
|
|
557
|
-
if (
|
|
558
|
-
// End list if we encounter an HR (possibly move into itemRegex?)
|
|
557
|
+
if (!(cap = itemRegex.exec(src))) {
|
|
559
558
|
break;
|
|
560
559
|
}
|
|
561
560
|
|
|
562
|
-
if (
|
|
561
|
+
if (this.rules.block.hr.test(src)) {
|
|
562
|
+
// End list if bullet was actually HR (possibly move into itemRegex?)
|
|
563
563
|
break;
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
|
|
566
|
+
raw = cap[0];
|
|
567
|
+
src = src.substring(raw.length);
|
|
568
|
+
line = cap[2].split('\n', 1)[0];
|
|
569
|
+
nextLine = src.split('\n', 1)[0];
|
|
567
570
|
|
|
568
571
|
if (this.options.pedantic) {
|
|
569
572
|
indent = 2;
|
|
570
|
-
itemContents =
|
|
573
|
+
itemContents = line.trimLeft();
|
|
571
574
|
} else {
|
|
572
575
|
indent = cap[2].search(/[^ ]/); // Find first non-space char
|
|
573
576
|
|
|
574
|
-
indent =
|
|
577
|
+
indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
|
|
575
578
|
|
|
576
|
-
itemContents =
|
|
579
|
+
itemContents = line.slice(indent);
|
|
580
|
+
indent += cap[1].length;
|
|
577
581
|
}
|
|
578
582
|
|
|
579
583
|
blankLine = false;
|
|
580
|
-
raw = cap[0];
|
|
581
584
|
|
|
582
|
-
if (!
|
|
583
|
-
//
|
|
584
|
-
raw
|
|
585
|
+
if (!line && /^ *$/.test(nextLine)) {
|
|
586
|
+
// Items begin with at most one blank line
|
|
587
|
+
raw += nextLine + '\n';
|
|
588
|
+
src = src.substring(nextLine.length + 1);
|
|
585
589
|
list.loose = true;
|
|
586
|
-
lines = [];
|
|
587
590
|
}
|
|
588
591
|
|
|
589
|
-
var nextBulletRegex = new RegExp("^ {0," + Math.min(3, indent - 1) + "}(?:[*+-]|\\d{1,9}[.)])");
|
|
592
|
+
var nextBulletRegex = new RegExp("^ {0," + Math.min(3, indent - 1) + "}(?:[*+-]|\\d{1,9}[.)])"); // Check if following lines should be included in List Item
|
|
590
593
|
|
|
591
|
-
|
|
592
|
-
|
|
594
|
+
while (src && !list.loose) {
|
|
595
|
+
rawLine = src.split('\n', 1)[0];
|
|
596
|
+
line = rawLine; // Re-align to follow commonmark nesting rules
|
|
593
597
|
|
|
594
598
|
if (this.options.pedantic) {
|
|
595
|
-
// Re-align to follow commonmark nesting rules
|
|
596
599
|
line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' ');
|
|
597
600
|
} // End list item if found start of new bullet
|
|
598
601
|
|
|
599
602
|
|
|
600
603
|
if (nextBulletRegex.test(line)) {
|
|
601
|
-
raw = cap[1] + lines.slice(0, i).join('\n') + '\n';
|
|
602
604
|
break;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if (!blankLine) {
|
|
607
|
-
if (!line.trim()) {
|
|
608
|
-
// Check if current line is empty
|
|
609
|
-
blankLine = true;
|
|
610
|
-
} // Dedent if possible
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
if (line.search(/[^ ]/) >= indent) {
|
|
614
|
-
itemContents += '\n' + line.slice(indent);
|
|
615
|
-
} else {
|
|
616
|
-
itemContents += '\n' + line;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
continue;
|
|
620
|
-
} // Dedent this line
|
|
621
|
-
|
|
605
|
+
}
|
|
622
606
|
|
|
623
607
|
if (line.search(/[^ ]/) >= indent || !line.trim()) {
|
|
608
|
+
// Dedent if possible
|
|
624
609
|
itemContents += '\n' + line.slice(indent);
|
|
625
|
-
|
|
610
|
+
} else if (!blankLine) {
|
|
611
|
+
// Until blank line, item doesn't need indentation
|
|
612
|
+
itemContents += '\n' + line;
|
|
626
613
|
} else {
|
|
627
|
-
//
|
|
628
|
-
raw = cap[1] + lines.slice(0, i).join('\n') + '\n';
|
|
614
|
+
// Otherwise, improper indentation ends this item
|
|
629
615
|
break;
|
|
630
616
|
}
|
|
617
|
+
|
|
618
|
+
if (!blankLine && !line.trim()) {
|
|
619
|
+
// Check if current line is blank
|
|
620
|
+
blankLine = true;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
raw += rawLine + '\n';
|
|
624
|
+
src = src.substring(rawLine.length + 1);
|
|
631
625
|
}
|
|
632
626
|
|
|
633
627
|
if (!list.loose) {
|
|
@@ -658,7 +652,6 @@ var Tokenizer = /*#__PURE__*/function () {
|
|
|
658
652
|
text: itemContents
|
|
659
653
|
});
|
|
660
654
|
list.raw += raw;
|
|
661
|
-
src = src.slice(raw.length);
|
|
662
655
|
} // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
|
|
663
656
|
|
|
664
657
|
|
|
@@ -671,7 +664,7 @@ var Tokenizer = /*#__PURE__*/function () {
|
|
|
671
664
|
this.lexer.state.top = false;
|
|
672
665
|
list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
|
|
673
666
|
|
|
674
|
-
if (list.items[i].tokens.some(function (t) {
|
|
667
|
+
if (!list.loose && list.items[i].tokens.some(function (t) {
|
|
675
668
|
return t.type === 'space';
|
|
676
669
|
})) {
|
|
677
670
|
list.loose = true;
|
|
@@ -1190,7 +1183,7 @@ var block = {
|
|
|
1190
1183
|
lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
|
|
1191
1184
|
// regex template, placeholders will be replaced according to different paragraph
|
|
1192
1185
|
// interruption rules of commonmark and the original markdown spec:
|
|
1193
|
-
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
|
|
1186
|
+
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
|
|
1194
1187
|
text: /^[^\n]+/
|
|
1195
1188
|
};
|
|
1196
1189
|
block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
|
|
@@ -1203,7 +1196,7 @@ block._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + '|c
|
|
|
1203
1196
|
block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
|
|
1204
1197
|
block.html = edit(block.html, 'i').replace('comment', block._comment).replace('tag', block._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
|
|
1205
1198
|
block.paragraph = edit(block._paragraph).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
1206
|
-
.replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1199
|
+
.replace('|table', '').replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1207
1200
|
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
|
|
1208
1201
|
.getRegex();
|
|
1209
1202
|
block.blockquote = edit(block.blockquote).replace('paragraph', block.paragraph).getRegex();
|
|
@@ -1225,6 +1218,11 @@ block.gfm = merge({}, block.normal, {
|
|
|
1225
1218
|
block.gfm.table = edit(block.gfm.table).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1226
1219
|
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
|
|
1227
1220
|
.getRegex();
|
|
1221
|
+
block.gfm.paragraph = edit(block._paragraph).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
1222
|
+
.replace('table', block.gfm.table) // interrupt paragraphs with table
|
|
1223
|
+
.replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1224
|
+
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
|
|
1225
|
+
.getRegex();
|
|
1228
1226
|
/**
|
|
1229
1227
|
* Pedantic grammar (original John Gruber's loose markdown specification)
|
|
1230
1228
|
*/
|
package/lib/marked.esm.js
CHANGED
|
@@ -452,7 +452,7 @@ class Tokenizer {
|
|
|
452
452
|
let cap = this.rules.block.list.exec(src);
|
|
453
453
|
if (cap) {
|
|
454
454
|
let raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine,
|
|
455
|
-
line,
|
|
455
|
+
line, nextLine, rawLine, itemContents;
|
|
456
456
|
|
|
457
457
|
let bull = cap[1].trim();
|
|
458
458
|
const isordered = bull.length > 1;
|
|
@@ -473,76 +473,73 @@ class Tokenizer {
|
|
|
473
473
|
}
|
|
474
474
|
|
|
475
475
|
// Get next list item
|
|
476
|
-
const itemRegex = new RegExp(`^( {0,3}${bull})((?: [^\\n]
|
|
476
|
+
const itemRegex = new RegExp(`^( {0,3}${bull})((?: [^\\n]*)?(?:\\n|$))`);
|
|
477
477
|
|
|
478
|
-
//
|
|
478
|
+
// Check if current bullet point can start a new List Item
|
|
479
479
|
while (src) {
|
|
480
|
-
if (
|
|
480
|
+
if (!(cap = itemRegex.exec(src))) {
|
|
481
481
|
break;
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
if (
|
|
484
|
+
if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)
|
|
485
485
|
break;
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
-
|
|
488
|
+
raw = cap[0];
|
|
489
|
+
src = src.substring(raw.length);
|
|
490
|
+
|
|
491
|
+
line = cap[2].split('\n', 1)[0];
|
|
492
|
+
nextLine = src.split('\n', 1)[0];
|
|
489
493
|
|
|
490
494
|
if (this.options.pedantic) {
|
|
491
495
|
indent = 2;
|
|
492
|
-
itemContents =
|
|
496
|
+
itemContents = line.trimLeft();
|
|
493
497
|
} else {
|
|
494
498
|
indent = cap[2].search(/[^ ]/); // Find first non-space char
|
|
495
|
-
indent =
|
|
496
|
-
itemContents =
|
|
499
|
+
indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
|
|
500
|
+
itemContents = line.slice(indent);
|
|
501
|
+
indent += cap[1].length;
|
|
497
502
|
}
|
|
498
503
|
|
|
499
504
|
blankLine = false;
|
|
500
|
-
raw = cap[0];
|
|
501
505
|
|
|
502
|
-
if (!
|
|
503
|
-
raw
|
|
506
|
+
if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line
|
|
507
|
+
raw += nextLine + '\n';
|
|
508
|
+
src = src.substring(nextLine.length + 1);
|
|
504
509
|
list.loose = true;
|
|
505
|
-
lines = [];
|
|
506
510
|
}
|
|
507
511
|
|
|
508
512
|
const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])`);
|
|
509
513
|
|
|
510
|
-
|
|
511
|
-
|
|
514
|
+
// Check if following lines should be included in List Item
|
|
515
|
+
while (src && !list.loose) {
|
|
516
|
+
rawLine = src.split('\n', 1)[0];
|
|
517
|
+
line = rawLine;
|
|
512
518
|
|
|
513
|
-
|
|
519
|
+
// Re-align to follow commonmark nesting rules
|
|
520
|
+
if (this.options.pedantic) {
|
|
514
521
|
line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' ');
|
|
515
522
|
}
|
|
516
523
|
|
|
517
524
|
// End list item if found start of new bullet
|
|
518
525
|
if (nextBulletRegex.test(line)) {
|
|
519
|
-
raw = cap[1] + lines.slice(0, i).join('\n') + '\n';
|
|
520
526
|
break;
|
|
521
527
|
}
|
|
522
528
|
|
|
523
|
-
|
|
524
|
-
if (!blankLine) {
|
|
525
|
-
if (!line.trim()) { // Check if current line is empty
|
|
526
|
-
blankLine = true;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// Dedent if possible
|
|
530
|
-
if (line.search(/[^ ]/) >= indent) {
|
|
531
|
-
itemContents += '\n' + line.slice(indent);
|
|
532
|
-
} else {
|
|
533
|
-
itemContents += '\n' + line;
|
|
534
|
-
}
|
|
535
|
-
continue;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Dedent this line
|
|
539
|
-
if (line.search(/[^ ]/) >= indent || !line.trim()) {
|
|
529
|
+
if (line.search(/[^ ]/) >= indent || !line.trim()) { // Dedent if possible
|
|
540
530
|
itemContents += '\n' + line.slice(indent);
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
531
|
+
} else if (!blankLine) { // Until blank line, item doesn't need indentation
|
|
532
|
+
itemContents += '\n' + line;
|
|
533
|
+
} else { // Otherwise, improper indentation ends this item
|
|
544
534
|
break;
|
|
545
535
|
}
|
|
536
|
+
|
|
537
|
+
if (!blankLine && !line.trim()) { // Check if current line is blank
|
|
538
|
+
blankLine = true;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
raw += rawLine + '\n';
|
|
542
|
+
src = src.substring(rawLine.length + 1);
|
|
546
543
|
}
|
|
547
544
|
|
|
548
545
|
if (!list.loose) {
|
|
@@ -573,7 +570,6 @@ class Tokenizer {
|
|
|
573
570
|
});
|
|
574
571
|
|
|
575
572
|
list.raw += raw;
|
|
576
|
-
src = src.slice(raw.length);
|
|
577
573
|
}
|
|
578
574
|
|
|
579
575
|
// Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
|
|
@@ -587,7 +583,7 @@ class Tokenizer {
|
|
|
587
583
|
for (i = 0; i < l; i++) {
|
|
588
584
|
this.lexer.state.top = false;
|
|
589
585
|
list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
|
|
590
|
-
if (list.items[i].tokens.some(t => t.type === 'space')) {
|
|
586
|
+
if (!list.loose && list.items[i].tokens.some(t => t.type === 'space')) {
|
|
591
587
|
list.loose = true;
|
|
592
588
|
list.items[i].loose = true;
|
|
593
589
|
}
|
|
@@ -1063,7 +1059,7 @@ const block = {
|
|
|
1063
1059
|
lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
|
|
1064
1060
|
// regex template, placeholders will be replaced according to different paragraph
|
|
1065
1061
|
// interruption rules of commonmark and the original markdown spec:
|
|
1066
|
-
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
|
|
1062
|
+
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
|
|
1067
1063
|
text: /^[^\n]+/
|
|
1068
1064
|
};
|
|
1069
1065
|
|
|
@@ -1102,6 +1098,7 @@ block.paragraph = edit(block._paragraph)
|
|
|
1102
1098
|
.replace('hr', block.hr)
|
|
1103
1099
|
.replace('heading', ' {0,3}#{1,6} ')
|
|
1104
1100
|
.replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
1101
|
+
.replace('|table', '')
|
|
1105
1102
|
.replace('blockquote', ' {0,3}>')
|
|
1106
1103
|
.replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
|
|
1107
1104
|
.replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
@@ -1140,6 +1137,17 @@ block.gfm.table = edit(block.gfm.table)
|
|
|
1140
1137
|
.replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
|
|
1141
1138
|
.getRegex();
|
|
1142
1139
|
|
|
1140
|
+
block.gfm.paragraph = edit(block._paragraph)
|
|
1141
|
+
.replace('hr', block.hr)
|
|
1142
|
+
.replace('heading', ' {0,3}#{1,6} ')
|
|
1143
|
+
.replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
1144
|
+
.replace('table', block.gfm.table) // interrupt paragraphs with table
|
|
1145
|
+
.replace('blockquote', ' {0,3}>')
|
|
1146
|
+
.replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
|
|
1147
|
+
.replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1148
|
+
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
|
|
1149
|
+
.replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
|
|
1150
|
+
.getRegex();
|
|
1143
1151
|
/**
|
|
1144
1152
|
* Pedantic grammar (original John Gruber's loose markdown specification)
|
|
1145
1153
|
*/
|
package/lib/marked.umd.js
CHANGED
|
@@ -535,7 +535,7 @@
|
|
|
535
535
|
var cap = this.rules.block.list.exec(src);
|
|
536
536
|
|
|
537
537
|
if (cap) {
|
|
538
|
-
var raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line,
|
|
538
|
+
var raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line, nextLine, rawLine, itemContents;
|
|
539
539
|
var bull = cap[1].trim();
|
|
540
540
|
var isordered = bull.length > 1;
|
|
541
541
|
var list = {
|
|
@@ -553,83 +553,77 @@
|
|
|
553
553
|
} // Get next list item
|
|
554
554
|
|
|
555
555
|
|
|
556
|
-
var itemRegex = new RegExp("^( {0,3}" + bull + ")((?: [^\\n]
|
|
556
|
+
var itemRegex = new RegExp("^( {0,3}" + bull + ")((?: [^\\n]*)?(?:\\n|$))"); // Check if current bullet point can start a new List Item
|
|
557
557
|
|
|
558
558
|
while (src) {
|
|
559
|
-
if (
|
|
560
|
-
// End list if we encounter an HR (possibly move into itemRegex?)
|
|
559
|
+
if (!(cap = itemRegex.exec(src))) {
|
|
561
560
|
break;
|
|
562
561
|
}
|
|
563
562
|
|
|
564
|
-
if (
|
|
563
|
+
if (this.rules.block.hr.test(src)) {
|
|
564
|
+
// End list if bullet was actually HR (possibly move into itemRegex?)
|
|
565
565
|
break;
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
-
|
|
568
|
+
raw = cap[0];
|
|
569
|
+
src = src.substring(raw.length);
|
|
570
|
+
line = cap[2].split('\n', 1)[0];
|
|
571
|
+
nextLine = src.split('\n', 1)[0];
|
|
569
572
|
|
|
570
573
|
if (this.options.pedantic) {
|
|
571
574
|
indent = 2;
|
|
572
|
-
itemContents =
|
|
575
|
+
itemContents = line.trimLeft();
|
|
573
576
|
} else {
|
|
574
577
|
indent = cap[2].search(/[^ ]/); // Find first non-space char
|
|
575
578
|
|
|
576
|
-
indent =
|
|
579
|
+
indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
|
|
577
580
|
|
|
578
|
-
itemContents =
|
|
581
|
+
itemContents = line.slice(indent);
|
|
582
|
+
indent += cap[1].length;
|
|
579
583
|
}
|
|
580
584
|
|
|
581
585
|
blankLine = false;
|
|
582
|
-
raw = cap[0];
|
|
583
586
|
|
|
584
|
-
if (!
|
|
585
|
-
//
|
|
586
|
-
raw
|
|
587
|
+
if (!line && /^ *$/.test(nextLine)) {
|
|
588
|
+
// Items begin with at most one blank line
|
|
589
|
+
raw += nextLine + '\n';
|
|
590
|
+
src = src.substring(nextLine.length + 1);
|
|
587
591
|
list.loose = true;
|
|
588
|
-
lines = [];
|
|
589
592
|
}
|
|
590
593
|
|
|
591
|
-
var nextBulletRegex = new RegExp("^ {0," + Math.min(3, indent - 1) + "}(?:[*+-]|\\d{1,9}[.)])");
|
|
594
|
+
var nextBulletRegex = new RegExp("^ {0," + Math.min(3, indent - 1) + "}(?:[*+-]|\\d{1,9}[.)])"); // Check if following lines should be included in List Item
|
|
592
595
|
|
|
593
|
-
|
|
594
|
-
|
|
596
|
+
while (src && !list.loose) {
|
|
597
|
+
rawLine = src.split('\n', 1)[0];
|
|
598
|
+
line = rawLine; // Re-align to follow commonmark nesting rules
|
|
595
599
|
|
|
596
600
|
if (this.options.pedantic) {
|
|
597
|
-
// Re-align to follow commonmark nesting rules
|
|
598
601
|
line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' ');
|
|
599
602
|
} // End list item if found start of new bullet
|
|
600
603
|
|
|
601
604
|
|
|
602
605
|
if (nextBulletRegex.test(line)) {
|
|
603
|
-
raw = cap[1] + lines.slice(0, i).join('\n') + '\n';
|
|
604
606
|
break;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
if (!blankLine) {
|
|
609
|
-
if (!line.trim()) {
|
|
610
|
-
// Check if current line is empty
|
|
611
|
-
blankLine = true;
|
|
612
|
-
} // Dedent if possible
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
if (line.search(/[^ ]/) >= indent) {
|
|
616
|
-
itemContents += '\n' + line.slice(indent);
|
|
617
|
-
} else {
|
|
618
|
-
itemContents += '\n' + line;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
continue;
|
|
622
|
-
} // Dedent this line
|
|
623
|
-
|
|
607
|
+
}
|
|
624
608
|
|
|
625
609
|
if (line.search(/[^ ]/) >= indent || !line.trim()) {
|
|
610
|
+
// Dedent if possible
|
|
626
611
|
itemContents += '\n' + line.slice(indent);
|
|
627
|
-
|
|
612
|
+
} else if (!blankLine) {
|
|
613
|
+
// Until blank line, item doesn't need indentation
|
|
614
|
+
itemContents += '\n' + line;
|
|
628
615
|
} else {
|
|
629
|
-
//
|
|
630
|
-
raw = cap[1] + lines.slice(0, i).join('\n') + '\n';
|
|
616
|
+
// Otherwise, improper indentation ends this item
|
|
631
617
|
break;
|
|
632
618
|
}
|
|
619
|
+
|
|
620
|
+
if (!blankLine && !line.trim()) {
|
|
621
|
+
// Check if current line is blank
|
|
622
|
+
blankLine = true;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
raw += rawLine + '\n';
|
|
626
|
+
src = src.substring(rawLine.length + 1);
|
|
633
627
|
}
|
|
634
628
|
|
|
635
629
|
if (!list.loose) {
|
|
@@ -660,7 +654,6 @@
|
|
|
660
654
|
text: itemContents
|
|
661
655
|
});
|
|
662
656
|
list.raw += raw;
|
|
663
|
-
src = src.slice(raw.length);
|
|
664
657
|
} // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
|
|
665
658
|
|
|
666
659
|
|
|
@@ -673,7 +666,7 @@
|
|
|
673
666
|
this.lexer.state.top = false;
|
|
674
667
|
list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
|
|
675
668
|
|
|
676
|
-
if (list.items[i].tokens.some(function (t) {
|
|
669
|
+
if (!list.loose && list.items[i].tokens.some(function (t) {
|
|
677
670
|
return t.type === 'space';
|
|
678
671
|
})) {
|
|
679
672
|
list.loose = true;
|
|
@@ -1192,7 +1185,7 @@
|
|
|
1192
1185
|
lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
|
|
1193
1186
|
// regex template, placeholders will be replaced according to different paragraph
|
|
1194
1187
|
// interruption rules of commonmark and the original markdown spec:
|
|
1195
|
-
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
|
|
1188
|
+
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
|
|
1196
1189
|
text: /^[^\n]+/
|
|
1197
1190
|
};
|
|
1198
1191
|
block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
|
|
@@ -1205,7 +1198,7 @@
|
|
|
1205
1198
|
block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
|
|
1206
1199
|
block.html = edit(block.html, 'i').replace('comment', block._comment).replace('tag', block._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
|
|
1207
1200
|
block.paragraph = edit(block._paragraph).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
1208
|
-
.replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1201
|
+
.replace('|table', '').replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1209
1202
|
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
|
|
1210
1203
|
.getRegex();
|
|
1211
1204
|
block.blockquote = edit(block.blockquote).replace('paragraph', block.paragraph).getRegex();
|
|
@@ -1227,6 +1220,11 @@
|
|
|
1227
1220
|
block.gfm.table = edit(block.gfm.table).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1228
1221
|
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
|
|
1229
1222
|
.getRegex();
|
|
1223
|
+
block.gfm.paragraph = edit(block._paragraph).replace('hr', block.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
1224
|
+
.replace('table', block.gfm.table) // interrupt paragraphs with table
|
|
1225
|
+
.replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
1226
|
+
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
|
|
1227
|
+
.getRegex();
|
|
1230
1228
|
/**
|
|
1231
1229
|
* Pedantic grammar (original John Gruber's loose markdown specification)
|
|
1232
1230
|
*/
|