1 | # marked
|
2 |
|
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 | var marked = require('marked');
|
20 | console.log(marked('I am using __markdown__.'));
|
21 | // Outputs: <p>I am using <strong>markdown</strong>.</p>
|
22 | ```
|
23 |
|
24 | Example setting options with default values:
|
25 |
|
26 | ```js
|
27 | var marked = require('marked');
|
28 | marked.setOptions({
|
29 | renderer: new marked.Renderer(),
|
30 | gfm: true,
|
31 | tables: true,
|
32 | breaks: false,
|
33 | pedantic: false,
|
34 | sanitize: true,
|
35 | smartLists: true,
|
36 | smartypants: false
|
37 | });
|
38 |
|
39 | console.log(marked('I am using __markdown__.'));
|
40 | ```
|
41 |
|
42 | ### Browser
|
43 |
|
44 | ```html
|
45 | <!doctype html>
|
46 | <html>
|
47 | <head>
|
48 | <meta charset="utf-8"/>
|
49 | <title>Marked in the browser</title>
|
50 | <script src="lib/marked.js"></script>
|
51 | </head>
|
52 | <body>
|
53 | <div id="content"></div>
|
54 | <script>
|
55 | document.getElementById('content').innerHTML =
|
56 | marked('# Marked in browser\n\nRendered by **marked**.');
|
57 | </script>
|
58 | </body>
|
59 | </html>
|
60 | ```
|
61 |
|
62 | ## marked(markdownString [,options] [,callback])
|
63 |
|
64 | ### markdownString
|
65 |
|
66 | Type: `string`
|
67 |
|
68 | String of markdown source to be compiled.
|
69 |
|
70 | ### options
|
71 |
|
72 | Type: `object`
|
73 |
|
74 | Hash of options. Can also be set using the `marked.setOptions` method as seen
|
75 | above.
|
76 |
|
77 | ### callback
|
78 |
|
79 | Type: `function`
|
80 |
|
81 | Function called when the `markdownString` has been fully parsed when using
|
82 | async highlighting. If the `options` argument is omitted, this can be used as
|
83 | the second argument.
|
84 |
|
85 | ## Options
|
86 |
|
87 | ### highlight
|
88 |
|
89 | Type: `function`
|
90 |
|
91 | A function to highlight code blocks. The first example below uses async highlighting with
|
92 | [node-pygmentize-bundled][pygmentize], and the second is a synchronous example using
|
93 | [highlight.js][highlight]:
|
94 |
|
95 | ```js
|
96 | var marked = require('marked');
|
97 |
|
98 | var markdownString = '```js\n console.log("hello"); \n```';
|
99 |
|
100 | // Async highlighting with pygmentize-bundled
|
101 | marked.setOptions({
|
102 | highlight: function (code, lang, callback) {
|
103 | require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {
|
104 | callback(err, result.toString());
|
105 | });
|
106 | }
|
107 | });
|
108 |
|
109 | // Using async version of marked
|
110 | marked(markdownString, function (err, content) {
|
111 | if (err) throw err;
|
112 | console.log(content);
|
113 | });
|
114 |
|
115 | // Synchronous highlighting with highlight.js
|
116 | marked.setOptions({
|
117 | highlight: function (code) {
|
118 | return require('highlight.js').highlightAuto(code).value;
|
119 | }
|
120 | });
|
121 |
|
122 | console.log(marked(markdownString));
|
123 | ```
|
124 |
|
125 | #### highlight arguments
|
126 |
|
127 | `code`
|
128 |
|
129 | Type: `string`
|
130 |
|
131 | The section of code to pass to the highlighter.
|
132 |
|
133 | `lang`
|
134 |
|
135 | Type: `string`
|
136 |
|
137 | The programming language specified in the code block.
|
138 |
|
139 | `callback`
|
140 |
|
141 | Type: `function`
|
142 |
|
143 | The callback function to call when using an async highlighter.
|
144 |
|
145 | ### renderer
|
146 |
|
147 | Type: `object`
|
148 | Default: `new Renderer()`
|
149 |
|
150 | An object containing functions to render tokens to HTML.
|
151 |
|
152 | #### Overriding renderer methods
|
153 |
|
154 | The renderer option allows you to render tokens in a custom manor. Here is an
|
155 | example of overriding the default heading token rendering by adding an embedded anchor tag like on GitHub:
|
156 |
|
157 | ```javascript
|
158 | var marked = require('marked');
|
159 | var renderer = new marked.Renderer();
|
160 |
|
161 | renderer.heading = function (text, level) {
|
162 | var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
|
163 |
|
164 | return '<h' + level + '><a name="' +
|
165 | escapedText +
|
166 | '" class="anchor" href="#' +
|
167 | escapedText +
|
168 | '"><span class="header-link"></span></a>' +
|
169 | text + '</h' + level + '>';
|
170 | },
|
171 |
|
172 | console.log(marked('# heading+', { renderer: renderer }));
|
173 | ```
|
174 | This code will output the following HTML:
|
175 | ```html
|
176 | <h1>
|
177 | <a name="heading-" class="anchor" href="#heading-">
|
178 | <span class="header-link"></span>
|
179 | </a>
|
180 | heading+
|
181 | </h1>
|
182 | ```
|
183 |
|
184 | #### Block level renderer methods
|
185 |
|
186 | - code(*string* code, *string* language)
|
187 | - blockquote(*string* quote)
|
188 | - html(*string* html)
|
189 | - heading(*string* text, *number* level)
|
190 | - hr()
|
191 | - list(*string* body, *boolean* ordered)
|
192 | - listitem(*string* text)
|
193 | - paragraph(*string* text)
|
194 | - table(*string* header, *string* body)
|
195 | - tablerow(*string* content)
|
196 | - tablecell(*string* content, *object* flags)
|
197 |
|
198 | `flags` has the following properties:
|
199 |
|
200 | ```js
|
201 | {
|
202 | header: true || false,
|
203 | align: 'center' || 'left' || 'right'
|
204 | }
|
205 | ```
|
206 |
|
207 | #### Inline level renderer methods
|
208 |
|
209 | - strong(*string* text)
|
210 | - em(*string* text)
|
211 | - codespan(*string* code)
|
212 | - br()
|
213 | - del(*string* text)
|
214 | - link(*string* href, *string* title, *string* text)
|
215 | - image(*string* href, *string* title, *string* text)
|
216 |
|
217 | ### gfm
|
218 |
|
219 | Type: `boolean`
|
220 | Default: `true`
|
221 |
|
222 | Enable [GitHub flavored markdown][gfm].
|
223 |
|
224 | ### tables
|
225 |
|
226 | Type: `boolean`
|
227 | Default: `true`
|
228 |
|
229 | Enable GFM [tables][tables].
|
230 | This option requires the `gfm` option to be true.
|
231 |
|
232 | ### breaks
|
233 |
|
234 | Type: `boolean`
|
235 | Default: `false`
|
236 |
|
237 | Enable GFM [line breaks][breaks].
|
238 | This option requires the `gfm` option to be true.
|
239 |
|
240 | ### pedantic
|
241 |
|
242 | Type: `boolean`
|
243 | Default: `false`
|
244 |
|
245 | Conform to obscure parts of `markdown.pl` as much as possible. Don't fix any of
|
246 | the original markdown bugs or poor behavior.
|
247 |
|
248 | ### sanitize
|
249 |
|
250 | Type: `boolean`
|
251 | Default: `false`
|
252 |
|
253 | Sanitize the output. Ignore any HTML that has been input.
|
254 |
|
255 | ### smartLists
|
256 |
|
257 | Type: `boolean`
|
258 | Default: `true`
|
259 |
|
260 | Use smarter list behavior than the original markdown. May eventually be
|
261 | default with the old behavior moved into `pedantic`.
|
262 |
|
263 | ### smartypants
|
264 |
|
265 | Type: `boolean`
|
266 | Default: `false`
|
267 |
|
268 | Use "smart" typograhic punctuation for things like quotes and dashes.
|
269 |
|
270 | ## Access to lexer and parser
|
271 |
|
272 | You also have direct access to the lexer and parser if you so desire.
|
273 |
|
274 | ``` js
|
275 | var tokens = marked.lexer(text, options);
|
276 | console.log(marked.parser(tokens));
|
277 | ```
|
278 |
|
279 | ``` js
|
280 | var lexer = new marked.Lexer(options);
|
281 | var tokens = lexer.lex(text);
|
282 | console.log(tokens);
|
283 | console.log(lexer.rules);
|
284 | ```
|
285 |
|
286 | ## CLI
|
287 |
|
288 | ``` bash
|
289 | $ marked -o hello.html
|
290 | hello world
|
291 | ^D
|
292 | $ cat hello.html
|
293 | <p>hello world</p>
|
294 | ```
|
295 |
|
296 | ## Philosophy behind marked
|
297 |
|
298 | The point of marked was to create a markdown compiler where it was possible to
|
299 | frequently parse huge chunks of markdown without having to worry about
|
300 | caching the compiled output somehow...or blocking for an unnecesarily long time.
|
301 |
|
302 | marked is very concise and still implements all markdown features. It is also
|
303 | now fully compatible with the client-side.
|
304 |
|
305 | marked more or less passes the official markdown test suite in its
|
306 | entirety. This is important because a surprising number of markdown compilers
|
307 | cannot pass more than a few tests. It was very difficult to get marked as
|
308 | compliant as it is. It could have cut corners in several areas for the sake
|
309 | of performance, but did not in order to be exactly what you expect in terms
|
310 | of a markdown rendering. In fact, this is why marked could be considered at a
|
311 | disadvantage in the benchmarks above.
|
312 |
|
313 | Along with implementing every markdown feature, marked also implements [GFM
|
314 | features][gfmf].
|
315 |
|
316 | ## Benchmarks
|
317 |
|
318 | node v0.8.x
|
319 |
|
320 | ``` bash
|
321 | $ node test --bench
|
322 | marked completed in 3411ms.
|
323 | marked (gfm) completed in 3727ms.
|
324 | marked (pedantic) completed in 3201ms.
|
325 | robotskirt completed in 808ms.
|
326 | showdown (reuse converter) completed in 11954ms.
|
327 | showdown (new converter) completed in 17774ms.
|
328 | markdown-js completed in 17191ms.
|
329 | ```
|
330 |
|
331 | __Marked is now faster than Discount, which is written in C.__
|
332 |
|
333 | For those feeling skeptical: These benchmarks run the entire markdown test suite 1000 times. The test suite tests every feature. It doesn't cater to specific aspects.
|
334 |
|
335 | ### Pro level
|
336 |
|
337 | You also have direct access to the lexer and parser if you so desire.
|
338 |
|
339 | ``` js
|
340 | var tokens = marked.lexer(text, options);
|
341 | console.log(marked.parser(tokens));
|
342 | ```
|
343 |
|
344 | ``` js
|
345 | var lexer = new marked.Lexer(options);
|
346 | var tokens = lexer.lex(text);
|
347 | console.log(tokens);
|
348 | console.log(lexer.rules);
|
349 | ```
|
350 |
|
351 | ``` bash
|
352 | $ node
|
353 | > require('marked').lexer('> i am using marked.')
|
354 | [ { type: 'blockquote_start' },
|
355 | { type: 'paragraph',
|
356 | text: 'i am using marked.' },
|
357 | { type: 'blockquote_end' },
|
358 | links: {} ]
|
359 | ```
|
360 |
|
361 | ## Running Tests & Contributing
|
362 |
|
363 | If you want to submit a pull request, make sure your changes pass the test
|
364 | suite. If you're adding a new feature, be sure to add your own test.
|
365 |
|
366 | The marked test suite is set up slightly strangely: `test/new` is for all tests
|
367 | that are not part of the original markdown.pl test suite (this is where your
|
368 | test should go if you make one). `test/original` is only for the original
|
369 | markdown.pl tests. `test/tests` houses both types of tests after they have been
|
370 | combined and moved/generated by running `node test --fix` or `marked --test
|
371 | --fix`.
|
372 |
|
373 | In other words, if you have a test to add, add it to `test/new/` and then
|
374 | regenerate the tests with `node test --fix`. Commit the result. If your test
|
375 | uses a certain feature, for example, maybe it assumes GFM is *not* enabled, you
|
376 | can add `.nogfm` to the filename. So, `my-test.text` becomes
|
377 | `my-test.nogfm.text`. You can do this with any marked option. Say you want
|
378 | line breaks and smartypants enabled, your filename should be:
|
379 | `my-test.breaks.smartypants.text`.
|
380 |
|
381 | To run the tests:
|
382 |
|
383 | ``` bash
|
384 | cd marked/
|
385 | node test
|
386 | ```
|
387 |
|
388 | ### Contribution and License Agreement
|
389 |
|
390 | If you contribute code to this project, you are implicitly allowing your code
|
391 | to be distributed under the MIT license. You are also implicitly verifying that
|
392 | all code is your original work. `</legalese>`
|
393 |
|
394 | ## License
|
395 |
|
396 | Copyright (c) 2011-2014, Christopher Jeffrey. (MIT License)
|
397 |
|
398 | See LICENSE for more info.
|
399 |
|
400 | [gfm]: https://help.github.com/articles/github-flavored-markdown
|
401 | [gfmf]: http://github.github.com/github-flavored-markdown/
|
402 | [pygmentize]: https://github.com/rvagg/node-pygmentize-bundled
|
403 | [highlight]: https://github.com/isagalaev/highlight.js
|
404 | [badge]: http://badge.fury.io/js/marked
|
405 | [tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables
|
406 | [breaks]: https://help.github.com/articles/github-flavored-markdown#newlines
|