UNPKG

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