2018-02-25 16:37:11 -05:00
## Extending Marked
2018-02-25 16:01:22 -05:00
2019-07-08 09:13:53 -05:00
To champion the single-responsibility and open/closed principles, we have tried to make it relatively painless to extend marked. If you are looking to add custom functionality, this is the place to start.
2018-02-25 16:01:22 -05:00
2018-02-25 21:56:00 -05:00
< h2 id = "renderer" > The renderer< / h2 >
2018-02-25 16:01:22 -05:00
2020-04-01 21:08:44 -05:00
The renderer defines the output of the parser.
2018-02-25 16:37:11 -05:00
**Example:** Overriding default heading token by adding an embedded anchor tag like on GitHub.
```js
// Create reference instance
2019-07-08 09:13:53 -05:00
const marked = require('marked');
2018-02-25 16:37:11 -05:00
// Get reference
2019-07-08 09:13:53 -05:00
const renderer = new marked.Renderer();
2018-02-25 16:37:11 -05:00
// Override function
2018-02-25 16:01:22 -05:00
renderer.heading = function (text, level) {
2019-07-08 09:13:53 -05:00
const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
2018-02-25 16:01:22 -05:00
2018-03-27 23:38:03 +03:00
return `
< h $ { level } >
< a name = "${escapedText}" class = "anchor" href = "#${escapedText}" >
2018-02-25 22:06:18 -05:00
< span class = "header-link" > < / span >
< / a >
${text}
< /h${level}>`;
2018-02-25 16:01:22 -05:00
};
2018-02-25 16:37:11 -05:00
// Run marked
2019-07-08 09:13:53 -05:00
console.log(marked('# heading+', { renderer: renderer }));
2018-02-25 16:01:22 -05:00
```
2018-02-25 16:37:11 -05:00
**Output:**
2018-02-25 16:01:22 -05:00
```html
< h1 >
< a name = "heading-" class = "anchor" href = " #heading -" >
< span class = "header-link" > < / span >
< / a >
heading+
< / h1 >
```
2018-02-25 16:37:11 -05:00
### Block level renderer methods
2018-02-25 16:01:22 -05:00
2019-02-13 14:42:33 +09:00
- code(*string* code, *string* infostring, *boolean* escaped)
2018-02-25 16:01:22 -05:00
- blockquote(*string* quote)
- html(*string* html)
2019-02-13 14:42:33 +09:00
- heading(*string* text, *number* level, *string* raw, *Slugger* slugger)
2018-02-25 16:01:22 -05:00
- hr()
2018-07-29 00:20:04 +09:00
- list(*string* body, *boolean* ordered, *number* start)
2019-03-08 17:28:01 -06:00
- listitem(*string* text, *boolean* task, *boolean* checked)
2019-02-13 14:42:33 +09:00
- checkbox(*boolean* checked)
2018-02-25 16:01:22 -05:00
- paragraph(*string* text)
- table(*string* header, *string* body)
- tablerow(*string* content)
- tablecell(*string* content, *object* flags)
2019-02-13 14:42:33 +09:00
`slugger` has the `slug` method to create an unique id from value:
```js
slugger.slug('foo') // foo
slugger.slug('foo') // foo-1
slugger.slug('foo') // foo-2
slugger.slug('foo 1') // foo-1-1
slugger.slug('foo-1') // foo-1-2
...
```
2018-02-25 16:01:22 -05:00
`flags` has the following properties:
```js
{
header: true || false,
align: 'center' || 'left' || 'right'
}
```
2018-02-25 16:37:11 -05:00
### Inline level renderer methods
2018-02-25 16:01:22 -05:00
- strong(*string* text)
- em(*string* text)
- codespan(*string* code)
- br()
- del(*string* text)
- link(*string* href, *string* title, *string* text)
- image(*string* href, *string* title, *string* text)
- text(*string* text)
2018-02-25 16:37:11 -05:00
< h2 id = "lexer" > The lexer< / h2 >
2020-04-01 21:08:44 -05:00
The lexer turns a markdown string into block level tokens.
2018-02-25 16:37:11 -05:00
2020-04-01 21:08:44 -05:00
< h2 id = "inlinelexer" > The inline lexer< / h2 >
The inline lexer adds inline tokens to the block level tokens.
2018-02-25 16:37:11 -05:00
< h2 id = "parser" > The parser< / h2 >
2020-04-01 21:08:44 -05:00
The parser takes tokens as input and calls the renderer functions that are accosiated with those tokens.
2018-02-25 16:37:11 -05:00
***
2018-02-25 16:01:22 -05:00
< h2 id = "extend" > Access to lexer and parser< / h2 >
2020-04-01 21:08:44 -05:00
You also have direct access to the lexer, inline lexer, and parser if you so desire.
2018-02-25 16:01:22 -05:00
``` js
2020-04-01 21:08:44 -05:00
const blocks = marked.lexer(markdown, options);
const tokens = marked.inlineLexer(blocks, options);
2019-11-06 16:03:39 -06:00
console.log(marked.parser(tokens, options));
2018-02-25 16:01:22 -05:00
```
``` js
2019-07-08 09:13:53 -05:00
const lexer = new marked.Lexer(options);
2020-04-01 21:08:44 -05:00
const inlineLexer = new marked.InlineLexer(options);
const blocks = lexer.lex(markdown);
const tokens = inlineLexer.lex(blocks);
2018-02-25 16:01:22 -05:00
console.log(tokens);
2020-04-01 21:08:44 -05:00
console.log(lexer.rules); // block level rules
console.log(inlineLexer.rules); // inline level rules
2018-02-25 16:01:22 -05:00
```
``` bash
$ node
> require('marked').lexer('> i am using marked.')
[ { type: 'blockquote_start' },
{ type: 'paragraph',
text: 'i am using marked.' },
{ type: 'blockquote_end' },
links: {} ]
2018-03-28 00:54:11 +03:00
```
2018-03-28 01:10:10 +03:00
2020-04-01 21:08:44 -05:00
The Lexer and InlineLexer build an array of tokens, which will be passed to the Parser.
The Parser processes each token in the token array,
2018-03-28 01:10:10 +03:00
which are removed from the array of tokens:
``` js
const marked = require('marked');
const md = `
# heading
[link][1]
[1]: #heading "heading"
`;
2020-04-01 21:08:44 -05:00
const blocks = marked.lexer(md);
const tokens = marked.inlineLexer(blocks);
2018-03-28 01:10:10 +03:00
console.log(tokens);
const html = marked.parser(tokens);
console.log(html);
console.log(tokens);
```
``` bash
[ { type: 'heading', depth: 1, text: 'heading' },
{ type: 'paragraph', text: ' [link][1]' },
{ type: 'space' },
links: { '1': { href: '#heading ', title: 'heading' } } ]
< h1 id = "heading" > heading< / h1 >
< p > < a href = " #heading " title = "heading" > link</ a ></ p >
[ links: { '1': { href: '#heading ', title: 'heading' } } ]
```