marked 0.3.16 → 0.4.0

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/lib/marked.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * marked - a markdown parser
3
3
  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
4
- * https://github.com/chjj/marked
4
+ * https://github.com/markedjs/marked
5
5
  */
6
6
 
7
- ;(function() {
7
+ ;(function(root) {
8
8
  'use strict';
9
9
 
10
10
  /**
@@ -16,59 +16,69 @@ var block = {
16
16
  code: /^( {4}[^\n]+\n*)+/,
17
17
  fences: noop,
18
18
  hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
19
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
19
+ heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,
20
20
  nptable: noop,
21
21
  blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
22
22
  list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
23
- html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
23
+ html: '^ {0,3}(?:' // optional indentation
24
+ + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
25
+ + '|comment[^\\n]*(\\n+|$)' // (2)
26
+ + '|<\\?[\\s\\S]*?\\?>\\n*' // (3)
27
+ + '|<![A-Z][\\s\\S]*?>\\n*' // (4)
28
+ + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)
29
+ + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
30
+ + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
31
+ + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
32
+ + ')',
24
33
  def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
25
34
  table: noop,
26
35
  lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
27
- paragraph: /^([^\n]+(?:\n?(?!hr|heading|lheading| {0,3}>|tag)[^\n]+)+)/,
36
+ paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,
28
37
  text: /^[^\n]+/
29
38
  };
30
39
 
31
- block._label = /(?:\\[\[\]]|[^\[\]])+/;
32
- block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/;
33
- block.def = replace(block.def)
34
- ('label', block._label)
35
- ('title', block._title)
36
- ();
40
+ block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
41
+ block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
42
+ block.def = edit(block.def)
43
+ .replace('label', block._label)
44
+ .replace('title', block._title)
45
+ .getRegex();
37
46
 
38
47
  block.bullet = /(?:[*+-]|\d+\.)/;
39
48
  block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
40
- block.item = replace(block.item, 'gm')
41
- (/bull/g, block.bullet)
42
- ();
43
-
44
- block.list = replace(block.list)
45
- (/bull/g, block.bullet)
46
- ('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
47
- ('def', '\\n+(?=' + block.def.source + ')')
48
- ();
49
-
50
- block._tag = '(?!(?:'
51
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
52
- + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
53
- + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b';
54
-
55
- block.html = replace(block.html)
56
- ('comment', /<!--[\s\S]*?-->/)
57
- ('closed', /<(tag)[\s\S]+?<\/\1>/)
58
- ('closing', /<tag(?:"[^"]*"|'[^']*'|\s[^'"\/>]*)*?\/?>/)
59
- (/tag/g, block._tag)
60
- ();
61
-
62
- block.paragraph = replace(block.paragraph)
63
- ('hr', block.hr)
64
- ('heading', block.heading)
65
- ('lheading', block.lheading)
66
- ('tag', '<' + block._tag)
67
- ();
68
-
69
- block.blockquote = replace(block.blockquote)
70
- ('paragraph', block.paragraph)
71
- ();
49
+ block.item = edit(block.item, 'gm')
50
+ .replace(/bull/g, block.bullet)
51
+ .getRegex();
52
+
53
+ block.list = edit(block.list)
54
+ .replace(/bull/g, block.bullet)
55
+ .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
56
+ .replace('def', '\\n+(?=' + block.def.source + ')')
57
+ .getRegex();
58
+
59
+ block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
60
+ + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
61
+ + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
62
+ + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
63
+ + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
64
+ + '|track|ul';
65
+ block._comment = /<!--(?!-?>)[\s\S]*?-->/;
66
+ block.html = edit(block.html, 'i')
67
+ .replace('comment', block._comment)
68
+ .replace('tag', block._tag)
69
+ .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
70
+ .getRegex();
71
+
72
+ block.paragraph = edit(block.paragraph)
73
+ .replace('hr', block.hr)
74
+ .replace('heading', block.heading)
75
+ .replace('lheading', block.lheading)
76
+ .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
77
+ .getRegex();
78
+
79
+ block.blockquote = edit(block.blockquote)
80
+ .replace('paragraph', block.paragraph)
81
+ .getRegex();
72
82
 
73
83
  /**
74
84
  * Normal Block Grammar
@@ -86,19 +96,37 @@ block.gfm = merge({}, block.normal, {
86
96
  heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
87
97
  });
88
98
 
89
- block.gfm.paragraph = replace(block.paragraph)
90
- ('(?!', '(?!'
99
+ block.gfm.paragraph = edit(block.paragraph)
100
+ .replace('(?!', '(?!'
91
101
  + block.gfm.fences.source.replace('\\1', '\\2') + '|'
92
102
  + block.list.source.replace('\\1', '\\3') + '|')
93
- ();
103
+ .getRegex();
94
104
 
95
105
  /**
96
106
  * GFM + Tables Block Grammar
97
107
  */
98
108
 
99
109
  block.tables = merge({}, block.gfm, {
100
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
101
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
110
+ nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,
111
+ table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/
112
+ });
113
+
114
+ /**
115
+ * Pedantic grammar
116
+ */
117
+
118
+ block.pedantic = merge({}, block.normal, {
119
+ html: edit(
120
+ '^ *(?:comment *(?:\\n|\\s*$)'
121
+ + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
122
+ + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
123
+ .replace('comment', block._comment)
124
+ .replace(/tag/g, '(?!(?:'
125
+ + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'
126
+ + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'
127
+ + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b')
128
+ .getRegex(),
129
+ def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/
102
130
  });
103
131
 
104
132
  /**
@@ -111,7 +139,9 @@ function Lexer(options) {
111
139
  this.options = options || marked.defaults;
112
140
  this.rules = block.normal;
113
141
 
114
- if (this.options.gfm) {
142
+ if (this.options.pedantic) {
143
+ this.rules = block.pedantic;
144
+ } else if (this.options.gfm) {
115
145
  if (this.options.tables) {
116
146
  this.rules = block.tables;
117
147
  } else {
@@ -154,17 +184,20 @@ Lexer.prototype.lex = function(src) {
154
184
  */
155
185
 
156
186
  Lexer.prototype.token = function(src, top) {
157
- var src = src.replace(/^ +$/gm, '')
158
- , next
159
- , loose
160
- , cap
161
- , bull
162
- , b
163
- , item
164
- , space
165
- , i
166
- , tag
167
- , l;
187
+ src = src.replace(/^ +$/gm, '');
188
+ var next,
189
+ loose,
190
+ cap,
191
+ bull,
192
+ b,
193
+ item,
194
+ space,
195
+ i,
196
+ tag,
197
+ l,
198
+ isordered,
199
+ istask,
200
+ ischecked;
168
201
 
169
202
  while (src) {
170
203
  // newline
@@ -214,34 +247,36 @@ Lexer.prototype.token = function(src, top) {
214
247
 
215
248
  // table no leading pipe (gfm)
216
249
  if (top && (cap = this.rules.nptable.exec(src))) {
217
- src = src.substring(cap[0].length);
218
-
219
250
  item = {
220
251
  type: 'table',
221
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
252
+ header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
222
253
  align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
223
- cells: cap[3].replace(/\n$/, '').split('\n')
254
+ cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
224
255
  };
225
256
 
226
- for (i = 0; i < item.align.length; i++) {
227
- if (/^ *-+: *$/.test(item.align[i])) {
228
- item.align[i] = 'right';
229
- } else if (/^ *:-+: *$/.test(item.align[i])) {
230
- item.align[i] = 'center';
231
- } else if (/^ *:-+ *$/.test(item.align[i])) {
232
- item.align[i] = 'left';
233
- } else {
234
- item.align[i] = null;
257
+ if (item.header.length === item.align.length) {
258
+ src = src.substring(cap[0].length);
259
+
260
+ for (i = 0; i < item.align.length; i++) {
261
+ if (/^ *-+: *$/.test(item.align[i])) {
262
+ item.align[i] = 'right';
263
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
264
+ item.align[i] = 'center';
265
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
266
+ item.align[i] = 'left';
267
+ } else {
268
+ item.align[i] = null;
269
+ }
235
270
  }
236
- }
237
271
 
238
- for (i = 0; i < item.cells.length; i++) {
239
- item.cells[i] = item.cells[i].split(/ *\| */);
240
- }
272
+ for (i = 0; i < item.cells.length; i++) {
273
+ item.cells[i] = splitCells(item.cells[i], item.header.length);
274
+ }
241
275
 
242
- this.tokens.push(item);
276
+ this.tokens.push(item);
243
277
 
244
- continue;
278
+ continue;
279
+ }
245
280
  }
246
281
 
247
282
  // hr
@@ -279,10 +314,12 @@ Lexer.prototype.token = function(src, top) {
279
314
  if (cap = this.rules.list.exec(src)) {
280
315
  src = src.substring(cap[0].length);
281
316
  bull = cap[2];
317
+ isordered = bull.length > 1;
282
318
 
283
319
  this.tokens.push({
284
320
  type: 'list_start',
285
- ordered: bull.length > 1
321
+ ordered: isordered,
322
+ start: isordered ? +bull : ''
286
323
  });
287
324
 
288
325
  // Get each top-level item.
@@ -328,10 +365,20 @@ Lexer.prototype.token = function(src, top) {
328
365
  if (!loose) loose = next;
329
366
  }
330
367
 
368
+ // Check for task list items
369
+ istask = /^\[[ xX]\] /.test(item);
370
+ ischecked = undefined;
371
+ if (istask) {
372
+ ischecked = item[1] !== ' ';
373
+ item = item.replace(/^\[[ xX]\] +/, '');
374
+ }
375
+
331
376
  this.tokens.push({
332
377
  type: loose
333
378
  ? 'loose_item_start'
334
- : 'list_item_start'
379
+ : 'list_item_start',
380
+ task: istask,
381
+ checked: ischecked
335
382
  });
336
383
 
337
384
  // Recurse.
@@ -366,8 +413,8 @@ Lexer.prototype.token = function(src, top) {
366
413
  // def
367
414
  if (top && (cap = this.rules.def.exec(src))) {
368
415
  src = src.substring(cap[0].length);
369
- if (cap[3]) cap[3] = cap[3].substring(1,cap[3].length-1);
370
- tag = cap[1].toLowerCase();
416
+ if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
417
+ tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
371
418
  if (!this.tokens.links[tag]) {
372
419
  this.tokens.links[tag] = {
373
420
  href: cap[2],
@@ -379,36 +426,38 @@ Lexer.prototype.token = function(src, top) {
379
426
 
380
427
  // table (gfm)
381
428
  if (top && (cap = this.rules.table.exec(src))) {
382
- src = src.substring(cap[0].length);
383
-
384
429
  item = {
385
430
  type: 'table',
386
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
431
+ header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
387
432
  align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
388
- cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
433
+ cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : []
389
434
  };
390
435
 
391
- for (i = 0; i < item.align.length; i++) {
392
- if (/^ *-+: *$/.test(item.align[i])) {
393
- item.align[i] = 'right';
394
- } else if (/^ *:-+: *$/.test(item.align[i])) {
395
- item.align[i] = 'center';
396
- } else if (/^ *:-+ *$/.test(item.align[i])) {
397
- item.align[i] = 'left';
398
- } else {
399
- item.align[i] = null;
436
+ if (item.header.length === item.align.length) {
437
+ src = src.substring(cap[0].length);
438
+
439
+ for (i = 0; i < item.align.length; i++) {
440
+ if (/^ *-+: *$/.test(item.align[i])) {
441
+ item.align[i] = 'right';
442
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
443
+ item.align[i] = 'center';
444
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
445
+ item.align[i] = 'left';
446
+ } else {
447
+ item.align[i] = null;
448
+ }
400
449
  }
401
- }
402
450
 
403
- for (i = 0; i < item.cells.length; i++) {
404
- item.cells[i] = item.cells[i]
405
- .replace(/^ *\| *| *\| *$/g, '')
406
- .split(/ *\| */);
407
- }
451
+ for (i = 0; i < item.cells.length; i++) {
452
+ item.cells[i] = splitCells(
453
+ item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
454
+ item.header.length);
455
+ }
408
456
 
409
- this.tokens.push(item);
457
+ this.tokens.push(item);
410
458
 
411
- continue;
459
+ continue;
460
+ }
412
461
  }
413
462
 
414
463
  // lheading
@@ -446,8 +495,7 @@ Lexer.prototype.token = function(src, top) {
446
495
  }
447
496
 
448
497
  if (src) {
449
- throw new
450
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
498
+ throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
451
499
  }
452
500
  }
453
501
 
@@ -459,40 +507,55 @@ Lexer.prototype.token = function(src, top) {
459
507
  */
460
508
 
461
509
  var inline = {
462
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
510
+ escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
463
511
  autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
464
512
  url: noop,
465
- tag: /^<!--[\s\S]*?-->|^<\/?[a-zA-Z0-9\-]+(?:"[^"]*"|'[^']*'|\s[^<'">\/]*)*?\/?>/,
466
- link: /^!?\[(inside)\]\(href\)/,
467
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
468
- nolink: /^!?\[((?:\[[^\]]*\]|\\[\[\]]|[^\[\]])*)\]/,
469
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
470
- em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/,
513
+ tag: '^comment'
514
+ + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
515
+ + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
516
+ + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
517
+ + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
518
+ + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
519
+ link: /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,
520
+ reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
521
+ nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
522
+ strong: /^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)|^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)/,
523
+ em: /^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*][\s\S]*?[^\s])\*(?!\*)|^_([^\s_])_(?!_)|^\*([^\s*])\*(?!\*)/,
471
524
  code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/,
472
525
  br: /^ {2,}\n(?!\s*$)/,
473
526
  del: noop,
474
527
  text: /^[\s\S]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/
475
528
  };
476
529
 
530
+ inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
531
+
477
532
  inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
478
533
  inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
534
+ inline.autolink = edit(inline.autolink)
535
+ .replace('scheme', inline._scheme)
536
+ .replace('email', inline._email)
537
+ .getRegex();
538
+
539
+ inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
479
540
 
480
- inline.autolink = replace(inline.autolink)
481
- ('scheme', inline._scheme)
482
- ('email', inline._email)
483
- ()
541
+ inline.tag = edit(inline.tag)
542
+ .replace('comment', block._comment)
543
+ .replace('attribute', inline._attribute)
544
+ .getRegex();
484
545
 
485
- inline._inside = /(?:\[[^\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/;
486
- inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
546
+ inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/;
547
+ inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?)/;
548
+ inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
487
549
 
488
- inline.link = replace(inline.link)
489
- ('inside', inline._inside)
490
- ('href', inline._href)
491
- ();
550
+ inline.link = edit(inline.link)
551
+ .replace('label', inline._label)
552
+ .replace('href', inline._href)
553
+ .replace('title', inline._title)
554
+ .getRegex();
492
555
 
493
- inline.reflink = replace(inline.reflink)
494
- ('inside', inline._inside)
495
- ();
556
+ inline.reflink = edit(inline.reflink)
557
+ .replace('label', inline._label)
558
+ .getRegex();
496
559
 
497
560
  /**
498
561
  * Normal Inline Grammar
@@ -506,7 +569,13 @@ inline.normal = merge({}, inline);
506
569
 
507
570
  inline.pedantic = merge({}, inline.normal, {
508
571
  strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
509
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
572
+ em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
573
+ link: edit(/^!?\[(label)\]\((.*?)\)/)
574
+ .replace('label', inline._label)
575
+ .getRegex(),
576
+ reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
577
+ .replace('label', inline._label)
578
+ .getRegex()
510
579
  });
511
580
 
512
581
  /**
@@ -514,16 +583,16 @@ inline.pedantic = merge({}, inline.normal, {
514
583
  */
515
584
 
516
585
  inline.gfm = merge({}, inline.normal, {
517
- escape: replace(inline.escape)('])', '~|])')(),
518
- url: replace(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/)
519
- ('email', inline._email)
520
- (),
586
+ escape: edit(inline.escape).replace('])', '~|])').getRegex(),
587
+ url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/)
588
+ .replace('email', inline._email)
589
+ .getRegex(),
521
590
  _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
522
591
  del: /^~~(?=\S)([\s\S]*?\S)~~/,
523
- text: replace(inline.text)
524
- (']|', '~]|')
525
- ('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|')
526
- ()
592
+ text: edit(inline.text)
593
+ .replace(']|', '~]|')
594
+ .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|')
595
+ .getRegex()
527
596
  });
528
597
 
529
598
  /**
@@ -531,8 +600,8 @@ inline.gfm = merge({}, inline.normal, {
531
600
  */
532
601
 
533
602
  inline.breaks = merge({}, inline.gfm, {
534
- br: replace(inline.br)('{2,}', '*')(),
535
- text: replace(inline.gfm.text)('{2,}', '*')()
603
+ br: edit(inline.br).replace('{2,}', '*').getRegex(),
604
+ text: edit(inline.gfm.text).replace('{2,}', '*').getRegex()
536
605
  });
537
606
 
538
607
  /**
@@ -543,22 +612,21 @@ function InlineLexer(links, options) {
543
612
  this.options = options || marked.defaults;
544
613
  this.links = links;
545
614
  this.rules = inline.normal;
546
- this.renderer = this.options.renderer || new Renderer;
615
+ this.renderer = this.options.renderer || new Renderer();
547
616
  this.renderer.options = this.options;
548
617
 
549
618
  if (!this.links) {
550
- throw new
551
- Error('Tokens array requires a `links` property.');
619
+ throw new Error('Tokens array requires a `links` property.');
552
620
  }
553
621
 
554
- if (this.options.gfm) {
622
+ if (this.options.pedantic) {
623
+ this.rules = inline.pedantic;
624
+ } else if (this.options.gfm) {
555
625
  if (this.options.breaks) {
556
626
  this.rules = inline.breaks;
557
627
  } else {
558
628
  this.rules = inline.gfm;
559
629
  }
560
- } else if (this.options.pedantic) {
561
- this.rules = inline.pedantic;
562
630
  }
563
631
  }
564
632
 
@@ -582,11 +650,12 @@ InlineLexer.output = function(src, links, options) {
582
650
  */
583
651
 
584
652
  InlineLexer.prototype.output = function(src) {
585
- var out = ''
586
- , link
587
- , text
588
- , href
589
- , cap;
653
+ var out = '',
654
+ link,
655
+ text,
656
+ href,
657
+ title,
658
+ cap;
590
659
 
591
660
  while (src) {
592
661
  // escape
@@ -649,9 +718,23 @@ InlineLexer.prototype.output = function(src) {
649
718
  if (cap = this.rules.link.exec(src)) {
650
719
  src = src.substring(cap[0].length);
651
720
  this.inLink = true;
721
+ href = cap[2];
722
+ if (this.options.pedantic) {
723
+ link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
724
+
725
+ if (link) {
726
+ href = link[1];
727
+ title = link[3];
728
+ } else {
729
+ title = '';
730
+ }
731
+ } else {
732
+ title = cap[3] ? cap[3].slice(1, -1) : '';
733
+ }
734
+ href = href.trim().replace(/^<([\s\S]*)>$/, '$1');
652
735
  out += this.outputLink(cap, {
653
- href: cap[2],
654
- title: cap[3]
736
+ href: InlineLexer.escapes(href),
737
+ title: InlineLexer.escapes(title)
655
738
  });
656
739
  this.inLink = false;
657
740
  continue;
@@ -677,14 +760,14 @@ InlineLexer.prototype.output = function(src) {
677
760
  // strong
678
761
  if (cap = this.rules.strong.exec(src)) {
679
762
  src = src.substring(cap[0].length);
680
- out += this.renderer.strong(this.output(cap[2] || cap[1]));
763
+ out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1]));
681
764
  continue;
682
765
  }
683
766
 
684
767
  // em
685
768
  if (cap = this.rules.em.exec(src)) {
686
769
  src = src.substring(cap[0].length);
687
- out += this.renderer.em(this.output(cap[2] || cap[1]));
770
+ out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));
688
771
  continue;
689
772
  }
690
773
 
@@ -717,21 +800,24 @@ InlineLexer.prototype.output = function(src) {
717
800
  }
718
801
 
719
802
  if (src) {
720
- throw new
721
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
803
+ throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
722
804
  }
723
805
  }
724
806
 
725
807
  return out;
726
808
  };
727
809
 
810
+ InlineLexer.escapes = function(text) {
811
+ return text ? text.replace(InlineLexer.rules._escapes, '$1') : text;
812
+ }
813
+
728
814
  /**
729
815
  * Compile Link
730
816
  */
731
817
 
732
818
  InlineLexer.prototype.outputLink = function(cap, link) {
733
- var href = escape(link.href)
734
- , title = link.title ? escape(link.title) : null;
819
+ var href = link.href,
820
+ title = link.title ? escape(link.title) : null;
735
821
 
736
822
  return cap[0].charAt(0) !== '!'
737
823
  ? this.renderer.link(href, title, this.output(cap[1]))
@@ -767,10 +853,10 @@ InlineLexer.prototype.smartypants = function(text) {
767
853
 
768
854
  InlineLexer.prototype.mangle = function(text) {
769
855
  if (!this.options.mangle) return text;
770
- var out = ''
771
- , l = text.length
772
- , i = 0
773
- , ch;
856
+ var out = '',
857
+ l = text.length,
858
+ i = 0,
859
+ ch;
774
860
 
775
861
  for (; i < l; i++) {
776
862
  ch = text.charCodeAt(i);
@@ -788,7 +874,7 @@ InlineLexer.prototype.mangle = function(text) {
788
874
  */
789
875
 
790
876
  function Renderer(options) {
791
- this.options = options || {};
877
+ this.options = options || marked.defaults;
792
878
  }
793
879
 
794
880
  Renderer.prototype.code = function(code, lang, escaped) {
@@ -803,7 +889,7 @@ Renderer.prototype.code = function(code, lang, escaped) {
803
889
  if (!lang) {
804
890
  return '<pre><code>'
805
891
  + (escaped ? code : escape(code, true))
806
- + '\n</code></pre>';
892
+ + '</code></pre>';
807
893
  }
808
894
 
809
895
  return '<pre><code class="'
@@ -811,7 +897,7 @@ Renderer.prototype.code = function(code, lang, escaped) {
811
897
  + escape(lang, true)
812
898
  + '">'
813
899
  + (escaped ? code : escape(code, true))
814
- + '\n</code></pre>\n';
900
+ + '</code></pre>\n';
815
901
  };
816
902
 
817
903
  Renderer.prototype.blockquote = function(quote) {
@@ -823,43 +909,56 @@ Renderer.prototype.html = function(html) {
823
909
  };
824
910
 
825
911
  Renderer.prototype.heading = function(text, level, raw) {
826
- return '<h'
827
- + level
828
- + ' id="'
829
- + this.options.headerPrefix
830
- + raw.toLowerCase().replace(/[^\w]+/g, '-')
831
- + '">'
832
- + text
833
- + '</h'
834
- + level
835
- + '>\n';
912
+ if (this.options.headerIds) {
913
+ return '<h'
914
+ + level
915
+ + ' id="'
916
+ + this.options.headerPrefix
917
+ + raw.toLowerCase().replace(/[^\w]+/g, '-')
918
+ + '">'
919
+ + text
920
+ + '</h'
921
+ + level
922
+ + '>\n';
923
+ }
924
+ // ignore IDs
925
+ return '<h' + level + '>' + text + '</h' + level + '>\n';
836
926
  };
837
927
 
838
928
  Renderer.prototype.hr = function() {
839
929
  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
840
930
  };
841
931
 
842
- Renderer.prototype.list = function(body, ordered) {
843
- var type = ordered ? 'ol' : 'ul';
844
- return '<' + type + '>\n' + body + '</' + type + '>\n';
932
+ Renderer.prototype.list = function(body, ordered, start) {
933
+ var type = ordered ? 'ol' : 'ul',
934
+ startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
935
+ return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
845
936
  };
846
937
 
847
938
  Renderer.prototype.listitem = function(text) {
848
939
  return '<li>' + text + '</li>\n';
849
940
  };
850
941
 
942
+ Renderer.prototype.checkbox = function(checked) {
943
+ return '<input '
944
+ + (checked ? 'checked="" ' : '')
945
+ + 'disabled="" type="checkbox"'
946
+ + (this.options.xhtml ? ' /' : '')
947
+ + '> ';
948
+ }
949
+
851
950
  Renderer.prototype.paragraph = function(text) {
852
951
  return '<p>' + text + '</p>\n';
853
952
  };
854
953
 
855
954
  Renderer.prototype.table = function(header, body) {
955
+ if (body) body = '<tbody>' + body + '</tbody>';
956
+
856
957
  return '<table>\n'
857
958
  + '<thead>\n'
858
959
  + header
859
960
  + '</thead>\n'
860
- + '<tbody>\n'
861
961
  + body
862
- + '</tbody>\n'
863
962
  + '</table>\n';
864
963
  };
865
964
 
@@ -870,7 +969,7 @@ Renderer.prototype.tablerow = function(content) {
870
969
  Renderer.prototype.tablecell = function(content, flags) {
871
970
  var type = flags.header ? 'th' : 'td';
872
971
  var tag = flags.align
873
- ? '<' + type + ' style="text-align:' + flags.align + '">'
972
+ ? '<' + type + ' align="' + flags.align + '">'
874
973
  : '<' + type + '>';
875
974
  return tag + content + '</' + type + '>\n';
876
975
  };
@@ -912,7 +1011,12 @@ Renderer.prototype.link = function(href, title, text) {
912
1011
  if (this.options.baseUrl && !originIndependentUrl.test(href)) {
913
1012
  href = resolveUrl(this.options.baseUrl, href);
914
1013
  }
915
- var out = '<a href="' + href + '"';
1014
+ try {
1015
+ href = encodeURI(href).replace(/%25/g, '%');
1016
+ } catch (e) {
1017
+ return text;
1018
+ }
1019
+ var out = '<a href="' + escape(href) + '"';
916
1020
  if (title) {
917
1021
  out += ' title="' + title + '"';
918
1022
  }
@@ -970,7 +1074,7 @@ function Parser(options) {
970
1074
  this.tokens = [];
971
1075
  this.token = null;
972
1076
  this.options = options || marked.defaults;
973
- this.options.renderer = this.options.renderer || new Renderer;
1077
+ this.options.renderer = this.options.renderer || new Renderer();
974
1078
  this.renderer = this.options.renderer;
975
1079
  this.renderer.options = this.options;
976
1080
  }
@@ -991,7 +1095,10 @@ Parser.parse = function(src, options) {
991
1095
  Parser.prototype.parse = function(src) {
992
1096
  this.inline = new InlineLexer(src.links, this.options);
993
1097
  // use an InlineLexer with a TextRenderer to extract pure text
994
- this.inlineText = new InlineLexer(src.links, merge({}, this.options, {renderer: new TextRenderer}));
1098
+ this.inlineText = new InlineLexer(
1099
+ src.links,
1100
+ merge({}, this.options, {renderer: new TextRenderer()})
1101
+ );
995
1102
  this.tokens = src.reverse();
996
1103
 
997
1104
  var out = '';
@@ -1056,12 +1163,12 @@ Parser.prototype.tok = function() {
1056
1163
  this.token.escaped);
1057
1164
  }
1058
1165
  case 'table': {
1059
- var header = ''
1060
- , body = ''
1061
- , i
1062
- , row
1063
- , cell
1064
- , j;
1166
+ var header = '',
1167
+ body = '',
1168
+ i,
1169
+ row,
1170
+ cell,
1171
+ j;
1065
1172
 
1066
1173
  // header
1067
1174
  cell = '';
@@ -1089,7 +1196,7 @@ Parser.prototype.tok = function() {
1089
1196
  return this.renderer.table(header, body);
1090
1197
  }
1091
1198
  case 'blockquote_start': {
1092
- var body = '';
1199
+ body = '';
1093
1200
 
1094
1201
  while (this.next().type !== 'blockquote_end') {
1095
1202
  body += this.tok();
@@ -1098,17 +1205,22 @@ Parser.prototype.tok = function() {
1098
1205
  return this.renderer.blockquote(body);
1099
1206
  }
1100
1207
  case 'list_start': {
1101
- var body = ''
1102
- , ordered = this.token.ordered;
1208
+ body = '';
1209
+ var ordered = this.token.ordered,
1210
+ start = this.token.start;
1103
1211
 
1104
1212
  while (this.next().type !== 'list_end') {
1105
1213
  body += this.tok();
1106
1214
  }
1107
1215
 
1108
- return this.renderer.list(body, ordered);
1216
+ return this.renderer.list(body, ordered, start);
1109
1217
  }
1110
1218
  case 'list_item_start': {
1111
- var body = '';
1219
+ body = '';
1220
+
1221
+ if (this.token.task) {
1222
+ body += this.renderer.checkbox(this.token.checked);
1223
+ }
1112
1224
 
1113
1225
  while (this.next().type !== 'list_item_end') {
1114
1226
  body += this.token.type === 'text'
@@ -1119,7 +1231,7 @@ Parser.prototype.tok = function() {
1119
1231
  return this.renderer.listitem(body);
1120
1232
  }
1121
1233
  case 'loose_item_start': {
1122
- var body = '';
1234
+ body = '';
1123
1235
 
1124
1236
  while (this.next().type !== 'list_item_end') {
1125
1237
  body += this.tok();
@@ -1128,10 +1240,8 @@ Parser.prototype.tok = function() {
1128
1240
  return this.renderer.listitem(body);
1129
1241
  }
1130
1242
  case 'html': {
1131
- var html = !this.token.pre && !this.options.pedantic
1132
- ? this.inline.output(this.token.text)
1133
- : this.token.text;
1134
- return this.renderer.html(html);
1243
+ // TODO parse inline content if parameter markdown=1
1244
+ return this.renderer.html(this.token.text);
1135
1245
  }
1136
1246
  case 'paragraph': {
1137
1247
  return this.renderer.paragraph(this.inline.output(this.token.text));
@@ -1156,7 +1266,7 @@ function escape(html, encode) {
1156
1266
  }
1157
1267
 
1158
1268
  function unescape(html) {
1159
- // explicitly match decimal, hex, and named HTML entities
1269
+ // explicitly match decimal, hex, and named HTML entities
1160
1270
  return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) {
1161
1271
  n = n.toLowerCase();
1162
1272
  if (n === 'colon') return ':';
@@ -1169,15 +1279,19 @@ function unescape(html) {
1169
1279
  });
1170
1280
  }
1171
1281
 
1172
- function replace(regex, opt) {
1173
- regex = regex.source;
1282
+ function edit(regex, opt) {
1283
+ regex = regex.source || regex;
1174
1284
  opt = opt || '';
1175
- return function self(name, val) {
1176
- if (!name) return new RegExp(regex, opt);
1177
- val = val.source || val;
1178
- val = val.replace(/(^|[^\[])\^/g, '$1');
1179
- regex = regex.replace(name, val);
1180
- return self;
1285
+ return {
1286
+ replace: function(name, val) {
1287
+ val = val.source || val;
1288
+ val = val.replace(/(^|[^\[])\^/g, '$1');
1289
+ regex = regex.replace(name, val);
1290
+ return this;
1291
+ },
1292
+ getRegex: function() {
1293
+ return new RegExp(regex, opt);
1294
+ }
1181
1295
  };
1182
1296
  }
1183
1297
 
@@ -1209,9 +1323,9 @@ function noop() {}
1209
1323
  noop.exec = noop;
1210
1324
 
1211
1325
  function merge(obj) {
1212
- var i = 1
1213
- , target
1214
- , key;
1326
+ var i = 1,
1327
+ target,
1328
+ key;
1215
1329
 
1216
1330
  for (; i < arguments.length; i++) {
1217
1331
  target = arguments[i];
@@ -1225,6 +1339,21 @@ function merge(obj) {
1225
1339
  return obj;
1226
1340
  }
1227
1341
 
1342
+ function splitCells(tableRow, count) {
1343
+ var cells = tableRow.replace(/([^\\])\|/g, '$1 |').split(/ +\| */),
1344
+ i = 0;
1345
+
1346
+ if (cells.length > count) {
1347
+ cells.splice(count);
1348
+ } else {
1349
+ while (cells.length < count) cells.push('');
1350
+ }
1351
+
1352
+ for (; i < cells.length; i++) {
1353
+ cells[i] = cells[i].replace(/\\\|/g, '|');
1354
+ }
1355
+ return cells;
1356
+ }
1228
1357
 
1229
1358
  /**
1230
1359
  * Marked
@@ -1232,12 +1361,13 @@ function merge(obj) {
1232
1361
 
1233
1362
  function marked(src, opt, callback) {
1234
1363
  // throw error in case of non string input
1235
- if (typeof src == 'undefined' || src === null)
1364
+ if (typeof src === 'undefined' || src === null) {
1236
1365
  throw new Error('marked(): input parameter is undefined or null');
1237
- if (typeof src != 'string')
1238
- throw new Error('marked(): input parameter is of type ' +
1239
- Object.prototype.toString.call(src) + ', string expected');
1240
-
1366
+ }
1367
+ if (typeof src !== 'string') {
1368
+ throw new Error('marked(): input parameter is of type '
1369
+ + Object.prototype.toString.call(src) + ', string expected');
1370
+ }
1241
1371
 
1242
1372
  if (callback || typeof opt === 'function') {
1243
1373
  if (!callback) {
@@ -1247,10 +1377,10 @@ function marked(src, opt, callback) {
1247
1377
 
1248
1378
  opt = merge({}, marked.defaults, opt || {});
1249
1379
 
1250
- var highlight = opt.highlight
1251
- , tokens
1252
- , pending
1253
- , i = 0;
1380
+ var highlight = opt.highlight,
1381
+ tokens,
1382
+ pending,
1383
+ i = 0;
1254
1384
 
1255
1385
  try {
1256
1386
  tokens = Lexer.lex(src, opt)
@@ -1312,7 +1442,7 @@ function marked(src, opt, callback) {
1312
1442
  if (opt) opt = merge({}, marked.defaults, opt);
1313
1443
  return Parser.parse(Lexer.lex(src, opt), opt);
1314
1444
  } catch (e) {
1315
- e.message += '\nPlease report this to https://github.com/chjj/marked.';
1445
+ e.message += '\nPlease report this to https://github.com/markedjs/marked.';
1316
1446
  if ((opt || marked.defaults).silent) {
1317
1447
  return '<p>An error occurred:</p><pre>'
1318
1448
  + escape(e.message + '', true)
@@ -1332,24 +1462,29 @@ marked.setOptions = function(opt) {
1332
1462
  return marked;
1333
1463
  };
1334
1464
 
1335
- marked.defaults = {
1336
- gfm: true,
1337
- tables: true,
1338
- breaks: false,
1339
- pedantic: false,
1340
- sanitize: false,
1341
- sanitizer: null,
1342
- mangle: true,
1343
- smartLists: false,
1344
- silent: false,
1345
- highlight: null,
1346
- langPrefix: 'lang-',
1347
- smartypants: false,
1348
- headerPrefix: '',
1349
- renderer: new Renderer,
1350
- xhtml: false,
1351
- baseUrl: null
1352
- };
1465
+ marked.getDefaults = function () {
1466
+ return {
1467
+ baseUrl: null,
1468
+ breaks: false,
1469
+ gfm: true,
1470
+ headerIds: true,
1471
+ headerPrefix: '',
1472
+ highlight: null,
1473
+ langPrefix: 'language-',
1474
+ mangle: true,
1475
+ pedantic: false,
1476
+ renderer: new Renderer(),
1477
+ sanitize: false,
1478
+ sanitizer: null,
1479
+ silent: false,
1480
+ smartLists: false,
1481
+ smartypants: false,
1482
+ tables: true,
1483
+ xhtml: false
1484
+ };
1485
+ }
1486
+
1487
+ marked.defaults = marked.getDefaults();
1353
1488
 
1354
1489
  /**
1355
1490
  * Expose
@@ -1374,9 +1509,6 @@ if (typeof module !== 'undefined' && typeof exports === 'object') {
1374
1509
  } else if (typeof define === 'function' && define.amd) {
1375
1510
  define(function() { return marked; });
1376
1511
  } else {
1377
- this.marked = marked;
1512
+ root.marked = marked;
1378
1513
  }
1379
-
1380
- }).call(function() {
1381
- return this || (typeof window !== 'undefined' ? window : global);
1382
- }());
1514
+ })(this || (typeof window !== 'undefined' ? window : global));