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