UNPKG

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