marked 0.2.9 → 0.2.10

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.
package/README.md CHANGED
@@ -1,7 +1,200 @@
1
1
  # marked
2
2
 
3
- A full-featured markdown parser and compiler, written in javascript.
4
- Built for speed.
3
+ > A full-featured markdown parser and compiler, written in javascript. Built
4
+ > for speed.
5
+
6
+ [![NPM version](https://badge.fury.io/js/marked.png)][badge]
7
+
8
+ ## Install
9
+
10
+ ``` bash
11
+ npm install marked --save
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ Minimal usage:
17
+
18
+ ```js
19
+ console.log(marked('I am using __markdown__.'));
20
+ // Outputs: <p>I am using <i>markdown</i>.</p>
21
+ ```
22
+
23
+ Example using all options:
24
+
25
+ ```js
26
+ // Set default options except highlight which has no default
27
+ marked.setOptions({
28
+ gfm: true,
29
+ highlight: function (code, lang, callback) {
30
+ pygmentize({ lang: lang, format: 'html' }, code, function (err, result) {
31
+ if (err) return callback(err);
32
+ callback(null, result.toString());
33
+ });
34
+ },
35
+ tables: true,
36
+ breaks: false,
37
+ pedantic: false,
38
+ sanitize: true,
39
+ smartLists: true,
40
+ smartypants: false,
41
+ langPrefix: 'lang-'
42
+ });
43
+
44
+ // Using async version of marked
45
+ marked('I am using __markdown__.', function (err, content) {
46
+ if (err) throw err;
47
+ console.log(content);
48
+ });
49
+ ```
50
+
51
+ ## marked(markdownString, [options], [callback])
52
+
53
+ ### markdownString
54
+
55
+ Type: `String`
56
+
57
+ String of markdown source to be compiled.
58
+
59
+ ### options
60
+
61
+ Type: `Object`
62
+
63
+ Hash of options. Can also be set using the `marked.setOptions` method as seen
64
+ above.
65
+
66
+ ### callback
67
+
68
+ Type: `Function`
69
+
70
+ Function called when the `markdownString` has been fully parsed when using
71
+ async highlighting. If the `options` argument is omitted, this can be used as
72
+ the second argument as seen above:
73
+
74
+ ## Options
75
+
76
+ ### gfm
77
+
78
+ Type: `Boolean`
79
+ Default: `true`
80
+
81
+ Enable [GitHub flavored markdown][gfm].
82
+
83
+ ### highlight
84
+
85
+ Type: `Function`
86
+
87
+ A function to highlight code blocks. The function takes three arguments: code,
88
+ lang, and callback. The above example uses async highlighting with
89
+ [node-pygementize-bundled][pygmentize], and here is a synchronous example using
90
+ [highlight.js][highlight] which doesn't require the callback argument:
91
+
92
+ ```js
93
+ marked.setOptions({
94
+ highlight: function (code, lang) {
95
+ return hljs.highlightAuto(lang, code).value;
96
+ }
97
+ });
98
+ ```
99
+
100
+ #### highlight arguments
101
+
102
+ `code`
103
+
104
+ Type: `String`
105
+
106
+ The section of code to pass to the highlighter.
107
+
108
+ `lang`
109
+
110
+ Type: `String`
111
+
112
+ The programming language specified in the code block.
113
+
114
+ `callback`
115
+
116
+ Type: `String`
117
+
118
+ The callback function to call when using an async highlighter.
119
+
120
+ ### tables
121
+
122
+ Type: `Boolean`
123
+ Default: `true`
124
+
125
+ Enable GFM [tables][tables].
126
+ This option requires the `gfm` option to be true.
127
+
128
+ ### breaks
129
+
130
+ Type: `Boolean`
131
+ Default: `false`
132
+
133
+ Enable GFM [line breaks][breaks].
134
+ This option requires the `gfm` option to be true.
135
+
136
+ ### pedantic
137
+
138
+ Type: `Boolean`
139
+ Default: `false`
140
+
141
+ Conform to obscure parts of `markdown.pl` as much as possible. Don't fix any of
142
+ the original markdown bugs or poor behavior.
143
+
144
+ ### sanitize
145
+
146
+ Type: `Boolean`
147
+ Default: `false`
148
+
149
+ Sanitize the output. Ignore any HTML that has been input.
150
+
151
+ ### smartLists
152
+
153
+ Type: `Boolean`
154
+ Default: `true`
155
+
156
+ Use smarter list behavior than the original markdown. May eventually be
157
+ default with the old behavior moved into `pedantic`.
158
+
159
+ ### smartypants
160
+
161
+ Type: `Boolean`
162
+ Default: `false`
163
+
164
+ Use "smart" typograhic punctuation for things like quotes and dashes.
165
+
166
+ ### langPrefix
167
+
168
+ Type: `String`
169
+ Default: `lang-`
170
+
171
+ Set the prefix for code block classes.
172
+
173
+ ## Access to lexer and parser
174
+
175
+ You also have direct access to the lexer and parser if you so desire.
176
+
177
+ ``` js
178
+ var tokens = marked.lexer(text, options);
179
+ console.log(marked.parser(tokens));
180
+ ```
181
+
182
+ ``` js
183
+ var lexer = new marked.Lexer(options);
184
+ var tokens = lexer.lex(text);
185
+ console.log(tokens);
186
+ console.log(lexer.rules);
187
+ ```
188
+
189
+ ## CLI
190
+
191
+ ``` bash
192
+ $ marked -o hello.html
193
+ hello world
194
+ ^D
195
+ $ cat hello.html
196
+ <p>hello world</p>
197
+ ```
5
198
 
6
199
  ## Benchmarks
7
200
 
@@ -47,12 +240,6 @@ showdown (new converter) completed in 17774ms.
47
240
  markdown-js completed in 17191ms.
48
241
  ```
49
242
 
50
- ## Install
51
-
52
- ``` bash
53
- $ npm install marked
54
- ```
55
-
56
243
  ## Another Javascript Markdown Parser
57
244
 
58
245
  The point of marked was to create a markdown compiler where it was possible to
@@ -70,61 +257,8 @@ of performance, but did not in order to be exactly what you expect in terms
70
257
  of a markdown rendering. In fact, this is why marked could be considered at a
71
258
  disadvantage in the benchmarks above.
72
259
 
73
- Along with implementing every markdown feature, marked also implements
74
- [GFM features](http://github.github.com/github-flavored-markdown/).
75
-
76
- ## Options
77
-
78
- marked has a few different switches which change behavior.
79
-
80
- - __pedantic__: Conform to obscure parts of `markdown.pl` as much as possible.
81
- Don't fix any of the original markdown bugs or poor behavior.
82
- - __gfm__: Enable github flavored markdown (enabled by default).
83
- - __sanitize__: Sanitize the output. Ignore any HTML that has been input.
84
- - __highlight__: A callback to highlight code blocks.
85
- - __tables__: Enable GFM tables. This is enabled by default. (Requires the
86
- `gfm` option in order to be enabled).
87
- - __breaks__: Enable GFM line breaks. Disabled by default.
88
- - __smartLists__: Use smarter list behavior than the original markdown.
89
- Disabled by default. May eventually be default with the old behavior
90
- moved into `pedantic`.
91
- - __langPrefix__: Set the prefix for code block classes. Defaults to `lang-`.
92
-
93
- ## Usage
94
-
95
- ``` js
96
- // Set default options
97
- marked.setOptions({
98
- gfm: true,
99
- tables: true,
100
- breaks: false,
101
- pedantic: false,
102
- sanitize: true,
103
- smartLists: true,
104
- langPrefix: 'language-',
105
- highlight: function(code, lang) {
106
- if (lang === 'js') {
107
- return highlighter.javascript(code);
108
- }
109
- return code;
110
- }
111
- });
112
- console.log(marked('i am using __markdown__.'));
113
- ```
114
-
115
- You also have direct access to the lexer and parser if you so desire.
116
-
117
- ``` js
118
- var tokens = marked.lexer(text, options);
119
- console.log(marked.parser(tokens));
120
- ```
121
-
122
- ``` js
123
- var lexer = new marked.Lexer(options);
124
- var tokens = lexer.lex(text);
125
- console.log(tokens);
126
- console.log(lexer.rules);
127
- ```
260
+ Along with implementing every markdown feature, marked also implements [GFM
261
+ features][gfmf].
128
262
 
129
263
  ``` bash
130
264
  $ node
@@ -136,18 +270,49 @@ $ node
136
270
  links: {} ]
137
271
  ```
138
272
 
139
- ## CLI
273
+ ## Running Tests & Contributing
274
+
275
+ If you want to submit a pull request, make sure your changes pass the test
276
+ suite. If you're adding a new feature, be sure to add your own test.
277
+
278
+ The marked test suite is set up slightly strangely: `test/new` is for all tests
279
+ that are not part of the original markdown.pl test suite (this is where your
280
+ test should go if you make one). `test/original` is only for the original
281
+ markdown.pl tests. `test/tests` houses both types of tests after they have been
282
+ combined and moved/generated by running `node test --fix` or `marked --test
283
+ --fix`.
284
+
285
+ In other words, if you have a test to add, add it to `test/new/` and then
286
+ regenerate the tests with `node test --fix`. Commit the result. If your test
287
+ uses a certain feature, for example, maybe it assumes GFM is *not* enabled, you
288
+ can add `.nogfm` to the filename. So, `my-test.text` becomes
289
+ `my-test.nogfm.text`. You can do this with any marked option. Say you want
290
+ line breaks and smartypants enabled, your filename should be:
291
+ `my-test.breaks.smartypants.text`.
292
+
293
+ To run the tests:
140
294
 
141
295
  ``` bash
142
- $ marked -o hello.html
143
- hello world
144
- ^D
145
- $ cat hello.html
146
- <p>hello world</p>
296
+ cd marked/
297
+ node test
147
298
  ```
148
299
 
300
+ ### Contribution and License Agreement
301
+
302
+ If you contribute code to marked, you are implicitly allowing your code to be
303
+ distributed under the MIT license. You are also implicitly verifying that all
304
+ code is your original work. `</legalese>`
305
+
149
306
  ## License
150
307
 
151
308
  Copyright (c) 2011-2013, Christopher Jeffrey. (MIT License)
152
309
 
153
310
  See LICENSE for more info.
311
+
312
+ [gfm]: https://help.github.com/articles/github-flavored-markdown
313
+ [gfmf]: http://github.github.com/github-flavored-markdown/
314
+ [pygmentize]: https://github.com/rvagg/node-pygmentize-bundled
315
+ [highlight]: https://github.com/isagalaev/highlight.js
316
+ [badge]: http://badge.fury.io/js/marked
317
+ [tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables
318
+ [breaks]: https://help.github.com/articles/github-flavored-markdown#newlines
package/component.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "marked",
3
+ "version": "0.2.9",
4
+ "repo": "chjj/marked",
5
+ "description": "A markdown parser built for speed",
6
+ "keywords": ["markdown", "markup", "html"],
7
+ "scripts": ["lib/marked.js"],
8
+ "main": "lib/marked.js",
9
+ "license": "MIT"
10
+ }
package/lib/marked.js CHANGED
@@ -17,7 +17,7 @@ var block = {
17
17
  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
18
18
  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
19
19
  nptable: noop,
20
- lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
20
+ lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
21
21
  blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
22
22
  list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
23
23
  html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
@@ -75,7 +75,9 @@ block.gfm = merge({}, block.normal, {
75
75
  });
76
76
 
77
77
  block.gfm.paragraph = replace(block.paragraph)
78
- ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
78
+ ('(?!', '(?!'
79
+ + block.gfm.fences.source.replace('\\1', '\\2') + '|'
80
+ + block.list.source.replace('\\1', '\\3') + '|')
79
81
  ();
80
82
 
81
83
  /**
@@ -308,7 +310,7 @@ Lexer.prototype.token = function(src, top) {
308
310
  // Determine whether the next list item belongs here.
309
311
  // Backpedal if it does not belong in this list.
310
312
  if (this.options.smartLists && i !== l - 1) {
311
- b = block.bullet.exec(cap[i+1])[0];
313
+ b = block.bullet.exec(cap[i + 1])[0];
312
314
  if (bull !== b && !(bull.length > 1 && b.length > 1)) {
313
315
  src = cap.slice(i + 1).join('\n') + src;
314
316
  i = l - 1;
@@ -320,7 +322,7 @@ Lexer.prototype.token = function(src, top) {
320
322
  // for discount behavior.
321
323
  loose = next || /\n\n(?!\s*$)/.test(item);
322
324
  if (i !== l - 1) {
323
- next = item[item.length-1] === '\n';
325
+ next = item.charAt(item.length - 1) === '\n';
324
326
  if (!loose) loose = next;
325
327
  }
326
328
 
@@ -352,7 +354,7 @@ Lexer.prototype.token = function(src, top) {
352
354
  type: this.options.sanitize
353
355
  ? 'paragraph'
354
356
  : 'html',
355
- pre: cap[1] === 'pre' || cap[1] === 'script',
357
+ pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
356
358
  text: cap[0]
357
359
  });
358
360
  continue;
@@ -407,7 +409,7 @@ Lexer.prototype.token = function(src, top) {
407
409
  src = src.substring(cap[0].length);
408
410
  this.tokens.push({
409
411
  type: 'paragraph',
410
- text: cap[1][cap[1].length-1] === '\n'
412
+ text: cap[1].charAt(cap[1].length - 1) === '\n'
411
413
  ? cap[1].slice(0, -1)
412
414
  : cap[1]
413
415
  });
@@ -454,8 +456,8 @@ var inline = {
454
456
  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
455
457
  };
456
458
 
457
- inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
458
- inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
459
+ inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
460
+ inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
459
461
 
460
462
  inline.link = replace(inline.link)
461
463
  ('inside', inline._inside)
@@ -567,7 +569,7 @@ InlineLexer.prototype.output = function(src) {
567
569
  if (cap = this.rules.autolink.exec(src)) {
568
570
  src = src.substring(cap[0].length);
569
571
  if (cap[2] === '@') {
570
- text = cap[1][6] === ':'
572
+ text = cap[1].charAt(6) === ':'
571
573
  ? this.mangle(cap[1].substring(7))
572
574
  : this.mangle(cap[1]);
573
575
  href = this.mangle('mailto:') + text;
@@ -622,7 +624,7 @@ InlineLexer.prototype.output = function(src) {
622
624
  link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
623
625
  link = this.links[link.toLowerCase()];
624
626
  if (!link || !link.href) {
625
- out += cap[0][0];
627
+ out += cap[0].charAt(0);
626
628
  src = cap[0].substring(1) + src;
627
629
  continue;
628
630
  }
@@ -694,7 +696,7 @@ InlineLexer.prototype.output = function(src) {
694
696
  */
695
697
 
696
698
  InlineLexer.prototype.outputLink = function(cap, link) {
697
- if (cap[0][0] !== '!') {
699
+ if (cap[0].charAt(0) !== '!') {
698
700
  return '<a href="'
699
701
  + escape(link.href)
700
702
  + '"'
@@ -728,9 +730,17 @@ InlineLexer.prototype.outputLink = function(cap, link) {
728
730
  InlineLexer.prototype.smartypants = function(text) {
729
731
  if (!this.options.smartypants) return text;
730
732
  return text
733
+ // em-dashes
731
734
  .replace(/--/g, '\u2014')
732
- .replace(/'([^']*)'/g, '\u2018$1\u2019')
733
- .replace(/"([^"]*)"/g, '\u201C$1\u201D')
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
734
744
  .replace(/\.{3}/g, '\u2026');
735
745
  };
736
746
 
@@ -803,7 +813,7 @@ Parser.prototype.next = function() {
803
813
  */
804
814
 
805
815
  Parser.prototype.peek = function() {
806
- return this.tokens[this.tokens.length-1] || 0;
816
+ return this.tokens[this.tokens.length - 1] || 0;
807
817
  };
808
818
 
809
819
  /**
@@ -835,7 +845,9 @@ Parser.prototype.tok = function() {
835
845
  case 'heading': {
836
846
  return '<h'
837
847
  + this.token.depth
838
- + '>'
848
+ + ' id="'
849
+ + this.token.text.toLowerCase().replace(/[^\w]+/g, '-')
850
+ + '">'
839
851
  + this.inline.output(this.token.text)
840
852
  + '</h'
841
853
  + this.token.depth
@@ -877,9 +889,11 @@ Parser.prototype.tok = function() {
877
889
  body += '<thead>\n<tr>\n';
878
890
  for (i = 0; i < this.token.header.length; i++) {
879
891
  heading = this.inline.output(this.token.header[i]);
880
- body += this.token.align[i]
881
- ? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n'
882
- : '<th>' + heading + '</th>\n';
892
+ body += '<th';
893
+ if (this.token.align[i]) {
894
+ body += ' style="text-align:' + this.token.align[i] + '"';
895
+ }
896
+ body += '>' + heading + '</th>\n';
883
897
  }
884
898
  body += '</tr>\n</thead>\n';
885
899
 
@@ -890,9 +904,11 @@ Parser.prototype.tok = function() {
890
904
  body += '<tr>\n';
891
905
  for (j = 0; j < row.length; j++) {
892
906
  cell = this.inline.output(row[j]);
893
- body += this.token.align[j]
894
- ? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n'
895
- : '<td>' + cell + '</td>\n';
907
+ body += '<td';
908
+ if (this.token.align[j]) {
909
+ body += ' style="text-align:' + this.token.align[j] + '"';
910
+ }
911
+ body += '>' + cell + '</td>\n';
896
912
  }
897
913
  body += '</tr>\n';
898
914
  }
@@ -1027,7 +1043,7 @@ function marked(src, opt, callback) {
1027
1043
  opt = null;
1028
1044
  }
1029
1045
 
1030
- if (opt) opt = merge({}, marked.defaults, opt);
1046
+ opt = merge({}, marked.defaults, opt || {});
1031
1047
 
1032
1048
  var highlight = opt.highlight
1033
1049
  , tokens
@@ -1042,13 +1058,9 @@ function marked(src, opt, callback) {
1042
1058
 
1043
1059
  pending = tokens.length;
1044
1060
 
1045
- var done = function(hi) {
1061
+ var done = function() {
1046
1062
  var out, err;
1047
1063
 
1048
- if (hi !== true) {
1049
- delete opt.highlight;
1050
- }
1051
-
1052
1064
  try {
1053
1065
  out = Parser.parse(tokens, opt);
1054
1066
  } catch (e) {
@@ -1063,9 +1075,11 @@ function marked(src, opt, callback) {
1063
1075
  };
1064
1076
 
1065
1077
  if (!highlight || highlight.length < 3) {
1066
- return done(true);
1078
+ return done();
1067
1079
  }
1068
1080
 
1081
+ delete opt.highlight;
1082
+
1069
1083
  if (!pending) return done();
1070
1084
 
1071
1085
  for (; i < tokens.length; i++) {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "marked",
3
3
  "description": "A markdown parser built for speed",
4
4
  "author": "Christopher Jeffrey",
5
- "version": "0.2.9",
5
+ "version": "0.2.10",
6
6
  "main": "./lib/marked.js",
7
7
  "bin": "./bin/marked",
8
8
  "man": "./man/marked.1",