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