marked-rails 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Marked::Rails
2
2
 
3
- [Marked]("https://github.com/chjj/marked") is an awesome, fast Markdown parser and compiler.
3
+ [Marked](https://github.com/chjj/marked) is an awesome, fast Markdown parser and compiler.
4
4
  This is marked - wrapped in a gem - to make use of rubygems as a package manager.
5
5
  Marked is also available through Node Package Manager, but if you're working in Rails it's nice
6
6
  to have in gem form for simple integration into your rails apps.
7
7
 
8
- We are currently tracking marked version 0.2.5
8
+ We are currently tracking marked version 0.2.7
9
9
 
10
10
  ## Installation
11
11
 
@@ -29,7 +29,7 @@ Or install it yourself as:
29
29
 
30
30
  ## Usage (Without Asset Pipeline)
31
31
 
32
- _Coming soon_
32
+ _Coming ...Eventually_
33
33
 
34
34
  ## Contributing
35
35
 
@@ -41,4 +41,4 @@ Feel free to open an issue ticket if you find something that could be improved.
41
41
 
42
42
  ## Acknowledgements
43
43
 
44
- * This README is __heavily__ inspired by the one for [jquery-rails](https://github.com/rails/jquery-rails)
44
+ * This README is __heavily__ inspired by the one for [jquery-rails](https://github.com/rails/jquery-rails)
@@ -1,5 +1,5 @@
1
1
  module Marked
2
2
  module Rails
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  /**
2
- * marked - A markdown parser (https://github.com/chjj/marked)
3
- * Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed)
2
+ * marked - a markdown parser
3
+ * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
4
+ * https://github.com/chjj/marked
4
5
  */
5
6
 
6
7
  ;(function() {
@@ -15,11 +16,13 @@ var block = {
15
16
  fences: noop,
16
17
  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
17
18
  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
19
+ nptable: noop,
18
20
  lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
19
21
  blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
20
- list: /^( *)(bull) [^\0]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
22
+ list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
21
23
  html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
22
24
  def: /^ *\[([^\]]+)\]: *([^\s]+)(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
25
+ table: noop,
23
26
  paragraph: /^([^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+\n*/,
24
27
  text: /^[^\n]+/
25
28
  };
@@ -35,11 +38,16 @@ block.list = replace(block.list)
35
38
  ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
36
39
  ();
37
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
+
38
46
  block.html = replace(block.html)
39
- ('comment', /<!--[^\0]*?-->/)
40
- ('closed', /<(tag)[^\0]+?<\/\1>/)
47
+ ('comment', /<!--[\s\S]*?-->/)
48
+ ('closed', /<(tag)[\s\S]+?<\/\1>/)
41
49
  ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
42
- (/tag/g, tag())
50
+ (/tag/g, block._tag)
43
51
  ();
44
52
 
45
53
  block.paragraph = replace(block.paragraph)
@@ -47,41 +55,91 @@ block.paragraph = replace(block.paragraph)
47
55
  ('heading', block.heading)
48
56
  ('lheading', block.lheading)
49
57
  ('blockquote', block.blockquote)
50
- ('tag', '<' + tag())
58
+ ('tag', '<' + block._tag)
51
59
  ('def', block.def)
52
60
  ();
53
61
 
54
- block.normal = {
55
- fences: block.fences,
56
- paragraph: block.paragraph
57
- };
62
+ /**
63
+ * Normal Block Grammar
64
+ */
65
+
66
+ block.normal = merge({}, block);
67
+
68
+ /**
69
+ * GFM Block Grammar
70
+ */
58
71
 
59
- block.gfm = {
60
- fences: /^ *(```|~~~) *(\w+)? *\n([^\0]+?)\s*\1 *(?:\n+|$)/,
72
+ block.gfm = merge({}, block.normal, {
73
+ fences: /^ *(`{3,}|~{3,}) *(\w+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
61
74
  paragraph: /^/
62
- };
75
+ });
63
76
 
64
77
  block.gfm.paragraph = replace(block.paragraph)
65
78
  ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
66
79
  ();
67
80
 
81
+ /**
82
+ * GFM + Tables Block Grammar
83
+ */
84
+
85
+ block.tables = merge({}, block.gfm, {
86
+ nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
87
+ table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
88
+ });
89
+
68
90
  /**
69
91
  * Block Lexer
70
92
  */
71
93
 
72
- block.lexer = function(src) {
73
- var tokens = [];
94
+ function Lexer(options) {
95
+ this.tokens = [];
96
+ this.tokens.links = {};
97
+ this.options = options || marked.defaults;
98
+ this.rules = block.normal;
99
+
100
+ if (this.options.gfm) {
101
+ if (this.options.tables) {
102
+ this.rules = block.tables;
103
+ } else {
104
+ this.rules = block.gfm;
105
+ }
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Expose Block Rules
111
+ */
112
+
113
+ Lexer.rules = block;
114
+
115
+ /**
116
+ * Static Lex Method
117
+ */
74
118
 
75
- tokens.links = {};
119
+ Lexer.lex = function(src, options) {
120
+ var lexer = new Lexer(options);
121
+ return lexer.lex(src);
122
+ };
123
+
124
+ /**
125
+ * Preprocessing
126
+ */
76
127
 
128
+ Lexer.prototype.lex = function(src) {
77
129
  src = src
78
130
  .replace(/\r\n|\r/g, '\n')
79
- .replace(/\t/g, ' ');
131
+ .replace(/\t/g, ' ')
132
+ .replace(/\u00a0/g, ' ')
133
+ .replace(/\u2424/g, '\n');
80
134
 
81
- return block.token(src, tokens, true);
135
+ return this.token(src, true);
82
136
  };
83
137
 
84
- block.token = function(src, tokens, top) {
138
+ /**
139
+ * Lexing
140
+ */
141
+
142
+ Lexer.prototype.token = function(src, top) {
85
143
  var src = src.replace(/^ +$/gm, '')
86
144
  , next
87
145
  , loose
@@ -93,22 +151,22 @@ block.token = function(src, tokens, top) {
93
151
 
94
152
  while (src) {
95
153
  // newline
96
- if (cap = block.newline.exec(src)) {
154
+ if (cap = this.rules.newline.exec(src)) {
97
155
  src = src.substring(cap[0].length);
98
156
  if (cap[0].length > 1) {
99
- tokens.push({
157
+ this.tokens.push({
100
158
  type: 'space'
101
159
  });
102
160
  }
103
161
  }
104
162
 
105
163
  // code
106
- if (cap = block.code.exec(src)) {
164
+ if (cap = this.rules.code.exec(src)) {
107
165
  src = src.substring(cap[0].length);
108
166
  cap = cap[0].replace(/^ {4}/gm, '');
109
- tokens.push({
167
+ this.tokens.push({
110
168
  type: 'code',
111
- text: !options.pedantic
169
+ text: !this.options.pedantic
112
170
  ? cap.replace(/\n+$/, '')
113
171
  : cap
114
172
  });
@@ -116,9 +174,9 @@ block.token = function(src, tokens, top) {
116
174
  }
117
175
 
118
176
  // fences (gfm)
119
- if (cap = block.fences.exec(src)) {
177
+ if (cap = this.rules.fences.exec(src)) {
120
178
  src = src.substring(cap[0].length);
121
- tokens.push({
179
+ this.tokens.push({
122
180
  type: 'code',
123
181
  lang: cap[2],
124
182
  text: cap[3]
@@ -127,9 +185,9 @@ block.token = function(src, tokens, top) {
127
185
  }
128
186
 
129
187
  // heading
130
- if (cap = block.heading.exec(src)) {
188
+ if (cap = this.rules.heading.exec(src)) {
131
189
  src = src.substring(cap[0].length);
132
- tokens.push({
190
+ this.tokens.push({
133
191
  type: 'heading',
134
192
  depth: cap[1].length,
135
193
  text: cap[2]
@@ -137,10 +195,42 @@ block.token = function(src, tokens, top) {
137
195
  continue;
138
196
  }
139
197
 
198
+ // table no leading pipe (gfm)
199
+ if (top && (cap = this.rules.nptable.exec(src))) {
200
+ src = src.substring(cap[0].length);
201
+
202
+ item = {
203
+ type: 'table',
204
+ header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
205
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
206
+ cells: cap[3].replace(/\n$/, '').split('\n')
207
+ };
208
+
209
+ for (i = 0; i < item.align.length; i++) {
210
+ if (/^ *-+: *$/.test(item.align[i])) {
211
+ item.align[i] = 'right';
212
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
213
+ item.align[i] = 'center';
214
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
215
+ item.align[i] = 'left';
216
+ } else {
217
+ item.align[i] = null;
218
+ }
219
+ }
220
+
221
+ for (i = 0; i < item.cells.length; i++) {
222
+ item.cells[i] = item.cells[i].split(/ *\| */);
223
+ }
224
+
225
+ this.tokens.push(item);
226
+
227
+ continue;
228
+ }
229
+
140
230
  // lheading
141
- if (cap = block.lheading.exec(src)) {
231
+ if (cap = this.rules.lheading.exec(src)) {
142
232
  src = src.substring(cap[0].length);
143
- tokens.push({
233
+ this.tokens.push({
144
234
  type: 'heading',
145
235
  depth: cap[2] === '=' ? 1 : 2,
146
236
  text: cap[1]
@@ -149,19 +239,19 @@ block.token = function(src, tokens, top) {
149
239
  }
150
240
 
151
241
  // hr
152
- if (cap = block.hr.exec(src)) {
242
+ if (cap = this.rules.hr.exec(src)) {
153
243
  src = src.substring(cap[0].length);
154
- tokens.push({
244
+ this.tokens.push({
155
245
  type: 'hr'
156
246
  });
157
247
  continue;
158
248
  }
159
249
 
160
250
  // blockquote
161
- if (cap = block.blockquote.exec(src)) {
251
+ if (cap = this.rules.blockquote.exec(src)) {
162
252
  src = src.substring(cap[0].length);
163
253
 
164
- tokens.push({
254
+ this.tokens.push({
165
255
  type: 'blockquote_start'
166
256
  });
167
257
 
@@ -170,9 +260,9 @@ block.token = function(src, tokens, top) {
170
260
  // Pass `top` to keep the current
171
261
  // "toplevel" state. This is exactly
172
262
  // how markdown.pl works.
173
- block.token(cap, tokens, top);
263
+ this.token(cap, top);
174
264
 
175
- tokens.push({
265
+ this.tokens.push({
176
266
  type: 'blockquote_end'
177
267
  });
178
268
 
@@ -180,16 +270,16 @@ block.token = function(src, tokens, top) {
180
270
  }
181
271
 
182
272
  // list
183
- if (cap = block.list.exec(src)) {
273
+ if (cap = this.rules.list.exec(src)) {
184
274
  src = src.substring(cap[0].length);
185
275
 
186
- tokens.push({
276
+ this.tokens.push({
187
277
  type: 'list_start',
188
278
  ordered: isFinite(cap[2])
189
279
  });
190
280
 
191
281
  // Get each top-level item.
192
- cap = cap[0].match(block.item);
282
+ cap = cap[0].match(this.rules.item);
193
283
 
194
284
  next = false;
195
285
  l = cap.length;
@@ -207,7 +297,7 @@ block.token = function(src, tokens, top) {
207
297
  // list item contains. Hacky.
208
298
  if (~item.indexOf('\n ')) {
209
299
  space -= item.length;
210
- item = !options.pedantic
300
+ item = !this.options.pedantic
211
301
  ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
212
302
  : item.replace(/^ {1,4}/gm, '');
213
303
  }
@@ -221,21 +311,21 @@ block.token = function(src, tokens, top) {
221
311
  if (!loose) loose = next;
222
312
  }
223
313
 
224
- tokens.push({
314
+ this.tokens.push({
225
315
  type: loose
226
316
  ? 'loose_item_start'
227
317
  : 'list_item_start'
228
318
  });
229
319
 
230
320
  // Recurse.
231
- block.token(item, tokens);
321
+ this.token(item, false);
232
322
 
233
- tokens.push({
323
+ this.tokens.push({
234
324
  type: 'list_item_end'
235
325
  });
236
326
  }
237
327
 
238
- tokens.push({
328
+ this.tokens.push({
239
329
  type: 'list_end'
240
330
  });
241
331
 
@@ -243,10 +333,10 @@ block.token = function(src, tokens, top) {
243
333
  }
244
334
 
245
335
  // html
246
- if (cap = block.html.exec(src)) {
336
+ if (cap = this.rules.html.exec(src)) {
247
337
  src = src.substring(cap[0].length);
248
- tokens.push({
249
- type: options.sanitize
338
+ this.tokens.push({
339
+ type: this.options.sanitize
250
340
  ? 'paragraph'
251
341
  : 'html',
252
342
  pre: cap[1] === 'pre',
@@ -256,19 +346,53 @@ block.token = function(src, tokens, top) {
256
346
  }
257
347
 
258
348
  // def
259
- if (top && (cap = block.def.exec(src))) {
349
+ if (top && (cap = this.rules.def.exec(src))) {
260
350
  src = src.substring(cap[0].length);
261
- tokens.links[cap[1].toLowerCase()] = {
351
+ this.tokens.links[cap[1].toLowerCase()] = {
262
352
  href: cap[2],
263
353
  title: cap[3]
264
354
  };
265
355
  continue;
266
356
  }
267
357
 
358
+ // table (gfm)
359
+ if (top && (cap = this.rules.table.exec(src))) {
360
+ src = src.substring(cap[0].length);
361
+
362
+ item = {
363
+ type: 'table',
364
+ header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
365
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
366
+ cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
367
+ };
368
+
369
+ for (i = 0; i < item.align.length; i++) {
370
+ if (/^ *-+: *$/.test(item.align[i])) {
371
+ item.align[i] = 'right';
372
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
373
+ item.align[i] = 'center';
374
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
375
+ item.align[i] = 'left';
376
+ } else {
377
+ item.align[i] = null;
378
+ }
379
+ }
380
+
381
+ for (i = 0; i < item.cells.length; i++) {
382
+ item.cells[i] = item.cells[i]
383
+ .replace(/^ *\| *| *\| *$/g, '')
384
+ .split(/ *\| */);
385
+ }
386
+
387
+ this.tokens.push(item);
388
+
389
+ continue;
390
+ }
391
+
268
392
  // top-level paragraph
269
- if (top && (cap = block.paragraph.exec(src))) {
393
+ if (top && (cap = this.rules.paragraph.exec(src))) {
270
394
  src = src.substring(cap[0].length);
271
- tokens.push({
395
+ this.tokens.push({
272
396
  type: 'paragraph',
273
397
  text: cap[0]
274
398
  });
@@ -276,75 +400,141 @@ block.token = function(src, tokens, top) {
276
400
  }
277
401
 
278
402
  // text
279
- if (cap = block.text.exec(src)) {
403
+ if (cap = this.rules.text.exec(src)) {
280
404
  // Top-level should never reach here.
281
405
  src = src.substring(cap[0].length);
282
- tokens.push({
406
+ this.tokens.push({
283
407
  type: 'text',
284
408
  text: cap[0]
285
409
  });
286
410
  continue;
287
411
  }
412
+
413
+ if (src) {
414
+ throw new
415
+ Error('Infinite loop on byte: ' + src.charCodeAt(0));
416
+ }
288
417
  }
289
418
 
290
- return tokens;
419
+ return this.tokens;
291
420
  };
292
421
 
293
422
  /**
294
- * Inline Processing
423
+ * Inline-Level Grammar
295
424
  */
296
425
 
297
426
  var inline = {
298
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
427
+ escape: /^\\([\\`*{}\[\]()#+\-.!_>|])/,
299
428
  autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
300
429
  url: noop,
301
- tag: /^<!--[^\0]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
430
+ tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
302
431
  link: /^!?\[(inside)\]\(href\)/,
303
432
  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
304
433
  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
305
- strong: /^__([^\0]+?)__(?!_)|^\*\*([^\0]+?)\*\*(?!\*)/,
306
- em: /^\b_((?:__|[^\0])+?)_\b|^\*((?:\*\*|[^\0])+?)\*(?!\*)/,
307
- code: /^(`+)([^\0]*?[^`])\1(?!`)/,
434
+ strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
435
+ em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
436
+ code: /^(`+)([\s\S]*?[^`])\1(?!`)/,
308
437
  br: /^ {2,}\n(?!\s*$)/,
309
- text: /^[^\0]+?(?=[\\<!\[_*`]| {2,}\n|$)/
438
+ del: noop,
439
+ text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
310
440
  };
311
441
 
312
- inline._linkInside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
313
- inline._linkHref = /\s*<?([^\s]*?)>?(?:\s+['"]([^\0]*?)['"])?\s*/;
442
+ inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
443
+ inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
314
444
 
315
445
  inline.link = replace(inline.link)
316
- ('inside', inline._linkInside)
317
- ('href', inline._linkHref)
446
+ ('inside', inline._inside)
447
+ ('href', inline._href)
318
448
  ();
319
449
 
320
450
  inline.reflink = replace(inline.reflink)
321
- ('inside', inline._linkInside)
451
+ ('inside', inline._inside)
322
452
  ();
323
453
 
324
- inline.normal = {
325
- url: inline.url,
326
- strong: inline.strong,
327
- em: inline.em,
328
- text: inline.text
329
- };
454
+ /**
455
+ * Normal Inline Grammar
456
+ */
330
457
 
331
- inline.pedantic = {
332
- strong: /^__(?=\S)([^\0]*?\S)__(?!_)|^\*\*(?=\S)([^\0]*?\S)\*\*(?!\*)/,
333
- em: /^_(?=\S)([^\0]*?\S)_(?!_)|^\*(?=\S)([^\0]*?\S)\*(?!\*)/
334
- };
458
+ inline.normal = merge({}, inline);
459
+
460
+ /**
461
+ * Pedantic Inline Grammar
462
+ */
463
+
464
+ inline.pedantic = merge({}, inline.normal, {
465
+ strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
466
+ em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
467
+ });
468
+
469
+ /**
470
+ * GFM Inline Grammar
471
+ */
335
472
 
336
- inline.gfm = {
473
+ inline.gfm = merge({}, inline.normal, {
474
+ escape: replace(inline.escape)('])', '~])')(),
337
475
  url: /^(https?:\/\/[^\s]+[^.,:;"')\]\s])/,
338
- text: /^[^\0]+?(?=[\\<!\[_*`]|https?:\/\/| {2,}\n|$)/
476
+ del: /^~{2,}([\s\S]+?)~{2,}/,
477
+ text: replace(inline.text)
478
+ (']|', '~]|')
479
+ ('|', '|https?://|')
480
+ ()
481
+ });
482
+
483
+ /**
484
+ * GFM + Line Breaks Inline Grammar
485
+ */
486
+
487
+ inline.breaks = merge({}, inline.gfm, {
488
+ br: replace(inline.br)('{2,}', '*')(),
489
+ text: replace(inline.gfm.text)('{2,}', '*')()
490
+ });
491
+
492
+ /**
493
+ * Inline Lexer & Compiler
494
+ */
495
+
496
+ function InlineLexer(links, options) {
497
+ this.options = options || marked.defaults;
498
+ this.links = links;
499
+ this.rules = inline.normal;
500
+
501
+ if (!this.links) {
502
+ throw new
503
+ Error('Tokens array requires a `links` property.');
504
+ }
505
+
506
+ if (this.options.gfm) {
507
+ if (this.options.breaks) {
508
+ this.rules = inline.breaks;
509
+ } else {
510
+ this.rules = inline.gfm;
511
+ }
512
+ } else if (this.options.pedantic) {
513
+ this.rules = inline.pedantic;
514
+ }
515
+ }
516
+
517
+ /**
518
+ * Expose Inline Rules
519
+ */
520
+
521
+ InlineLexer.rules = inline;
522
+
523
+ /**
524
+ * Static Lexing/Compiling Method
525
+ */
526
+
527
+ InlineLexer.output = function(src, links, opt) {
528
+ var inline = new InlineLexer(links, opt);
529
+ return inline.output(src);
339
530
  };
340
531
 
341
532
  /**
342
- * Inline Lexer
533
+ * Lexing/Compiling
343
534
  */
344
535
 
345
- inline.lexer = function(src) {
536
+ InlineLexer.prototype.output = function(src) {
346
537
  var out = ''
347
- , links = tokens.links
348
538
  , link
349
539
  , text
350
540
  , href
@@ -352,20 +542,20 @@ inline.lexer = function(src) {
352
542
 
353
543
  while (src) {
354
544
  // escape
355
- if (cap = inline.escape.exec(src)) {
545
+ if (cap = this.rules.escape.exec(src)) {
356
546
  src = src.substring(cap[0].length);
357
547
  out += cap[1];
358
548
  continue;
359
549
  }
360
550
 
361
551
  // autolink
362
- if (cap = inline.autolink.exec(src)) {
552
+ if (cap = this.rules.autolink.exec(src)) {
363
553
  src = src.substring(cap[0].length);
364
554
  if (cap[2] === '@') {
365
555
  text = cap[1][6] === ':'
366
- ? mangle(cap[1].substring(7))
367
- : mangle(cap[1]);
368
- href = mangle('mailto:') + text;
556
+ ? this.mangle(cap[1].substring(7))
557
+ : this.mangle(cap[1]);
558
+ href = this.mangle('mailto:') + text;
369
559
  } else {
370
560
  text = escape(cap[1]);
371
561
  href = text;
@@ -379,7 +569,7 @@ inline.lexer = function(src) {
379
569
  }
380
570
 
381
571
  // url (gfm)
382
- if (cap = inline.url.exec(src)) {
572
+ if (cap = this.rules.url.exec(src)) {
383
573
  src = src.substring(cap[0].length);
384
574
  text = escape(cap[1]);
385
575
  href = text;
@@ -392,18 +582,18 @@ inline.lexer = function(src) {
392
582
  }
393
583
 
394
584
  // tag
395
- if (cap = inline.tag.exec(src)) {
585
+ if (cap = this.rules.tag.exec(src)) {
396
586
  src = src.substring(cap[0].length);
397
- out += options.sanitize
587
+ out += this.options.sanitize
398
588
  ? escape(cap[0])
399
589
  : cap[0];
400
590
  continue;
401
591
  }
402
592
 
403
593
  // link
404
- if (cap = inline.link.exec(src)) {
594
+ if (cap = this.rules.link.exec(src)) {
405
595
  src = src.substring(cap[0].length);
406
- out += outputLink(cap, {
596
+ out += this.outputLink(cap, {
407
597
  href: cap[2],
408
598
  title: cap[3]
409
599
  });
@@ -411,40 +601,40 @@ inline.lexer = function(src) {
411
601
  }
412
602
 
413
603
  // reflink, nolink
414
- if ((cap = inline.reflink.exec(src))
415
- || (cap = inline.nolink.exec(src))) {
604
+ if ((cap = this.rules.reflink.exec(src))
605
+ || (cap = this.rules.nolink.exec(src))) {
416
606
  src = src.substring(cap[0].length);
417
607
  link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
418
- link = links[link.toLowerCase()];
608
+ link = this.links[link.toLowerCase()];
419
609
  if (!link || !link.href) {
420
610
  out += cap[0][0];
421
611
  src = cap[0].substring(1) + src;
422
612
  continue;
423
613
  }
424
- out += outputLink(cap, link);
614
+ out += this.outputLink(cap, link);
425
615
  continue;
426
616
  }
427
617
 
428
618
  // strong
429
- if (cap = inline.strong.exec(src)) {
619
+ if (cap = this.rules.strong.exec(src)) {
430
620
  src = src.substring(cap[0].length);
431
621
  out += '<strong>'
432
- + inline.lexer(cap[2] || cap[1])
622
+ + this.output(cap[2] || cap[1])
433
623
  + '</strong>';
434
624
  continue;
435
625
  }
436
626
 
437
627
  // em
438
- if (cap = inline.em.exec(src)) {
628
+ if (cap = this.rules.em.exec(src)) {
439
629
  src = src.substring(cap[0].length);
440
630
  out += '<em>'
441
- + inline.lexer(cap[2] || cap[1])
631
+ + this.output(cap[2] || cap[1])
442
632
  + '</em>';
443
633
  continue;
444
634
  }
445
635
 
446
636
  // code
447
- if (cap = inline.code.exec(src)) {
637
+ if (cap = this.rules.code.exec(src)) {
448
638
  src = src.substring(cap[0].length);
449
639
  out += '<code>'
450
640
  + escape(cap[2], true)
@@ -453,24 +643,42 @@ inline.lexer = function(src) {
453
643
  }
454
644
 
455
645
  // br
456
- if (cap = inline.br.exec(src)) {
646
+ if (cap = this.rules.br.exec(src)) {
457
647
  src = src.substring(cap[0].length);
458
648
  out += '<br>';
459
649
  continue;
460
650
  }
461
651
 
652
+ // del (gfm)
653
+ if (cap = this.rules.del.exec(src)) {
654
+ src = src.substring(cap[0].length);
655
+ out += '<del>'
656
+ + this.output(cap[1])
657
+ + '</del>';
658
+ continue;
659
+ }
660
+
462
661
  // text
463
- if (cap = inline.text.exec(src)) {
662
+ if (cap = this.rules.text.exec(src)) {
464
663
  src = src.substring(cap[0].length);
465
664
  out += escape(cap[0]);
466
665
  continue;
467
666
  }
667
+
668
+ if (src) {
669
+ throw new
670
+ Error('Infinite loop on byte: ' + src.charCodeAt(0));
671
+ }
468
672
  }
469
673
 
470
674
  return out;
471
675
  };
472
676
 
473
- function outputLink(cap, link) {
677
+ /**
678
+ * Compile Link
679
+ */
680
+
681
+ InlineLexer.prototype.outputLink = function(cap, link) {
474
682
  if (cap[0][0] !== '!') {
475
683
  return '<a href="'
476
684
  + escape(link.href)
@@ -481,7 +689,7 @@ function outputLink(cap, link) {
481
689
  + '"'
482
690
  : '')
483
691
  + '>'
484
- + inline.lexer(cap[1])
692
+ + this.output(cap[1])
485
693
  + '</a>';
486
694
  } else {
487
695
  return '<img src="'
@@ -496,21 +704,100 @@ function outputLink(cap, link) {
496
704
  : '')
497
705
  + '>';
498
706
  }
499
- }
707
+ };
500
708
 
501
709
  /**
502
- * Parsing
710
+ * Mangle Links
503
711
  */
504
712
 
505
- var tokens
506
- , token;
713
+ InlineLexer.prototype.mangle = function(text) {
714
+ var out = ''
715
+ , l = text.length
716
+ , i = 0
717
+ , ch;
718
+
719
+ for (; i < l; i++) {
720
+ ch = text.charCodeAt(i);
721
+ if (Math.random() > 0.5) {
722
+ ch = 'x' + ch.toString(16);
723
+ }
724
+ out += '&#' + ch + ';';
725
+ }
507
726
 
508
- function next() {
509
- return token = tokens.pop();
727
+ return out;
728
+ };
729
+
730
+ /**
731
+ * Parsing & Compiling
732
+ */
733
+
734
+ function Parser(options) {
735
+ this.tokens = [];
736
+ this.token = null;
737
+ this.options = options || marked.defaults;
510
738
  }
511
739
 
512
- function tok() {
513
- switch (token.type) {
740
+ /**
741
+ * Static Parse Method
742
+ */
743
+
744
+ Parser.parse = function(src, options) {
745
+ var parser = new Parser(options);
746
+ return parser.parse(src);
747
+ };
748
+
749
+ /**
750
+ * Parse Loop
751
+ */
752
+
753
+ Parser.prototype.parse = function(src) {
754
+ this.inline = new InlineLexer(src.links, this.options);
755
+ this.tokens = src.reverse();
756
+
757
+ var out = '';
758
+ while (this.next()) {
759
+ out += this.tok();
760
+ }
761
+
762
+ return out;
763
+ };
764
+
765
+ /**
766
+ * Next Token
767
+ */
768
+
769
+ Parser.prototype.next = function() {
770
+ return this.token = this.tokens.pop();
771
+ };
772
+
773
+ /**
774
+ * Preview Next Token
775
+ */
776
+
777
+ Parser.prototype.peek = function() {
778
+ return this.tokens[this.tokens.length-1] || 0;
779
+ };
780
+
781
+ /**
782
+ * Parse Text Tokens
783
+ */
784
+
785
+ Parser.prototype.parseText = function() {
786
+ var body = this.token.text;
787
+
788
+ while (this.peek().type === 'text') {
789
+ body += '\n' + this.next().text;
790
+ }
791
+
792
+ return this.inline.output(body);
793
+ };
794
+
795
+ /**
796
+ * Parse Current Token
797
+ */
798
+
799
+ Parser.prototype.tok = function() {
800
+ switch (this.token.type) {
514
801
  case 'space': {
515
802
  return '';
516
803
  }
@@ -519,41 +806,78 @@ function tok() {
519
806
  }
520
807
  case 'heading': {
521
808
  return '<h'
522
- + token.depth
809
+ + this.token.depth
523
810
  + '>'
524
- + inline.lexer(token.text)
811
+ + this.inline.output(this.token.text)
525
812
  + '</h'
526
- + token.depth
813
+ + this.token.depth
527
814
  + '>\n';
528
815
  }
529
816
  case 'code': {
530
- if (options.highlight) {
531
- token.code = options.highlight(token.text, token.lang);
532
- if (token.code != null && token.code !== token.text) {
533
- token.escaped = true;
534
- token.text = token.code;
817
+ if (this.options.highlight) {
818
+ var code = this.options.highlight(this.token.text, this.token.lang);
819
+ if (code != null && code !== this.token.text) {
820
+ this.token.escaped = true;
821
+ this.token.text = code;
535
822
  }
536
823
  }
537
824
 
538
- if (!token.escaped) {
539
- token.text = escape(token.text, true);
825
+ if (!this.token.escaped) {
826
+ this.token.text = escape(this.token.text, true);
540
827
  }
541
828
 
542
829
  return '<pre><code'
543
- + (token.lang
830
+ + (this.token.lang
544
831
  ? ' class="lang-'
545
- + token.lang
832
+ + this.token.lang
546
833
  + '"'
547
834
  : '')
548
835
  + '>'
549
- + token.text
836
+ + this.token.text
550
837
  + '</code></pre>\n';
551
838
  }
839
+ case 'table': {
840
+ var body = ''
841
+ , heading
842
+ , i
843
+ , row
844
+ , cell
845
+ , j;
846
+
847
+ // header
848
+ body += '<thead>\n<tr>\n';
849
+ for (i = 0; i < this.token.header.length; i++) {
850
+ heading = this.inline.output(this.token.header[i]);
851
+ body += this.token.align[i]
852
+ ? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n'
853
+ : '<th>' + heading + '</th>\n';
854
+ }
855
+ body += '</tr>\n</thead>\n';
856
+
857
+ // body
858
+ body += '<tbody>\n'
859
+ for (i = 0; i < this.token.cells.length; i++) {
860
+ row = this.token.cells[i];
861
+ body += '<tr>\n';
862
+ for (j = 0; j < row.length; j++) {
863
+ cell = this.inline.output(row[j]);
864
+ body += this.token.align[j]
865
+ ? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n'
866
+ : '<td>' + cell + '</td>\n';
867
+ }
868
+ body += '</tr>\n';
869
+ }
870
+ body += '</tbody>\n';
871
+
872
+ return '<table>\n'
873
+ + body
874
+ + '</table>\n';
875
+ }
552
876
  case 'blockquote_start': {
553
877
  var body = '';
554
878
 
555
- while (next().type !== 'blockquote_end') {
556
- body += tok();
879
+ while (this.next().type !== 'blockquote_end') {
880
+ body += this.tok();
557
881
  }
558
882
 
559
883
  return '<blockquote>\n'
@@ -561,11 +885,11 @@ function tok() {
561
885
  + '</blockquote>\n';
562
886
  }
563
887
  case 'list_start': {
564
- var type = token.ordered ? 'ol' : 'ul'
888
+ var type = this.token.ordered ? 'ol' : 'ul'
565
889
  , body = '';
566
890
 
567
- while (next().type !== 'list_end') {
568
- body += tok();
891
+ while (this.next().type !== 'list_end') {
892
+ body += this.tok();
569
893
  }
570
894
 
571
895
  return '<'
@@ -579,10 +903,10 @@ function tok() {
579
903
  case 'list_item_start': {
580
904
  var body = '';
581
905
 
582
- while (next().type !== 'list_item_end') {
583
- body += token.type === 'text'
584
- ? parseText()
585
- : tok();
906
+ while (this.next().type !== 'list_item_end') {
907
+ body += this.token.type === 'text'
908
+ ? this.parseText()
909
+ : this.tok();
586
910
  }
587
911
 
588
912
  return '<li>'
@@ -592,8 +916,8 @@ function tok() {
592
916
  case 'loose_item_start': {
593
917
  var body = '';
594
918
 
595
- while (next().type !== 'list_item_end') {
596
- body += tok();
919
+ while (this.next().type !== 'list_item_end') {
920
+ body += this.tok();
597
921
  }
598
922
 
599
923
  return '<li>'
@@ -601,48 +925,22 @@ function tok() {
601
925
  + '</li>\n';
602
926
  }
603
927
  case 'html': {
604
- return !token.pre && !options.pedantic
605
- ? inline.lexer(token.text)
606
- : token.text;
928
+ return !this.token.pre && !this.options.pedantic
929
+ ? this.inline.output(this.token.text)
930
+ : this.token.text;
607
931
  }
608
932
  case 'paragraph': {
609
933
  return '<p>'
610
- + inline.lexer(token.text)
934
+ + this.inline.output(this.token.text)
611
935
  + '</p>\n';
612
936
  }
613
937
  case 'text': {
614
938
  return '<p>'
615
- + parseText()
939
+ + this.parseText()
616
940
  + '</p>\n';
617
941
  }
618
942
  }
619
- }
620
-
621
- function parseText() {
622
- var body = token.text
623
- , top;
624
-
625
- while ((top = tokens[tokens.length-1])
626
- && top.type === 'text') {
627
- body += '\n' + next().text;
628
- }
629
-
630
- return inline.lexer(body);
631
- }
632
-
633
- function parse(src) {
634
- tokens = src.reverse();
635
-
636
- var out = '';
637
- while (next()) {
638
- out += tok();
639
- }
640
-
641
- tokens = null;
642
- token = null;
643
-
644
- return out;
645
- }
943
+ };
646
944
 
647
945
  /**
648
946
  * Helpers
@@ -657,32 +955,6 @@ function escape(html, encode) {
657
955
  .replace(/'/g, '&#39;');
658
956
  }
659
957
 
660
- function mangle(text) {
661
- var out = ''
662
- , l = text.length
663
- , i = 0
664
- , ch;
665
-
666
- for (; i < l; i++) {
667
- ch = text.charCodeAt(i);
668
- if (Math.random() > 0.5) {
669
- ch = 'x' + ch.toString(16);
670
- }
671
- out += '&#' + ch + ';';
672
- }
673
-
674
- return out;
675
- }
676
-
677
- function tag() {
678
- var tag = '(?!(?:'
679
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
680
- + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
681
- + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
682
-
683
- return tag;
684
- }
685
-
686
958
  function replace(regex, opt) {
687
959
  regex = regex.source;
688
960
  opt = opt || '';
@@ -698,80 +970,78 @@ function replace(regex, opt) {
698
970
  function noop() {}
699
971
  noop.exec = noop;
700
972
 
973
+ function merge(obj) {
974
+ var i = 1
975
+ , target
976
+ , key;
977
+
978
+ for (; i < arguments.length; i++) {
979
+ target = arguments[i];
980
+ for (key in target) {
981
+ if (Object.prototype.hasOwnProperty.call(target, key)) {
982
+ obj[key] = target[key];
983
+ }
984
+ }
985
+ }
986
+
987
+ return obj;
988
+ }
989
+
701
990
  /**
702
991
  * Marked
703
992
  */
704
993
 
705
994
  function marked(src, opt) {
706
- setOptions(opt);
707
- return parse(block.lexer(src));
995
+ try {
996
+ return Parser.parse(Lexer.lex(src, opt), opt);
997
+ } catch (e) {
998
+ e.message += '\nPlease report this to https://github.com/chjj/marked.';
999
+ if ((opt || marked.defaults).silent) {
1000
+ return 'An error occured:\n' + e.message;
1001
+ }
1002
+ throw e;
1003
+ }
708
1004
  }
709
1005
 
710
1006
  /**
711
1007
  * Options
712
1008
  */
713
1009
 
714
- var options
715
- , defaults;
716
-
717
- function setOptions(opt) {
718
- if (!opt) opt = defaults;
719
- if (options === opt) return;
720
- options = opt;
721
-
722
- if (options.gfm) {
723
- block.fences = block.gfm.fences;
724
- block.paragraph = block.gfm.paragraph;
725
- inline.text = inline.gfm.text;
726
- inline.url = inline.gfm.url;
727
- } else {
728
- block.fences = block.normal.fences;
729
- block.paragraph = block.normal.paragraph;
730
- inline.text = inline.normal.text;
731
- inline.url = inline.normal.url;
732
- }
733
-
734
- if (options.pedantic) {
735
- inline.em = inline.pedantic.em;
736
- inline.strong = inline.pedantic.strong;
737
- } else {
738
- inline.em = inline.normal.em;
739
- inline.strong = inline.normal.strong;
740
- }
741
- }
742
-
743
1010
  marked.options =
744
1011
  marked.setOptions = function(opt) {
745
- defaults = opt;
746
- setOptions(opt);
1012
+ marked.defaults = opt;
747
1013
  return marked;
748
1014
  };
749
1015
 
750
- marked.setOptions({
1016
+ marked.defaults = {
751
1017
  gfm: true,
1018
+ tables: true,
1019
+ breaks: false,
752
1020
  pedantic: false,
753
1021
  sanitize: false,
1022
+ silent: false,
754
1023
  highlight: null
755
- });
1024
+ };
756
1025
 
757
1026
  /**
758
1027
  * Expose
759
1028
  */
760
1029
 
761
- marked.parser = function(src, opt) {
762
- setOptions(opt);
763
- return parse(src);
764
- };
1030
+ marked.Parser = Parser;
1031
+ marked.parser = Parser.parse;
765
1032
 
766
- marked.lexer = function(src, opt) {
767
- setOptions(opt);
768
- return block.lexer(src);
769
- };
1033
+ marked.Lexer = Lexer;
1034
+ marked.lexer = Lexer.lex;
1035
+
1036
+ marked.InlineLexer = InlineLexer;
1037
+ marked.inlineLexer = InlineLexer.output;
770
1038
 
771
1039
  marked.parse = marked;
772
1040
 
773
1041
  if (typeof module !== 'undefined') {
774
1042
  module.exports = marked;
1043
+ } else if (typeof define === 'function' && define.amd) {
1044
+ define(function() { return marked; });
775
1045
  } else {
776
1046
  this.marked = marked;
777
1047
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marked-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-10-04 00:00:00.000000000 Z
13
+ date: 2013-01-08 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: ! 'A gemified verison of the chjj/marked: "A full-featured markdown parser
16
16
  and compiler, written in javascript."'
@@ -42,21 +42,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
42
  - - ! '>='
43
43
  - !ruby/object:Gem::Version
44
44
  version: '0'
45
- segments:
46
- - 0
47
- hash: -1520128397969079230
48
45
  required_rubygems_version: !ruby/object:Gem::Requirement
49
46
  none: false
50
47
  requirements:
51
48
  - - ! '>='
52
49
  - !ruby/object:Gem::Version
53
50
  version: '0'
54
- segments:
55
- - 0
56
- hash: -1520128397969079230
57
51
  requirements: []
58
52
  rubyforge_project:
59
- rubygems_version: 1.8.24
53
+ rubygems_version: 1.8.10
60
54
  signing_key:
61
55
  specification_version: 3
62
56
  summary: A gemified verison of the chjj/marked