1 | # remarkable
|
---|
2 |
|
---|
3 | [](https://travis-ci.org/jonschlinkert/remarkable)
|
---|
4 | [](https://www.npmjs.org/package/remarkable)
|
---|
5 | [](https://www.jsdelivr.com/package/npm/remarkable)
|
---|
6 | [](https://coveralls.io/r/jonschlinkert/remarkable?branch=dev)
|
---|
7 |
|
---|
8 | > Markdown parser done right. Fast and easy to extend.
|
---|
9 |
|
---|
10 | __[Live demo](http://jonschlinkert.github.io/remarkable/demo/)__
|
---|
11 |
|
---|
12 | - Supports the [CommonMark](http://commonmark.org/) spec +
|
---|
13 | [syntax extensions](#syntax-extensions) + sugar (URL autolinking, typographer).
|
---|
14 | - Configurable syntax! You can add new rules and even replace existing ones.
|
---|
15 | - [High speed](#benchmark)!
|
---|
16 | - [Community plugins](https://www.npmjs.org/browse/keyword/remarkable) on npm.
|
---|
17 |
|
---|
18 |
|
---|
19 | ## Install
|
---|
20 |
|
---|
21 | **node.js:**
|
---|
22 |
|
---|
23 | ```bash
|
---|
24 | npm install remarkable --save
|
---|
25 | ```
|
---|
26 |
|
---|
27 | **browser (CDN):**
|
---|
28 |
|
---|
29 | - [jsDeliver CDN](http://www.jsdelivr.com/#!remarkable "jsDelivr CDN")
|
---|
30 | - [cdnjs](https://cdnjs.com/libraries/remarkable "cdnjs")
|
---|
31 |
|
---|
32 |
|
---|
33 | ## Usage
|
---|
34 |
|
---|
35 | ```js
|
---|
36 | import { Remarkable } from 'remarkable';
|
---|
37 | var md = new Remarkable();
|
---|
38 |
|
---|
39 | console.log(md.render('# Remarkable rulezz!'));
|
---|
40 | // => <h1>Remarkable rulezz!</h1>
|
---|
41 | ```
|
---|
42 |
|
---|
43 | or with commonjs
|
---|
44 |
|
---|
45 | ```js
|
---|
46 | const { Remarkable } = require('remarkable');
|
---|
47 | var md = new Remarkable();
|
---|
48 |
|
---|
49 | console.log(md.render('# Remarkable rulezz!'));
|
---|
50 | // => <h1>Remarkable rulezz!</h1>
|
---|
51 | ```
|
---|
52 |
|
---|
53 |
|
---|
54 | If installed globally with `npm`:
|
---|
55 |
|
---|
56 | ```sh
|
---|
57 | cat myfile.md | remarkable
|
---|
58 | remarkable --file myfile.md
|
---|
59 |
|
---|
60 | # get options
|
---|
61 | remarkable -h
|
---|
62 | ```
|
---|
63 |
|
---|
64 | ## Documentation
|
---|
65 |
|
---|
66 | See the [docs](docs/) directory for documentation on the following topics:
|
---|
67 |
|
---|
68 | - [parser](docs/parser.md)
|
---|
69 | - [parsing_block](docs/parsing_block.md)
|
---|
70 | - [parsing_core](docs/parsing_core.md)
|
---|
71 | - [parsing_inline](docs/parsing_inline.md)
|
---|
72 | - [plugins](docs/plugins.md)
|
---|
73 | - [renderer](docs/renderer.md)
|
---|
74 |
|
---|
75 | ### Options
|
---|
76 |
|
---|
77 | By default, remarkable is configured to be similar to GFM, but with HTML disabled.
|
---|
78 | This is easy to change if you prefer different settings.
|
---|
79 |
|
---|
80 | There are two ways to define options.
|
---|
81 |
|
---|
82 | #### constructor
|
---|
83 |
|
---|
84 | Define options in the constructor:
|
---|
85 |
|
---|
86 | ```js
|
---|
87 | // Actual default values
|
---|
88 | var md = new Remarkable({
|
---|
89 | html: false, // Enable HTML tags in source
|
---|
90 | xhtmlOut: false, // Use '/' to close single tags (<br />)
|
---|
91 | breaks: false, // Convert '\n' in paragraphs into <br>
|
---|
92 | langPrefix: 'language-', // CSS language prefix for fenced blocks
|
---|
93 |
|
---|
94 | // Enable some language-neutral replacement + quotes beautification
|
---|
95 | typographer: false,
|
---|
96 |
|
---|
97 | // Double + single quotes replacement pairs, when typographer enabled,
|
---|
98 | // and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
|
---|
99 | quotes: '“”‘’',
|
---|
100 |
|
---|
101 | // Highlighter function. Should return escaped HTML,
|
---|
102 | // or '' if the source string is not changed
|
---|
103 | highlight: function (/*str, lang*/) { return ''; }
|
---|
104 | });
|
---|
105 |
|
---|
106 | console.log(md.render('# Remarkable rulezz!'));
|
---|
107 | // => <h1>Remarkable rulezz!</h1>
|
---|
108 | ```
|
---|
109 |
|
---|
110 | #### .set
|
---|
111 |
|
---|
112 | Or define options via the `.set()` method:
|
---|
113 |
|
---|
114 | ```js
|
---|
115 | import { Remarkable } from 'remarkable';
|
---|
116 |
|
---|
117 | var md = new Remarkable();
|
---|
118 |
|
---|
119 | md.set({
|
---|
120 | html: true,
|
---|
121 | breaks: true
|
---|
122 | });
|
---|
123 | ```
|
---|
124 |
|
---|
125 | **Note:** To achieve the best possible performance, don't modify a `Remarkable`
|
---|
126 | instance on the fly. If you need multiple configurations, create
|
---|
127 | multiple instances and initialize each with a configuration that is ideal for
|
---|
128 | that instance.
|
---|
129 |
|
---|
130 |
|
---|
131 | ### Presets
|
---|
132 |
|
---|
133 | Remarkable offers some "presets" as a convenience to quickly enable/disable
|
---|
134 | active syntax rules and options for common use cases.
|
---|
135 |
|
---|
136 | #### commonmark
|
---|
137 |
|
---|
138 | Enable strict [CommonMark](http://commonmark.org/) mode with the `commonmark` preset:
|
---|
139 |
|
---|
140 | ```js
|
---|
141 | import { Remarkable } from 'remarkable';
|
---|
142 | var md = new Remarkable('commonmark');
|
---|
143 | ```
|
---|
144 |
|
---|
145 | #### full
|
---|
146 |
|
---|
147 | Enable all available rules (but still with default options, if not set):
|
---|
148 |
|
---|
149 | ```js
|
---|
150 | import { Remarkable } from 'remarkable';
|
---|
151 | var md = new Remarkable('full');
|
---|
152 |
|
---|
153 | // Or with options:
|
---|
154 | var md = new Remarkable('full', {
|
---|
155 | html: true,
|
---|
156 | typographer: true
|
---|
157 | });
|
---|
158 | ```
|
---|
159 |
|
---|
160 |
|
---|
161 | ### Syntax highlighting
|
---|
162 |
|
---|
163 | Apply syntax highlighting to fenced code blocks with the `highlight` option:
|
---|
164 |
|
---|
165 | ```js
|
---|
166 | import { Remarkable } from 'remarkable';
|
---|
167 | import hljs from 'highlight.js' // https://highlightjs.org/
|
---|
168 |
|
---|
169 | // Actual default values
|
---|
170 | var md = new Remarkable({
|
---|
171 | highlight: function (str, lang) {
|
---|
172 | if (lang && hljs.getLanguage(lang)) {
|
---|
173 | try {
|
---|
174 | return hljs.highlight(lang, str).value;
|
---|
175 | } catch (err) {}
|
---|
176 | }
|
---|
177 |
|
---|
178 | try {
|
---|
179 | return hljs.highlightAuto(str).value;
|
---|
180 | } catch (err) {}
|
---|
181 |
|
---|
182 | return ''; // use external default escaping
|
---|
183 | }
|
---|
184 | });
|
---|
185 | ```
|
---|
186 |
|
---|
187 |
|
---|
188 | ### Syntax extensions
|
---|
189 |
|
---|
190 | Enabled by default:
|
---|
191 |
|
---|
192 | - [Footnotes](http://johnmacfarlane.net/pandoc/README.html#footnotes)
|
---|
193 | - [Tables](https://help.github.com/articles/github-flavored-markdown/#tables) (GFM)
|
---|
194 | - [\<del>](https://help.github.com/articles/github-flavored-markdown/#strikethrough)
|
---|
195 | (GFM strikethrough) - `~~deleted text~~`
|
---|
196 |
|
---|
197 | Disabled by default:
|
---|
198 |
|
---|
199 | - [\<sup>](http://johnmacfarlane.net/pandoc/README.html#superscripts-and-subscripts) - `19^th^`
|
---|
200 | - [\<sub>](http://johnmacfarlane.net/pandoc/README.html#superscripts-and-subscripts) - `H~2~O`
|
---|
201 | - [abbreviations](https://michelf.ca/projects/php-markdown/extra/#abbr)
|
---|
202 | - __\<ins>__ - `++inserted text++` (experimental)
|
---|
203 | - __\<mark>__ - `==marked text==` (experimental)
|
---|
204 |
|
---|
205 | **HEADS UP!**: Experimental extensions can be changed later for something like [Critic Markup](http://criticmarkup.com/), but you will still be able to use old-style rules via external plugins if you prefer.
|
---|
206 |
|
---|
207 |
|
---|
208 | ### Manage rules
|
---|
209 |
|
---|
210 | ```js
|
---|
211 | var md = new Remarkable();
|
---|
212 | md.inline.ruler.enable([ 'ins', 'mark' ]);
|
---|
213 | md.block.ruler.disable([ 'table', 'footnote' ]);
|
---|
214 |
|
---|
215 | // Enable everything
|
---|
216 | md = new Remarkable('full', {
|
---|
217 | html: true,
|
---|
218 | typographer: true,
|
---|
219 | });
|
---|
220 |
|
---|
221 | //
|
---|
222 | // Manually enable rules, disabled by default:
|
---|
223 | //
|
---|
224 | var md = new Remarkable();
|
---|
225 | md.core.ruler.enable([
|
---|
226 | 'abbr'
|
---|
227 | ]);
|
---|
228 | md.block.ruler.enable([
|
---|
229 | 'footnote',
|
---|
230 | 'deflist'
|
---|
231 | ]);
|
---|
232 | md.inline.ruler.enable([
|
---|
233 | 'footnote_inline',
|
---|
234 | 'ins',
|
---|
235 | 'mark',
|
---|
236 | 'sub',
|
---|
237 | 'sup'
|
---|
238 | ]);
|
---|
239 | ```
|
---|
240 |
|
---|
241 |
|
---|
242 | ### Typographer
|
---|
243 |
|
---|
244 | Although full-weight typographical replacements are language specific, `remarkable`
|
---|
245 | provides coverage for the most common and universal use cases:
|
---|
246 |
|
---|
247 | ```js
|
---|
248 | import { Remarkable } from 'remarkable';
|
---|
249 | var md = new Remarkable({
|
---|
250 | typographer: true,
|
---|
251 | quotes: '“”‘’'
|
---|
252 | });
|
---|
253 |
|
---|
254 | // Disable rules at all:
|
---|
255 | md.core.ruler.disable([ 'replacements', 'smartquotes' ]);
|
---|
256 |
|
---|
257 | // Actual default replacements:
|
---|
258 | //
|
---|
259 | // '' → ‘’
|
---|
260 | // "" → “”. Set '«»' for Russian, '„“' for German, empty to disable
|
---|
261 | // (c) (C) → ©
|
---|
262 | // (tm) (TM) → ™
|
---|
263 | // (r) (R) → ®
|
---|
264 | // +- → ±
|
---|
265 | // (p) (P) -> §
|
---|
266 | // ... → … (also ?.... → ?.., !.... → !..)
|
---|
267 | // ???????? → ???, !!!!! → !!!, `,,` → `,`
|
---|
268 | // -- → –, --- → —
|
---|
269 | //
|
---|
270 | ```
|
---|
271 |
|
---|
272 | Of course, you can also add your own rules or replace the defaults with something
|
---|
273 | more advanced or specific to your language.
|
---|
274 |
|
---|
275 |
|
---|
276 | ### Plugins
|
---|
277 |
|
---|
278 | Easily load plugins with the `.use()` method:
|
---|
279 |
|
---|
280 | ```js
|
---|
281 | var md = new Remarkable();
|
---|
282 |
|
---|
283 | md.use(plugin1)
|
---|
284 | .use(plugin2, opts)
|
---|
285 | .use(plugin3);
|
---|
286 | ```
|
---|
287 |
|
---|
288 | Please refer to the [plugin documentation](docs/plugins.md) to create your own
|
---|
289 | plugins.
|
---|
290 |
|
---|
291 | ### linkify plugin
|
---|
292 |
|
---|
293 | Autoconvert URL-like text to links
|
---|
294 |
|
---|
295 | ```js
|
---|
296 | import { Remarkable } from 'remarkable';
|
---|
297 | import { linkify } from 'remarkable/linkify';
|
---|
298 |
|
---|
299 | var md = new Remarkable().use(linkify);
|
---|
300 | ```
|
---|
301 |
|
---|
302 | ### UMD
|
---|
303 |
|
---|
304 | UMD bundle provides linkify out of the box
|
---|
305 |
|
---|
306 | ```js
|
---|
307 | const { Remarkable, linkify, utils } = window.remarkable;
|
---|
308 | ```
|
---|
309 |
|
---|
310 |
|
---|
311 | ## References / Thanks
|
---|
312 |
|
---|
313 | Big thanks to [John MacFarlane](https://github.com/jgm) for his work on the
|
---|
314 | CommonMark spec and reference implementations. His work saved us a lot of time
|
---|
315 | during this project's development.
|
---|
316 |
|
---|
317 | **Related Links:**
|
---|
318 |
|
---|
319 | 1. https://github.com/jgm/CommonMark - reference CommonMark implementations in C & JS,
|
---|
320 | also contains latest spec & online demo.
|
---|
321 | 2. http://talk.commonmark.org - CommonMark forum, good place to collaborate
|
---|
322 | developers' efforts.
|
---|
323 |
|
---|
324 |
|
---|
325 | ## Development / Modification
|
---|
326 |
|
---|
327 | [Parser](docs/parser.md) consists of several responsibility chains filled with
|
---|
328 | rules. You can reconfigure any of them as you wish. [Renderer](docs/renderer.md) also
|
---|
329 | can be modified and extended. See source code to understand details. Pay
|
---|
330 | attention to these properties:
|
---|
331 |
|
---|
332 | ```js
|
---|
333 | Remarkable.core
|
---|
334 | Remarkable.core.ruler
|
---|
335 | Remarkable.block
|
---|
336 | Remarkable.block.ruler
|
---|
337 | Remarkable.inline
|
---|
338 | Remarkable.inline.ruler
|
---|
339 | Remarkable.renderer
|
---|
340 | Remarkable.renderer.rules
|
---|
341 | ```
|
---|
342 |
|
---|
343 | ## Benchmark
|
---|
344 |
|
---|
345 | Here is result of CommonMark spec parse at Core i5 2.4 GHz (i5-4258U):
|
---|
346 |
|
---|
347 | ```bash
|
---|
348 | $ benchmark/benchmark.js spec
|
---|
349 | Selected samples: (1 of 27)
|
---|
350 | > spec
|
---|
351 |
|
---|
352 | Sample: spec.txt (110610 bytes)
|
---|
353 | > commonmark-reference x 40.42 ops/sec ±4.07% (51 runs sampled)
|
---|
354 | > current x 74.99 ops/sec ±4.69% (67 runs sampled)
|
---|
355 | > current-commonmark x 93.76 ops/sec ±1.23% (79 runs sampled)
|
---|
356 | > marked-0.3.2 x 22.92 ops/sec ±0.79% (41 runs sampled)
|
---|
357 | ```
|
---|
358 |
|
---|
359 | As you can see, `remarkable` doesn't pay with speed for its flexibility. Because
|
---|
360 | it's written in monomorphic style and uses JIT inline caches effectively.
|
---|
361 |
|
---|
362 |
|
---|
363 | ## Authors
|
---|
364 |
|
---|
365 | - Jon Schlinkert [github/jonschlinkert](https://github.com/jonschlinkert)
|
---|
366 | - Alex Kocharin [github/rlidwka](https://github.com/rlidwka)
|
---|
367 | - Vitaly Puzrin [github/puzrin](https://github.com/puzrin)
|
---|
368 |
|
---|
369 |
|
---|
370 | ## License
|
---|
371 |
|
---|
372 | [MIT](https://github.com/jonschlinkert/remarkable/blob/master/LICENSE)
|
---|