marked/docs/USING_PRO.md

172 lines
4.1 KiB
Markdown
Raw Normal View History

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
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
- code(*string* code, *string* infostring, *boolean* escaped)
2018-02-25 16:01:22 -05:00
- blockquote(*string* quote)
- html(*string* html)
- heading(*string* text, *number* level, *string* raw, *Slugger* slugger)
2018-02-25 16:01:22 -05:00
- hr()
- list(*string* body, *boolean* ordered, *number* start)
2019-03-08 17:28:01 -06:00
- listitem(*string* text, *boolean* task, *boolean* checked)
- 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)
`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: {} ]
```
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,
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);
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' } } ]
```