PageSourceSearch

https://xautshuanglong.github.io/js/marked.js

js xautshuanglong.github.io collected 2026-10-03 10:11:20 UTC 28,695 bytes, 1,286 lines download raw bytes

1/**
2 * marked - a markdown parser
3 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
4 * https://github.com/chjj/marked
5 */
6
7;(function() {
8
9/**
10 * Block-Level Grammar
11 */
12
13var block = {
14  newline: /^\n+/,
15  code: /^( {4}[^\n]+\n*)+/,
16  fences: noop,
17  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
18  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
19  nptable: noop,
20  lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
21  blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
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*$))/,
24  def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
25  table: noop,
26  paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
27  text: /^[^\n]+/
28};
29
30block.bullet = /(?:[*+-]|\d+\.)/;
31block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
32block.item = replace(block.item, 'gm')
33  (/bull/g, block.bullet)
34  ();
35
36block.list = replace(block.list)
37  (/bull/g, block.bullet)
38  ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
39  ('def', '\\n+(?=' + block.def.source + ')')
40  ();
41
42block.blockquote = replace(block.blockquote)
43  ('def', block.def)
44  ();
45
46block._tag = '(?!(?:'
47  + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
48  + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
49  + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
50
51block.html = replace(block.html)
52  ('comment', /<!--[\s\S]*?-->/)
53  ('closed', /<(tag)[\s\S]+?<\/\1>/)
54  ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
55  (/tag/g, block._tag)
56  ();
57
58block.paragraph = replace(block.paragraph)
59  ('hr', block.hr)
60  ('heading', block.heading)
61  ('lheading', block.lheading)
62  ('blockquote', block.blockquote)
63  ('tag', '<' + block._tag)
64  ('def', block.def)
65  ();
66
67/**
68 * Normal Block Grammar
69 */
70
71block.normal = merge({}, block);
72
73/**
74 * GFM Block Grammar
75 */
76
77block.gfm = merge({}, block.normal, {
78  fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
79  paragraph: /^/,
80  heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
81});
82
83block.gfm.paragraph = replace(block.paragraph)
84  ('(?!', '(?!'
85    + block.gfm.fences.source.replace('\\1', '\\2') + '|'
86    + block.list.source.replace('\\1', '\\3') + '|')
87  ();
88
89/**
90 * GFM + Tables Block Grammar
91 */
92
93block.tables = merge({}, block.gfm, {
94  nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
95  table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
96});
97
98/**
99 * Block Lexer
100 */
101
102function Lexer(options) {
103  this.tokens = [];
104  this.tokens.links = {};
105  this.options = options || marked.defaults;
106  this.rules = block.normal;
107
108  if (this.options.gfm) {
109    if (this.options.tables) {
110      this.rules = block.tables;
111    } else {
112      this.rules = block.gfm;
113    }
114  }
115}
116
117/**
118 * Expose Block Rules
119 */
120
121Lexer.rules = block;
122
123/**
124 * Static Lex Method
125 */
126
127Lexer.lex = function(src, options) {
128  var lexer = new Lexer(options);
129  return lexer.lex(src);
130};
131
132/**
133 * Preprocessing
134 */
135
136Lexer.prototype.lex = function(src) {
137  src = src
138    .replace(/\r\n|\r/g, '\n')
139    .replace(/\t/g, '    ')
140    .replace(/\u00a0/g, ' ')
141    .replace(/\u2424/g, '\n');
142
143  return this.token(src, true);
144};
145
146/**
147 * Lexing
148 */
149
150Lexer.prototype.token = function(src, top, bq) {
151  var src = src.replace(/^ +$/gm, '')
152    , next
153    , loose
154    , cap
155    , bull
156    , b
157    , item
158    , space
159    , i
160    , l;
161
162  while (src) {
163    // newline
164    if (cap = this.rules.newline.exec(src)) {
165      src = src.substring(cap[0].length);
166      if (cap[0].length > 1) {
167        this.tokens.push({
168          type: 'space'
169        });
170      }
171    }
172
173    // code
174    if (cap = this.rules.code.exec(src)) {
175      src = src.substring(cap[0].length);
176      cap = cap[0].replace(/^ {4}/gm, '');
177      this.tokens.push({
178        type: 'code',
179        text: !this.options.pedantic
180          ? cap.replace(/\n+$/, '')
181          : cap
182      });
183      continue;
184    }
185
186    // fences (gfm)
187    if (cap = this.rules.fences.exec(src)) {
188      src = src.substring(cap[0].length);
189      this.tokens.push({
190        type: 'code',
191        lang: cap[2],
192        text: cap[3] || ''
193      });
194      continue;
195    }
196
197    // heading
198    if (cap = this.rules.heading.exec(src)) {
199      src = src.substring(cap[0].length);
200      this.tokens.push({
201        type: 'heading',
202        depth: cap[1].length,
203        text: cap[2]
204      });
205      continue;
206    }
207
208    // table no leading pipe (gfm)
209    if (top && (cap = this.rules.nptable.exec(src))) {
210      src = src.substring(cap[0].length);
211
212      item = {
213        type: 'table',
214        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
215        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
216        cells: cap[3].replace(/\n$/, '').split('\n')
217      };
218
219      for (i = 0; i < item.align.length; i++) {
220        if (/^ *-+: *$/.test(item.align[i])) {
221          item.align[i] = 'right';
222        } else if (/^ *:-+: *$/.test(item.align[i])) {
223          item.align[i] = 'center';
224        } else if (/^ *:-+ *$/.test(item.align[i])) {
225          item.align[i] = 'left';
226        } else {
227          item.align[i] = null;
228        }
229      }
230
231      for (i = 0; i < item.cells.length; i++) {
232        item.cells[i] = item.cells[i].split(/ *\| */);
233      }
234
235      this.tokens.push(item);
236
237      continue;
238    }
239
240    // lheading
241    if (cap = this.rules.lheading.exec(src)) {
242      src = src.substring(cap[0].length);
243      this.tokens.push({
244        type: 'heading',
245        depth: cap[2] === '=' ? 1 : 2,
246        text: cap[1]
247      });
248      continue;
249    }
250
251    // hr
252    if (cap = this.rules.hr.exec(src)) {
253      src = src.substring(cap[0].length);
254      this.tokens.push({
255        type: 'hr'
256      });
257      continue;
258    }
259
260    // blockquote
261    if (cap = this.rules.blockquote.exec(src)) {
262      src = src.substring(cap[0].length);
263
264      this.tokens.push({
265        type: 'blockquote_start'
266      });
267
268      cap = cap[0].replace(/^ *> ?/gm, '');
269
270      // Pass `top` to keep the current
271      // "toplevel" state. This is exactly
272      // how markdown.pl works.
273      this.token(cap, top, true);
274
275      this.tokens.push({
276        type: 'blockquote_end'
277      });
278
279      continue;
280    }
281
282    // list
283    if (cap = this.rules.list.exec(src)) {
284      src = src.substring(cap[0].length);
285      bull = cap[2];
286
287      this.tokens.push({
288        type: 'list_start',
289        ordered: bull.length > 1
290      });
291
292      // Get each top-level item.
293      cap = cap[0].match(this.rules.item);
294
295      next = false;
296      l = cap.length;
297      i = 0;
298
299      for (; i < l; i++) {
300        item = cap[i];
301
302        // Remove the list item's bullet
303        // so it is seen as the next token.
304        space = item.length;
305        item = item.replace(/^ *([*+-]|\d+\.) +/, '');
306
307        // Outdent whatever the
308        // list item contains. Hacky.
309        if (~item.indexOf('\n ')) {
310          space -= item.length;
311          item = !this.options.pedantic
312            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
313            : item.replace(/^ {1,4}/gm, '');
314        }
315
316        // Determine whether the next list item belongs here.
317        // Backpedal if it does not belong in this list.
318        if (this.options.smartLists && i !== l - 1) {
319          b = block.bullet.exec(cap[i + 1])[0];
320          if (bull !== b && !(bull.length > 1 && b.length > 1)) {
321            src = cap.slice(i + 1).join('\n') + src;
322            i = l - 1;
323          }
324        }
325
326        // Determine whether item is loose or not.
327        // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
328        // for discount behavior.
329        loose = next || /\n\n(?!\s*$)/.test(item);
330        if (i !== l - 1) {
331          next = item.charAt(item.length - 1) === '\n';
332          if (!loose) loose = next;
333        }
334
335        this.tokens.push({
336          type: loose
337            ? 'loose_item_start'
338            : 'list_item_start'
339        });
340
341        // Recurse.
342        this.token(item, false, bq);
343
344        this.tokens.push({
345          type: 'list_item_end'
346        });
347      }
348
349      this.tokens.push({
350        type: 'list_end'
351      });
352
353      continue;
354    }
355
356    // html
357    if (cap = this.rules.html.exec(src)) {
358      src = src.substring(cap[0].length);
359      this.tokens.push({
360        type: this.options.sanitize
361          ? 'paragraph'
362          : 'html',
363        pre: !this.options.sanitizer
364          && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
365        text: cap[0]
366      });
367      continue;
368    }
369
370    // def
371    if ((!bq && top) && (cap = this.rules.def.exec(src))) {
372      src = src.substring(cap[0].length);
373      this.tokens.links[cap[1].toLowerCase()] = {
374        href: cap[2],
375        title: cap[3]
376      };
377      continue;
378    }
379
380    // table (gfm)
381    if (top && (cap = this.rules.table.exec(src))) {
382      src = src.substring(cap[0].length);
383
384      item = {
385        type: 'table',
386        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
387        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
388        cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
389      };
390
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;
400        }
401      }
402
403      for (i = 0; i < item.cells.length; i++) {
404        item.cells[i] = item.cells[i]
405          .replace(/^ *\| *| *\| *$/g, '')
406          .split(/ *\| */);
407      }
408
409      this.tokens.push(item);
410
411      continue;
412    }
413
414    // top-level paragraph
415    if (top && (cap = this.rules.paragraph.exec(src))) {
416      src = src.substring(cap[0].length);
417      this.tokens.push({
418        type: 'paragraph',
419        text: cap[1].charAt(cap[1].length - 1) === '\n'
420          ? cap[1].slice(0, -1)
421          : cap[1]
422      });
423      continue;
424    }
425
426    // text
427    if (cap = this.rules.text.exec(src)) {
428      // Top-level should never reach here.
429      src = src.substring(cap[0].length);
430      this.tokens.push({
431        type: 'text',
432        text: cap[0]
433      });
434      continue;
435    }
436
437    if (src) {
438      throw new
439        Error('Infinite loop on byte: ' + src.charCodeAt(0));
440    }
441  }
442
443  return this.tokens;
444};
445
446/**
447 * Inline-Level Grammar
448 */
449
450var inline = {
451  escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
452  autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
453  url: noop,
454  tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
455  link: /^!?\[(inside)\]\(href\)/,
456  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
457  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
458  strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
459  em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
460  code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
461  br: /^ {2,}\n(?!\s*$)/,
462  del: noop,
463  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
464};
465
466inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
467inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
468
469inline.link = replace(inline.link)
470  ('inside', inline._inside)
471  ('href', inline._href)
472  ();
473
474inline.reflink = replace(inline.reflink)
475  ('inside', inline._inside)
476  ();
477
478/**
479 * Normal Inline Grammar
480 */
481
482inline.normal = merge({}, inline);
483
484/**
485 * Pedantic Inline Grammar
486 */
487
488inline.pedantic = merge({}, inline.normal, {
489  strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
490  em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
491});
492
493/**
494 * GFM Inline Grammar
495 */
496
497inline.gfm = merge({}, inline.normal, {
498  escape: replace(inline.escape)('])', '~|])')(),
499  url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
500  del: /^~~(?=\S)([\s\S]*?\S)~~/,
501  text: replace(inline.text)
502    (']|', '~]|')
503    ('|', '|https?://|')
504    ()
505});
506
507/**
508 * GFM + Line Breaks Inline Grammar
509 */
510
511inline.breaks = merge({}, inline.gfm, {
512  br: replace(inline.br)('{2,}', '*')(),
513  text: replace(inline.gfm.text)('{2,}', '*')()
514});
515
516/**
517 * Inline Lexer & Compiler
518 */
519
520function InlineLexer(links, options) {
521  this.options = options || marked.defaults;
522  this.links = links;
523  this.rules = inline.normal;
524  this.renderer = this.options.renderer || new Renderer;
525  this.renderer.options = this.options;
526
527  if (!this.links) {
528    throw new
529      Error('Tokens array requires a `links` property.');
530  }
531
532  if (this.options.gfm) {
533    if (this.options.breaks) {
534      this.rules = inline.breaks;
535    } else {
536      this.rules = inline.gfm;
537    }
538  } else if (this.options.pedantic) {
539    this.rules = inline.pedantic;
540  }
541}
542
543/**
544 * Expose Inline Rules
545 */
546
547InlineLexer.rules = inline;
548
549/**
550 * Static Lexing/Compiling Method
551 */
552
553InlineLexer.output = function(src, links, options) {
554  var inline = new InlineLexer(links, options);
555  return inline.output(src);
556};
557
558/**
559 * Lexing/Compiling
560 */
561
562InlineLexer.prototype.output = function(src) {
563  var out = ''
564    , link
565    , text
566    , href
567    , cap;
568
569  while (src) {
570    // escape
571    if (cap = this.rules.escape.exec(src)) {
572      src = src.substring(cap[0].length);
573      out += cap[1];
574      continue;
575    }
576
577    // autolink
578    if (cap = this.rules.autolink.exec(src)) {
579      src = src.substring(cap[0].length);
580      if (cap[2] === '@') {
581        text = cap[1].charAt(6) === ':'
582          ? this.mangle(cap[1].substring(7))
583          : this.mangle(cap[1]);
584        href = this.mangle('mailto:') + text;
585      } else {
586        text = escape(cap[1]);
587        href = text;
588      }
589      out += this.renderer.link(href, null, text);
590      continue;
591    }
592
593    // url (gfm)
594    if (!this.inLink && (cap = this.rules.url.exec(src))) {
595      src = src.substring(cap[0].length);
596      text = escape(cap[1]);
597      href = text;
598      out += this.renderer.link(href, null, text);
599      continue;
600    }
601
602    // tag
603    if (cap = this.rules.tag.exec(src)) {
604      if (!this.inLink && /^<a /i.test(cap[0])) {
605        this.inLink = true;
606      } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
607        this.inLink = false;
608      }
609      src = src.substring(cap[0].length);
610      out += this.options.sanitize
611        ? this.options.sanitizer
612          ? this.options.sanitizer(cap[0])
613          : escape(cap[0])
614        : cap[0]
615      continue;
616    }
617
618    // link
619    if (cap = this.rules.link.exec(src)) {
620      src = src.substring(cap[0].length);
621      this.inLink = true;
622      out += this.outputLink(cap, {
623        href: cap[2],
624        title: cap[3]
625      });
626      this.inLink = false;
627      continue;
628    }
629
630    // reflink, nolink
631    if ((cap = this.rules.reflink.exec(src))
632        || (cap = this.rules.nolink.exec(src))) {
633      src = src.substring(cap[0].length);
634      link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
635      link = this.links[link.toLowerCase()];
636      if (!link || !link.href) {
637        out += cap[0].charAt(0);
638        src = cap[0].substring(1) + src;
639        continue;
640      }
641      this.inLink = true;
642      out += this.outputLink(cap, link);
643      this.inLink = false;
644      continue;
645    }
646
647    // strong
648    if (cap = this.rules.strong.exec(src)) {
649      src = src.substring(cap[0].length);
650      out += this.renderer.strong(this.output(cap[2] || cap[1]));
651      continue;
652    }
653
654    // em
655    if (cap = this.rules.em.exec(src)) {
656      src = src.substring(cap[0].length);
657      out += this.renderer.em(this.output(cap[2] || cap[1]));
658      continue;
659    }
660
661    // code
662    if (cap = this.rules.code.exec(src)) {
663      src = src.substring(cap[0].length);
664      out += this.renderer.codespan(escape(cap[2], true));
665      continue;
666    }
667
668    // br
669    if (cap = this.rules.br.exec(src)) {
670      src = src.substring(cap[0].length);
671      out += this.renderer.br();
672      continue;
673    }
674
675    // del (gfm)
676    if (cap = this.rules.del.exec(src)) {
677      src = src.substring(cap[0].length);
678      out += this.renderer.del(this.output(cap[1]));
679      continue;
680    }
681
682    // text
683    if (cap = this.rules.text.exec(src)) {
684      src = src.substring(cap[0].length);
685      out += this.renderer.text(escape(this.smartypants(cap[0])));
686      continue;
687    }
688
689    if (src) {
690      throw new
691        Error('Infinite loop on byte: ' + src.charCodeAt(0));
692    }
693  }
694
695  return out;
696};
697
698/**
699 * Compile Link
700 */
701
702InlineLexer.prototype.outputLink = function(cap, link) {
703  var href = escape(link.href)
704    , title = link.title ? escape(link.title) : null;
705
706  return cap[0].charAt(0) !== '!'
707    ? this.renderer.link(href, title, this.output(cap[1]))
708    : this.renderer.image(href, title, escape(cap[1]));
709};
710
711/**
712 * Smartypants Transformations
713 */
714
715InlineLexer.prototype.smartypants = function(text) {
716  if (!this.options.smartypants) return text;
717  return text
718    // em-dashes
719    .replace(/---/g, '\u2014')
720    // en-dashes
721    .replace(/--/g, '\u2013')
722    // opening singles
723    .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
724    // closing singles & apostrophes
725    .replace(/'/g, '\u2019')
726    // opening doubles
727    .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
728    // closing doubles
729    .replace(/"/g, '\u201d')
730    // ellipses
731    .replace(/\.{3}/g, '\u2026');
732};
733
734/**
735 * Mangle Links
736 */
737
738InlineLexer.prototype.mangle = function(text) {
739  if (!this.options.mangle) return text;
740  var out = ''
741    , l = text.length
742    , i = 0
743    , ch;
744
745  for (; i < l; i++) {
746    ch = text.charCodeAt(i);
747    if (Math.random() > 0.5) {
748      ch = 'x' + ch.toString(16);
749    }
750    out += '&#' + ch + ';';
751  }
752
753  return out;
754};
755
756/**
757 * Renderer
758 */
759
760function Renderer(options) {
761  this.options = options || {};
762}
763
764Renderer.prototype.code = function(code, lang, escaped) {
765  if (this.options.highlight) {
766    var out = this.options.highlight(code, lang);
767    if (out != null && out !== code) {
768      escaped = true;
769      code = out;
770    }
771  }
772
773  if (!lang) {
774    return '<pre><code>'
775      + (escaped ? code : escape(code, true))
776      + '\n</code></pre>';
777  }
778
779  return '<pre><code class="'
780    + this.options.langPrefix
781    + escape(lang, true)
782    + '">'
783    + (escaped ? code : escape(code, true))
784    + '\n</code></pre>\n';
785};
786
787Renderer.prototype.blockquote = function(quote) {
788  return '<blockquote>\n' + quote + '</blockquote>\n';
789};
790
791Renderer.prototype.html = function(html) {
792  return html;
793};
794
795Renderer.prototype.heading = function(text, level, raw) {
796  return '<h'
797    + level
798    + ' id="'
799    + this.options.headerPrefix
800    + raw.toLowerCase().replace(/[^\w]+/g, '-')
801    + '">'
802    + text
803    + '</h'
804    + level
805    + '>\n';
806};
807
808Renderer.prototype.hr = function() {
809  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
810};
811
812Renderer.prototype.list = function(body, ordered) {
813  var type = ordered ? 'ol' : 'ul';
814  return '<' + type + '>\n' + body + '</' + type + '>\n';
815};
816
817Renderer.prototype.listitem = function(text) {
818  return '<li>
818' + text + '</li>\n';
819};
820
821Renderer.prototype.paragraph = function(text) {
822  return '<p>' + text + '</p>\n';
823};
824
825Renderer.prototype.table = function(header, body) {
826  return '<table>\n'
827    + '<thead>\n'
828    + header
829    + '</thead>\n'
830    + '<tbody>\n'
831    + body
832    + '</tbody>\n'
833    + '</table>\n';
834};
835
836Renderer.prototype.tablerow = function(content) {
837  return '<tr>\n' + content + '</tr>\n';
838};
839
840Renderer.prototype.tablecell = function(content, flags) {
841  var type = flags.header ? 'th' : 'td';
842  var tag = flags.align
843    ? '<' + type + ' style="text-align:' + flags.align + '">'
844    : '<' + type + '>';
845  return tag + content + '</' + type + '>\n';
846};
847
848// span level renderer
849Renderer.prototype.strong = function(text) {
850  return '<strong>' + text + '</strong>';
851};
852
853Renderer.prototype.em = function(text) {
854  return '<em>' + text + '</em>';
855};
856
857Renderer.prototype.codespan = function(text) {
858  return '<code>' + text + '</code>';
859};
860
861Renderer.prototype.br = function() {
862  return this.options.xhtml ? '<br/>' : '<br>';
863};
864
865Renderer.prototype.del = function(text) {
866  return '<del>' + text + '</del>';
867};
868
869Renderer.prototype.link = function(href, title, text) {
870  if (this.options.sanitize) {
871    try {
872      var prot = decodeURIComponent(unescape(href))
873        .replace(/[^\w:]/g, '')
874        .toLowerCase();
875    } catch (e) {
876      return '';
877    }
878    if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
879      return '';
880    }
881  }
882  var out = '<a href="' + href + '"';
883  if (title) {
884    out += ' title="' + title + '"';
885  }
886  out += '>
886' + text + '</a>';
887  return out;
888};
889
890Renderer.prototype.image = function(href, title, text) {
891  var out = '<img src="' + href + '" alt="' + text + '"';
892  if (title) {
893    out += ' title="' + title + '"';
894  }
895  out += this.options.xhtml ? '/>' : '>';
896  return out;
897};
898
899Renderer.prototype.text = function(text) {
900  return text;
901};
902
903/**
904 * Parsing & Compiling
905 */
906
907function Parser(options) {
908  this.tokens = [];
909  this.token = null;
910  this.options = options || marked.defaults;
911  this.options.renderer = this.options.renderer || new Renderer;
912  this.renderer = this.options.renderer;
913  this.renderer.options = this.options;
914}
915
916/**
917 * Static Parse Method
918 */
919
920Parser.parse = function(src, options, renderer) {
921  var parser = new Parser(options, renderer);
922  return parser.parse(src);
923};
924
925/**
926 * Parse Loop
927 */
928
929Parser.prototype.parse = function(src) {
930  this.inline = new InlineLexer(src.links, this.options, this.renderer);
931  this.tokens = src.reverse();
932
933  var out = '';
934  while (this.next()) {
935    out += this.tok();
936  }
937
938  return out;
939};
940
941/**
942 * Next Token
943 */
944
945Parser.prototype.next = function() {
946  return this.token = this.tokens.pop();
947};
948
949/**
950 * Preview Next Token
951 */
952
953Parser.prototype.peek = function() {
954  return this.tokens[this.tokens.length - 1] || 0;
955};
956
957/**
958 * Parse Text Tokens
959 */
960
961Parser.prototype.parseText = function() {
962  var body = this.token.text;
963
964  while (this.peek().type === 'text') {
965    body += '\n' + this.next().text;
966  }
967
968  return this.inline.output(body);
969};
970
971/**
972 * Parse Current Token
973 */
974
975Parser.prototype.tok = function() {
976  switch (this.token.type) {
977    case 'space': {
978      return '';
979    }
980    case 'hr': {
981      return this.renderer.hr();
982    }
983    case 'heading': {
984      return this.renderer.heading(
985        this.inline.output(this.token.text),
986        this.token.depth,
987        this.token.text);
988    }
989    case 'code': {
990      return this.renderer.code(this.token.text,
991        this.token.lang,
992        this.token.escaped);
993    }
994    case 'table': {
995      var header = ''
996        , body = ''
997        , i
998        , row
999        , cell
1000        , flags
1001        , j;
1002
1003      // header
1004      cell = '';
1005      for (i = 0; i < this.token.header.length; i++) {
1006        flags = { header: true, align: this.token.align[i] };
1007        cell += this.renderer.tablecell(
1008          this.inline.output(this.token.header[i]),
1009          { header: true, align: this.token.align[i] }
1010        );
1011      }
1012      header += this.renderer.tablerow(cell);
1013
1014      for (i = 0; i < this.token.cells.length; i++) {
1015        row = this.token.cells[i];
1016
1017        cell = '';
1018        for (j = 0; j < row.length; j++) {
1019          cell += this.renderer.tablecell(
1020            this.inline.output(row[j]),
1021            { header: false, align: this.token.align[j] }
1022          );
1023        }
1024
1025        body += this.renderer.tablerow(cell);
1026      }
1027      return this.renderer.table(header, body);
1028    }
1029    case 'blockquote_start': {
1030      var body = '';
1031
1032      while (this.next().type !== 'blockquote_end') {
1033        body += this.tok();
1034      }
1035
1036      return this.renderer.blockquote(body);
1037    }
1038    case 'list_start': {
1039      var body = ''
1040        , ordered = this.token.ordered;
1041
1042      while (this.next().type !== 'list_end') {
1043        body += this.tok();
1044      }
1045
1046      return this.renderer.list(body, ordered);
1047    }
1048    case 'list_item_start': {
1049      var body = '';
1050
1051      while (this.next().type !== 'list_item_end') {
1052        body += this.token.type === 'text'
1053          ? this.parseText()
1054          : this.tok();
1055      }
1056
1057      return this.renderer.listitem(body);
1058    }
1059    case 'loose_item_start': {
1060      var body = '';
1061
1062      while (this.next().type !== 'list_item_end') {
1063        body += this.tok();
1064      }
1065
1066      return this.renderer.listitem(body);
1067    }
1068    case 'html': {
1069      var html = !this.token.pre && !this.options.pedantic
1070        ? this.inline.output(this.token.text)
1071        : this.token.text;
1072      return this.renderer.html(html);
1073    }
1074    case 'paragraph': {
1075      return this.renderer.paragraph(this.inline.output(this.token.text));
1076    }
1077    case 'text': {
1078      return this.renderer.paragraph(this.parseText());
1079    }
1080  }
1081};
1082
1083/**
1084 * Helpers
1085 */
1086
1087function escape(html, encode) {
1088  return html
1089    .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
1090    .replace(/</g, '&lt;')
1091    .replace(/>/g, '&gt;')
1092    .replace(/"/g, '&quot;')
1093    .replace(/'/g, '&#39;');
1094}
1095
1096function unescape(html) {
1097	// explicitly match decimal, hex, and named HTML entities 
1098  return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
1099    n = n.toLowerCase();
1100    if (n === 'colon') return ':';
1101    if (n.charAt(0) === '#') {
1102      return n.charAt(1) === 'x'
1103        ? String.fromCharCode(parseInt(n.substring(2), 16))
1104        : String.fromCharCode(+n.substring(1));
1105    }
1106    return '';
1107  });
1108}
1109
1110function replace(regex, opt) {
1111  regex = regex.source;
1112  opt = opt || '';
1113  return function self(name, val) {
1114    if (!name) return new RegExp(regex, opt);
1115    val = val.source || val;
1116    val = val.replace(/(^|[^\[])\^/g, '$1');
1117    regex = regex.replace(name, val);
1118    return self;
1119  };
1120}
1121
1122function noop() {}
1123noop.exec = noop;
1124
1125function merge(obj) {
1126  var i = 1
1127    , target
1128    , key;
1129
1130  for (; i < arguments.length; i++) {
1131    target = arguments[i];
1132    for (key in target) {
1133      if (Object.prototype.hasOwnProperty.call(target, key)) {
1134        obj[key] = target[key];
1135      }
1136    }
1137  }
1138
1139  return obj;
1140}
1141
1142
1143/**
1144 * Marked
1145 */
1146
1147function marked(src, opt, callback) {
1148  if (callback || typeof opt === 'function') {
1149    if (!callback) {
1150      callback = opt;
1151      opt = null;
1152    }
1153
1154    opt = merge({}, marked.defaults, opt || {});
1155
1156    var highlight = opt.highlight
1157      , tokens
1158      , pending
1159      , i = 0;
1160
1161    try {
1162      tokens = Lexer.lex(src, opt)
1163    } catch (e) {
1164      return callback(e);
1165    }
1166
1167    pending = tokens.length;
1168
1169    var done = function(err) {
1170      if (err) {
1171        opt.highlight = highlight;
1172        return callback(err);
1173      }
1174
1175      var out;
1176
1177      try {
1178        out = Parser.parse(tokens, opt);
1179      } catch (e) {
1180        err = e;
1181      }
1182
1183      opt.highlight = highlight;
1184
1185      return err
1186        ? callback(err)
1187        : callback(null, out);
1188    };
1189
1190    if (!highlight || highlight.length < 3) {
1191      return done();
1192    }
1193
1194    delete opt.highlight;
1195
1196    if (!pending) return done();
1197
1198    for (; i < tokens.length; i++) {
1199      (function(token) {
1200        if (token.type !== 'code') {
1201          return --pending || done();
1202        }
1203        return highlight(token.text, token.lang, function(err, code) {
1204          if (err) return done(err);
1205          if (code == null || code === token.text) {
1206            return --pending || done();
1207          }
1208          token.text = code;
1209          token.escaped = true;
1210          --pending || done();
1211        });
1212      })(tokens[i]);
1213    }
1214
1215    return;
1216  }
1217  try {
1218    if (opt) opt = merge({}, marked.defaults, opt);
1219    return Parser.parse(Lexer.lex(src, opt), opt);
1220  } catch (e) {
1221    e.message += '\nPlease report this to https://github.com/chjj/marked.';
1222    if ((opt || marked.defaults).silent) {
1223      return '<p>An error occured:</p><pre>'
1224        + escape(e.message + '', true)
1225        + '</pre>';
1226    }
1227    throw e;
1228  }
1229}
1230
1231/**
1232 * Options
1233 */
1234
1235marked.options =
1236marked.setOptions = function(opt) {
1237  merge(marked.defaults, opt);
1238  return marked;
1239};
1240
1241marked.defaults = {
1242  gfm: true,
1243  tables: true,
1244  breaks: false,
1245  pedantic: false,
1246  sanitize: false,
1247  sanitizer: null,
1248  mangle: true,
1249  smartLists: false,
1250  silent: false,
1251  highlight: null,
1252  langPrefix: 'lang-',
1253  smartypants: false,
1254  headerPrefix: '',
1255  renderer: new Renderer,
1256  xhtml: false
1257};
1258
1259/**
1260 * Expose
1261 */
1262
1263marked.Parser = Parser;
1264marked.parser = Parser.parse;
1265
1266marked.Renderer = Renderer;
1267
1268marked.Lexer = Lexer;
1269marked.lexer = Lexer.lex;
1270
1271marked.InlineLexer = InlineLexer;
1272marked.inlineLexer = InlineLexer.output;
1273
1274marked.parse = marked;
1275
1276if (typeof module !== 'undefined' && typeof exports === 'object') {
1277  module.exports = marked;
1278} else if (typeof define === 'function' && define.amd) {
1279  define(function() { return marked; });
1280} else {
1281  this.marked = marked;
1282}
1283
1284}).call(function() {
1285  return this || (typeof window !== 'undefined' ? window : global);
1286}());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.