UNPKG

16.1 kBMarkdownView Raw
1# Smarkdown
2
3[![npm](https://badgen.net/npm/v/smarkdown)](https://www.npmjs.com/package/smarkdown)
4[![gzip size](https://img.badgesize.io/https://cdn.jsdelivr.net/npm/smarkdown/dist/smarkdown.min.js?compression=gzip)](https://cdn.jsdelivr.net/npm/smarkdown/dist/smarkdown.min.js)
5[![install size](https://badgen.net/packagephobia/install/smarkdown)](https://packagephobia.now.sh/result?p=smarkdown)
6[![downloads](https://badgen.net/npm/dt/smarkdown)](https://www.npmjs.com/package/smarkdown)
7[![Build Status](https://travis-ci.org/yahtnif/smarkdown.svg?branch=master)](https://travis-ci.org/yahtnif/smarkdown)
8
9> Markdown parser, simplicity and extensibility. Fork of [marked](https://github.com/markedjs/marked) and [marked-ts](https://github.com/KostyaTretyak/marked-ts).
10
11## Features
12
13- **Awesome:** ES6, TypeScript, Rollup, Jest...
14- **Extensible:** Add your own [extensions](#extensions)
15- **Fast:** Low-level compiler for parsing markdown without caching or blocking for long periods of time
16- **Lightweight:** It's 9kb of minified and gzipped
17
18## Table of contents
19
20- [Install](#install)
21- [Usage](#usage)
22- [Options](#options)
23- [Extension](#extension)
24- [Renderer](#renderer)
25- [Comparison](#comparison)
26- [License](#license)
27
28## Install
29
30```sh
31yarn add smarkdown
32# or
33npm install smarkdown
34```
35
36**browser (CDN):** [jsDelivr](https://www.jsdelivr.com/package/npm/smarkdown) | [unpkg](https://unpkg.com/smarkdown/)
37
38## Usage
39
40Import the library as a module:
41
42```js
43import Smarkdown from 'smarkdown'
44```
45
46Or import the library with a script tag:
47
48```html
49<script src="https://cdn.jsdelivr.net/npm/smarkdown/dist/smarkdown.min.js"></script>
50```
51
52Example:
53
54```js
55// Resetting options
56Smarkdown.resetOptions()
57
58// Setting options
59Smarkdown.setOptions({
60 breaks: true
61})
62
63const str = 'I am using **Smarkdown**.'
64
65console.log(Smarkdown.parse(str))
66// <p>I am using <strong>Smarkdown</strong>.</p>
67
68console.log(Smarkdown.parse(str, { nop: true }))
69// I am using <strong>Smarkdown</strong>.
70```
71
72### Syntax highlighting
73
74```js
75// highlight.js
76import Smarkdown from 'smarkdown'
77import { highlight } from 'highlight.js'
78
79Smarkdown.setOptions({
80 highlight: (code, lang) => {
81 return lang && highlight.getLanguage(lang)
82 ? highlight.highlight(lang, code).value
83 : highlight.highlightAuto(code).value
84 }
85})
86```
87
88```js
89// prismjs
90import Smarkdown from 'smarkdown'
91import Prism from 'prismjs'
92import 'prismjs/components/prism-markdown'
93
94Smarkdown.setOptions({
95 highlight: (code, lang) => {
96 const language = Prism.languages[lang] ? lang : 'markdown'
97
98 return Prism.highlight(code, Prism.languages[language], language)
99 }
100})
101```
102
103## Options
104
105| Name | Type | Default | Note |
106| :-----------: | :-----------------: | :-----------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
107| baseUrl | String | null | A prefix url for any relative link. |
108| breaks | Boolean | false | If true, add `<br>` on a single line break (copies GitHub). Requires `gfm` be `true`. |
109| disabledRules | Array | [] | If set to `['lheading']`, will disable headers of an underline-ish style. |
110| extra | Boolean | false | If true, enable `footnote`. Requires `gfm` be `true`. |
111| gfm | Boolean | true | If true, use approved [GitHub Flavored Markdown (GFM) specification](https://github.github.com/gfm/). |
112| headerId | Boolean \| String | false | Include an `id` attribute when emitting headings.<br>If true, for all headings.<br>If set to `on`, for “non-close” atx-style headings (## h2, etc).<br>If set to `off`, for “close” atx-style headings (## h2 ##, etc). |
113| headerPrefix | String | '' | A string to prefix the id attribute when emitting headings. |
114| highlight | Function | (code, lang) => string | A function to highlight code blocks, see [Syntax highlighting](#syntax-highlighting) |
115| langAttribute | Boolean | false | If `true`, add `data-lang` attribute to highlight block code. |
116| langPrefix | String | 'language-' | A string to prefix the className in a `<code>` block. Useful for syntax highlighting. |
117| linksInNewTab | Boolean \| Function | false | If true, open links in new tabs. |
118| mangle | Boolean | true | If true, autolinked email address is escaped with HTML character references. |
119| nop | Boolean | false | If `true`, an inline text will not be taken in paragraph. |
120| pedantic | Boolean | false | If true, conform to the original `markdown.pl` as much as possible. Don't fix original markdown bugs or behavior. Turns off and overrides `gfm`. |
121| renderer | Renderer | Renderer | An object containing functions to render tokens to HTML. See [Renderer](#renderer) for more details. |
122| sanitize | Boolean | false | If true, sanitize the HTML passed into `markdownString` with the `sanitizer` function. |
123| sanitizer | Function | null | A function to sanitize the HTML passed into `markdownString`. |
124| silent | Boolean | false | If true, the parser does not throw any exception. |
125| slug | Function | str => built_in_slug(str) | Slugify `id` attribute for heading and footnote. |
126| smartLists | Boolean | false | If true, use smarter list behavior than those found in `markdown.pl`. |
127| smartypants | Boolean | false | If true, use "smart" typographic punctuation for things like quotes and dashes. |
128| trimLinkText | Function | null | Useful for text truncation. |
129| xhtml | Boolean | false | Self-close the tags for void elements (&lt;br/&gt;, &lt;img/&gt;, etc.) with a "/" as required by XHTML. |
130
131## Extension
132
133Using `Smarkdown.setRule(regExp, callback, [, options])`, which takes a regular expression as the first argument, and returns result `regExp.exec(string)` to `callback(execArr)`, which can be passed as a second argument.
134
135Extension options:
136
137| Name | Type | Default | inline | block |
138| :----------: | :------: | :-----: | :----: | :---: |
139| priority | Number | null | ✓ | ✓ |
140| checkPreChar | Function | null | ✓ | |
141
142### Inline
143
144```js
145/**
146 * sub
147 *
148 * H~2~O
149 * H<sub>2</sub>O
150 */
151const subRegex = /~(?=\S)([\s\S]*?\S)~/
152Smarkdown.setRule(subRegex, function(execArr) {
153 return `<sub>${this.output(execArr[1])}</sub>`
154})
155
156/**
157 * sup
158 *
159 * 1^st^
160 * 1<sup>st</sup>
161 */
162const supRegex = /\^(?=\S)([\s\S]*?\S)\^/
163Smarkdown.setRule(supRegex, function(execArr) {
164 return `<sup>${this.output(execArr[1])}</sup>`
165})
166
167/**
168 * mark
169 *
170 * ==Experience== is the best teacher.
171 * <mark>Experience</mark> is the best teacher.
172 */
173const markRegex = /==(?=\S)([\s\S]*?\S)==/
174Smarkdown.setRule(markRegex, function(execArr) {
175 return `<mark>${this.output(execArr[1])}</mark>`
176})
177
178/**
179 * hashtag
180 *
181 * #tag
182 * <span class="hashtag">tag</span>
183 */
184const hashtagRegex = /#([^\s#]+)((?:\b)|(?=\s|$))/
185Smarkdown.setRule(
186 hashtagRegex,
187 function(execArr) {
188 return `<span class="hashtag">${execArr[1]}</span>`
189 },
190 {
191 checkPreChar(char) {
192 return !char || /\s|\B/.test(char)
193 }
194 }
195)
196
197/**
198 * ruby annotation
199 *
200 * [注音]{zhuyin}
201 * <ruby>注音<rt>zhuyin</rt></ruby>
202 */
203const rubyAnnotationRegex = /\[([^\[\]{}]+)\]\{([^\[\]{}]+)\}/
204Smarkdown.setRule(
205 rubyAnnotationRegex,
206 function(execArr) {
207 return `<ruby>${execArr[1]}<rt>${execArr[2]}</rt></ruby>`
208 },
209 {
210 priority: 1
211 }
212)
213
214/**
215 * small text
216 *
217 * --small text-- => <span class="small-text">small text</span>
218 */
219const smallTextRegex = /--(?=\S)([\s\S]*?\S)--/
220Smarkdown.setRule(smallTextRegex, function(execArr) {
221 return `<span class="small-text">${execArr[1]}</span>`
222})
223
224/**
225 * large text
226 *
227 * ++large text++ => <span class="large-text is-1">large text</span>
228 * +++large text+++ => <span class="large-text is-2">large text</span>
229 * ++++large text++++ => <span class="large-text is-3">large text</span>
230 */
231const largeTextRegex = /(\+{2,})(?=\S)([\s\S]*?\S)\+{2,}/
232Smarkdown.setRule(largeTextRegex, function(execArr) {
233 let size = execArr[1].length - 1
234
235 if (size > 3) {
236 size = 3
237 }
238
239 return `<span class="large-text is-${size}">${execArr[2]}</span>`
240})
241```
242
243### Block
244
245```js
246// block container
247const extRegex = /::: *([\w-_]+) *\n([\s\S]*?)\n:::\s?/
248Smarkdown.setRule(extRegex, execArr => {
249 return `<div class="${execArr[1]}">${execArr[2]}</div>`
250})
251
252const str = `::: warning
253Lorem ipsum dolor sit amet, consectetur adipiscing elit lorem ipsum dolor.
254:::`
255
256console.log(Smarkdown.parse(str))
257
258// <div class="warning">Lorem ipsum dolor sit amet, consectetur adipiscing elit lorem ipsum dolor.</div>
259```
260
261### Unset
262
263```js
264Smarkdown.unsetRule(regExp)
265```
266
267## Renderer
268
269### Methods
270
271```js
272//*** Block level renderer methods. ***
273
274blockquote(quote)
275
276code(code, lang, escaped)
277
278footnote(footnotes)
279
280heading(text, level, raw, ends)
281
282hr()
283
284html(html)
285
286list(body, ordered, start, isTaskList)
287
288listitem(text, checked)
289
290paragraph(text)
291
292table(header, body)
293
294tablerow(content)
295
296tablecell(content, flags)
297
298//*** Inline level renderer methods. ***
299
300br()
301
302codespan(text)
303
304del(text)
305
306em(text)
307
308fnref(refname)
309
310image(href, title, text)
311
312link(href, title, text)
313
314strong(text)
315
316text(text)
317```
318
319### Overriding Renderer methods
320
321```js
322import Smarkdown from 'smarkdown'
323
324class NewRenderer extends Smarkdown.Renderer {
325 // Overriding parent method.
326 table(header, body) {
327 if (body) body = '<tbody>' + body + '</tbody>'
328
329 // add class .table to table
330 return `
331<table class="table">
332<thead>
333${header}</thead>
334${body}</table>
335`
336 }
337}
338
339Smarkdown.setOptions({ renderer: NewRenderer })
340// or pass new options to new Renderer
341Smarkdown.setOptions({ renderer: new NewRenderer(NewOptions) })
342```
343
344## Comparison
345
346| | Smarkdown | Marked | markdown-it |
347| :----------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
348| Version | [![npm](https://badgen.net/npm/v/smarkdown)](https://www.npmjs.com/package/smarkdown) | [![npm](https://badgen.net/npm/v/marked)](https://www.npmjs.com/package/marked) | [![npm](https://badgen.net/npm/v/markdown-it)](https://www.npmjs.com/package/markdown-it) |
349| Minified & Gzipped | [![gzip size](https://img.badgesize.io/https://cdn.jsdelivr.net/npm/smarkdown/dist/smarkdown.min.js?compression=gzip)](https://cdn.jsdelivr.net/npm/smarkdown/dist/smarkdown.min.js) | [![gzip size](https://img.badgesize.io/https://cdn.jsdelivr.net/npm/marked/marked.min.js?compression=gzip)](https://cdn.jsdelivr.net/npm/marked/marked.min.js) | [![gzip size](https://img.badgesize.io/https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js?compression=gzip)](https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js) |
350
351## License
352
353[MIT](./LICENSE)