marked-rails 0.0.4 → 0.0.5

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.
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