fix: remove deprecated options (#2936)
BREAKING CHANGE: deprecated options removed. See https://marked.js.org/using_advanced#options to see how to enable the removed options with extensions.
This commit is contained in:
parent
fc643a2625
commit
22ebdb2507
@ -54,16 +54,21 @@ console.log(marked.parse(markdownString));
|
|||||||
|silent |`boolean` |`false` |v0.2.7 |If true, the parser does not throw any exception or log any warning. Any error will be returned as a string.|
|
|silent |`boolean` |`false` |v0.2.7 |If true, the parser does not throw any exception or log any warning. Any error will be returned as a string.|
|
||||||
|tokenizer |`object` |`new Tokenizer()`|v1.0.0|An object containing functions to create tokens from markdown. See [extensibility](/using_pro) for more details.|
|
|tokenizer |`object` |`new Tokenizer()`|v1.0.0|An object containing functions to create tokens from markdown. See [extensibility](/using_pro) for more details.|
|
||||||
|walkTokens |`function` |`null`|v1.1.0|A function which is called for every token. See [extensibility](/using_pro) for more details.|
|
|walkTokens |`function` |`null`|v1.1.0|A function which is called for every token. See [extensibility](/using_pro) for more details.|
|
||||||
|baseUrl (**deprecated**)|`string` |`null` |v0.3.9 |Deprecated in v5.0.0 use [`marked-base-url`](https://www.npmjs.com/package/marked-base-url) to prefix url for any relative link. |
|
|
||||||
|headerIds (**deprecated**)|`boolean` |`true` |v0.4.0 |Deprecated in v5.0.0 use [`marked-gfm-heading-id`](https://www.npmjs.com/package/marked-gfm-heading-id) to include an `id` attribute when emitting headings (h1, h2, h3, etc).|
|
## Old Options
|
||||||
|headerPrefix (**deprecated**)|`string` |`''` |v0.3.0 |Deprecated in v5.0.0 use [`marked-gfm-heading-id`](https://www.npmjs.com/package/marked-gfm-heading-id) to add a string to prefix the `id` attribute when emitting headings (h1, h2, h3, etc).|
|
|
||||||
|highlight (**deprecated**)|`function`|`null` |v0.3.0 |Deprecated in v5.0.0 use [`marked-highlight`](https://www.npmjs.com/package/marked-highlight) to add highlighting to code blocks. |
|
|Member |Type |Default |Since |Notes |
|
||||||
|langPrefix (**deprecated**)|`string` |`'language-'`|v0.3.0|Deprecated in v5.0.0 use [`marked-highlight`](https://www.npmjs.com/package/marked-highlight) to prefix the className in a `<code>` block. Useful for syntax highlighting.|
|
|:-----------|:---------|:--------|:--------|:-------------|
|
||||||
|mangle (**deprecated**)|`boolean` |`true` |v0.3.4 |Deprecated in v5.0.0 use [`marked-mangle`](https://www.npmjs.com/package/marked-mangle) to mangle email addresses.|
|
|baseUrl (**removed**)|`string` |`null` |v0.3.9 |Removed in v8.0.0 use [`marked-base-url`](https://www.npmjs.com/package/marked-base-url) to prefix url for any relative link. |
|
||||||
|sanitize (**deprecated**)|`boolean` |`false` |v0.2.1 |If true, sanitize the HTML passed into `markdownString` with the `sanitizer` function.<br>**Warning**: This feature is deprecated and it should NOT be used as it cannot be considered secure.<br>Instead use a sanitize library, like [DOMPurify](https://github.com/cure53/DOMPurify) (recommended), [sanitize-html](https://github.com/apostrophecms/sanitize-html) or [insane](https://github.com/bevacqua/insane) on the output HTML! |
|
|headerIds (**removed**)|`boolean` |`true` |v0.4.0 |Removed in v8.0.0 use [`marked-gfm-heading-id`](https://www.npmjs.com/package/marked-gfm-heading-id) to include an `id` attribute when emitting headings (h1, h2, h3, etc).|
|
||||||
|sanitizer (**deprecated**)|`function`|`null` |v0.3.4 |A function to sanitize the HTML passed into `markdownString`.|
|
|headerPrefix (**removed**)|`string` |`''` |v0.3.0 |Removed in v8.0.0 use [`marked-gfm-heading-id`](https://www.npmjs.com/package/marked-gfm-heading-id) to add a string to prefix the `id` attribute when emitting headings (h1, h2, h3, etc).|
|
||||||
|smartypants (**deprecated**)|`boolean` |`false` |v0.2.9 |Deprecated in v5.0.0 use [`marked-smartypants`](https://www.npmjs.com/package/marked-smartypants) to use "smart" typographic punctuation for things like quotes and dashes.|
|
|highlight (**removed**)|`function`|`null` |v0.3.0 |Removed in v8.0.0 use [`marked-highlight`](https://www.npmjs.com/package/marked-highlight) to add highlighting to code blocks. |
|
||||||
|xhtml (**deprecated**)|`boolean` |`false` |v0.3.2 |Deprecated in v5.0.0 use [`marked-xhtml`](https://www.npmjs.com/package/marked-xhtml) to emit self-closing HTML tags for void elements (<br/>, <img/>, etc.) with a "/" as required by XHTML.|
|
|langPrefix (**removed**)|`string` |`'language-'`|v0.3.0|Removed in v8.0.0 use [`marked-highlight`](https://www.npmjs.com/package/marked-highlight) to prefix the className in a `<code>` block. Useful for syntax highlighting.|
|
||||||
|
|mangle (**removed**)|`boolean` |`true` |v0.3.4 |Removed in v8.0.0 use [`marked-mangle`](https://www.npmjs.com/package/marked-mangle) to mangle email addresses.|
|
||||||
|
|sanitize (**removed**)|`boolean` |`false` |v0.2.1 |Removed in v8.0.0 use a sanitize library, like [DOMPurify](https://github.com/cure53/DOMPurify) (recommended), [sanitize-html](https://github.com/apostrophecms/sanitize-html) or [insane](https://github.com/bevacqua/insane) on the output HTML! |
|
||||||
|
|sanitizer (**removed**)|`function`|`null` |v0.3.4 |Removed in v8.0.0 use a sanitize library, like [DOMPurify](https://github.com/cure53/DOMPurify) (recommended), [sanitize-html](https://github.com/apostrophecms/sanitize-html) or [insane](https://github.com/bevacqua/insane) on the output HTML!|
|
||||||
|
|smartypants (**removed**)|`boolean` |`false` |v0.2.9 |Removed in v8.0.0 use [`marked-smartypants`](https://www.npmjs.com/package/marked-smartypants) to use "smart" typographic punctuation for things like quotes and dashes.|
|
||||||
|
|xhtml (**removed**)|`boolean` |`false` |v0.3.2 |Removed in v8.0.0 use [`marked-xhtml`](https://www.npmjs.com/package/marked-xhtml) to emit self-closing HTML tags for void elements (<br/>, <img/>, etc.) with a "/" as required by XHTML.|
|
||||||
|
|
||||||
<h2 id="extensions">Known Extensions</h2>
|
<h2 id="extensions">Known Extensions</h2>
|
||||||
|
|
||||||
|
@ -13,10 +13,7 @@ import { marked } from 'marked';
|
|||||||
marked.use({
|
marked.use({
|
||||||
pedantic: false,
|
pedantic: false,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
breaks: false,
|
breaks: false
|
||||||
sanitize: false,
|
|
||||||
smartypants: false,
|
|
||||||
xhtml: false
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -249,25 +246,9 @@ console.log(marked.parse('$ latex code $\n\n` other code `'));
|
|||||||
- <code>**codespan**(*string* src)</code>
|
- <code>**codespan**(*string* src)</code>
|
||||||
- <code>**br**(*string* src)</code>
|
- <code>**br**(*string* src)</code>
|
||||||
- <code>**del**(*string* src)</code>
|
- <code>**del**(*string* src)</code>
|
||||||
- <code>**autolink**(*string* src, *function* mangle)</code>
|
- <code>**autolink**(*string* src)</code>
|
||||||
- <code>**url**(*string* src, *function* mangle)</code>
|
- <code>**url**(*string* src)</code>
|
||||||
- <code>**inlineText**(*string* src, *function* smartypants)</code>
|
- <code>**inlineText**(*string* src)</code>
|
||||||
|
|
||||||
`mangle` is a method that changes text to HTML character references:
|
|
||||||
|
|
||||||
```js
|
|
||||||
mangle('test@example.com')
|
|
||||||
// "test@example.com"
|
|
||||||
```
|
|
||||||
|
|
||||||
`smartypants` is a method that translates plain ASCII punctuation characters into “smart” typographic punctuation HTML entities:
|
|
||||||
|
|
||||||
https://daringfireball.net/projects/smartypants/
|
|
||||||
|
|
||||||
```js
|
|
||||||
smartypants('"this ... string"')
|
|
||||||
// "“this … string”"
|
|
||||||
```
|
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
@ -337,17 +318,18 @@ marked.use({ hooks: { preprocess } });
|
|||||||
// Run marked
|
// Run marked
|
||||||
console.log(marked.parse(`
|
console.log(marked.parse(`
|
||||||
---
|
---
|
||||||
headerIds: false
|
breaks: true
|
||||||
---
|
---
|
||||||
|
|
||||||
## test
|
line1
|
||||||
|
line2
|
||||||
`.trim()));
|
`.trim()));
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:**
|
**Output:**
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<h2>test</h2>
|
<p>line1<br>line2</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example:** Sanitize HTML with [isomorphic-dompurify](https://www.npmjs.com/package/isomorphic-dompurify)
|
**Example:** Sanitize HTML with [isomorphic-dompurify](https://www.npmjs.com/package/isomorphic-dompurify)
|
||||||
|
343
lib/marked.cjs
generated
343
lib/marked.cjs
generated
@ -17,25 +17,15 @@
|
|||||||
function _getDefaults() {
|
function _getDefaults() {
|
||||||
return {
|
return {
|
||||||
async: false,
|
async: false,
|
||||||
baseUrl: null,
|
|
||||||
breaks: false,
|
breaks: false,
|
||||||
extensions: null,
|
extensions: null,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
headerIds: false,
|
|
||||||
headerPrefix: '',
|
|
||||||
highlight: null,
|
|
||||||
hooks: null,
|
hooks: null,
|
||||||
langPrefix: 'language-',
|
|
||||||
mangle: false,
|
|
||||||
pedantic: false,
|
pedantic: false,
|
||||||
renderer: null,
|
renderer: null,
|
||||||
sanitize: false,
|
|
||||||
sanitizer: null,
|
|
||||||
silent: false,
|
silent: false,
|
||||||
smartypants: false,
|
|
||||||
tokenizer: null,
|
tokenizer: null,
|
||||||
walkTokens: null,
|
walkTokens: null
|
||||||
xhtml: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
exports.defaults = _getDefaults();
|
exports.defaults = _getDefaults();
|
||||||
@ -103,26 +93,7 @@ function edit(regex, opt) {
|
|||||||
};
|
};
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
const nonWordAndColonTest = /[^\w:]/g;
|
function cleanUrl(href) {
|
||||||
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
|
|
||||||
function cleanUrl(sanitize, base, href) {
|
|
||||||
if (sanitize) {
|
|
||||||
let prot;
|
|
||||||
try {
|
|
||||||
prot = decodeURIComponent(unescape(href))
|
|
||||||
.replace(nonWordAndColonTest, '')
|
|
||||||
.toLowerCase();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (base && !originIndependentUrl.test(href)) {
|
|
||||||
href = resolveUrl(base, href);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
href = encodeURI(href).replace(/%25/g, '%');
|
href = encodeURI(href).replace(/%25/g, '%');
|
||||||
}
|
}
|
||||||
@ -131,40 +102,6 @@ function cleanUrl(sanitize, base, href) {
|
|||||||
}
|
}
|
||||||
return href;
|
return href;
|
||||||
}
|
}
|
||||||
const baseUrls = {};
|
|
||||||
const justDomain = /^[^:]+:\/*[^/]*$/;
|
|
||||||
const protocol = /^([^:]+:)[\s\S]*$/;
|
|
||||||
const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
|
|
||||||
function resolveUrl(base, href) {
|
|
||||||
if (!baseUrls[' ' + base]) {
|
|
||||||
// we can ignore everything in base after the last slash of its path component,
|
|
||||||
// but we might need to add _that_
|
|
||||||
// https://tools.ietf.org/html/rfc3986#section-3
|
|
||||||
if (justDomain.test(base)) {
|
|
||||||
baseUrls[' ' + base] = base + '/';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
baseUrls[' ' + base] = rtrim(base, '/', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base = baseUrls[' ' + base];
|
|
||||||
const relativeBase = base.indexOf(':') === -1;
|
|
||||||
if (href.substring(0, 2) === '//') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(protocol, '$1') + href;
|
|
||||||
}
|
|
||||||
else if (href.charAt(0) === '/') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(domain, '$1') + href;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return base + href;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const noopTest = { exec: () => null };
|
const noopTest = { exec: () => null };
|
||||||
function splitCells(tableRow, count) {
|
function splitCells(tableRow, count) {
|
||||||
// ensure that every cell-delimiting pipe has a space
|
// ensure that every cell-delimiting pipe has a space
|
||||||
@ -258,35 +195,6 @@ function findClosingBracket(str, b) {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
function checkDeprecations(opt, callback) {
|
|
||||||
if (!opt || opt.silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (callback) {
|
|
||||||
console.warn('marked(): callback is deprecated since version 5.0.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/using_pro#async');
|
|
||||||
}
|
|
||||||
if (opt.sanitize || opt.sanitizer) {
|
|
||||||
console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
|
|
||||||
}
|
|
||||||
if (opt.highlight || opt.langPrefix !== 'language-') {
|
|
||||||
console.warn('marked(): highlight and langPrefix parameters are deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-highlight.');
|
|
||||||
}
|
|
||||||
if (opt.mangle) {
|
|
||||||
console.warn('marked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.');
|
|
||||||
}
|
|
||||||
if (opt.baseUrl) {
|
|
||||||
console.warn('marked(): baseUrl parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-base-url.');
|
|
||||||
}
|
|
||||||
if (opt.smartypants) {
|
|
||||||
console.warn('marked(): smartypants parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-smartypants.');
|
|
||||||
}
|
|
||||||
if (opt.xhtml) {
|
|
||||||
console.warn('marked(): xhtml parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-xhtml.');
|
|
||||||
}
|
|
||||||
if (opt.headerIds || opt.headerPrefix) {
|
|
||||||
console.warn('marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function outputLink(cap, link, raw, lexer) {
|
function outputLink(cap, link, raw, lexer) {
|
||||||
const href = link.href;
|
const href = link.href;
|
||||||
@ -603,17 +511,9 @@ class _Tokenizer {
|
|||||||
type: 'html',
|
type: 'html',
|
||||||
block: true,
|
block: true,
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
pre: !this.options.sanitizer
|
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
|
||||||
&& (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
|
|
||||||
text: cap[0]
|
text: cap[0]
|
||||||
};
|
};
|
||||||
if (this.options.sanitize) {
|
|
||||||
const text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
|
|
||||||
const paragraph = token;
|
|
||||||
paragraph.type = 'paragraph';
|
|
||||||
paragraph.text = text;
|
|
||||||
paragraph.tokens = this.lexer.inline(text);
|
|
||||||
}
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -751,18 +651,12 @@ class _Tokenizer {
|
|||||||
this.lexer.state.inRawBlock = false;
|
this.lexer.state.inRawBlock = false;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: this.options.sanitize
|
type: 'html',
|
||||||
? 'text'
|
|
||||||
: 'html',
|
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
inLink: this.lexer.state.inLink,
|
inLink: this.lexer.state.inLink,
|
||||||
inRawBlock: this.lexer.state.inRawBlock,
|
inRawBlock: this.lexer.state.inRawBlock,
|
||||||
block: false,
|
block: false,
|
||||||
text: this.options.sanitize
|
text: cap[0]
|
||||||
? (this.options.sanitizer
|
|
||||||
? this.options.sanitizer(cap[0])
|
|
||||||
: escape(cap[0]))
|
|
||||||
: cap[0]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -933,12 +827,12 @@ class _Tokenizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
autolink(src, mangle) {
|
autolink(src) {
|
||||||
const cap = this.rules.inline.autolink.exec(src);
|
const cap = this.rules.inline.autolink.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
|
text = escape(cap[1]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -960,12 +854,12 @@ class _Tokenizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
url(src, mangle) {
|
url(src) {
|
||||||
let cap;
|
let cap;
|
||||||
if (cap = this.rules.inline.url.exec(src)) {
|
if (cap = this.rules.inline.url.exec(src)) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -998,15 +892,15 @@ class _Tokenizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inlineText(src, smartypants) {
|
inlineText(src) {
|
||||||
const cap = this.rules.inline.text.exec(src);
|
const cap = this.rules.inline.text.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text;
|
let text;
|
||||||
if (this.lexer.state.inRawBlock) {
|
if (this.lexer.state.inRawBlock) {
|
||||||
text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0];
|
text = cap[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@ -1294,39 +1188,6 @@ inline.breaks = {
|
|||||||
.getRegex()
|
.getRegex()
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* smartypants text replacement
|
|
||||||
*/
|
|
||||||
function smartypants(text) {
|
|
||||||
return text
|
|
||||||
// em-dashes
|
|
||||||
.replace(/---/g, '\u2014')
|
|
||||||
// en-dashes
|
|
||||||
.replace(/--/g, '\u2013')
|
|
||||||
// opening singles
|
|
||||||
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
|
||||||
// closing singles & apostrophes
|
|
||||||
.replace(/'/g, '\u2019')
|
|
||||||
// opening doubles
|
|
||||||
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
|
||||||
// closing doubles
|
|
||||||
.replace(/"/g, '\u201d')
|
|
||||||
// ellipses
|
|
||||||
.replace(/\.{3}/g, '\u2026');
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* mangle email addresses
|
|
||||||
*/
|
|
||||||
function mangle(text) {
|
|
||||||
let out = '';
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
const ch = Math.random() > 0.5
|
|
||||||
? 'x' + text.charCodeAt(i).toString(16)
|
|
||||||
: text.charCodeAt(i).toString();
|
|
||||||
out += '&#' + ch + ';';
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Block Lexer
|
* Block Lexer
|
||||||
*/
|
*/
|
||||||
@ -1700,13 +1561,13 @@ class _Lexer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// autolink
|
// autolink
|
||||||
if (token = this.tokenizer.autolink(src, mangle)) {
|
if (token = this.tokenizer.autolink(src)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// url (gfm)
|
// url (gfm)
|
||||||
if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
|
if (!this.state.inLink && (token = this.tokenizer.url(src))) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
@ -1728,7 +1589,7 @@ class _Lexer {
|
|||||||
cutSrc = src.substring(0, startIndex + 1);
|
cutSrc = src.substring(0, startIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
|
if (token = this.tokenizer.inlineText(cutSrc)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
||||||
prevChar = token.raw.slice(-1);
|
prevChar = token.raw.slice(-1);
|
||||||
@ -1769,21 +1630,13 @@ class _Renderer {
|
|||||||
}
|
}
|
||||||
code(code, infostring, escaped) {
|
code(code, infostring, escaped) {
|
||||||
const lang = (infostring || '').match(/^\S*/)?.[0];
|
const lang = (infostring || '').match(/^\S*/)?.[0];
|
||||||
if (this.options.highlight) {
|
|
||||||
const out = this.options.highlight(code, lang);
|
|
||||||
if (out != null && out !== code) {
|
|
||||||
escaped = true;
|
|
||||||
code = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code = code.replace(/\n$/, '') + '\n';
|
code = code.replace(/\n$/, '') + '\n';
|
||||||
if (!lang) {
|
if (!lang) {
|
||||||
return '<pre><code>'
|
return '<pre><code>'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
+ '</code></pre>\n';
|
+ '</code></pre>\n';
|
||||||
}
|
}
|
||||||
return '<pre><code class="'
|
return '<pre><code class="language-'
|
||||||
+ this.options.langPrefix
|
|
||||||
+ escape(lang)
|
+ escape(lang)
|
||||||
+ '">'
|
+ '">'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
@ -1795,16 +1648,12 @@ class _Renderer {
|
|||||||
html(html, block) {
|
html(html, block) {
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
heading(text, level, raw, slugger) {
|
heading(text, level, raw) {
|
||||||
if (this.options.headerIds) {
|
|
||||||
const id = this.options.headerPrefix + slugger.slug(raw);
|
|
||||||
return `<h${level} id="${id}">${text}</h${level}>\n`;
|
|
||||||
}
|
|
||||||
// ignore IDs
|
// ignore IDs
|
||||||
return `<h${level}>${text}</h${level}>\n`;
|
return `<h${level}>${text}</h${level}>\n`;
|
||||||
}
|
}
|
||||||
hr() {
|
hr() {
|
||||||
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
|
return '<hr>\n';
|
||||||
}
|
}
|
||||||
list(body, ordered, start) {
|
list(body, ordered, start) {
|
||||||
const type = ordered ? 'ol' : 'ul';
|
const type = ordered ? 'ol' : 'ul';
|
||||||
@ -1817,9 +1666,7 @@ class _Renderer {
|
|||||||
checkbox(checked) {
|
checkbox(checked) {
|
||||||
return '<input '
|
return '<input '
|
||||||
+ (checked ? 'checked="" ' : '')
|
+ (checked ? 'checked="" ' : '')
|
||||||
+ 'disabled="" type="checkbox"'
|
+ 'disabled="" type="checkbox">';
|
||||||
+ (this.options.xhtml ? ' /' : '')
|
|
||||||
+ '> ';
|
|
||||||
}
|
}
|
||||||
paragraph(text) {
|
paragraph(text) {
|
||||||
return `<p>${text}</p>\n`;
|
return `<p>${text}</p>\n`;
|
||||||
@ -1857,13 +1704,13 @@ class _Renderer {
|
|||||||
return `<code>${text}</code>`;
|
return `<code>${text}</code>`;
|
||||||
}
|
}
|
||||||
br() {
|
br() {
|
||||||
return this.options.xhtml ? '<br/>' : '<br>';
|
return '<br>';
|
||||||
}
|
}
|
||||||
del(text) {
|
del(text) {
|
||||||
return `<del>${text}</del>`;
|
return `<del>${text}</del>`;
|
||||||
}
|
}
|
||||||
link(href, title, text) {
|
link(href, title, text) {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -1876,7 +1723,7 @@ class _Renderer {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
image(href, title, text) {
|
image(href, title, text) {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -1885,7 +1732,7 @@ class _Renderer {
|
|||||||
if (title) {
|
if (title) {
|
||||||
out += ` title="${title}"`;
|
out += ` title="${title}"`;
|
||||||
}
|
}
|
||||||
out += this.options.xhtml ? '/>' : '>';
|
out += '>';
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
text(text) {
|
text(text) {
|
||||||
@ -1928,52 +1775,6 @@ class _TextRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Slugger generates header id
|
|
||||||
*/
|
|
||||||
class _Slugger {
|
|
||||||
seen;
|
|
||||||
constructor() {
|
|
||||||
this.seen = {};
|
|
||||||
}
|
|
||||||
serialize(value) {
|
|
||||||
return value
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
// remove html tags
|
|
||||||
.replace(/<[!\/a-z].*?>/ig, '')
|
|
||||||
// remove unwanted chars
|
|
||||||
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
|
|
||||||
.replace(/\s/g, '-');
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Finds the next safe (unique) slug to use
|
|
||||||
*/
|
|
||||||
getNextSafeSlug(originalSlug, isDryRun) {
|
|
||||||
let slug = originalSlug;
|
|
||||||
let occurenceAccumulator = 0;
|
|
||||||
if (this.seen.hasOwnProperty(slug)) {
|
|
||||||
occurenceAccumulator = this.seen[originalSlug];
|
|
||||||
do {
|
|
||||||
occurenceAccumulator++;
|
|
||||||
slug = originalSlug + '-' + occurenceAccumulator;
|
|
||||||
} while (this.seen.hasOwnProperty(slug));
|
|
||||||
}
|
|
||||||
if (!isDryRun) {
|
|
||||||
this.seen[originalSlug] = occurenceAccumulator;
|
|
||||||
this.seen[slug] = 0;
|
|
||||||
}
|
|
||||||
return slug;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Convert string to unique id
|
|
||||||
*/
|
|
||||||
slug(value, options = {}) {
|
|
||||||
const slug = this.serialize(value);
|
|
||||||
return this.getNextSafeSlug(slug, options.dryrun);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsing & Compiling
|
* Parsing & Compiling
|
||||||
*/
|
*/
|
||||||
@ -1981,14 +1782,12 @@ class _Parser {
|
|||||||
options;
|
options;
|
||||||
renderer;
|
renderer;
|
||||||
textRenderer;
|
textRenderer;
|
||||||
slugger;
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.options = options || exports.defaults;
|
this.options = options || exports.defaults;
|
||||||
this.options.renderer = this.options.renderer || new _Renderer();
|
this.options.renderer = this.options.renderer || new _Renderer();
|
||||||
this.renderer = this.options.renderer;
|
this.renderer = this.options.renderer;
|
||||||
this.renderer.options = this.options;
|
this.renderer.options = this.options;
|
||||||
this.textRenderer = new _TextRenderer();
|
this.textRenderer = new _TextRenderer();
|
||||||
this.slugger = new _Slugger();
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Static Parse Method
|
* Static Parse Method
|
||||||
@ -2030,7 +1829,7 @@ class _Parser {
|
|||||||
}
|
}
|
||||||
case 'heading': {
|
case 'heading': {
|
||||||
const headingToken = token;
|
const headingToken = token;
|
||||||
out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)), this.slugger);
|
out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case 'code': {
|
case 'code': {
|
||||||
@ -2253,7 +2052,6 @@ class Marked {
|
|||||||
Lexer = _Lexer;
|
Lexer = _Lexer;
|
||||||
lexer = _Lexer.lex;
|
lexer = _Lexer.lex;
|
||||||
Tokenizer = _Tokenizer;
|
Tokenizer = _Tokenizer;
|
||||||
Slugger = _Slugger;
|
|
||||||
Hooks = _Hooks;
|
Hooks = _Hooks;
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
this.use(...args);
|
this.use(...args);
|
||||||
@ -2450,12 +2248,8 @@ class Marked {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
#parseMarkdown(lexer, parser) {
|
#parseMarkdown(lexer, parser) {
|
||||||
return (src, optOrCallback, callback) => {
|
return (src, options) => {
|
||||||
if (typeof optOrCallback === 'function') {
|
const origOpt = { ...options };
|
||||||
callback = optOrCallback;
|
|
||||||
optOrCallback = null;
|
|
||||||
}
|
|
||||||
const origOpt = { ...optOrCallback };
|
|
||||||
const opt = { ...this.defaults, ...origOpt };
|
const opt = { ...this.defaults, ...origOpt };
|
||||||
// Show warning if an extension set async to true but the parse was called with async: false
|
// Show warning if an extension set async to true but the parse was called with async: false
|
||||||
if (this.defaults.async === true && origOpt.async === false) {
|
if (this.defaults.async === true && origOpt.async === false) {
|
||||||
@ -2464,7 +2258,7 @@ class Marked {
|
|||||||
}
|
}
|
||||||
opt.async = true;
|
opt.async = true;
|
||||||
}
|
}
|
||||||
const throwError = this.#onError(!!opt.silent, !!opt.async, callback);
|
const throwError = this.#onError(!!opt.silent, !!opt.async);
|
||||||
// throw error in case of non string input
|
// throw error in case of non string input
|
||||||
if (typeof src === 'undefined' || src === null) {
|
if (typeof src === 'undefined' || src === null) {
|
||||||
return throwError(new Error('marked(): input parameter is undefined or null'));
|
return throwError(new Error('marked(): input parameter is undefined or null'));
|
||||||
@ -2473,76 +2267,9 @@ class Marked {
|
|||||||
return throwError(new Error('marked(): input parameter is of type '
|
return throwError(new Error('marked(): input parameter is of type '
|
||||||
+ Object.prototype.toString.call(src) + ', string expected'));
|
+ Object.prototype.toString.call(src) + ', string expected'));
|
||||||
}
|
}
|
||||||
checkDeprecations(opt, callback);
|
|
||||||
if (opt.hooks) {
|
if (opt.hooks) {
|
||||||
opt.hooks.options = opt;
|
opt.hooks.options = opt;
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
const resultCallback = callback;
|
|
||||||
const highlight = opt.highlight;
|
|
||||||
let tokens;
|
|
||||||
try {
|
|
||||||
if (opt.hooks) {
|
|
||||||
src = opt.hooks.preprocess(src);
|
|
||||||
}
|
|
||||||
tokens = lexer(src, opt);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return throwError(e);
|
|
||||||
}
|
|
||||||
const done = (err) => {
|
|
||||||
let out;
|
|
||||||
if (!err) {
|
|
||||||
try {
|
|
||||||
if (opt.walkTokens) {
|
|
||||||
this.walkTokens(tokens, opt.walkTokens);
|
|
||||||
}
|
|
||||||
out = parser(tokens, opt);
|
|
||||||
if (opt.hooks) {
|
|
||||||
out = opt.hooks.postprocess(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
err = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opt.highlight = highlight;
|
|
||||||
return err
|
|
||||||
? throwError(err)
|
|
||||||
: resultCallback(null, out);
|
|
||||||
};
|
|
||||||
if (!highlight || highlight.length < 3) {
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
delete opt.highlight;
|
|
||||||
if (!tokens.length)
|
|
||||||
return done();
|
|
||||||
let pending = 0;
|
|
||||||
this.walkTokens(tokens, (token) => {
|
|
||||||
if (token.type === 'code') {
|
|
||||||
pending++;
|
|
||||||
setTimeout(() => {
|
|
||||||
highlight(token.text, token.lang, (err, code) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
if (code != null && code !== token.text) {
|
|
||||||
token.text = code;
|
|
||||||
token.escaped = true;
|
|
||||||
}
|
|
||||||
pending--;
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (opt.async) {
|
if (opt.async) {
|
||||||
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
||||||
.then(src => lexer(src, opt))
|
.then(src => lexer(src, opt))
|
||||||
@ -2570,7 +2297,7 @@ class Marked {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#onError(silent, async, callback) {
|
#onError(silent, async) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
||||||
if (silent) {
|
if (silent) {
|
||||||
@ -2580,27 +2307,19 @@ class Marked {
|
|||||||
if (async) {
|
if (async) {
|
||||||
return Promise.resolve(msg);
|
return Promise.resolve(msg);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(null, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
if (async) {
|
if (async) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const markedInstance = new Marked();
|
const markedInstance = new Marked();
|
||||||
function marked(src, opt, callback) {
|
function marked(src, opt) {
|
||||||
return markedInstance.parse(src, opt, callback);
|
return markedInstance.parse(src, opt);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Sets the default options.
|
* Sets the default options.
|
||||||
@ -2652,7 +2371,6 @@ marked.TextRenderer = _TextRenderer;
|
|||||||
marked.Lexer = _Lexer;
|
marked.Lexer = _Lexer;
|
||||||
marked.lexer = _Lexer.lex;
|
marked.lexer = _Lexer.lex;
|
||||||
marked.Tokenizer = _Tokenizer;
|
marked.Tokenizer = _Tokenizer;
|
||||||
marked.Slugger = _Slugger;
|
|
||||||
marked.Hooks = _Hooks;
|
marked.Hooks = _Hooks;
|
||||||
marked.parse = marked;
|
marked.parse = marked;
|
||||||
const options = marked.options;
|
const options = marked.options;
|
||||||
@ -2669,7 +2387,6 @@ exports.Lexer = _Lexer;
|
|||||||
exports.Marked = Marked;
|
exports.Marked = Marked;
|
||||||
exports.Parser = _Parser;
|
exports.Parser = _Parser;
|
||||||
exports.Renderer = _Renderer;
|
exports.Renderer = _Renderer;
|
||||||
exports.Slugger = _Slugger;
|
|
||||||
exports.TextRenderer = _TextRenderer;
|
exports.TextRenderer = _TextRenderer;
|
||||||
exports.Tokenizer = _Tokenizer;
|
exports.Tokenizer = _Tokenizer;
|
||||||
exports.getDefaults = _getDefaults;
|
exports.getDefaults = _getDefaults;
|
||||||
|
2
lib/marked.cjs.map
generated
2
lib/marked.cjs.map
generated
File diff suppressed because one or more lines are too long
448
lib/marked.d.ts
generated
vendored
448
lib/marked.d.ts
generated
vendored
@ -152,6 +152,132 @@ declare module "Tokens" {
|
|||||||
links: Links;
|
links: Links;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
declare module "rules" {
|
||||||
|
export type Rule = RegExp | string;
|
||||||
|
export interface Rules {
|
||||||
|
[ruleName: string]: Pick<RegExp, 'exec'> | Rule | Rules;
|
||||||
|
}
|
||||||
|
type BlockRuleNames = 'newline' | 'code' | 'fences' | 'hr' | 'heading' | 'blockquote' | 'list' | 'html' | 'def' | 'lheading' | '_paragraph' | 'text' | '_label' | '_title' | 'bullet' | 'listItemStart' | '_tag' | '_comment' | 'paragraph' | 'uote';
|
||||||
|
type BlockSubRuleNames = 'normal' | 'gfm' | 'pedantic';
|
||||||
|
type InlineRuleNames = 'escape' | 'autolink' | 'tag' | 'link' | 'reflink' | 'nolink' | 'reflinkSearch' | 'code' | 'br' | 'text' | '_punctuation' | 'punctuation' | 'blockSkip' | 'escapedEmSt' | '_comment' | '_escapes' | '_scheme' | '_email' | '_attribute' | '_label' | '_href' | '_title' | 'strong' | '_extended_email' | '_backpedal';
|
||||||
|
type InlineSubRuleNames = 'gfm' | 'emStrong' | 'normal' | 'pedantic' | 'breaks';
|
||||||
|
/**
|
||||||
|
* Block-Level Grammar
|
||||||
|
*/
|
||||||
|
export const block: Record<BlockRuleNames, Rule> & Record<BlockSubRuleNames, Rules> & Rules;
|
||||||
|
/**
|
||||||
|
* Inline-Level Grammar
|
||||||
|
*/
|
||||||
|
export const inline: Record<InlineRuleNames, Rule> & Record<InlineSubRuleNames, Rules> & Rules;
|
||||||
|
}
|
||||||
|
declare module "helpers" {
|
||||||
|
import type { Rule } from "rules";
|
||||||
|
export function escape(html: string, encode?: boolean): string;
|
||||||
|
export function unescape(html: string): string;
|
||||||
|
export function edit(regex: Rule, opt?: string): {
|
||||||
|
replace: (name: string | RegExp, val: string | RegExp) => any;
|
||||||
|
getRegex: () => RegExp;
|
||||||
|
};
|
||||||
|
export function cleanUrl(href: string): string | null;
|
||||||
|
export const noopTest: {
|
||||||
|
exec: () => null;
|
||||||
|
};
|
||||||
|
export function splitCells(tableRow: string, count?: number): string[];
|
||||||
|
/**
|
||||||
|
* Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
|
||||||
|
* /c*$/ is vulnerable to REDOS.
|
||||||
|
*
|
||||||
|
* @param str
|
||||||
|
* @param c
|
||||||
|
* @param invert Remove suffix of non-c chars instead. Default falsey.
|
||||||
|
*/
|
||||||
|
export function rtrim(str: string, c: string, invert?: boolean): string;
|
||||||
|
export function findClosingBracket(str: string, b: string): number;
|
||||||
|
}
|
||||||
|
declare module "Renderer" {
|
||||||
|
import type { MarkedOptions } from "MarkedOptions";
|
||||||
|
/**
|
||||||
|
* Renderer
|
||||||
|
*/
|
||||||
|
export class _Renderer {
|
||||||
|
options: MarkedOptions;
|
||||||
|
constructor(options?: MarkedOptions);
|
||||||
|
code(code: string, infostring: string | undefined, escaped: boolean): string;
|
||||||
|
blockquote(quote: string): string;
|
||||||
|
html(html: string, block?: boolean): string;
|
||||||
|
heading(text: string, level: number, raw: string): string;
|
||||||
|
hr(): string;
|
||||||
|
list(body: string, ordered: boolean, start: number | ''): string;
|
||||||
|
listitem(text: string, task: boolean, checked: boolean): string;
|
||||||
|
checkbox(checked: boolean): string;
|
||||||
|
paragraph(text: string): string;
|
||||||
|
table(header: string, body: string): string;
|
||||||
|
tablerow(content: string): string;
|
||||||
|
tablecell(content: string, flags: {
|
||||||
|
header: boolean;
|
||||||
|
align: 'center' | 'left' | 'right' | null;
|
||||||
|
}): string;
|
||||||
|
/**
|
||||||
|
* span level renderer
|
||||||
|
*/
|
||||||
|
strong(text: string): string;
|
||||||
|
em(text: string): string;
|
||||||
|
codespan(text: string): string;
|
||||||
|
br(): string;
|
||||||
|
del(text: string): string;
|
||||||
|
link(href: string, title: string | null | undefined, text: string): string;
|
||||||
|
image(href: string, title: string | null, text: string): string;
|
||||||
|
text(text: string): string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "TextRenderer" {
|
||||||
|
/**
|
||||||
|
* TextRenderer
|
||||||
|
* returns only the textual part of the token
|
||||||
|
*/
|
||||||
|
export class _TextRenderer {
|
||||||
|
strong(text: string): string;
|
||||||
|
em(text: string): string;
|
||||||
|
codespan(text: string): string;
|
||||||
|
del(text: string): string;
|
||||||
|
html(text: string): string;
|
||||||
|
text(text: string): string;
|
||||||
|
link(href: string, title: string | null | undefined, text: string): string;
|
||||||
|
image(href: string, title: string | null, text: string): string;
|
||||||
|
br(): string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "Parser" {
|
||||||
|
import { _Renderer } from "Renderer";
|
||||||
|
import { _TextRenderer } from "TextRenderer";
|
||||||
|
import type { Token } from "Tokens";
|
||||||
|
import type { MarkedOptions } from "MarkedOptions";
|
||||||
|
/**
|
||||||
|
* Parsing & Compiling
|
||||||
|
*/
|
||||||
|
export class _Parser {
|
||||||
|
options: MarkedOptions;
|
||||||
|
renderer: _Renderer;
|
||||||
|
textRenderer: _TextRenderer;
|
||||||
|
constructor(options?: MarkedOptions);
|
||||||
|
/**
|
||||||
|
* Static Parse Method
|
||||||
|
*/
|
||||||
|
static parse(tokens: Token[], options?: MarkedOptions): string;
|
||||||
|
/**
|
||||||
|
* Static Parse Inline Method
|
||||||
|
*/
|
||||||
|
static parseInline(tokens: Token[], options?: MarkedOptions): string;
|
||||||
|
/**
|
||||||
|
* Parse Loop
|
||||||
|
*/
|
||||||
|
parse(tokens: Token[], top?: boolean): string;
|
||||||
|
/**
|
||||||
|
* Parse Inline Tokens
|
||||||
|
*/
|
||||||
|
parseInline(tokens: Token[], renderer?: _Renderer | _TextRenderer): string;
|
||||||
|
}
|
||||||
|
}
|
||||||
declare module "Tokenizer" {
|
declare module "Tokenizer" {
|
||||||
import type { _Lexer } from "Lexer";
|
import type { _Lexer } from "Lexer";
|
||||||
import type { Links, Tokens } from "Tokens";
|
import type { Links, Tokens } from "Tokens";
|
||||||
@ -171,7 +297,7 @@ declare module "Tokenizer" {
|
|||||||
hr(src: string): Tokens.Hr | undefined;
|
hr(src: string): Tokens.Hr | undefined;
|
||||||
blockquote(src: string): Tokens.Blockquote | undefined;
|
blockquote(src: string): Tokens.Blockquote | undefined;
|
||||||
list(src: string): Tokens.List | undefined;
|
list(src: string): Tokens.List | undefined;
|
||||||
html(src: string): Tokens.HTML | Tokens.Paragraph | undefined;
|
html(src: string): Tokens.HTML | undefined;
|
||||||
def(src: string): Tokens.Def | undefined;
|
def(src: string): Tokens.Def | undefined;
|
||||||
table(src: string): Tokens.Table | undefined;
|
table(src: string): Tokens.Table | undefined;
|
||||||
lheading(src: string): Tokens.Heading | undefined;
|
lheading(src: string): Tokens.Heading | undefined;
|
||||||
@ -185,29 +311,11 @@ declare module "Tokenizer" {
|
|||||||
codespan(src: string): Tokens.Codespan | undefined;
|
codespan(src: string): Tokens.Codespan | undefined;
|
||||||
br(src: string): Tokens.Br | undefined;
|
br(src: string): Tokens.Br | undefined;
|
||||||
del(src: string): Tokens.Del | undefined;
|
del(src: string): Tokens.Del | undefined;
|
||||||
autolink(src: string, mangle: (cap: string) => string): Tokens.Link | undefined;
|
autolink(src: string): Tokens.Link | undefined;
|
||||||
url(src: string, mangle: (cap: string) => string): Tokens.Link | undefined;
|
url(src: string): Tokens.Link | undefined;
|
||||||
inlineText(src: string, smartypants: (cap: string) => string): Tokens.Text | undefined;
|
inlineText(src: string): Tokens.Text | undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module "rules" {
|
|
||||||
export type Rule = RegExp | string;
|
|
||||||
export interface Rules {
|
|
||||||
[ruleName: string]: Pick<RegExp, 'exec'> | Rule | Rules;
|
|
||||||
}
|
|
||||||
type BlockRuleNames = 'newline' | 'code' | 'fences' | 'hr' | 'heading' | 'blockquote' | 'list' | 'html' | 'def' | 'lheading' | '_paragraph' | 'text' | '_label' | '_title' | 'bullet' | 'listItemStart' | '_tag' | '_comment' | 'paragraph' | 'uote';
|
|
||||||
type BlockSubRuleNames = 'normal' | 'gfm' | 'pedantic';
|
|
||||||
type InlineRuleNames = 'escape' | 'autolink' | 'tag' | 'link' | 'reflink' | 'nolink' | 'reflinkSearch' | 'code' | 'br' | 'text' | '_punctuation' | 'punctuation' | 'blockSkip' | 'escapedEmSt' | '_comment' | '_escapes' | '_scheme' | '_email' | '_attribute' | '_label' | '_href' | '_title' | 'strong' | '_extended_email' | '_backpedal';
|
|
||||||
type InlineSubRuleNames = 'gfm' | 'emStrong' | 'normal' | 'pedantic' | 'breaks';
|
|
||||||
/**
|
|
||||||
* Block-Level Grammar
|
|
||||||
*/
|
|
||||||
export const block: Record<BlockRuleNames, Rule> & Record<BlockSubRuleNames, Rules> & Rules;
|
|
||||||
/**
|
|
||||||
* Inline-Level Grammar
|
|
||||||
*/
|
|
||||||
export const inline: Record<InlineRuleNames, Rule> & Record<InlineSubRuleNames, Rules> & Rules;
|
|
||||||
}
|
|
||||||
declare module "Lexer" {
|
declare module "Lexer" {
|
||||||
import type { Token, TokensList } from "Tokens";
|
import type { Token, TokensList } from "Tokens";
|
||||||
import type { MarkedOptions } from "MarkedOptions";
|
import type { MarkedOptions } from "MarkedOptions";
|
||||||
@ -254,188 +362,12 @@ declare module "Lexer" {
|
|||||||
inlineTokens(src: string, tokens?: Token[]): Token[];
|
inlineTokens(src: string, tokens?: Token[]): Token[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module "TextRenderer" {
|
|
||||||
/**
|
|
||||||
* TextRenderer
|
|
||||||
* returns only the textual part of the token
|
|
||||||
*/
|
|
||||||
export class _TextRenderer {
|
|
||||||
strong(text: string): string;
|
|
||||||
em(text: string): string;
|
|
||||||
codespan(text: string): string;
|
|
||||||
del(text: string): string;
|
|
||||||
html(text: string): string;
|
|
||||||
text(text: string): string;
|
|
||||||
link(href: string, title: string | null | undefined, text: string): string;
|
|
||||||
image(href: string, title: string | null, text: string): string;
|
|
||||||
br(): string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module "Slugger" {
|
|
||||||
import type { SluggerOptions } from "MarkedOptions";
|
|
||||||
/**
|
|
||||||
* Slugger generates header id
|
|
||||||
*/
|
|
||||||
export class _Slugger {
|
|
||||||
seen: {
|
|
||||||
[slugValue: string]: number;
|
|
||||||
};
|
|
||||||
constructor();
|
|
||||||
serialize(value: string): string;
|
|
||||||
/**
|
|
||||||
* Finds the next safe (unique) slug to use
|
|
||||||
*/
|
|
||||||
getNextSafeSlug(originalSlug: string, isDryRun: boolean | undefined): string;
|
|
||||||
/**
|
|
||||||
* Convert string to unique id
|
|
||||||
*/
|
|
||||||
slug(value: string, options?: SluggerOptions): string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module "Instance" {
|
|
||||||
import { _Lexer } from "Lexer";
|
|
||||||
import { _Parser } from "Parser";
|
|
||||||
import { _Hooks } from "Hooks";
|
|
||||||
import { _Renderer } from "Renderer";
|
|
||||||
import { _Tokenizer } from "Tokenizer";
|
|
||||||
import { _TextRenderer } from "TextRenderer";
|
|
||||||
import { _Slugger } from "Slugger";
|
|
||||||
import type { MarkedExtension, MarkedOptions } from "MarkedOptions";
|
|
||||||
import type { Token, TokensList } from "Tokens";
|
|
||||||
export type ResultCallback = (error: Error | null, parseResult?: string) => undefined | void;
|
|
||||||
export type MaybePromise = void | Promise<void>;
|
|
||||||
export class Marked {
|
|
||||||
#private;
|
|
||||||
defaults: MarkedOptions;
|
|
||||||
options: (opt: MarkedOptions) => this;
|
|
||||||
parse: (src: string, optOrCallback?: MarkedOptions | ResultCallback | undefined | null, callback?: ResultCallback | undefined) => string | Promise<string | undefined> | undefined;
|
|
||||||
parseInline: (src: string, optOrCallback?: MarkedOptions | ResultCallback | undefined | null, callback?: ResultCallback | undefined) => string | Promise<string | undefined> | undefined;
|
|
||||||
Parser: typeof _Parser;
|
|
||||||
parser: typeof _Parser.parse;
|
|
||||||
Renderer: typeof _Renderer;
|
|
||||||
TextRenderer: typeof _TextRenderer;
|
|
||||||
Lexer: typeof _Lexer;
|
|
||||||
lexer: typeof _Lexer.lex;
|
|
||||||
Tokenizer: typeof _Tokenizer;
|
|
||||||
Slugger: typeof _Slugger;
|
|
||||||
Hooks: typeof _Hooks;
|
|
||||||
constructor(...args: MarkedExtension[]);
|
|
||||||
/**
|
|
||||||
* Run callback for every token
|
|
||||||
*/
|
|
||||||
walkTokens(tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]): MaybePromise[];
|
|
||||||
use(...args: MarkedExtension[]): this;
|
|
||||||
setOptions(opt: MarkedOptions): this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module "helpers" {
|
|
||||||
import type { MarkedOptions } from "MarkedOptions";
|
|
||||||
import type { ResultCallback } from "Instance";
|
|
||||||
import type { Rule } from "rules";
|
|
||||||
export function escape(html: string, encode?: boolean): string;
|
|
||||||
export function unescape(html: string): string;
|
|
||||||
export function edit(regex: Rule, opt?: string): {
|
|
||||||
replace: (name: string | RegExp, val: string | RegExp) => any;
|
|
||||||
getRegex: () => RegExp;
|
|
||||||
};
|
|
||||||
export function cleanUrl(sanitize: boolean | undefined, base: string | undefined | null, href: string): string | null;
|
|
||||||
export function resolveUrl(base: string, href: string): string;
|
|
||||||
export const noopTest: {
|
|
||||||
exec: () => null;
|
|
||||||
};
|
|
||||||
export function splitCells(tableRow: string, count?: number): string[];
|
|
||||||
/**
|
|
||||||
* Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
|
|
||||||
* /c*$/ is vulnerable to REDOS.
|
|
||||||
*
|
|
||||||
* @param str
|
|
||||||
* @param c
|
|
||||||
* @param invert Remove suffix of non-c chars instead. Default falsey.
|
|
||||||
*/
|
|
||||||
export function rtrim(str: string, c: string, invert?: boolean): string;
|
|
||||||
export function findClosingBracket(str: string, b: string): number;
|
|
||||||
export function checkDeprecations(opt: MarkedOptions, callback?: ResultCallback): void;
|
|
||||||
}
|
|
||||||
declare module "Renderer" {
|
|
||||||
import type { MarkedOptions } from "MarkedOptions";
|
|
||||||
import type { _Slugger } from "Slugger";
|
|
||||||
/**
|
|
||||||
* Renderer
|
|
||||||
*/
|
|
||||||
export class _Renderer {
|
|
||||||
options: MarkedOptions;
|
|
||||||
constructor(options?: MarkedOptions);
|
|
||||||
code(code: string, infostring: string | undefined, escaped: boolean): string;
|
|
||||||
blockquote(quote: string): string;
|
|
||||||
html(html: string, block?: boolean): string;
|
|
||||||
heading(text: string, level: number, raw: string, slugger: _Slugger): string;
|
|
||||||
hr(): string;
|
|
||||||
list(body: string, ordered: boolean, start: number | ''): string;
|
|
||||||
listitem(text: string, task: boolean, checked: boolean): string;
|
|
||||||
checkbox(checked: boolean): string;
|
|
||||||
paragraph(text: string): string;
|
|
||||||
table(header: string, body: string): string;
|
|
||||||
tablerow(content: string): string;
|
|
||||||
tablecell(content: string, flags: {
|
|
||||||
header: boolean;
|
|
||||||
align: 'center' | 'left' | 'right' | null;
|
|
||||||
}): string;
|
|
||||||
/**
|
|
||||||
* span level renderer
|
|
||||||
*/
|
|
||||||
strong(text: string): string;
|
|
||||||
em(text: string): string;
|
|
||||||
codespan(text: string): string;
|
|
||||||
br(): string;
|
|
||||||
del(text: string): string;
|
|
||||||
link(href: string, title: string | null | undefined, text: string): string;
|
|
||||||
image(href: string, title: string | null, text: string): string;
|
|
||||||
text(text: string): string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module "Parser" {
|
|
||||||
import { _Renderer } from "Renderer";
|
|
||||||
import { _TextRenderer } from "TextRenderer";
|
|
||||||
import { _Slugger } from "Slugger";
|
|
||||||
import type { Token } from "Tokens";
|
|
||||||
import type { MarkedOptions } from "MarkedOptions";
|
|
||||||
/**
|
|
||||||
* Parsing & Compiling
|
|
||||||
*/
|
|
||||||
export class _Parser {
|
|
||||||
options: MarkedOptions;
|
|
||||||
renderer: _Renderer;
|
|
||||||
textRenderer: _TextRenderer;
|
|
||||||
slugger: _Slugger;
|
|
||||||
constructor(options?: MarkedOptions);
|
|
||||||
/**
|
|
||||||
* Static Parse Method
|
|
||||||
*/
|
|
||||||
static parse(tokens: Token[], options?: MarkedOptions): string;
|
|
||||||
/**
|
|
||||||
* Static Parse Inline Method
|
|
||||||
*/
|
|
||||||
static parseInline(tokens: Token[], options?: MarkedOptions): string;
|
|
||||||
/**
|
|
||||||
* Parse Loop
|
|
||||||
*/
|
|
||||||
parse(tokens: Token[], top?: boolean): string;
|
|
||||||
/**
|
|
||||||
* Parse Inline Tokens
|
|
||||||
*/
|
|
||||||
parseInline(tokens: Token[], renderer?: _Renderer | _TextRenderer): string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module "MarkedOptions" {
|
declare module "MarkedOptions" {
|
||||||
import type { Token, Tokens, TokensList } from "Tokens";
|
import type { Token, Tokens, TokensList } from "Tokens";
|
||||||
import type { _Parser } from "Parser";
|
import type { _Parser } from "Parser";
|
||||||
import type { _Lexer } from "Lexer";
|
import type { _Lexer } from "Lexer";
|
||||||
import type { _Renderer } from "Renderer";
|
import type { _Renderer } from "Renderer";
|
||||||
import type { _Tokenizer } from "Tokenizer";
|
import type { _Tokenizer } from "Tokenizer";
|
||||||
export interface SluggerOptions {
|
|
||||||
/** Generates the next unique slug without updating the internal accumulator. */
|
|
||||||
dryrun?: boolean;
|
|
||||||
}
|
|
||||||
export interface TokenizerThis {
|
export interface TokenizerThis {
|
||||||
lexer: _Lexer;
|
lexer: _Lexer;
|
||||||
}
|
}
|
||||||
@ -470,11 +402,6 @@ declare module "MarkedOptions" {
|
|||||||
* True will tell marked to await any walkTokens functions before parsing the tokens and returning an HTML string.
|
* True will tell marked to await any walkTokens functions before parsing the tokens and returning an HTML string.
|
||||||
*/
|
*/
|
||||||
async?: boolean;
|
async?: boolean;
|
||||||
/**
|
|
||||||
* A prefix URL for any relative link.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-base-url to prefix url for any relative link.
|
|
||||||
*/
|
|
||||||
baseUrl?: string | undefined | null;
|
|
||||||
/**
|
/**
|
||||||
* Enable GFM line breaks. This option requires the gfm option to be true.
|
* Enable GFM line breaks. This option requires the gfm option to be true.
|
||||||
*/
|
*/
|
||||||
@ -487,24 +414,6 @@ declare module "MarkedOptions" {
|
|||||||
* Enable GitHub flavored markdown.
|
* Enable GitHub flavored markdown.
|
||||||
*/
|
*/
|
||||||
gfm?: boolean | undefined;
|
gfm?: boolean | undefined;
|
||||||
/**
|
|
||||||
* Include an id attribute when emitting headings.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-gfm-heading-id to include an id attribute when emitting headings (h1, h2, h3, etc).
|
|
||||||
*/
|
|
||||||
headerIds?: boolean | undefined;
|
|
||||||
/**
|
|
||||||
* Set the prefix for header tag ids.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-gfm-heading-id to add a string to prefix the id attribute when emitting headings (h1, h2, h3, etc).
|
|
||||||
*/
|
|
||||||
headerPrefix?: string | undefined;
|
|
||||||
/**
|
|
||||||
* A function to highlight code blocks. The function can either be
|
|
||||||
* synchronous (returning a string) or asynchronous (callback invoked
|
|
||||||
* with an error if any occurred during highlighting and a string
|
|
||||||
* if highlighting was successful)
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-highlight to add highlighting to code blocks.
|
|
||||||
*/
|
|
||||||
highlight?: ((code: string, lang: string | undefined, callback?: (error: Error, code?: string) => void) => string | void) | null;
|
|
||||||
/**
|
/**
|
||||||
* Hooks are methods that hook into some part of marked.
|
* Hooks are methods that hook into some part of marked.
|
||||||
* preprocess is called to process markdown before sending it to marked.
|
* preprocess is called to process markdown before sending it to marked.
|
||||||
@ -515,16 +424,6 @@ declare module "MarkedOptions" {
|
|||||||
postprocess: (html: string) => string | Promise<string>;
|
postprocess: (html: string) => string | Promise<string>;
|
||||||
options?: MarkedOptions;
|
options?: MarkedOptions;
|
||||||
} | null;
|
} | null;
|
||||||
/**
|
|
||||||
* Set the prefix for code block classes.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-highlight to prefix the className in a <code> block. Useful for syntax highlighting.
|
|
||||||
*/
|
|
||||||
langPrefix?: string | undefined;
|
|
||||||
/**
|
|
||||||
* Mangle autolinks (<email@domain.com>).
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-mangle to mangle email addresses.
|
|
||||||
*/
|
|
||||||
mangle?: boolean | undefined;
|
|
||||||
/**
|
/**
|
||||||
* Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
|
* Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
|
||||||
*/
|
*/
|
||||||
@ -535,29 +434,10 @@ declare module "MarkedOptions" {
|
|||||||
* An object containing functions to render tokens to HTML.
|
* An object containing functions to render tokens to HTML.
|
||||||
*/
|
*/
|
||||||
renderer?: RendererObject | undefined | null;
|
renderer?: RendererObject | undefined | null;
|
||||||
/**
|
|
||||||
* Sanitize the output. Ignore any HTML that has been input. If true, sanitize the HTML passed into markdownString with the sanitizer function.
|
|
||||||
* @deprecated Warning: This feature is deprecated and it should NOT be used as it cannot be considered secure. Instead use a sanitize library, like DOMPurify (recommended), sanitize-html or insane on the output HTML!
|
|
||||||
*/
|
|
||||||
sanitize?: boolean | undefined;
|
|
||||||
/**
|
|
||||||
* Optionally sanitize found HTML with a sanitizer function.
|
|
||||||
* @deprecated A function to sanitize the HTML passed into markdownString.
|
|
||||||
*/
|
|
||||||
sanitizer?: ((html: string) => string) | null;
|
|
||||||
/**
|
/**
|
||||||
* Shows an HTML error message when rendering fails.
|
* Shows an HTML error message when rendering fails.
|
||||||
*/
|
*/
|
||||||
silent?: boolean | undefined;
|
silent?: boolean | undefined;
|
||||||
/**
|
|
||||||
* Use smarter list behavior than the original markdown. May eventually be default with the old behavior moved into pedantic.
|
|
||||||
*/
|
|
||||||
smartLists?: boolean | undefined;
|
|
||||||
/**
|
|
||||||
* Use "smart" typograhic punctuation for things like quotes and dashes.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-smartypants to use "smart" typographic punctuation for things like quotes and dashes.
|
|
||||||
*/
|
|
||||||
smartypants?: boolean | undefined;
|
|
||||||
/**
|
/**
|
||||||
* The tokenizer defines how to turn markdown text into tokens.
|
* The tokenizer defines how to turn markdown text into tokens.
|
||||||
*/
|
*/
|
||||||
@ -569,11 +449,6 @@ declare module "MarkedOptions" {
|
|||||||
* The return value of the function is ignored.
|
* The return value of the function is ignored.
|
||||||
*/
|
*/
|
||||||
walkTokens?: ((token: Token) => void | Promise<void>) | undefined | null;
|
walkTokens?: ((token: Token) => void | Promise<void>) | undefined | null;
|
||||||
/**
|
|
||||||
* Generate closing slash for self-closing tags (<br/> instead of <br>)
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-xhtml to emit self-closing HTML tags for void elements (<br/>, <img/>, etc.) with a "/" as required by XHTML.
|
|
||||||
*/
|
|
||||||
xhtml?: boolean | undefined;
|
|
||||||
}
|
}
|
||||||
export interface MarkedOptions extends Omit<MarkedExtension, 'renderer' | 'tokenizer' | 'extensions' | 'walkTokens'> {
|
export interface MarkedOptions extends Omit<MarkedExtension, 'renderer' | 'tokenizer' | 'extensions' | 'walkTokens'> {
|
||||||
/**
|
/**
|
||||||
@ -632,18 +507,50 @@ declare module "Hooks" {
|
|||||||
postprocess(html: string): string;
|
postprocess(html: string): string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
declare module "Instance" {
|
||||||
|
import { _Lexer } from "Lexer";
|
||||||
|
import { _Parser } from "Parser";
|
||||||
|
import { _Hooks } from "Hooks";
|
||||||
|
import { _Renderer } from "Renderer";
|
||||||
|
import { _Tokenizer } from "Tokenizer";
|
||||||
|
import { _TextRenderer } from "TextRenderer";
|
||||||
|
import type { MarkedExtension, MarkedOptions } from "MarkedOptions";
|
||||||
|
import type { Token, TokensList } from "Tokens";
|
||||||
|
export type MaybePromise = void | Promise<void>;
|
||||||
|
export class Marked {
|
||||||
|
#private;
|
||||||
|
defaults: MarkedOptions;
|
||||||
|
options: (opt: MarkedOptions) => this;
|
||||||
|
parse: (src: string, options?: MarkedOptions | undefined | null) => string | Promise<string>;
|
||||||
|
parseInline: (src: string, options?: MarkedOptions | undefined | null) => string | Promise<string>;
|
||||||
|
Parser: typeof _Parser;
|
||||||
|
parser: typeof _Parser.parse;
|
||||||
|
Renderer: typeof _Renderer;
|
||||||
|
TextRenderer: typeof _TextRenderer;
|
||||||
|
Lexer: typeof _Lexer;
|
||||||
|
lexer: typeof _Lexer.lex;
|
||||||
|
Tokenizer: typeof _Tokenizer;
|
||||||
|
Hooks: typeof _Hooks;
|
||||||
|
constructor(...args: MarkedExtension[]);
|
||||||
|
/**
|
||||||
|
* Run callback for every token
|
||||||
|
*/
|
||||||
|
walkTokens(tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]): MaybePromise[];
|
||||||
|
use(...args: MarkedExtension[]): this;
|
||||||
|
setOptions(opt: MarkedOptions): this;
|
||||||
|
}
|
||||||
|
}
|
||||||
declare module "marked" {
|
declare module "marked" {
|
||||||
import { _Lexer } from "Lexer";
|
import { _Lexer } from "Lexer";
|
||||||
import { _Parser } from "Parser";
|
import { _Parser } from "Parser";
|
||||||
import { _Tokenizer } from "Tokenizer";
|
import { _Tokenizer } from "Tokenizer";
|
||||||
import { _Renderer } from "Renderer";
|
import { _Renderer } from "Renderer";
|
||||||
import { _TextRenderer } from "TextRenderer";
|
import { _TextRenderer } from "TextRenderer";
|
||||||
import { _Slugger } from "Slugger";
|
|
||||||
import { _Hooks } from "Hooks";
|
import { _Hooks } from "Hooks";
|
||||||
import { _getDefaults } from "defaults";
|
import { _getDefaults } from "defaults";
|
||||||
import type { MarkedExtension, MarkedOptions } from "MarkedOptions";
|
import type { MarkedExtension, MarkedOptions } from "MarkedOptions";
|
||||||
import type { Token, TokensList } from "Tokens";
|
import type { Token, TokensList } from "Tokens";
|
||||||
import type { ResultCallback, MaybePromise } from "Instance";
|
import type { MaybePromise } from "Instance";
|
||||||
/**
|
/**
|
||||||
* Compiles markdown to HTML asynchronously.
|
* Compiles markdown to HTML asynchronously.
|
||||||
*
|
*
|
||||||
@ -663,26 +570,11 @@ declare module "marked" {
|
|||||||
*/
|
*/
|
||||||
export function marked(src: string, options?: MarkedOptions): string;
|
export function marked(src: string, options?: MarkedOptions): string;
|
||||||
/**
|
/**
|
||||||
* Compiles markdown to HTML asynchronously with a callback.
|
* Compiles markdown to HTML synchronously.
|
||||||
*
|
*
|
||||||
* @param src String of markdown source to be compiled
|
* @param src String of markdown source to be compiled
|
||||||
* @param callback Function called when the markdownString has been fully parsed when using async highlighting
|
* @param options Optional hash of options
|
||||||
*/
|
* @return String of compiled HTML
|
||||||
export function marked(src: string, callback: ResultCallback): void;
|
|
||||||
/**
|
|
||||||
* Compiles markdown to HTML asynchronously with a callback.
|
|
||||||
*
|
|
||||||
* @param src String of markdown source to be compiled
|
|
||||||
* @param options Hash of options
|
|
||||||
* @param callback Function called when the markdownString has been fully parsed when using async highlighting
|
|
||||||
*/
|
|
||||||
export function marked(src: string, options: MarkedOptions, callback: ResultCallback): void;
|
|
||||||
/**
|
|
||||||
* Compiles markdown to HTML asynchronously with a callback.
|
|
||||||
*
|
|
||||||
* @param src String of markdown source to be compiled
|
|
||||||
* @param options Hash of options
|
|
||||||
* @param callback Function called when the markdownString has been fully parsed when using async highlighting
|
|
||||||
*/
|
*/
|
||||||
export namespace marked {
|
export namespace marked {
|
||||||
var options: (options: MarkedOptions) => typeof marked;
|
var options: (options: MarkedOptions) => typeof marked;
|
||||||
@ -691,7 +583,7 @@ declare module "marked" {
|
|||||||
var defaults: MarkedOptions;
|
var defaults: MarkedOptions;
|
||||||
var use: (...args: MarkedExtension[]) => typeof marked;
|
var use: (...args: MarkedExtension[]) => typeof marked;
|
||||||
var walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[];
|
var walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[];
|
||||||
var parseInline: (src: string, optOrCallback?: MarkedOptions | ResultCallback | null | undefined, callback?: ResultCallback | undefined) => string | Promise<string | undefined> | undefined;
|
var parseInline: (src: string, options?: MarkedOptions | null | undefined) => string | Promise<string>;
|
||||||
var Parser: typeof _Parser;
|
var Parser: typeof _Parser;
|
||||||
var parser: typeof _Parser.parse;
|
var parser: typeof _Parser.parse;
|
||||||
var Renderer: typeof _Renderer;
|
var Renderer: typeof _Renderer;
|
||||||
@ -699,7 +591,6 @@ declare module "marked" {
|
|||||||
var Lexer: typeof _Lexer;
|
var Lexer: typeof _Lexer;
|
||||||
var lexer: typeof _Lexer.lex;
|
var lexer: typeof _Lexer.lex;
|
||||||
var Tokenizer: typeof _Tokenizer;
|
var Tokenizer: typeof _Tokenizer;
|
||||||
var Slugger: typeof _Slugger;
|
|
||||||
var Hooks: typeof _Hooks;
|
var Hooks: typeof _Hooks;
|
||||||
var parse: typeof marked;
|
var parse: typeof marked;
|
||||||
}
|
}
|
||||||
@ -707,7 +598,7 @@ declare module "marked" {
|
|||||||
export const setOptions: (options: MarkedOptions) => typeof marked;
|
export const setOptions: (options: MarkedOptions) => typeof marked;
|
||||||
export const use: (...args: MarkedExtension[]) => typeof marked;
|
export const use: (...args: MarkedExtension[]) => typeof marked;
|
||||||
export const walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[];
|
export const walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[];
|
||||||
export const parseInline: (src: string, optOrCallback?: MarkedOptions | ResultCallback | null | undefined, callback?: ResultCallback | undefined) => string | Promise<string | undefined> | undefined;
|
export const parseInline: (src: string, options?: MarkedOptions | null | undefined) => string | Promise<string>;
|
||||||
export const parse: typeof marked;
|
export const parse: typeof marked;
|
||||||
export const parser: typeof _Parser.parse;
|
export const parser: typeof _Parser.parse;
|
||||||
export const lexer: typeof _Lexer.lex;
|
export const lexer: typeof _Lexer.lex;
|
||||||
@ -717,7 +608,6 @@ declare module "marked" {
|
|||||||
export { _Tokenizer as Tokenizer } from "Tokenizer";
|
export { _Tokenizer as Tokenizer } from "Tokenizer";
|
||||||
export { _Renderer as Renderer } from "Renderer";
|
export { _Renderer as Renderer } from "Renderer";
|
||||||
export { _TextRenderer as TextRenderer } from "TextRenderer";
|
export { _TextRenderer as TextRenderer } from "TextRenderer";
|
||||||
export { _Slugger as Slugger } from "Slugger";
|
|
||||||
export { _Hooks as Hooks } from "Hooks";
|
export { _Hooks as Hooks } from "Hooks";
|
||||||
export { Marked } from "Instance";
|
export { Marked } from "Instance";
|
||||||
export type * from "MarkedOptions";
|
export type * from "MarkedOptions";
|
||||||
|
344
lib/marked.esm.js
generated
344
lib/marked.esm.js
generated
@ -15,25 +15,15 @@
|
|||||||
function _getDefaults() {
|
function _getDefaults() {
|
||||||
return {
|
return {
|
||||||
async: false,
|
async: false,
|
||||||
baseUrl: null,
|
|
||||||
breaks: false,
|
breaks: false,
|
||||||
extensions: null,
|
extensions: null,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
headerIds: false,
|
|
||||||
headerPrefix: '',
|
|
||||||
highlight: null,
|
|
||||||
hooks: null,
|
hooks: null,
|
||||||
langPrefix: 'language-',
|
|
||||||
mangle: false,
|
|
||||||
pedantic: false,
|
pedantic: false,
|
||||||
renderer: null,
|
renderer: null,
|
||||||
sanitize: false,
|
|
||||||
sanitizer: null,
|
|
||||||
silent: false,
|
silent: false,
|
||||||
smartypants: false,
|
|
||||||
tokenizer: null,
|
tokenizer: null,
|
||||||
walkTokens: null,
|
walkTokens: null
|
||||||
xhtml: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let _defaults = _getDefaults();
|
let _defaults = _getDefaults();
|
||||||
@ -101,26 +91,7 @@ function edit(regex, opt) {
|
|||||||
};
|
};
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
const nonWordAndColonTest = /[^\w:]/g;
|
function cleanUrl(href) {
|
||||||
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
|
|
||||||
function cleanUrl(sanitize, base, href) {
|
|
||||||
if (sanitize) {
|
|
||||||
let prot;
|
|
||||||
try {
|
|
||||||
prot = decodeURIComponent(unescape(href))
|
|
||||||
.replace(nonWordAndColonTest, '')
|
|
||||||
.toLowerCase();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (base && !originIndependentUrl.test(href)) {
|
|
||||||
href = resolveUrl(base, href);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
href = encodeURI(href).replace(/%25/g, '%');
|
href = encodeURI(href).replace(/%25/g, '%');
|
||||||
}
|
}
|
||||||
@ -129,40 +100,6 @@ function cleanUrl(sanitize, base, href) {
|
|||||||
}
|
}
|
||||||
return href;
|
return href;
|
||||||
}
|
}
|
||||||
const baseUrls = {};
|
|
||||||
const justDomain = /^[^:]+:\/*[^/]*$/;
|
|
||||||
const protocol = /^([^:]+:)[\s\S]*$/;
|
|
||||||
const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
|
|
||||||
function resolveUrl(base, href) {
|
|
||||||
if (!baseUrls[' ' + base]) {
|
|
||||||
// we can ignore everything in base after the last slash of its path component,
|
|
||||||
// but we might need to add _that_
|
|
||||||
// https://tools.ietf.org/html/rfc3986#section-3
|
|
||||||
if (justDomain.test(base)) {
|
|
||||||
baseUrls[' ' + base] = base + '/';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
baseUrls[' ' + base] = rtrim(base, '/', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base = baseUrls[' ' + base];
|
|
||||||
const relativeBase = base.indexOf(':') === -1;
|
|
||||||
if (href.substring(0, 2) === '//') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(protocol, '$1') + href;
|
|
||||||
}
|
|
||||||
else if (href.charAt(0) === '/') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(domain, '$1') + href;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return base + href;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const noopTest = { exec: () => null };
|
const noopTest = { exec: () => null };
|
||||||
function splitCells(tableRow, count) {
|
function splitCells(tableRow, count) {
|
||||||
// ensure that every cell-delimiting pipe has a space
|
// ensure that every cell-delimiting pipe has a space
|
||||||
@ -256,35 +193,6 @@ function findClosingBracket(str, b) {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
function checkDeprecations(opt, callback) {
|
|
||||||
if (!opt || opt.silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (callback) {
|
|
||||||
console.warn('marked(): callback is deprecated since version 5.0.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/using_pro#async');
|
|
||||||
}
|
|
||||||
if (opt.sanitize || opt.sanitizer) {
|
|
||||||
console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
|
|
||||||
}
|
|
||||||
if (opt.highlight || opt.langPrefix !== 'language-') {
|
|
||||||
console.warn('marked(): highlight and langPrefix parameters are deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-highlight.');
|
|
||||||
}
|
|
||||||
if (opt.mangle) {
|
|
||||||
console.warn('marked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.');
|
|
||||||
}
|
|
||||||
if (opt.baseUrl) {
|
|
||||||
console.warn('marked(): baseUrl parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-base-url.');
|
|
||||||
}
|
|
||||||
if (opt.smartypants) {
|
|
||||||
console.warn('marked(): smartypants parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-smartypants.');
|
|
||||||
}
|
|
||||||
if (opt.xhtml) {
|
|
||||||
console.warn('marked(): xhtml parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-xhtml.');
|
|
||||||
}
|
|
||||||
if (opt.headerIds || opt.headerPrefix) {
|
|
||||||
console.warn('marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function outputLink(cap, link, raw, lexer) {
|
function outputLink(cap, link, raw, lexer) {
|
||||||
const href = link.href;
|
const href = link.href;
|
||||||
@ -601,17 +509,9 @@ class _Tokenizer {
|
|||||||
type: 'html',
|
type: 'html',
|
||||||
block: true,
|
block: true,
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
pre: !this.options.sanitizer
|
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
|
||||||
&& (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
|
|
||||||
text: cap[0]
|
text: cap[0]
|
||||||
};
|
};
|
||||||
if (this.options.sanitize) {
|
|
||||||
const text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
|
|
||||||
const paragraph = token;
|
|
||||||
paragraph.type = 'paragraph';
|
|
||||||
paragraph.text = text;
|
|
||||||
paragraph.tokens = this.lexer.inline(text);
|
|
||||||
}
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -749,18 +649,12 @@ class _Tokenizer {
|
|||||||
this.lexer.state.inRawBlock = false;
|
this.lexer.state.inRawBlock = false;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: this.options.sanitize
|
type: 'html',
|
||||||
? 'text'
|
|
||||||
: 'html',
|
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
inLink: this.lexer.state.inLink,
|
inLink: this.lexer.state.inLink,
|
||||||
inRawBlock: this.lexer.state.inRawBlock,
|
inRawBlock: this.lexer.state.inRawBlock,
|
||||||
block: false,
|
block: false,
|
||||||
text: this.options.sanitize
|
text: cap[0]
|
||||||
? (this.options.sanitizer
|
|
||||||
? this.options.sanitizer(cap[0])
|
|
||||||
: escape(cap[0]))
|
|
||||||
: cap[0]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -931,12 +825,12 @@ class _Tokenizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
autolink(src, mangle) {
|
autolink(src) {
|
||||||
const cap = this.rules.inline.autolink.exec(src);
|
const cap = this.rules.inline.autolink.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
|
text = escape(cap[1]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -958,12 +852,12 @@ class _Tokenizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
url(src, mangle) {
|
url(src) {
|
||||||
let cap;
|
let cap;
|
||||||
if (cap = this.rules.inline.url.exec(src)) {
|
if (cap = this.rules.inline.url.exec(src)) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -996,15 +890,15 @@ class _Tokenizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inlineText(src, smartypants) {
|
inlineText(src) {
|
||||||
const cap = this.rules.inline.text.exec(src);
|
const cap = this.rules.inline.text.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text;
|
let text;
|
||||||
if (this.lexer.state.inRawBlock) {
|
if (this.lexer.state.inRawBlock) {
|
||||||
text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0];
|
text = cap[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@ -1292,39 +1186,6 @@ inline.breaks = {
|
|||||||
.getRegex()
|
.getRegex()
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* smartypants text replacement
|
|
||||||
*/
|
|
||||||
function smartypants(text) {
|
|
||||||
return text
|
|
||||||
// em-dashes
|
|
||||||
.replace(/---/g, '\u2014')
|
|
||||||
// en-dashes
|
|
||||||
.replace(/--/g, '\u2013')
|
|
||||||
// opening singles
|
|
||||||
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
|
||||||
// closing singles & apostrophes
|
|
||||||
.replace(/'/g, '\u2019')
|
|
||||||
// opening doubles
|
|
||||||
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
|
||||||
// closing doubles
|
|
||||||
.replace(/"/g, '\u201d')
|
|
||||||
// ellipses
|
|
||||||
.replace(/\.{3}/g, '\u2026');
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* mangle email addresses
|
|
||||||
*/
|
|
||||||
function mangle(text) {
|
|
||||||
let out = '';
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
const ch = Math.random() > 0.5
|
|
||||||
? 'x' + text.charCodeAt(i).toString(16)
|
|
||||||
: text.charCodeAt(i).toString();
|
|
||||||
out += '&#' + ch + ';';
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Block Lexer
|
* Block Lexer
|
||||||
*/
|
*/
|
||||||
@ -1698,13 +1559,13 @@ class _Lexer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// autolink
|
// autolink
|
||||||
if (token = this.tokenizer.autolink(src, mangle)) {
|
if (token = this.tokenizer.autolink(src)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// url (gfm)
|
// url (gfm)
|
||||||
if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
|
if (!this.state.inLink && (token = this.tokenizer.url(src))) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
@ -1726,7 +1587,7 @@ class _Lexer {
|
|||||||
cutSrc = src.substring(0, startIndex + 1);
|
cutSrc = src.substring(0, startIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
|
if (token = this.tokenizer.inlineText(cutSrc)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
||||||
prevChar = token.raw.slice(-1);
|
prevChar = token.raw.slice(-1);
|
||||||
@ -1767,21 +1628,13 @@ class _Renderer {
|
|||||||
}
|
}
|
||||||
code(code, infostring, escaped) {
|
code(code, infostring, escaped) {
|
||||||
const lang = (infostring || '').match(/^\S*/)?.[0];
|
const lang = (infostring || '').match(/^\S*/)?.[0];
|
||||||
if (this.options.highlight) {
|
|
||||||
const out = this.options.highlight(code, lang);
|
|
||||||
if (out != null && out !== code) {
|
|
||||||
escaped = true;
|
|
||||||
code = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code = code.replace(/\n$/, '') + '\n';
|
code = code.replace(/\n$/, '') + '\n';
|
||||||
if (!lang) {
|
if (!lang) {
|
||||||
return '<pre><code>'
|
return '<pre><code>'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
+ '</code></pre>\n';
|
+ '</code></pre>\n';
|
||||||
}
|
}
|
||||||
return '<pre><code class="'
|
return '<pre><code class="language-'
|
||||||
+ this.options.langPrefix
|
|
||||||
+ escape(lang)
|
+ escape(lang)
|
||||||
+ '">'
|
+ '">'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
@ -1793,16 +1646,12 @@ class _Renderer {
|
|||||||
html(html, block) {
|
html(html, block) {
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
heading(text, level, raw, slugger) {
|
heading(text, level, raw) {
|
||||||
if (this.options.headerIds) {
|
|
||||||
const id = this.options.headerPrefix + slugger.slug(raw);
|
|
||||||
return `<h${level} id="${id}">${text}</h${level}>\n`;
|
|
||||||
}
|
|
||||||
// ignore IDs
|
// ignore IDs
|
||||||
return `<h${level}>${text}</h${level}>\n`;
|
return `<h${level}>${text}</h${level}>\n`;
|
||||||
}
|
}
|
||||||
hr() {
|
hr() {
|
||||||
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
|
return '<hr>\n';
|
||||||
}
|
}
|
||||||
list(body, ordered, start) {
|
list(body, ordered, start) {
|
||||||
const type = ordered ? 'ol' : 'ul';
|
const type = ordered ? 'ol' : 'ul';
|
||||||
@ -1815,9 +1664,7 @@ class _Renderer {
|
|||||||
checkbox(checked) {
|
checkbox(checked) {
|
||||||
return '<input '
|
return '<input '
|
||||||
+ (checked ? 'checked="" ' : '')
|
+ (checked ? 'checked="" ' : '')
|
||||||
+ 'disabled="" type="checkbox"'
|
+ 'disabled="" type="checkbox">';
|
||||||
+ (this.options.xhtml ? ' /' : '')
|
|
||||||
+ '> ';
|
|
||||||
}
|
}
|
||||||
paragraph(text) {
|
paragraph(text) {
|
||||||
return `<p>${text}</p>\n`;
|
return `<p>${text}</p>\n`;
|
||||||
@ -1855,13 +1702,13 @@ class _Renderer {
|
|||||||
return `<code>${text}</code>`;
|
return `<code>${text}</code>`;
|
||||||
}
|
}
|
||||||
br() {
|
br() {
|
||||||
return this.options.xhtml ? '<br/>' : '<br>';
|
return '<br>';
|
||||||
}
|
}
|
||||||
del(text) {
|
del(text) {
|
||||||
return `<del>${text}</del>`;
|
return `<del>${text}</del>`;
|
||||||
}
|
}
|
||||||
link(href, title, text) {
|
link(href, title, text) {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -1874,7 +1721,7 @@ class _Renderer {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
image(href, title, text) {
|
image(href, title, text) {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -1883,7 +1730,7 @@ class _Renderer {
|
|||||||
if (title) {
|
if (title) {
|
||||||
out += ` title="${title}"`;
|
out += ` title="${title}"`;
|
||||||
}
|
}
|
||||||
out += this.options.xhtml ? '/>' : '>';
|
out += '>';
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
text(text) {
|
text(text) {
|
||||||
@ -1926,52 +1773,6 @@ class _TextRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Slugger generates header id
|
|
||||||
*/
|
|
||||||
class _Slugger {
|
|
||||||
seen;
|
|
||||||
constructor() {
|
|
||||||
this.seen = {};
|
|
||||||
}
|
|
||||||
serialize(value) {
|
|
||||||
return value
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
// remove html tags
|
|
||||||
.replace(/<[!\/a-z].*?>/ig, '')
|
|
||||||
// remove unwanted chars
|
|
||||||
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
|
|
||||||
.replace(/\s/g, '-');
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Finds the next safe (unique) slug to use
|
|
||||||
*/
|
|
||||||
getNextSafeSlug(originalSlug, isDryRun) {
|
|
||||||
let slug = originalSlug;
|
|
||||||
let occurenceAccumulator = 0;
|
|
||||||
if (this.seen.hasOwnProperty(slug)) {
|
|
||||||
occurenceAccumulator = this.seen[originalSlug];
|
|
||||||
do {
|
|
||||||
occurenceAccumulator++;
|
|
||||||
slug = originalSlug + '-' + occurenceAccumulator;
|
|
||||||
} while (this.seen.hasOwnProperty(slug));
|
|
||||||
}
|
|
||||||
if (!isDryRun) {
|
|
||||||
this.seen[originalSlug] = occurenceAccumulator;
|
|
||||||
this.seen[slug] = 0;
|
|
||||||
}
|
|
||||||
return slug;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Convert string to unique id
|
|
||||||
*/
|
|
||||||
slug(value, options = {}) {
|
|
||||||
const slug = this.serialize(value);
|
|
||||||
return this.getNextSafeSlug(slug, options.dryrun);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsing & Compiling
|
* Parsing & Compiling
|
||||||
*/
|
*/
|
||||||
@ -1979,14 +1780,12 @@ class _Parser {
|
|||||||
options;
|
options;
|
||||||
renderer;
|
renderer;
|
||||||
textRenderer;
|
textRenderer;
|
||||||
slugger;
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.options = options || _defaults;
|
this.options = options || _defaults;
|
||||||
this.options.renderer = this.options.renderer || new _Renderer();
|
this.options.renderer = this.options.renderer || new _Renderer();
|
||||||
this.renderer = this.options.renderer;
|
this.renderer = this.options.renderer;
|
||||||
this.renderer.options = this.options;
|
this.renderer.options = this.options;
|
||||||
this.textRenderer = new _TextRenderer();
|
this.textRenderer = new _TextRenderer();
|
||||||
this.slugger = new _Slugger();
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Static Parse Method
|
* Static Parse Method
|
||||||
@ -2028,7 +1827,7 @@ class _Parser {
|
|||||||
}
|
}
|
||||||
case 'heading': {
|
case 'heading': {
|
||||||
const headingToken = token;
|
const headingToken = token;
|
||||||
out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)), this.slugger);
|
out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case 'code': {
|
case 'code': {
|
||||||
@ -2251,7 +2050,6 @@ class Marked {
|
|||||||
Lexer = _Lexer;
|
Lexer = _Lexer;
|
||||||
lexer = _Lexer.lex;
|
lexer = _Lexer.lex;
|
||||||
Tokenizer = _Tokenizer;
|
Tokenizer = _Tokenizer;
|
||||||
Slugger = _Slugger;
|
|
||||||
Hooks = _Hooks;
|
Hooks = _Hooks;
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
this.use(...args);
|
this.use(...args);
|
||||||
@ -2448,12 +2246,8 @@ class Marked {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
#parseMarkdown(lexer, parser) {
|
#parseMarkdown(lexer, parser) {
|
||||||
return (src, optOrCallback, callback) => {
|
return (src, options) => {
|
||||||
if (typeof optOrCallback === 'function') {
|
const origOpt = { ...options };
|
||||||
callback = optOrCallback;
|
|
||||||
optOrCallback = null;
|
|
||||||
}
|
|
||||||
const origOpt = { ...optOrCallback };
|
|
||||||
const opt = { ...this.defaults, ...origOpt };
|
const opt = { ...this.defaults, ...origOpt };
|
||||||
// Show warning if an extension set async to true but the parse was called with async: false
|
// Show warning if an extension set async to true but the parse was called with async: false
|
||||||
if (this.defaults.async === true && origOpt.async === false) {
|
if (this.defaults.async === true && origOpt.async === false) {
|
||||||
@ -2462,7 +2256,7 @@ class Marked {
|
|||||||
}
|
}
|
||||||
opt.async = true;
|
opt.async = true;
|
||||||
}
|
}
|
||||||
const throwError = this.#onError(!!opt.silent, !!opt.async, callback);
|
const throwError = this.#onError(!!opt.silent, !!opt.async);
|
||||||
// throw error in case of non string input
|
// throw error in case of non string input
|
||||||
if (typeof src === 'undefined' || src === null) {
|
if (typeof src === 'undefined' || src === null) {
|
||||||
return throwError(new Error('marked(): input parameter is undefined or null'));
|
return throwError(new Error('marked(): input parameter is undefined or null'));
|
||||||
@ -2471,76 +2265,9 @@ class Marked {
|
|||||||
return throwError(new Error('marked(): input parameter is of type '
|
return throwError(new Error('marked(): input parameter is of type '
|
||||||
+ Object.prototype.toString.call(src) + ', string expected'));
|
+ Object.prototype.toString.call(src) + ', string expected'));
|
||||||
}
|
}
|
||||||
checkDeprecations(opt, callback);
|
|
||||||
if (opt.hooks) {
|
if (opt.hooks) {
|
||||||
opt.hooks.options = opt;
|
opt.hooks.options = opt;
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
const resultCallback = callback;
|
|
||||||
const highlight = opt.highlight;
|
|
||||||
let tokens;
|
|
||||||
try {
|
|
||||||
if (opt.hooks) {
|
|
||||||
src = opt.hooks.preprocess(src);
|
|
||||||
}
|
|
||||||
tokens = lexer(src, opt);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return throwError(e);
|
|
||||||
}
|
|
||||||
const done = (err) => {
|
|
||||||
let out;
|
|
||||||
if (!err) {
|
|
||||||
try {
|
|
||||||
if (opt.walkTokens) {
|
|
||||||
this.walkTokens(tokens, opt.walkTokens);
|
|
||||||
}
|
|
||||||
out = parser(tokens, opt);
|
|
||||||
if (opt.hooks) {
|
|
||||||
out = opt.hooks.postprocess(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
err = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opt.highlight = highlight;
|
|
||||||
return err
|
|
||||||
? throwError(err)
|
|
||||||
: resultCallback(null, out);
|
|
||||||
};
|
|
||||||
if (!highlight || highlight.length < 3) {
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
delete opt.highlight;
|
|
||||||
if (!tokens.length)
|
|
||||||
return done();
|
|
||||||
let pending = 0;
|
|
||||||
this.walkTokens(tokens, (token) => {
|
|
||||||
if (token.type === 'code') {
|
|
||||||
pending++;
|
|
||||||
setTimeout(() => {
|
|
||||||
highlight(token.text, token.lang, (err, code) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
if (code != null && code !== token.text) {
|
|
||||||
token.text = code;
|
|
||||||
token.escaped = true;
|
|
||||||
}
|
|
||||||
pending--;
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (opt.async) {
|
if (opt.async) {
|
||||||
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
||||||
.then(src => lexer(src, opt))
|
.then(src => lexer(src, opt))
|
||||||
@ -2568,7 +2295,7 @@ class Marked {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#onError(silent, async, callback) {
|
#onError(silent, async) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
||||||
if (silent) {
|
if (silent) {
|
||||||
@ -2578,27 +2305,19 @@ class Marked {
|
|||||||
if (async) {
|
if (async) {
|
||||||
return Promise.resolve(msg);
|
return Promise.resolve(msg);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(null, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
if (async) {
|
if (async) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const markedInstance = new Marked();
|
const markedInstance = new Marked();
|
||||||
function marked(src, opt, callback) {
|
function marked(src, opt) {
|
||||||
return markedInstance.parse(src, opt, callback);
|
return markedInstance.parse(src, opt);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Sets the default options.
|
* Sets the default options.
|
||||||
@ -2650,7 +2369,6 @@ marked.TextRenderer = _TextRenderer;
|
|||||||
marked.Lexer = _Lexer;
|
marked.Lexer = _Lexer;
|
||||||
marked.lexer = _Lexer.lex;
|
marked.lexer = _Lexer.lex;
|
||||||
marked.Tokenizer = _Tokenizer;
|
marked.Tokenizer = _Tokenizer;
|
||||||
marked.Slugger = _Slugger;
|
|
||||||
marked.Hooks = _Hooks;
|
marked.Hooks = _Hooks;
|
||||||
marked.parse = marked;
|
marked.parse = marked;
|
||||||
const options = marked.options;
|
const options = marked.options;
|
||||||
@ -2662,5 +2380,5 @@ const parse = marked;
|
|||||||
const parser = _Parser.parse;
|
const parser = _Parser.parse;
|
||||||
const lexer = _Lexer.lex;
|
const lexer = _Lexer.lex;
|
||||||
|
|
||||||
export { _Hooks as Hooks, _Lexer as Lexer, Marked, _Parser as Parser, _Renderer as Renderer, _Slugger as Slugger, _TextRenderer as TextRenderer, _Tokenizer as Tokenizer, _defaults as defaults, _getDefaults as getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };
|
export { _Hooks as Hooks, _Lexer as Lexer, Marked, _Parser as Parser, _Renderer as Renderer, _TextRenderer as TextRenderer, _Tokenizer as Tokenizer, _defaults as defaults, _getDefaults as getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };
|
||||||
//# sourceMappingURL=marked.esm.js.map
|
//# sourceMappingURL=marked.esm.js.map
|
||||||
|
2
lib/marked.esm.js.map
generated
2
lib/marked.esm.js.map
generated
File diff suppressed because one or more lines are too long
343
lib/marked.umd.js
generated
343
lib/marked.umd.js
generated
@ -21,25 +21,15 @@
|
|||||||
function _getDefaults() {
|
function _getDefaults() {
|
||||||
return {
|
return {
|
||||||
async: false,
|
async: false,
|
||||||
baseUrl: null,
|
|
||||||
breaks: false,
|
breaks: false,
|
||||||
extensions: null,
|
extensions: null,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
headerIds: false,
|
|
||||||
headerPrefix: '',
|
|
||||||
highlight: null,
|
|
||||||
hooks: null,
|
hooks: null,
|
||||||
langPrefix: 'language-',
|
|
||||||
mangle: false,
|
|
||||||
pedantic: false,
|
pedantic: false,
|
||||||
renderer: null,
|
renderer: null,
|
||||||
sanitize: false,
|
|
||||||
sanitizer: null,
|
|
||||||
silent: false,
|
silent: false,
|
||||||
smartypants: false,
|
|
||||||
tokenizer: null,
|
tokenizer: null,
|
||||||
walkTokens: null,
|
walkTokens: null
|
||||||
xhtml: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
exports.defaults = _getDefaults();
|
exports.defaults = _getDefaults();
|
||||||
@ -107,26 +97,7 @@
|
|||||||
};
|
};
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
const nonWordAndColonTest = /[^\w:]/g;
|
function cleanUrl(href) {
|
||||||
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
|
|
||||||
function cleanUrl(sanitize, base, href) {
|
|
||||||
if (sanitize) {
|
|
||||||
let prot;
|
|
||||||
try {
|
|
||||||
prot = decodeURIComponent(unescape(href))
|
|
||||||
.replace(nonWordAndColonTest, '')
|
|
||||||
.toLowerCase();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (base && !originIndependentUrl.test(href)) {
|
|
||||||
href = resolveUrl(base, href);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
href = encodeURI(href).replace(/%25/g, '%');
|
href = encodeURI(href).replace(/%25/g, '%');
|
||||||
}
|
}
|
||||||
@ -135,40 +106,6 @@
|
|||||||
}
|
}
|
||||||
return href;
|
return href;
|
||||||
}
|
}
|
||||||
const baseUrls = {};
|
|
||||||
const justDomain = /^[^:]+:\/*[^/]*$/;
|
|
||||||
const protocol = /^([^:]+:)[\s\S]*$/;
|
|
||||||
const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
|
|
||||||
function resolveUrl(base, href) {
|
|
||||||
if (!baseUrls[' ' + base]) {
|
|
||||||
// we can ignore everything in base after the last slash of its path component,
|
|
||||||
// but we might need to add _that_
|
|
||||||
// https://tools.ietf.org/html/rfc3986#section-3
|
|
||||||
if (justDomain.test(base)) {
|
|
||||||
baseUrls[' ' + base] = base + '/';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
baseUrls[' ' + base] = rtrim(base, '/', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base = baseUrls[' ' + base];
|
|
||||||
const relativeBase = base.indexOf(':') === -1;
|
|
||||||
if (href.substring(0, 2) === '//') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(protocol, '$1') + href;
|
|
||||||
}
|
|
||||||
else if (href.charAt(0) === '/') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(domain, '$1') + href;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return base + href;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const noopTest = { exec: () => null };
|
const noopTest = { exec: () => null };
|
||||||
function splitCells(tableRow, count) {
|
function splitCells(tableRow, count) {
|
||||||
// ensure that every cell-delimiting pipe has a space
|
// ensure that every cell-delimiting pipe has a space
|
||||||
@ -262,35 +199,6 @@
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
function checkDeprecations(opt, callback) {
|
|
||||||
if (!opt || opt.silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (callback) {
|
|
||||||
console.warn('marked(): callback is deprecated since version 5.0.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/using_pro#async');
|
|
||||||
}
|
|
||||||
if (opt.sanitize || opt.sanitizer) {
|
|
||||||
console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
|
|
||||||
}
|
|
||||||
if (opt.highlight || opt.langPrefix !== 'language-') {
|
|
||||||
console.warn('marked(): highlight and langPrefix parameters are deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-highlight.');
|
|
||||||
}
|
|
||||||
if (opt.mangle) {
|
|
||||||
console.warn('marked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.');
|
|
||||||
}
|
|
||||||
if (opt.baseUrl) {
|
|
||||||
console.warn('marked(): baseUrl parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-base-url.');
|
|
||||||
}
|
|
||||||
if (opt.smartypants) {
|
|
||||||
console.warn('marked(): smartypants parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-smartypants.');
|
|
||||||
}
|
|
||||||
if (opt.xhtml) {
|
|
||||||
console.warn('marked(): xhtml parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-xhtml.');
|
|
||||||
}
|
|
||||||
if (opt.headerIds || opt.headerPrefix) {
|
|
||||||
console.warn('marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function outputLink(cap, link, raw, lexer) {
|
function outputLink(cap, link, raw, lexer) {
|
||||||
const href = link.href;
|
const href = link.href;
|
||||||
@ -607,17 +515,9 @@
|
|||||||
type: 'html',
|
type: 'html',
|
||||||
block: true,
|
block: true,
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
pre: !this.options.sanitizer
|
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
|
||||||
&& (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
|
|
||||||
text: cap[0]
|
text: cap[0]
|
||||||
};
|
};
|
||||||
if (this.options.sanitize) {
|
|
||||||
const text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
|
|
||||||
const paragraph = token;
|
|
||||||
paragraph.type = 'paragraph';
|
|
||||||
paragraph.text = text;
|
|
||||||
paragraph.tokens = this.lexer.inline(text);
|
|
||||||
}
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,18 +655,12 @@
|
|||||||
this.lexer.state.inRawBlock = false;
|
this.lexer.state.inRawBlock = false;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: this.options.sanitize
|
type: 'html',
|
||||||
? 'text'
|
|
||||||
: 'html',
|
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
inLink: this.lexer.state.inLink,
|
inLink: this.lexer.state.inLink,
|
||||||
inRawBlock: this.lexer.state.inRawBlock,
|
inRawBlock: this.lexer.state.inRawBlock,
|
||||||
block: false,
|
block: false,
|
||||||
text: this.options.sanitize
|
text: cap[0]
|
||||||
? (this.options.sanitizer
|
|
||||||
? this.options.sanitizer(cap[0])
|
|
||||||
: escape(cap[0]))
|
|
||||||
: cap[0]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -937,12 +831,12 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
autolink(src, mangle) {
|
autolink(src) {
|
||||||
const cap = this.rules.inline.autolink.exec(src);
|
const cap = this.rules.inline.autolink.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
|
text = escape(cap[1]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -964,12 +858,12 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
url(src, mangle) {
|
url(src) {
|
||||||
let cap;
|
let cap;
|
||||||
if (cap = this.rules.inline.url.exec(src)) {
|
if (cap = this.rules.inline.url.exec(src)) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1002,15 +896,15 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inlineText(src, smartypants) {
|
inlineText(src) {
|
||||||
const cap = this.rules.inline.text.exec(src);
|
const cap = this.rules.inline.text.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text;
|
let text;
|
||||||
if (this.lexer.state.inRawBlock) {
|
if (this.lexer.state.inRawBlock) {
|
||||||
text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0];
|
text = cap[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@ -1298,39 +1192,6 @@
|
|||||||
.getRegex()
|
.getRegex()
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* smartypants text replacement
|
|
||||||
*/
|
|
||||||
function smartypants(text) {
|
|
||||||
return text
|
|
||||||
// em-dashes
|
|
||||||
.replace(/---/g, '\u2014')
|
|
||||||
// en-dashes
|
|
||||||
.replace(/--/g, '\u2013')
|
|
||||||
// opening singles
|
|
||||||
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
|
||||||
// closing singles & apostrophes
|
|
||||||
.replace(/'/g, '\u2019')
|
|
||||||
// opening doubles
|
|
||||||
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
|
||||||
// closing doubles
|
|
||||||
.replace(/"/g, '\u201d')
|
|
||||||
// ellipses
|
|
||||||
.replace(/\.{3}/g, '\u2026');
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* mangle email addresses
|
|
||||||
*/
|
|
||||||
function mangle(text) {
|
|
||||||
let out = '';
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
const ch = Math.random() > 0.5
|
|
||||||
? 'x' + text.charCodeAt(i).toString(16)
|
|
||||||
: text.charCodeAt(i).toString();
|
|
||||||
out += '&#' + ch + ';';
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Block Lexer
|
* Block Lexer
|
||||||
*/
|
*/
|
||||||
@ -1704,13 +1565,13 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// autolink
|
// autolink
|
||||||
if (token = this.tokenizer.autolink(src, mangle)) {
|
if (token = this.tokenizer.autolink(src)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// url (gfm)
|
// url (gfm)
|
||||||
if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
|
if (!this.state.inLink && (token = this.tokenizer.url(src))) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
@ -1732,7 +1593,7 @@
|
|||||||
cutSrc = src.substring(0, startIndex + 1);
|
cutSrc = src.substring(0, startIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
|
if (token = this.tokenizer.inlineText(cutSrc)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
||||||
prevChar = token.raw.slice(-1);
|
prevChar = token.raw.slice(-1);
|
||||||
@ -1773,21 +1634,13 @@
|
|||||||
}
|
}
|
||||||
code(code, infostring, escaped) {
|
code(code, infostring, escaped) {
|
||||||
const lang = (infostring || '').match(/^\S*/)?.[0];
|
const lang = (infostring || '').match(/^\S*/)?.[0];
|
||||||
if (this.options.highlight) {
|
|
||||||
const out = this.options.highlight(code, lang);
|
|
||||||
if (out != null && out !== code) {
|
|
||||||
escaped = true;
|
|
||||||
code = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code = code.replace(/\n$/, '') + '\n';
|
code = code.replace(/\n$/, '') + '\n';
|
||||||
if (!lang) {
|
if (!lang) {
|
||||||
return '<pre><code>'
|
return '<pre><code>'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
+ '</code></pre>\n';
|
+ '</code></pre>\n';
|
||||||
}
|
}
|
||||||
return '<pre><code class="'
|
return '<pre><code class="language-'
|
||||||
+ this.options.langPrefix
|
|
||||||
+ escape(lang)
|
+ escape(lang)
|
||||||
+ '">'
|
+ '">'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
@ -1799,16 +1652,12 @@
|
|||||||
html(html, block) {
|
html(html, block) {
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
heading(text, level, raw, slugger) {
|
heading(text, level, raw) {
|
||||||
if (this.options.headerIds) {
|
|
||||||
const id = this.options.headerPrefix + slugger.slug(raw);
|
|
||||||
return `<h${level} id="${id}">${text}</h${level}>\n`;
|
|
||||||
}
|
|
||||||
// ignore IDs
|
// ignore IDs
|
||||||
return `<h${level}>${text}</h${level}>\n`;
|
return `<h${level}>${text}</h${level}>\n`;
|
||||||
}
|
}
|
||||||
hr() {
|
hr() {
|
||||||
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
|
return '<hr>\n';
|
||||||
}
|
}
|
||||||
list(body, ordered, start) {
|
list(body, ordered, start) {
|
||||||
const type = ordered ? 'ol' : 'ul';
|
const type = ordered ? 'ol' : 'ul';
|
||||||
@ -1821,9 +1670,7 @@
|
|||||||
checkbox(checked) {
|
checkbox(checked) {
|
||||||
return '<input '
|
return '<input '
|
||||||
+ (checked ? 'checked="" ' : '')
|
+ (checked ? 'checked="" ' : '')
|
||||||
+ 'disabled="" type="checkbox"'
|
+ 'disabled="" type="checkbox">';
|
||||||
+ (this.options.xhtml ? ' /' : '')
|
|
||||||
+ '> ';
|
|
||||||
}
|
}
|
||||||
paragraph(text) {
|
paragraph(text) {
|
||||||
return `<p>${text}</p>\n`;
|
return `<p>${text}</p>\n`;
|
||||||
@ -1861,13 +1708,13 @@
|
|||||||
return `<code>${text}</code>`;
|
return `<code>${text}</code>`;
|
||||||
}
|
}
|
||||||
br() {
|
br() {
|
||||||
return this.options.xhtml ? '<br/>' : '<br>';
|
return '<br>';
|
||||||
}
|
}
|
||||||
del(text) {
|
del(text) {
|
||||||
return `<del>${text}</del>`;
|
return `<del>${text}</del>`;
|
||||||
}
|
}
|
||||||
link(href, title, text) {
|
link(href, title, text) {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -1880,7 +1727,7 @@
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
image(href, title, text) {
|
image(href, title, text) {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -1889,7 +1736,7 @@
|
|||||||
if (title) {
|
if (title) {
|
||||||
out += ` title="${title}"`;
|
out += ` title="${title}"`;
|
||||||
}
|
}
|
||||||
out += this.options.xhtml ? '/>' : '>';
|
out += '>';
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
text(text) {
|
text(text) {
|
||||||
@ -1932,52 +1779,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Slugger generates header id
|
|
||||||
*/
|
|
||||||
class _Slugger {
|
|
||||||
seen;
|
|
||||||
constructor() {
|
|
||||||
this.seen = {};
|
|
||||||
}
|
|
||||||
serialize(value) {
|
|
||||||
return value
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
// remove html tags
|
|
||||||
.replace(/<[!\/a-z].*?>/ig, '')
|
|
||||||
// remove unwanted chars
|
|
||||||
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
|
|
||||||
.replace(/\s/g, '-');
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Finds the next safe (unique) slug to use
|
|
||||||
*/
|
|
||||||
getNextSafeSlug(originalSlug, isDryRun) {
|
|
||||||
let slug = originalSlug;
|
|
||||||
let occurenceAccumulator = 0;
|
|
||||||
if (this.seen.hasOwnProperty(slug)) {
|
|
||||||
occurenceAccumulator = this.seen[originalSlug];
|
|
||||||
do {
|
|
||||||
occurenceAccumulator++;
|
|
||||||
slug = originalSlug + '-' + occurenceAccumulator;
|
|
||||||
} while (this.seen.hasOwnProperty(slug));
|
|
||||||
}
|
|
||||||
if (!isDryRun) {
|
|
||||||
this.seen[originalSlug] = occurenceAccumulator;
|
|
||||||
this.seen[slug] = 0;
|
|
||||||
}
|
|
||||||
return slug;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Convert string to unique id
|
|
||||||
*/
|
|
||||||
slug(value, options = {}) {
|
|
||||||
const slug = this.serialize(value);
|
|
||||||
return this.getNextSafeSlug(slug, options.dryrun);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsing & Compiling
|
* Parsing & Compiling
|
||||||
*/
|
*/
|
||||||
@ -1985,14 +1786,12 @@
|
|||||||
options;
|
options;
|
||||||
renderer;
|
renderer;
|
||||||
textRenderer;
|
textRenderer;
|
||||||
slugger;
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.options = options || exports.defaults;
|
this.options = options || exports.defaults;
|
||||||
this.options.renderer = this.options.renderer || new _Renderer();
|
this.options.renderer = this.options.renderer || new _Renderer();
|
||||||
this.renderer = this.options.renderer;
|
this.renderer = this.options.renderer;
|
||||||
this.renderer.options = this.options;
|
this.renderer.options = this.options;
|
||||||
this.textRenderer = new _TextRenderer();
|
this.textRenderer = new _TextRenderer();
|
||||||
this.slugger = new _Slugger();
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Static Parse Method
|
* Static Parse Method
|
||||||
@ -2034,7 +1833,7 @@
|
|||||||
}
|
}
|
||||||
case 'heading': {
|
case 'heading': {
|
||||||
const headingToken = token;
|
const headingToken = token;
|
||||||
out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)), this.slugger);
|
out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case 'code': {
|
case 'code': {
|
||||||
@ -2257,7 +2056,6 @@
|
|||||||
Lexer = _Lexer;
|
Lexer = _Lexer;
|
||||||
lexer = _Lexer.lex;
|
lexer = _Lexer.lex;
|
||||||
Tokenizer = _Tokenizer;
|
Tokenizer = _Tokenizer;
|
||||||
Slugger = _Slugger;
|
|
||||||
Hooks = _Hooks;
|
Hooks = _Hooks;
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
this.use(...args);
|
this.use(...args);
|
||||||
@ -2454,12 +2252,8 @@
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
#parseMarkdown(lexer, parser) {
|
#parseMarkdown(lexer, parser) {
|
||||||
return (src, optOrCallback, callback) => {
|
return (src, options) => {
|
||||||
if (typeof optOrCallback === 'function') {
|
const origOpt = { ...options };
|
||||||
callback = optOrCallback;
|
|
||||||
optOrCallback = null;
|
|
||||||
}
|
|
||||||
const origOpt = { ...optOrCallback };
|
|
||||||
const opt = { ...this.defaults, ...origOpt };
|
const opt = { ...this.defaults, ...origOpt };
|
||||||
// Show warning if an extension set async to true but the parse was called with async: false
|
// Show warning if an extension set async to true but the parse was called with async: false
|
||||||
if (this.defaults.async === true && origOpt.async === false) {
|
if (this.defaults.async === true && origOpt.async === false) {
|
||||||
@ -2468,7 +2262,7 @@
|
|||||||
}
|
}
|
||||||
opt.async = true;
|
opt.async = true;
|
||||||
}
|
}
|
||||||
const throwError = this.#onError(!!opt.silent, !!opt.async, callback);
|
const throwError = this.#onError(!!opt.silent, !!opt.async);
|
||||||
// throw error in case of non string input
|
// throw error in case of non string input
|
||||||
if (typeof src === 'undefined' || src === null) {
|
if (typeof src === 'undefined' || src === null) {
|
||||||
return throwError(new Error('marked(): input parameter is undefined or null'));
|
return throwError(new Error('marked(): input parameter is undefined or null'));
|
||||||
@ -2477,76 +2271,9 @@
|
|||||||
return throwError(new Error('marked(): input parameter is of type '
|
return throwError(new Error('marked(): input parameter is of type '
|
||||||
+ Object.prototype.toString.call(src) + ', string expected'));
|
+ Object.prototype.toString.call(src) + ', string expected'));
|
||||||
}
|
}
|
||||||
checkDeprecations(opt, callback);
|
|
||||||
if (opt.hooks) {
|
if (opt.hooks) {
|
||||||
opt.hooks.options = opt;
|
opt.hooks.options = opt;
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
const resultCallback = callback;
|
|
||||||
const highlight = opt.highlight;
|
|
||||||
let tokens;
|
|
||||||
try {
|
|
||||||
if (opt.hooks) {
|
|
||||||
src = opt.hooks.preprocess(src);
|
|
||||||
}
|
|
||||||
tokens = lexer(src, opt);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return throwError(e);
|
|
||||||
}
|
|
||||||
const done = (err) => {
|
|
||||||
let out;
|
|
||||||
if (!err) {
|
|
||||||
try {
|
|
||||||
if (opt.walkTokens) {
|
|
||||||
this.walkTokens(tokens, opt.walkTokens);
|
|
||||||
}
|
|
||||||
out = parser(tokens, opt);
|
|
||||||
if (opt.hooks) {
|
|
||||||
out = opt.hooks.postprocess(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
err = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opt.highlight = highlight;
|
|
||||||
return err
|
|
||||||
? throwError(err)
|
|
||||||
: resultCallback(null, out);
|
|
||||||
};
|
|
||||||
if (!highlight || highlight.length < 3) {
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
delete opt.highlight;
|
|
||||||
if (!tokens.length)
|
|
||||||
return done();
|
|
||||||
let pending = 0;
|
|
||||||
this.walkTokens(tokens, (token) => {
|
|
||||||
if (token.type === 'code') {
|
|
||||||
pending++;
|
|
||||||
setTimeout(() => {
|
|
||||||
highlight(token.text, token.lang, (err, code) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
if (code != null && code !== token.text) {
|
|
||||||
token.text = code;
|
|
||||||
token.escaped = true;
|
|
||||||
}
|
|
||||||
pending--;
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (opt.async) {
|
if (opt.async) {
|
||||||
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
||||||
.then(src => lexer(src, opt))
|
.then(src => lexer(src, opt))
|
||||||
@ -2574,7 +2301,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#onError(silent, async, callback) {
|
#onError(silent, async) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
||||||
if (silent) {
|
if (silent) {
|
||||||
@ -2584,27 +2311,19 @@
|
|||||||
if (async) {
|
if (async) {
|
||||||
return Promise.resolve(msg);
|
return Promise.resolve(msg);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(null, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
if (async) {
|
if (async) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const markedInstance = new Marked();
|
const markedInstance = new Marked();
|
||||||
function marked(src, opt, callback) {
|
function marked(src, opt) {
|
||||||
return markedInstance.parse(src, opt, callback);
|
return markedInstance.parse(src, opt);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Sets the default options.
|
* Sets the default options.
|
||||||
@ -2656,7 +2375,6 @@
|
|||||||
marked.Lexer = _Lexer;
|
marked.Lexer = _Lexer;
|
||||||
marked.lexer = _Lexer.lex;
|
marked.lexer = _Lexer.lex;
|
||||||
marked.Tokenizer = _Tokenizer;
|
marked.Tokenizer = _Tokenizer;
|
||||||
marked.Slugger = _Slugger;
|
|
||||||
marked.Hooks = _Hooks;
|
marked.Hooks = _Hooks;
|
||||||
marked.parse = marked;
|
marked.parse = marked;
|
||||||
const options = marked.options;
|
const options = marked.options;
|
||||||
@ -2673,7 +2391,6 @@
|
|||||||
exports.Marked = Marked;
|
exports.Marked = Marked;
|
||||||
exports.Parser = _Parser;
|
exports.Parser = _Parser;
|
||||||
exports.Renderer = _Renderer;
|
exports.Renderer = _Renderer;
|
||||||
exports.Slugger = _Slugger;
|
|
||||||
exports.TextRenderer = _TextRenderer;
|
exports.TextRenderer = _TextRenderer;
|
||||||
exports.Tokenizer = _Tokenizer;
|
exports.Tokenizer = _Tokenizer;
|
||||||
exports.getDefaults = _getDefaults;
|
exports.getDefaults = _getDefaults;
|
||||||
|
2
lib/marked.umd.js.map
generated
2
lib/marked.umd.js.map
generated
File diff suppressed because one or more lines are too long
19
man/marked.1
19
man/marked.1
@ -7,9 +7,7 @@ marked \- a javascript markdown parser
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B marked
|
.B marked
|
||||||
[\-o \fI<output>\fP] [\-i \fI<input>\fP] [\-s \fI<string>\fP] [\-\-help]
|
[\-o \fI<output>\fP] [\-i \fI<input>\fP] [\-s \fI<string>\fP] [\-\-help]
|
||||||
[\-c \fI<config>\fP] [\-\-tokens] [\-\-pedantic] [\-\-gfm]
|
[\-c \fI<config>\fP] [\-\-tokens] [\-\-pedantic] [\-\-gfm] [\-\-breaks]
|
||||||
[\-\-breaks] [\-\-sanitize]
|
|
||||||
[\-\-smart\-lists] [\-\-lang\-prefix \fI<prefix>\fP]
|
|
||||||
[\-\-no\-etc...] [\-\-silent] [\fIfilename\fP]
|
[\-\-no\-etc...] [\-\-silent] [\fIfilename\fP]
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@ -56,21 +54,6 @@ Enable github flavored markdown.
|
|||||||
.BI \-\-breaks
|
.BI \-\-breaks
|
||||||
Enable GFM line breaks. Only works with the gfm option.
|
Enable GFM line breaks. Only works with the gfm option.
|
||||||
.TP
|
.TP
|
||||||
.BI \-\-sanitize
|
|
||||||
Sanitize output. Ignore any HTML input.
|
|
||||||
.TP
|
|
||||||
.BI \-\-smart\-lists
|
|
||||||
Use smarter list behavior than the original markdown.
|
|
||||||
.TP
|
|
||||||
.BI \-\-lang\-prefix\ [\fIprefix\fP]
|
|
||||||
Set the prefix for code block classes.
|
|
||||||
.TP
|
|
||||||
.BI \-\-mangle
|
|
||||||
Mangle email addresses.
|
|
||||||
.TP
|
|
||||||
.BI \-\-no\-sanitize,\ \-no-etc...
|
|
||||||
The inverse of any of the marked options above.
|
|
||||||
.TP
|
|
||||||
.BI \-\-silent
|
.BI \-\-silent
|
||||||
Silence error output.
|
Silence error output.
|
||||||
.TP
|
.TP
|
||||||
|
@ -5,8 +5,7 @@ NAME
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
marked [-o <output>] [-i <input>] [-s <string>] [--help] [--tokens]
|
marked [-o <output>] [-i <input>] [-s <string>] [--help] [--tokens]
|
||||||
[--pedantic] [--gfm] [--breaks] [--sanitize] [--smart-lists]
|
[--pedantic] [--gfm] [--breaks] [--no-etc...] [--silent] [filename]
|
||||||
[--lang-prefix <prefix>] [--no-etc...] [--silent] [filename]
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -45,19 +44,7 @@ OPTIONS
|
|||||||
--breaks
|
--breaks
|
||||||
Enable GFM line breaks. Only works with the gfm option.
|
Enable GFM line breaks. Only works with the gfm option.
|
||||||
|
|
||||||
--sanitize
|
--no-breaks, -no-etc...
|
||||||
Sanitize output. Ignore any HTML input.
|
|
||||||
|
|
||||||
--smart-lists
|
|
||||||
Use smarter list behavior than the original markdown.
|
|
||||||
|
|
||||||
--lang-prefix [prefix]
|
|
||||||
Set the prefix for code block classes.
|
|
||||||
|
|
||||||
--mangle
|
|
||||||
Mangle email addresses.
|
|
||||||
|
|
||||||
--no-sanitize, -no-etc...
|
|
||||||
The inverse of any of the marked options above.
|
The inverse of any of the marked options above.
|
||||||
|
|
||||||
--silent
|
--silent
|
||||||
|
11
marked.min.js
generated
vendored
11
marked.min.js
generated
vendored
File diff suppressed because one or more lines are too long
105
src/Instance.ts
105
src/Instance.ts
@ -5,15 +5,12 @@ import { _Hooks } from './Hooks.ts';
|
|||||||
import { _Renderer } from './Renderer.ts';
|
import { _Renderer } from './Renderer.ts';
|
||||||
import { _Tokenizer } from './Tokenizer.ts';
|
import { _Tokenizer } from './Tokenizer.ts';
|
||||||
import { _TextRenderer } from './TextRenderer.ts';
|
import { _TextRenderer } from './TextRenderer.ts';
|
||||||
import { _Slugger } from './Slugger.ts';
|
|
||||||
import {
|
import {
|
||||||
checkDeprecations,
|
|
||||||
escape
|
escape
|
||||||
} from './helpers.ts';
|
} from './helpers.ts';
|
||||||
import type { MarkedExtension, MarkedOptions } from './MarkedOptions.ts';
|
import type { MarkedExtension, MarkedOptions } from './MarkedOptions.ts';
|
||||||
import type { Token, Tokens, TokensList } from './Tokens.ts';
|
import type { Token, Tokens, TokensList } from './Tokens.ts';
|
||||||
|
|
||||||
export type ResultCallback = (error: Error | null, parseResult?: string) => undefined | void;
|
|
||||||
export type MaybePromise = void | Promise<void>;
|
export type MaybePromise = void | Promise<void>;
|
||||||
|
|
||||||
type UnknownFunction = (...args: unknown[]) => unknown;
|
type UnknownFunction = (...args: unknown[]) => unknown;
|
||||||
@ -33,7 +30,6 @@ export class Marked {
|
|||||||
Lexer = _Lexer;
|
Lexer = _Lexer;
|
||||||
lexer = _Lexer.lex;
|
lexer = _Lexer.lex;
|
||||||
Tokenizer = _Tokenizer;
|
Tokenizer = _Tokenizer;
|
||||||
Slugger = _Slugger;
|
|
||||||
Hooks = _Hooks;
|
Hooks = _Hooks;
|
||||||
|
|
||||||
constructor(...args: MarkedExtension[]) {
|
constructor(...args: MarkedExtension[]) {
|
||||||
@ -237,13 +233,8 @@ export class Marked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#parseMarkdown(lexer: (src: string, options?: MarkedOptions) => TokensList | Token[], parser: (tokens: Token[], options?: MarkedOptions) => string) {
|
#parseMarkdown(lexer: (src: string, options?: MarkedOptions) => TokensList | Token[], parser: (tokens: Token[], options?: MarkedOptions) => string) {
|
||||||
return (src: string, optOrCallback?: MarkedOptions | ResultCallback | undefined | null, callback?: ResultCallback | undefined): string | Promise<string | undefined> | undefined => {
|
return (src: string, options?: MarkedOptions | undefined | null): string | Promise<string> => {
|
||||||
if (typeof optOrCallback === 'function') {
|
const origOpt = { ...options };
|
||||||
callback = optOrCallback;
|
|
||||||
optOrCallback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const origOpt = { ...optOrCallback };
|
|
||||||
const opt = { ...this.defaults, ...origOpt };
|
const opt = { ...this.defaults, ...origOpt };
|
||||||
|
|
||||||
// Show warning if an extension set async to true but the parse was called with async: false
|
// Show warning if an extension set async to true but the parse was called with async: false
|
||||||
@ -255,7 +246,7 @@ export class Marked {
|
|||||||
opt.async = true;
|
opt.async = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const throwError = this.#onError(!!opt.silent, !!opt.async, callback);
|
const throwError = this.#onError(!!opt.silent, !!opt.async);
|
||||||
|
|
||||||
// throw error in case of non string input
|
// throw error in case of non string input
|
||||||
if (typeof src === 'undefined' || src === null) {
|
if (typeof src === 'undefined' || src === null) {
|
||||||
@ -266,88 +257,10 @@ export class Marked {
|
|||||||
+ Object.prototype.toString.call(src) + ', string expected'));
|
+ Object.prototype.toString.call(src) + ', string expected'));
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDeprecations(opt, callback);
|
|
||||||
|
|
||||||
if (opt.hooks) {
|
if (opt.hooks) {
|
||||||
opt.hooks.options = opt;
|
opt.hooks.options = opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
|
||||||
const resultCallback = callback;
|
|
||||||
const highlight = opt.highlight;
|
|
||||||
let tokens: TokensList | Token[];
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (opt.hooks) {
|
|
||||||
src = opt.hooks.preprocess(src) as string;
|
|
||||||
}
|
|
||||||
tokens = lexer(src, opt);
|
|
||||||
} catch (e) {
|
|
||||||
return throwError(e as Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const done = (err?: Error) => {
|
|
||||||
let out;
|
|
||||||
|
|
||||||
if (!err) {
|
|
||||||
try {
|
|
||||||
if (opt.walkTokens) {
|
|
||||||
this.walkTokens(tokens, opt.walkTokens);
|
|
||||||
}
|
|
||||||
out = parser(tokens, opt);
|
|
||||||
if (opt.hooks) {
|
|
||||||
out = opt.hooks.postprocess(out) as string;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
err = e as Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opt.highlight = highlight;
|
|
||||||
|
|
||||||
return err
|
|
||||||
? throwError(err)
|
|
||||||
: resultCallback(null, out) as undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!highlight || highlight.length < 3) {
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete opt.highlight;
|
|
||||||
|
|
||||||
if (!tokens.length) return done();
|
|
||||||
|
|
||||||
let pending = 0;
|
|
||||||
this.walkTokens(tokens, (token) => {
|
|
||||||
if (token.type === 'code') {
|
|
||||||
pending++;
|
|
||||||
setTimeout(() => {
|
|
||||||
highlight(token.text, token.lang, (err, code) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
if (code != null && code !== token.text) {
|
|
||||||
token.text = code;
|
|
||||||
token.escaped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pending--;
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pending === 0) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.async) {
|
if (opt.async) {
|
||||||
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
|
||||||
.then(src => lexer(src, opt))
|
.then(src => lexer(src, opt))
|
||||||
@ -376,8 +289,8 @@ export class Marked {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#onError(silent: boolean, async: boolean, callback?: ResultCallback) {
|
#onError(silent: boolean, async: boolean) {
|
||||||
return (e: Error): string | Promise<string> | undefined => {
|
return (e: Error): string | Promise<string> => {
|
||||||
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
||||||
|
|
||||||
if (silent) {
|
if (silent) {
|
||||||
@ -387,20 +300,12 @@ export class Marked {
|
|||||||
if (async) {
|
if (async) {
|
||||||
return Promise.resolve(msg);
|
return Promise.resolve(msg);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(null, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (async) {
|
if (async) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
43
src/Lexer.ts
43
src/Lexer.ts
@ -5,43 +5,6 @@ import type { Token, TokensList, Tokens } from './Tokens.ts';
|
|||||||
import type { MarkedOptions, TokenizerExtension } from './MarkedOptions.ts';
|
import type { MarkedOptions, TokenizerExtension } from './MarkedOptions.ts';
|
||||||
import type { Rules } from './rules.ts';
|
import type { Rules } from './rules.ts';
|
||||||
|
|
||||||
/**
|
|
||||||
* smartypants text replacement
|
|
||||||
*/
|
|
||||||
function smartypants(text: string) {
|
|
||||||
return text
|
|
||||||
// em-dashes
|
|
||||||
.replace(/---/g, '\u2014')
|
|
||||||
// en-dashes
|
|
||||||
.replace(/--/g, '\u2013')
|
|
||||||
// opening singles
|
|
||||||
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
|
||||||
// closing singles & apostrophes
|
|
||||||
.replace(/'/g, '\u2019')
|
|
||||||
// opening doubles
|
|
||||||
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
|
||||||
// closing doubles
|
|
||||||
.replace(/"/g, '\u201d')
|
|
||||||
// ellipses
|
|
||||||
.replace(/\.{3}/g, '\u2026');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mangle email addresses
|
|
||||||
*/
|
|
||||||
function mangle(text: string) {
|
|
||||||
let out = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
const ch = Math.random() > 0.5
|
|
||||||
? 'x' + text.charCodeAt(i).toString(16)
|
|
||||||
: text.charCodeAt(i).toString();
|
|
||||||
out += '&#' + ch + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block Lexer
|
* Block Lexer
|
||||||
*/
|
*/
|
||||||
@ -456,14 +419,14 @@ export class _Lexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// autolink
|
// autolink
|
||||||
if (token = this.tokenizer.autolink(src, mangle)) {
|
if (token = this.tokenizer.autolink(src)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// url (gfm)
|
// url (gfm)
|
||||||
if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
|
if (!this.state.inLink && (token = this.tokenizer.url(src))) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
continue;
|
continue;
|
||||||
@ -484,7 +447,7 @@ export class _Lexer {
|
|||||||
cutSrc = src.substring(0, startIndex + 1);
|
cutSrc = src.substring(0, startIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
|
if (token = this.tokenizer.inlineText(cutSrc)) {
|
||||||
src = src.substring(token.raw.length);
|
src = src.substring(token.raw.length);
|
||||||
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
|
||||||
prevChar = token.raw.slice(-1);
|
prevChar = token.raw.slice(-1);
|
||||||
|
@ -4,11 +4,6 @@ import type { _Lexer } from './Lexer.ts';
|
|||||||
import type { _Renderer } from './Renderer.ts';
|
import type { _Renderer } from './Renderer.ts';
|
||||||
import type { _Tokenizer } from './Tokenizer.ts';
|
import type { _Tokenizer } from './Tokenizer.ts';
|
||||||
|
|
||||||
export interface SluggerOptions {
|
|
||||||
/** Generates the next unique slug without updating the internal accumulator. */
|
|
||||||
dryrun?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TokenizerThis {
|
export interface TokenizerThis {
|
||||||
lexer: _Lexer;
|
lexer: _Lexer;
|
||||||
}
|
}
|
||||||
@ -54,12 +49,6 @@ export interface MarkedExtension {
|
|||||||
*/
|
*/
|
||||||
async?: boolean;
|
async?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* A prefix URL for any relative link.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-base-url to prefix url for any relative link.
|
|
||||||
*/
|
|
||||||
baseUrl?: string | undefined | null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable GFM line breaks. This option requires the gfm option to be true.
|
* Enable GFM line breaks. This option requires the gfm option to be true.
|
||||||
*/
|
*/
|
||||||
@ -77,27 +66,6 @@ export interface MarkedExtension {
|
|||||||
*/
|
*/
|
||||||
gfm?: boolean | undefined;
|
gfm?: boolean | undefined;
|
||||||
|
|
||||||
/**
|
|
||||||
* Include an id attribute when emitting headings.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-gfm-heading-id to include an id attribute when emitting headings (h1, h2, h3, etc).
|
|
||||||
*/
|
|
||||||
headerIds?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the prefix for header tag ids.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-gfm-heading-id to add a string to prefix the id attribute when emitting headings (h1, h2, h3, etc).
|
|
||||||
*/
|
|
||||||
headerPrefix?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A function to highlight code blocks. The function can either be
|
|
||||||
* synchronous (returning a string) or asynchronous (callback invoked
|
|
||||||
* with an error if any occurred during highlighting and a string
|
|
||||||
* if highlighting was successful)
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-highlight to add highlighting to code blocks.
|
|
||||||
*/
|
|
||||||
highlight?: ((code: string, lang: string | undefined, callback?: (error: Error, code?: string) => void) => string | void) | null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hooks are methods that hook into some part of marked.
|
* Hooks are methods that hook into some part of marked.
|
||||||
* preprocess is called to process markdown before sending it to marked.
|
* preprocess is called to process markdown before sending it to marked.
|
||||||
@ -110,18 +78,6 @@ export interface MarkedExtension {
|
|||||||
options?: MarkedOptions
|
options?: MarkedOptions
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the prefix for code block classes.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-highlight to prefix the className in a <code> block. Useful for syntax highlighting.
|
|
||||||
*/
|
|
||||||
langPrefix?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mangle autolinks (<email@domain.com>).
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-mangle to mangle email addresses.
|
|
||||||
*/
|
|
||||||
mangle?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
|
* Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
|
||||||
*/
|
*/
|
||||||
@ -134,34 +90,11 @@ export interface MarkedExtension {
|
|||||||
*/
|
*/
|
||||||
renderer?: RendererObject | undefined | null;
|
renderer?: RendererObject | undefined | null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Sanitize the output. Ignore any HTML that has been input. If true, sanitize the HTML passed into markdownString with the sanitizer function.
|
|
||||||
* @deprecated Warning: This feature is deprecated and it should NOT be used as it cannot be considered secure. Instead use a sanitize library, like DOMPurify (recommended), sanitize-html or insane on the output HTML!
|
|
||||||
*/
|
|
||||||
sanitize?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optionally sanitize found HTML with a sanitizer function.
|
|
||||||
* @deprecated A function to sanitize the HTML passed into markdownString.
|
|
||||||
*/
|
|
||||||
sanitizer?: ((html: string) => string) | null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows an HTML error message when rendering fails.
|
* Shows an HTML error message when rendering fails.
|
||||||
*/
|
*/
|
||||||
silent?: boolean | undefined;
|
silent?: boolean | undefined;
|
||||||
|
|
||||||
/**
|
|
||||||
* Use smarter list behavior than the original markdown. May eventually be default with the old behavior moved into pedantic.
|
|
||||||
*/
|
|
||||||
smartLists?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use "smart" typograhic punctuation for things like quotes and dashes.
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-smartypants to use "smart" typographic punctuation for things like quotes and dashes.
|
|
||||||
*/
|
|
||||||
smartypants?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tokenizer defines how to turn markdown text into tokens.
|
* The tokenizer defines how to turn markdown text into tokens.
|
||||||
*/
|
*/
|
||||||
@ -174,11 +107,6 @@ export interface MarkedExtension {
|
|||||||
* The return value of the function is ignored.
|
* The return value of the function is ignored.
|
||||||
*/
|
*/
|
||||||
walkTokens?: ((token: Token) => void | Promise<void>) | undefined | null;
|
walkTokens?: ((token: Token) => void | Promise<void>) | undefined | null;
|
||||||
/**
|
|
||||||
* Generate closing slash for self-closing tags (<br/> instead of <br>)
|
|
||||||
* @deprecated Deprecated in v5.0.0 use marked-xhtml to emit self-closing HTML tags for void elements (<br/>, <img/>, etc.) with a "/" as required by XHTML.
|
|
||||||
*/
|
|
||||||
xhtml?: boolean | undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarkedOptions extends Omit<MarkedExtension, 'renderer' | 'tokenizer' | 'extensions' | 'walkTokens'> {
|
export interface MarkedOptions extends Omit<MarkedExtension, 'renderer' | 'tokenizer' | 'extensions' | 'walkTokens'> {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { _Renderer } from './Renderer.ts';
|
import { _Renderer } from './Renderer.ts';
|
||||||
import { _TextRenderer } from './TextRenderer.ts';
|
import { _TextRenderer } from './TextRenderer.ts';
|
||||||
import { _Slugger } from './Slugger.ts';
|
|
||||||
import { _defaults } from './defaults.ts';
|
import { _defaults } from './defaults.ts';
|
||||||
import {
|
import {
|
||||||
unescape
|
unescape
|
||||||
@ -15,14 +14,12 @@ export class _Parser {
|
|||||||
options: MarkedOptions;
|
options: MarkedOptions;
|
||||||
renderer: _Renderer;
|
renderer: _Renderer;
|
||||||
textRenderer: _TextRenderer;
|
textRenderer: _TextRenderer;
|
||||||
slugger: _Slugger;
|
|
||||||
constructor(options?: MarkedOptions) {
|
constructor(options?: MarkedOptions) {
|
||||||
this.options = options || _defaults;
|
this.options = options || _defaults;
|
||||||
this.options.renderer = this.options.renderer || new _Renderer();
|
this.options.renderer = this.options.renderer || new _Renderer();
|
||||||
this.renderer = this.options.renderer;
|
this.renderer = this.options.renderer;
|
||||||
this.renderer.options = this.options;
|
this.renderer.options = this.options;
|
||||||
this.textRenderer = new _TextRenderer();
|
this.textRenderer = new _TextRenderer();
|
||||||
this.slugger = new _Slugger();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,8 +70,7 @@ export class _Parser {
|
|||||||
out += this.renderer.heading(
|
out += this.renderer.heading(
|
||||||
this.parseInline(headingToken.tokens),
|
this.parseInline(headingToken.tokens),
|
||||||
headingToken.depth,
|
headingToken.depth,
|
||||||
unescape(this.parseInline(headingToken.tokens, this.textRenderer)),
|
unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
|
||||||
this.slugger);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case 'code': {
|
case 'code': {
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
escape
|
escape
|
||||||
} from './helpers.ts';
|
} from './helpers.ts';
|
||||||
import type { MarkedOptions } from './MarkedOptions.ts';
|
import type { MarkedOptions } from './MarkedOptions.ts';
|
||||||
import type { _Slugger } from './Slugger.ts';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renderer
|
* Renderer
|
||||||
@ -17,13 +16,6 @@ export class _Renderer {
|
|||||||
|
|
||||||
code(code: string, infostring: string | undefined, escaped: boolean): string {
|
code(code: string, infostring: string | undefined, escaped: boolean): string {
|
||||||
const lang = (infostring || '').match(/^\S*/)?.[0];
|
const lang = (infostring || '').match(/^\S*/)?.[0];
|
||||||
if (this.options.highlight) {
|
|
||||||
const out = this.options.highlight(code, lang);
|
|
||||||
if (out != null && out !== code) {
|
|
||||||
escaped = true;
|
|
||||||
code = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code = code.replace(/\n$/, '') + '\n';
|
code = code.replace(/\n$/, '') + '\n';
|
||||||
|
|
||||||
@ -33,8 +25,7 @@ export class _Renderer {
|
|||||||
+ '</code></pre>\n';
|
+ '</code></pre>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<pre><code class="'
|
return '<pre><code class="language-'
|
||||||
+ this.options.langPrefix
|
|
||||||
+ escape(lang)
|
+ escape(lang)
|
||||||
+ '">'
|
+ '">'
|
||||||
+ (escaped ? code : escape(code, true))
|
+ (escaped ? code : escape(code, true))
|
||||||
@ -49,18 +40,13 @@ export class _Renderer {
|
|||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
heading(text: string, level: number, raw: string, slugger: _Slugger): string {
|
heading(text: string, level: number, raw: string): string {
|
||||||
if (this.options.headerIds) {
|
|
||||||
const id = this.options.headerPrefix + slugger.slug(raw);
|
|
||||||
return `<h${level} id="${id}">${text}</h${level}>\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore IDs
|
// ignore IDs
|
||||||
return `<h${level}>${text}</h${level}>\n`;
|
return `<h${level}>${text}</h${level}>\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr(): string {
|
hr(): string {
|
||||||
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
|
return '<hr>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
list(body: string, ordered: boolean, start: number | ''): string {
|
list(body: string, ordered: boolean, start: number | ''): string {
|
||||||
@ -76,9 +62,7 @@ export class _Renderer {
|
|||||||
checkbox(checked: boolean): string {
|
checkbox(checked: boolean): string {
|
||||||
return '<input '
|
return '<input '
|
||||||
+ (checked ? 'checked="" ' : '')
|
+ (checked ? 'checked="" ' : '')
|
||||||
+ 'disabled="" type="checkbox"'
|
+ 'disabled="" type="checkbox">';
|
||||||
+ (this.options.xhtml ? ' /' : '')
|
|
||||||
+ '> ';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paragraph(text: string): string {
|
paragraph(text: string): string {
|
||||||
@ -127,7 +111,7 @@ export class _Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
br(): string {
|
br(): string {
|
||||||
return this.options.xhtml ? '<br/>' : '<br>';
|
return '<br>';
|
||||||
}
|
}
|
||||||
|
|
||||||
del(text: string): string {
|
del(text: string): string {
|
||||||
@ -135,7 +119,7 @@ export class _Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
link(href: string, title: string | null | undefined, text: string): string {
|
link(href: string, title: string | null | undefined, text: string): string {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -149,7 +133,7 @@ export class _Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
image(href: string, title: string | null, text: string): string {
|
image(href: string, title: string | null, text: string): string {
|
||||||
const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
const cleanHref = cleanUrl(href);
|
||||||
if (cleanHref === null) {
|
if (cleanHref === null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -159,7 +143,7 @@ export class _Renderer {
|
|||||||
if (title) {
|
if (title) {
|
||||||
out += ` title="${title}"`;
|
out += ` title="${title}"`;
|
||||||
}
|
}
|
||||||
out += this.options.xhtml ? '/>' : '>';
|
out += '>';
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
import type { SluggerOptions } from './MarkedOptions.ts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Slugger generates header id
|
|
||||||
*/
|
|
||||||
export class _Slugger {
|
|
||||||
seen: { [slugValue: string]: number };
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.seen = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
serialize(value: string) {
|
|
||||||
return value
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
// remove html tags
|
|
||||||
.replace(/<[!\/a-z].*?>/ig, '')
|
|
||||||
// remove unwanted chars
|
|
||||||
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
|
|
||||||
.replace(/\s/g, '-');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the next safe (unique) slug to use
|
|
||||||
*/
|
|
||||||
getNextSafeSlug(originalSlug: string, isDryRun: boolean | undefined) {
|
|
||||||
let slug = originalSlug;
|
|
||||||
let occurenceAccumulator = 0;
|
|
||||||
if (this.seen.hasOwnProperty(slug)) {
|
|
||||||
occurenceAccumulator = this.seen[originalSlug];
|
|
||||||
do {
|
|
||||||
occurenceAccumulator++;
|
|
||||||
slug = originalSlug + '-' + occurenceAccumulator;
|
|
||||||
} while (this.seen.hasOwnProperty(slug));
|
|
||||||
}
|
|
||||||
if (!isDryRun) {
|
|
||||||
this.seen[originalSlug] = occurenceAccumulator;
|
|
||||||
this.seen[slug] = 0;
|
|
||||||
}
|
|
||||||
return slug;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert string to unique id
|
|
||||||
*/
|
|
||||||
slug(value: string, options: SluggerOptions = {}) {
|
|
||||||
const slug = this.serialize(value);
|
|
||||||
return this.getNextSafeSlug(slug, options.dryrun);
|
|
||||||
}
|
|
||||||
}
|
|
@ -366,24 +366,16 @@ export class _Tokenizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html(src: string): Tokens.HTML | Tokens.Paragraph | undefined {
|
html(src: string): Tokens.HTML | undefined {
|
||||||
const cap = this.rules.block.html.exec(src);
|
const cap = this.rules.block.html.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
const token: Tokens.HTML | Tokens.Paragraph = {
|
const token: Tokens.HTML = {
|
||||||
type: 'html',
|
type: 'html',
|
||||||
block: true,
|
block: true,
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
pre: !this.options.sanitizer
|
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
|
||||||
&& (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
|
|
||||||
text: cap[0]
|
text: cap[0]
|
||||||
};
|
};
|
||||||
if (this.options.sanitize) {
|
|
||||||
const text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
|
|
||||||
const paragraph = token as unknown as Tokens.Paragraph;
|
|
||||||
paragraph.type = 'paragraph';
|
|
||||||
paragraph.text = text;
|
|
||||||
paragraph.tokens = this.lexer.inline(text);
|
|
||||||
}
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -530,18 +522,12 @@ export class _Tokenizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: this.options.sanitize
|
type: 'html',
|
||||||
? 'text'
|
|
||||||
: 'html',
|
|
||||||
raw: cap[0],
|
raw: cap[0],
|
||||||
inLink: this.lexer.state.inLink,
|
inLink: this.lexer.state.inLink,
|
||||||
inRawBlock: this.lexer.state.inRawBlock,
|
inRawBlock: this.lexer.state.inRawBlock,
|
||||||
block: false,
|
block: false,
|
||||||
text: this.options.sanitize
|
text: cap[0]
|
||||||
? (this.options.sanitizer
|
|
||||||
? this.options.sanitizer(cap[0])
|
|
||||||
: escape(cap[0]))
|
|
||||||
: cap[0]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -729,12 +715,12 @@ export class _Tokenizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
autolink(src: string, mangle: (cap: string) => string): Tokens.Link | undefined {
|
autolink(src: string): Tokens.Link | undefined {
|
||||||
const cap = this.rules.inline.autolink.exec(src);
|
const cap = this.rules.inline.autolink.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
|
text = escape(cap[1]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
} else {
|
} else {
|
||||||
text = escape(cap[1]);
|
text = escape(cap[1]);
|
||||||
@ -757,12 +743,12 @@ export class _Tokenizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url(src: string, mangle: (cap: string) => string): Tokens.Link | undefined {
|
url(src: string): Tokens.Link | undefined {
|
||||||
let cap;
|
let cap;
|
||||||
if (cap = this.rules.inline.url.exec(src)) {
|
if (cap = this.rules.inline.url.exec(src)) {
|
||||||
let text, href;
|
let text, href;
|
||||||
if (cap[2] === '@') {
|
if (cap[2] === '@') {
|
||||||
text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
href = 'mailto:' + text;
|
href = 'mailto:' + text;
|
||||||
} else {
|
} else {
|
||||||
// do extended autolink path validation
|
// do extended autolink path validation
|
||||||
@ -794,14 +780,14 @@ export class _Tokenizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inlineText(src: string, smartypants: (cap: string) => string): Tokens.Text | undefined {
|
inlineText(src: string): Tokens.Text | undefined {
|
||||||
const cap = this.rules.inline.text.exec(src);
|
const cap = this.rules.inline.text.exec(src);
|
||||||
if (cap) {
|
if (cap) {
|
||||||
let text;
|
let text;
|
||||||
if (this.lexer.state.inRawBlock) {
|
if (this.lexer.state.inRawBlock) {
|
||||||
text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0];
|
text = cap[0];
|
||||||
} else {
|
} else {
|
||||||
text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
|
text = escape(cap[0]);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
@ -6,25 +6,15 @@ import type { MarkedOptions } from './MarkedOptions.ts';
|
|||||||
export function _getDefaults(): MarkedOptions {
|
export function _getDefaults(): MarkedOptions {
|
||||||
return {
|
return {
|
||||||
async: false,
|
async: false,
|
||||||
baseUrl: null,
|
|
||||||
breaks: false,
|
breaks: false,
|
||||||
extensions: null,
|
extensions: null,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
headerIds: false,
|
|
||||||
headerPrefix: '',
|
|
||||||
highlight: null,
|
|
||||||
hooks: null,
|
hooks: null,
|
||||||
langPrefix: 'language-',
|
|
||||||
mangle: false,
|
|
||||||
pedantic: false,
|
pedantic: false,
|
||||||
renderer: null,
|
renderer: null,
|
||||||
sanitize: false,
|
|
||||||
sanitizer: null,
|
|
||||||
silent: false,
|
silent: false,
|
||||||
smartypants: false,
|
|
||||||
tokenizer: null,
|
tokenizer: null,
|
||||||
walkTokens: null,
|
walkTokens: null
|
||||||
xhtml: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import type { MarkedOptions } from './MarkedOptions.ts';
|
|
||||||
import type { ResultCallback } from './Instance.ts';
|
|
||||||
import type { Rule } from './rules.ts';
|
import type { Rule } from './rules.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,26 +65,7 @@ export function edit(regex: Rule, opt?: string) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nonWordAndColonTest = /[^\w:]/g;
|
export function cleanUrl(href: string) {
|
||||||
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
|
|
||||||
|
|
||||||
export function cleanUrl(sanitize: boolean | undefined, base: string | undefined | null, href: string) {
|
|
||||||
if (sanitize) {
|
|
||||||
let prot;
|
|
||||||
try {
|
|
||||||
prot = decodeURIComponent(unescape(href))
|
|
||||||
.replace(nonWordAndColonTest, '')
|
|
||||||
.toLowerCase();
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (base && !originIndependentUrl.test(href)) {
|
|
||||||
href = resolveUrl(base, href);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
href = encodeURI(href).replace(/%25/g, '%');
|
href = encodeURI(href).replace(/%25/g, '%');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -95,40 +74,6 @@ export function cleanUrl(sanitize: boolean | undefined, base: string | undefined
|
|||||||
return href;
|
return href;
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseUrls: Record<string, string> = {};
|
|
||||||
const justDomain = /^[^:]+:\/*[^/]*$/;
|
|
||||||
const protocol = /^([^:]+:)[\s\S]*$/;
|
|
||||||
const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
|
|
||||||
|
|
||||||
export function resolveUrl(base: string, href: string) {
|
|
||||||
if (!baseUrls[' ' + base]) {
|
|
||||||
// we can ignore everything in base after the last slash of its path component,
|
|
||||||
// but we might need to add _that_
|
|
||||||
// https://tools.ietf.org/html/rfc3986#section-3
|
|
||||||
if (justDomain.test(base)) {
|
|
||||||
baseUrls[' ' + base] = base + '/';
|
|
||||||
} else {
|
|
||||||
baseUrls[' ' + base] = rtrim(base, '/', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base = baseUrls[' ' + base];
|
|
||||||
const relativeBase = base.indexOf(':') === -1;
|
|
||||||
|
|
||||||
if (href.substring(0, 2) === '//') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(protocol, '$1') + href;
|
|
||||||
} else if (href.charAt(0) === '/') {
|
|
||||||
if (relativeBase) {
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
return base.replace(domain, '$1') + href;
|
|
||||||
} else {
|
|
||||||
return base + href;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const noopTest = { exec: () => null };
|
export const noopTest = { exec: () => null };
|
||||||
|
|
||||||
export function splitCells(tableRow: string, count?: number) {
|
export function splitCells(tableRow: string, count?: number) {
|
||||||
@ -225,41 +170,3 @@ export function findClosingBracket(str: string, b: string) {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkDeprecations(opt: MarkedOptions, callback?: ResultCallback) {
|
|
||||||
if (!opt || opt.silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) {
|
|
||||||
console.warn('marked(): callback is deprecated since version 5.0.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/using_pro#async');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.sanitize || opt.sanitizer) {
|
|
||||||
console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.highlight || opt.langPrefix !== 'language-') {
|
|
||||||
console.warn('marked(): highlight and langPrefix parameters are deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-highlight.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.mangle) {
|
|
||||||
console.warn('marked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.baseUrl) {
|
|
||||||
console.warn('marked(): baseUrl parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-base-url.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.smartypants) {
|
|
||||||
console.warn('marked(): smartypants parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-smartypants.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.xhtml) {
|
|
||||||
console.warn('marked(): xhtml parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-xhtml.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.headerIds || opt.headerPrefix) {
|
|
||||||
console.warn('marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,6 @@ import { _Parser } from './Parser.ts';
|
|||||||
import { _Tokenizer } from './Tokenizer.ts';
|
import { _Tokenizer } from './Tokenizer.ts';
|
||||||
import { _Renderer } from './Renderer.ts';
|
import { _Renderer } from './Renderer.ts';
|
||||||
import { _TextRenderer } from './TextRenderer.ts';
|
import { _TextRenderer } from './TextRenderer.ts';
|
||||||
import { _Slugger } from './Slugger.ts';
|
|
||||||
import { _Hooks } from './Hooks.ts';
|
import { _Hooks } from './Hooks.ts';
|
||||||
import { Marked } from './Instance.ts';
|
import { Marked } from './Instance.ts';
|
||||||
import {
|
import {
|
||||||
@ -13,7 +12,7 @@ import {
|
|||||||
} from './defaults.ts';
|
} from './defaults.ts';
|
||||||
import type { MarkedExtension, MarkedOptions } from './MarkedOptions.ts';
|
import type { MarkedExtension, MarkedOptions } from './MarkedOptions.ts';
|
||||||
import type { Token, TokensList } from './Tokens.ts';
|
import type { Token, TokensList } from './Tokens.ts';
|
||||||
import type { ResultCallback, MaybePromise } from './Instance.ts';
|
import type { MaybePromise } from './Instance.ts';
|
||||||
|
|
||||||
const markedInstance = new Marked();
|
const markedInstance = new Marked();
|
||||||
|
|
||||||
@ -34,29 +33,8 @@ export function marked(src: string, options: MarkedOptions & { async: true }): P
|
|||||||
* @return String of compiled HTML
|
* @return String of compiled HTML
|
||||||
*/
|
*/
|
||||||
export function marked(src: string, options?: MarkedOptions): string;
|
export function marked(src: string, options?: MarkedOptions): string;
|
||||||
|
export function marked(src: string, opt?: MarkedOptions): string | Promise<string> {
|
||||||
/**
|
return markedInstance.parse(src, opt);
|
||||||
* Compiles markdown to HTML asynchronously with a callback.
|
|
||||||
*
|
|
||||||
* @param src String of markdown source to be compiled
|
|
||||||
* @param callback Function called when the markdownString has been fully parsed when using async highlighting
|
|
||||||
*/
|
|
||||||
export function marked(src: string, callback: ResultCallback): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles markdown to HTML asynchronously with a callback.
|
|
||||||
*
|
|
||||||
* @param src String of markdown source to be compiled
|
|
||||||
* @param options Hash of options
|
|
||||||
* @param callback Function called when the markdownString has been fully parsed when using async highlighting
|
|
||||||
*/
|
|
||||||
export function marked(
|
|
||||||
src: string,
|
|
||||||
options: MarkedOptions,
|
|
||||||
callback: ResultCallback,
|
|
||||||
): void;
|
|
||||||
export function marked(src: string, opt?: MarkedOptions | ResultCallback, callback?: ResultCallback): string | Promise<string | undefined> | undefined {
|
|
||||||
return markedInstance.parse(src, opt, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,7 +95,6 @@ marked.TextRenderer = _TextRenderer;
|
|||||||
marked.Lexer = _Lexer;
|
marked.Lexer = _Lexer;
|
||||||
marked.lexer = _Lexer.lex;
|
marked.lexer = _Lexer.lex;
|
||||||
marked.Tokenizer = _Tokenizer;
|
marked.Tokenizer = _Tokenizer;
|
||||||
marked.Slugger = _Slugger;
|
|
||||||
marked.Hooks = _Hooks;
|
marked.Hooks = _Hooks;
|
||||||
marked.parse = marked;
|
marked.parse = marked;
|
||||||
|
|
||||||
@ -135,7 +112,6 @@ export { _Parser as Parser } from './Parser.ts';
|
|||||||
export { _Tokenizer as Tokenizer } from './Tokenizer.ts';
|
export { _Tokenizer as Tokenizer } from './Tokenizer.ts';
|
||||||
export { _Renderer as Renderer } from './Renderer.ts';
|
export { _Renderer as Renderer } from './Renderer.ts';
|
||||||
export { _TextRenderer as TextRenderer } from './TextRenderer.ts';
|
export { _TextRenderer as TextRenderer } from './TextRenderer.ts';
|
||||||
export { _Slugger as Slugger } from './Slugger.ts';
|
|
||||||
export { _Hooks as Hooks } from './Hooks.ts';
|
export { _Hooks as Hooks } from './Hooks.ts';
|
||||||
export { Marked } from './Instance.ts';
|
export { Marked } from './Instance.ts';
|
||||||
export type * from './MarkedOptions.ts';
|
export type * from './MarkedOptions.ts';
|
||||||
|
21
test/bench.js
vendored
21
test/bench.js
vendored
@ -35,12 +35,9 @@ export async function runBench(options) {
|
|||||||
|
|
||||||
// Non-GFM, Non-pedantic
|
// Non-GFM, Non-pedantic
|
||||||
cjsMarked.setOptions({
|
cjsMarked.setOptions({
|
||||||
headerIds: false,
|
|
||||||
mangle: false,
|
|
||||||
gfm: false,
|
gfm: false,
|
||||||
breaks: false,
|
breaks: false,
|
||||||
pedantic: false,
|
pedantic: false
|
||||||
sanitize: false
|
|
||||||
});
|
});
|
||||||
if (options.marked) {
|
if (options.marked) {
|
||||||
cjsMarked.setOptions(options.marked);
|
cjsMarked.setOptions(options.marked);
|
||||||
@ -48,29 +45,15 @@ export async function runBench(options) {
|
|||||||
tests['cjs marked'] = cjsMarked.parse;
|
tests['cjs marked'] = cjsMarked.parse;
|
||||||
|
|
||||||
esmMarked.setOptions({
|
esmMarked.setOptions({
|
||||||
headerIds: false,
|
|
||||||
mangle: false,
|
|
||||||
gfm: false,
|
gfm: false,
|
||||||
breaks: false,
|
breaks: false,
|
||||||
pedantic: false,
|
pedantic: false
|
||||||
sanitize: false
|
|
||||||
});
|
});
|
||||||
if (options.marked) {
|
if (options.marked) {
|
||||||
esmMarked.setOptions(options.marked);
|
esmMarked.setOptions(options.marked);
|
||||||
}
|
}
|
||||||
tests['esm marked'] = esmMarked.parse;
|
tests['esm marked'] = esmMarked.parse;
|
||||||
|
|
||||||
// esmMarked.setOptions({
|
|
||||||
// gfm: true,
|
|
||||||
// breaks: false,
|
|
||||||
// pedantic: false,
|
|
||||||
// sanitize: false
|
|
||||||
// });
|
|
||||||
// if (options.marked) {
|
|
||||||
// esmMarked.setOptions(options.marked);
|
|
||||||
// }
|
|
||||||
// tests['esm marked (gfm)'] = esmMarked.parse;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tests.commonmark = (await (async() => {
|
tests.commonmark = (await (async() => {
|
||||||
const { Parser, HtmlRenderer } = await import('commonmark');
|
const { Parser, HtmlRenderer } = await import('commonmark');
|
||||||
|
5
test/recheck.js
vendored
5
test/recheck.js
vendored
@ -28,11 +28,6 @@ function checkRegexp(obj, name) {
|
|||||||
console.log(`
|
console.log(`
|
||||||
import { marked } from './src/marked.js';
|
import { marked } from './src/marked.js';
|
||||||
|
|
||||||
marked.use({
|
|
||||||
mangle: false,
|
|
||||||
headerIds: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
<h3 id="heading-with-html">Heading with <em>html</em></h3>
|
|
||||||
|
|
||||||
<h3 id="heading-with-a-link">Heading with a <a href="http://github.com/">link</a></h3>
|
|
||||||
|
|
||||||
<h3 id="heading-with-some-italic-text">Heading with some <em>italic text</em></h3>
|
|
||||||
|
|
||||||
<h3 id="or-some-strong">Or some <strong>strong</strong></h3>
|
|
||||||
|
|
||||||
<p>(which doesn't really make any difference, here)</p>
|
|
||||||
|
|
||||||
<h3 id="or-even-code">Or even <code>code</code></h3>
|
|
||||||
|
|
||||||
<h3 id="what-about-strikethrough">What about <del>strikethrough</del></h3>
|
|
||||||
|
|
||||||
<h2 id="and-a-ref-link">And a ref <a href="/some/url" title="link to nowhere">link</a></h2>
|
|
@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
headerIds: true
|
|
||||||
---
|
|
||||||
### Heading with <em>html</em>
|
|
||||||
|
|
||||||
### Heading with a [link](http://github.com/)
|
|
||||||
|
|
||||||
### Heading with some _italic text_
|
|
||||||
|
|
||||||
### Or some **strong**
|
|
||||||
(which doesn't really make any difference, here)
|
|
||||||
|
|
||||||
### Or even `code`
|
|
||||||
|
|
||||||
### What about ~~strikethrough~~
|
|
||||||
|
|
||||||
## And a ref [link][destination]
|
|
||||||
|
|
||||||
[destination]: /some/url "link to nowhere"
|
|
@ -1,5 +0,0 @@
|
|||||||
<p>Image</p>
|
|
||||||
<p>Image</p>
|
|
||||||
<p>Image</p>
|
|
||||||
<p>Image</p>
|
|
||||||
<p>Image</p>
|
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
---
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||

|
|
@ -1,6 +1,3 @@
|
|||||||
---
|
|
||||||
headerIds: false
|
|
||||||
---
|
|
||||||
## *list
|
## *list
|
||||||
|
|
||||||
* list1
|
* list1
|
||||||
@ -19,7 +16,7 @@ headerIds: false
|
|||||||
-Not list(without space)
|
-Not list(without space)
|
||||||
- list2
|
- list2
|
||||||
|
|
||||||
## number(1.)list
|
## number(1.)list
|
||||||
1. list
|
1. list
|
||||||
1.Notlist(without space)
|
1.Notlist(without space)
|
||||||
1. list
|
1. list
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<p><<svg/onload="alert(1)"//@x></p>
|
|
||||||
|
|
||||||
<p><bar"onclick="alert('XSS')"@foo></p>
|
|
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
sanatize: true
|
|
||||||
mangle: false
|
|
||||||
---
|
|
||||||
<<svg/onload="alert(1)"//@x>
|
|
||||||
|
|
||||||
<bar"onclick="alert('XSS')"@foo>
|
|
@ -1,35 +0,0 @@
|
|||||||
<h1>Absolutization of RFC 3986 URIs</h1>
|
|
||||||
|
|
||||||
<h2>Absolute URI</h2>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/"><img src="http://example.com/logo" alt="section 4.3"></a></p>
|
|
||||||
|
|
||||||
<h2>Network-path reference</h2>
|
|
||||||
|
|
||||||
<p><a href="//example.com/"><img src="//example.com/logo" alt="section 4.2"></a></p>
|
|
||||||
|
|
||||||
<h2>Absolute path</h2>
|
|
||||||
|
|
||||||
<p><a href="/path/to/content"><img src="/path/to/img" alt="section 4.2"></a></p>
|
|
||||||
|
|
||||||
<h2>Relative path</h2>
|
|
||||||
|
|
||||||
<p><a href="/base/content"><img src="/base/img" alt="section 4.2"></a></p>
|
|
||||||
|
|
||||||
<h2>Dot-relative path</h2>
|
|
||||||
|
|
||||||
<p><a href="/base/./content"><img src="/base/./img" alt="section 3.3"></a></p>
|
|
||||||
|
|
||||||
<p><a href="/base/../content"><img src="/base/../img" alt="section 3.3"></a></p>
|
|
||||||
|
|
||||||
<h2>Same-document query</h2>
|
|
||||||
|
|
||||||
<p><a href="?"><img src="?type=image" alt="section 4.4"></a></p>
|
|
||||||
|
|
||||||
<h2>Same-document fragment</h2>
|
|
||||||
|
|
||||||
<p><a href="#"><img src="#img" alt="section 4.4"></a></p>
|
|
||||||
|
|
||||||
<h2>Empty</h2>
|
|
||||||
|
|
||||||
<p><a href="">section 4.2</a></p>
|
|
@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
baseUrl: "/base/"
|
|
||||||
---
|
|
||||||
# Absolutization of RFC 3986 URIs
|
|
||||||
|
|
||||||
## Absolute URI
|
|
||||||
[](http://example.com/)
|
|
||||||
|
|
||||||
## Network-path reference
|
|
||||||
[](//example.com/)
|
|
||||||
|
|
||||||
## Absolute path
|
|
||||||
[](/path/to/content)
|
|
||||||
|
|
||||||
## Relative path
|
|
||||||
[](content)
|
|
||||||
|
|
||||||
## Dot-relative path
|
|
||||||
[](./content)
|
|
||||||
|
|
||||||
[](../content)
|
|
||||||
|
|
||||||
## Same-document query
|
|
||||||
[](?)
|
|
||||||
|
|
||||||
## Same-document fragment
|
|
||||||
[](#)
|
|
||||||
|
|
||||||
## Empty
|
|
||||||
[section 4.2]()
|
|
@ -1,35 +0,0 @@
|
|||||||
<h1>Absolutization of RFC 3986 URIs</h1>
|
|
||||||
|
|
||||||
<h2>Absolute URI</h2>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/"><img src="http://example.com/logo" alt="section 4.3"></a></p>
|
|
||||||
|
|
||||||
<h2>Network-path reference</h2>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/"><img src="http://example.com/logo" alt="section 4.2"></a></p>
|
|
||||||
|
|
||||||
<h2>Absolute path</h2>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/path/to/content"><img src="http://example.com/path/to/img" alt="section 4.2"></a></p>
|
|
||||||
|
|
||||||
<h2>Relative path</h2>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/base/content"><img src="http://example.com/base/img" alt="section 4.2"></a></p>
|
|
||||||
|
|
||||||
<h2>Dot-relative path</h2>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/base/./content"><img src="http://example.com/base/./img" alt="section 3.3"></a></p>
|
|
||||||
|
|
||||||
<p><a href="http://example.com/base/../content"><img src="http://example.com/base/../img" alt="section 3.3"></a></p>
|
|
||||||
|
|
||||||
<h2>Same-document query</h2>
|
|
||||||
|
|
||||||
<p><a href="?"><img src="?type=image" alt="section 4.4"></a></p>
|
|
||||||
|
|
||||||
<h2>Same-document fragment</h2>
|
|
||||||
|
|
||||||
<p><a href="#"><img src="#img" alt="section 4.4"></a></p>
|
|
||||||
|
|
||||||
<h2>Empty</h2>
|
|
||||||
|
|
||||||
<p><a href="">section 4.2</a></p>
|
|
@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
baseUrl: "http://example.com/base/"
|
|
||||||
---
|
|
||||||
# Absolutization of RFC 3986 URIs
|
|
||||||
|
|
||||||
## Absolute URI
|
|
||||||
[](http://example.com/)
|
|
||||||
|
|
||||||
## Network-path reference
|
|
||||||
[](//example.com/)
|
|
||||||
|
|
||||||
## Absolute path
|
|
||||||
[](/path/to/content)
|
|
||||||
|
|
||||||
## Relative path
|
|
||||||
[](content)
|
|
||||||
|
|
||||||
## Dot-relative path
|
|
||||||
[](./content)
|
|
||||||
|
|
||||||
[](../content)
|
|
||||||
|
|
||||||
## Same-document query
|
|
||||||
[](?)
|
|
||||||
|
|
||||||
## Same-document fragment
|
|
||||||
[](#)
|
|
||||||
|
|
||||||
## Empty
|
|
||||||
[section 4.2]()
|
|
@ -1,5 +0,0 @@
|
|||||||
<p>URL</p>
|
|
||||||
<p>URL</p>
|
|
||||||
<p>URL</p>
|
|
||||||
<p>URL</p>
|
|
||||||
<p>URL</p>
|
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
---
|
|
||||||
[URL](javascript:alert)
|
|
||||||
|
|
||||||
[URL](vbscript:alert)
|
|
||||||
|
|
||||||
[URL](javascript:alert(1))
|
|
||||||
|
|
||||||
[URL](javascript:document;alert(1))
|
|
||||||
|
|
||||||
[URL](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
|
|
@ -1,6 +0,0 @@
|
|||||||
<p>Hello world ‘how’ “are” you – today…</p>
|
|
||||||
|
|
||||||
<p>“It’s a more ‘challenging’ smartypants test…”</p>
|
|
||||||
|
|
||||||
<p>‘And,’ as a bonus — “one
|
|
||||||
multiline” test!</p>
|
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
smartypants: true
|
|
||||||
---
|
|
||||||
Hello world 'how' "are" you -- today...
|
|
||||||
|
|
||||||
"It's a more 'challenging' smartypants test..."
|
|
||||||
|
|
||||||
'And,' as a bonus --- "one
|
|
||||||
multiline" test!
|
|
@ -1,11 +0,0 @@
|
|||||||
<pre>&</pre>
|
|
||||||
<p><code>--foo</code>
|
|
||||||
<kbd>---foo</kbd></p>
|
|
||||||
<script>--foo</script>
|
|
||||||
|
|
||||||
<p>Ensure that text such as custom tags that happen to
|
|
||||||
begin with the same letters as the above tags don’t
|
|
||||||
match and thus benefit from Smartypants-ing.</p>
|
|
||||||
|
|
||||||
<p><script-custom>–foo</script-custom>
|
|
||||||
<code>--foo</code> <codebar –foo codebar></p>
|
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
smartypants: true
|
|
||||||
description: SmartyPants does not modify characters within <pre>, <code>, <kbd>, or <script> tag blocks.
|
|
||||||
spec: https://daringfireball.net/projects/smartypants/
|
|
||||||
---
|
|
||||||
<pre>&</pre>
|
|
||||||
<code>--foo</code>
|
|
||||||
<kbd>---foo</kbd>
|
|
||||||
<script>--foo</script>
|
|
||||||
|
|
||||||
Ensure that text such as custom tags that happen to
|
|
||||||
begin with the same letters as the above tags don't
|
|
||||||
match and thus benefit from Smartypants-ing.
|
|
||||||
<script-custom>--foo</script-custom>
|
|
||||||
`--foo` <codebar --foo codebar>
|
|
@ -1,2 +0,0 @@
|
|||||||
<p>lowerclick melower
|
|
||||||
upperclick meupper</p>
|
|
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
---
|
|
||||||
lower[click me](javascript:...)lower
|
|
||||||
upper[click me](javascript:...)upper
|
|
@ -1,4 +1,4 @@
|
|||||||
<h1 id="markdown-basics">Markdown: Basics</h1>
|
<h1>Markdown: Basics</h1>
|
||||||
|
|
||||||
<ul id="ProjectSubmenu">
|
<ul id="ProjectSubmenu">
|
||||||
<li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
|
<li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
|
||||||
@ -8,7 +8,7 @@
|
|||||||
<li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
|
<li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 id="getting-the-gist-of-markdowns-formatting-syntax">Getting the Gist of Markdown's Formatting Syntax</h2>
|
<h2>Getting the Gist of Markdown's Formatting Syntax</h2>
|
||||||
|
|
||||||
<p>This page offers a brief overview of what it's like to use Markdown.
|
<p>This page offers a brief overview of what it's like to use Markdown.
|
||||||
The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for
|
The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for
|
||||||
@ -24,7 +24,7 @@ and translate it to XHTML.</p>
|
|||||||
<p><strong>Note:</strong> This document is itself written using Markdown; you
|
<p><strong>Note:</strong> This document is itself written using Markdown; you
|
||||||
can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p>
|
can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p>
|
||||||
|
|
||||||
<h2 id="paragraphs-headers-blockquotes">Paragraphs, Headers, Blockquotes</h2>
|
<h2>Paragraphs, Headers, Blockquotes</h2>
|
||||||
|
|
||||||
<p>A paragraph is simply one or more consecutive lines of text, separated
|
<p>A paragraph is simply one or more consecutive lines of text, separated
|
||||||
by one or more blank lines. (A blank line is any line that looks like a
|
by one or more blank lines. (A blank line is any line that looks like a
|
||||||
@ -58,7 +58,7 @@ dog's back.
|
|||||||
### Header 3
|
### Header 3
|
||||||
|
|
||||||
> This is a blockquote.
|
> This is a blockquote.
|
||||||
>
|
>
|
||||||
> This is the second paragraph in the blockquote.
|
> This is the second paragraph in the blockquote.
|
||||||
>
|
>
|
||||||
> ## This is an H2 in a blockquote
|
> ## This is an H2 in a blockquote
|
||||||
@ -88,7 +88,7 @@ dog's back.</p>
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<h3 id="phrase-emphasis">Phrase Emphasis</h3>
|
<h3>Phrase Emphasis</h3>
|
||||||
|
|
||||||
<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>
|
<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ Some of these words <em>are emphasized also</em>.</p>
|
|||||||
Or, if you prefer, <strong>use two underscores instead</strong>.</p>
|
Or, if you prefer, <strong>use two underscores instead</strong>.</p>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<h2 id="lists">Lists</h2>
|
<h2>Lists</h2>
|
||||||
|
|
||||||
<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,
|
<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,
|
||||||
<code>+</code>, and <code>-</code>) as list markers. These three markers are
|
<code>+</code>, and <code>-</code>) as list markers. These three markers are
|
||||||
@ -181,7 +181,7 @@ the paragraphs by 4 spaces or 1 tab:</p>
|
|||||||
</ul>
|
</ul>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<h3 id="links">Links</h3>
|
<h3>Links</h3>
|
||||||
|
|
||||||
<p>Markdown supports two styles for creating links: <em>inline</em> and
|
<p>Markdown supports two styles for creating links: <em>inline</em> and
|
||||||
<em>reference</em>. With both styles, you use square brackets to delimit the
|
<em>reference</em>. With both styles, you use square brackets to delimit the
|
||||||
@ -244,7 +244,7 @@ numbers and spaces, but are <em>not</em> case sensitive:</p>
|
|||||||
<a href="http://www.nytimes.com/">The New York Times</a>.</p>
|
<a href="http://www.nytimes.com/">The New York Times</a>.</p>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<h3 id="images">Images</h3>
|
<h3>Images</h3>
|
||||||
|
|
||||||
<p>Image syntax is very much like link syntax.</p>
|
<p>Image syntax is very much like link syntax.</p>
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ numbers and spaces, but are <em>not</em> case sensitive:</p>
|
|||||||
<pre><code><img src="/path/to/img.jpg" alt="alt text" title="Title" />
|
<pre><code><img src="/path/to/img.jpg" alt="alt text" title="Title" />
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<h3 id="code">Code</h3>
|
<h3>Code</h3>
|
||||||
|
|
||||||
<p>In a regular paragraph, you can create code span by wrapping text in
|
<p>In a regular paragraph, you can create code span by wrapping text in
|
||||||
backtick quotes. Any ampersands (<code>&</code>) and angle brackets (<code><</code> or
|
backtick quotes. Any ampersands (<code>&</code>) and angle brackets (<code><</code> or
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
pedantic: true
|
pedantic: true
|
||||||
headerIds: true
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Markdown: Basics
|
Markdown: Basics
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
pedantic: true
|
pedantic: true
|
||||||
headerIds: false
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Markdown: Syntax
|
Markdown: Syntax
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
---
|
|
||||||
headerIds: false
|
|
||||||
---
|
|
||||||
## Unordered
|
## Unordered
|
||||||
|
|
||||||
Asterisks tight:
|
Asterisks tight:
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
markdown: `# #${' '.repeat(50000)}a`,
|
markdown: `# #${' '.repeat(50000)}a`,
|
||||||
html: '<h1># a</h1>',
|
html: '<h1># a</h1>'
|
||||||
options: {
|
|
||||||
headerIds: false
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -24,11 +24,6 @@ function runSpecs(title, dir, showCompletionTable, options) {
|
|||||||
spec.options.silent = true;
|
spec.options.silent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spec.options.sanitizer) {
|
|
||||||
// eslint-disable-next-line no-eval
|
|
||||||
spec.options.sanitizer = eval(spec.options.sanitizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
(spec.only ? fit : (spec.skip ? xit : it))('should ' + passFail + example, async() => {
|
(spec.only ? fit : (spec.skip ? xit : it))('should ' + passFail + example, async() => {
|
||||||
const before = process.hrtime();
|
const before = process.hrtime();
|
||||||
if (spec.shouldFail) {
|
if (spec.shouldFail) {
|
||||||
@ -50,9 +45,8 @@ function runSpecs(title, dir, showCompletionTable, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
runSpecs('GFM', './gfm', true, { gfm: true, pedantic: false, headerIds: false });
|
runSpecs('GFM', './gfm', true, { gfm: true, pedantic: false });
|
||||||
runSpecs('CommonMark', './commonmark', true, { gfm: false, pedantic: false, headerIds: false });
|
runSpecs('CommonMark', './commonmark', true, { gfm: false, pedantic: false });
|
||||||
runSpecs('Original', './original', false, { gfm: false, pedantic: true });
|
runSpecs('Original', './original', false, { gfm: false, pedantic: true });
|
||||||
runSpecs('New', './new');
|
runSpecs('New', './new');
|
||||||
runSpecs('ReDOS', './redos');
|
runSpecs('ReDOS', './redos');
|
||||||
runSpecs('Security', './security');
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
<p>AAA<script> <img <script> src=x onerror=alert(1) />BBB</p>
|
|
||||||
|
|
||||||
<p>AAA<sometag> <img <sometag> src=x onerror=alert(1)BBB</p>
|
|
||||||
|
|
||||||
<p><a>a2<a2t>a2</a> b <c>c</c> d</p>
|
|
||||||
<h1><img src="URL" alt="text"></h1>
|
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
---
|
|
||||||
AAA<script> <img <script> src=x onerror=alert(1) />BBB
|
|
||||||
|
|
||||||
AAA<sometag> <img <sometag> src=x onerror=alert(1)BBB
|
|
||||||
|
|
||||||
<a>a2<a2t>a2</a> b <c>c</c> d
|
|
||||||
# 
|
|
@ -1,2 +0,0 @@
|
|||||||
<p>a2a2 b c d</p>
|
|
||||||
<h1><img src="URL" alt="text"></h1>
|
|
@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
sanitizer: () => ''
|
|
||||||
---
|
|
||||||
<a>a2<a2t>a2</a> b <c>c</c> d
|
|
||||||
# 
|
|
@ -1 +0,0 @@
|
|||||||
<p>AAA</p>
|
|
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
sanitizer: () => ''
|
|
||||||
---
|
|
||||||
AAA<script> <img <script> src=x onerror=alert(1) />BBB
|
|
@ -1 +0,0 @@
|
|||||||
<p>AAA <img src=x onerror=alert(1)BBB</p>
|
|
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
sanitize: true
|
|
||||||
sanitizer: () => ''
|
|
||||||
---
|
|
||||||
AAA<sometag> <img <sometag> src=x onerror=alert(1)BBB
|
|
@ -4,7 +4,7 @@ import { expectType } from 'ts-expect';
|
|||||||
|
|
||||||
// other exports
|
// other exports
|
||||||
|
|
||||||
import { Lexer, Parser, Tokenizer, Renderer, TextRenderer, Slugger } from 'marked';
|
import { Lexer, Parser, Tokenizer, Renderer, TextRenderer } from 'marked';
|
||||||
import type { Tokens, MarkedExtension, TokenizerAndRendererExtension, Token ,TokenizerExtension, MarkedOptions, TokensList, Rules, RendererExtension } from 'marked';
|
import type { Tokens, MarkedExtension, TokenizerAndRendererExtension, Token ,TokenizerExtension, MarkedOptions, TokensList, Rules, RendererExtension } from 'marked';
|
||||||
|
|
||||||
const tokenizer = new marked.Tokenizer();
|
const tokenizer = new marked.Tokenizer();
|
||||||
@ -31,18 +31,10 @@ tokenizer.inlineText = function inlineText(...args: Parameters<Tokenizer['inline
|
|||||||
};
|
};
|
||||||
|
|
||||||
let options: MarkedOptions = {
|
let options: MarkedOptions = {
|
||||||
baseUrl: '',
|
|
||||||
gfm: true,
|
gfm: true,
|
||||||
breaks: false,
|
breaks: false,
|
||||||
pedantic: false,
|
pedantic: false,
|
||||||
sanitize: true,
|
|
||||||
smartLists: true,
|
|
||||||
silent: false,
|
silent: false,
|
||||||
highlight(code: string, lang: string | undefined) {
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
langPrefix: 'lang-',
|
|
||||||
smartypants: false,
|
|
||||||
tokenizer,
|
tokenizer,
|
||||||
renderer: new marked.Renderer(),
|
renderer: new marked.Renderer(),
|
||||||
walkTokens: token => {
|
walkTokens: token => {
|
||||||
@ -52,11 +44,6 @@ let options: MarkedOptions = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
options.highlight = (code: string, lang: string | undefined, callback?: (error: any, code?: string) => string | void) => {
|
|
||||||
callback?.(new Error());
|
|
||||||
callback?.(null, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
options = marked.getDefaults();
|
options = marked.getDefaults();
|
||||||
options = marked.defaults;
|
options = marked.defaults;
|
||||||
|
|
||||||
@ -70,13 +57,9 @@ myOldMarked = marked.setOptions(options);
|
|||||||
|
|
||||||
console.log(marked('1) I am using __markdown__.'));
|
console.log(marked('1) I am using __markdown__.'));
|
||||||
console.log(marked('2) I am using __markdown__.', options));
|
console.log(marked('2) I am using __markdown__.', options));
|
||||||
marked('3) I am using __markdown__.', callback);
|
|
||||||
marked('4) I am using __markdown__.', options, callback);
|
|
||||||
|
|
||||||
console.log(marked.parse('5) I am using __markdown__.'));
|
console.log(marked.parse('5) I am using __markdown__.'));
|
||||||
console.log(marked.parse('6) I am using __markdown__.', options));
|
console.log(marked.parse('6) I am using __markdown__.', options));
|
||||||
marked.parse('7) I am using __markdown__.', callback);
|
|
||||||
marked.parse('8) I am using __markdown__.', options, callback);
|
|
||||||
|
|
||||||
console.log(marked.parseInline('9) I am using __markdown__.'));
|
console.log(marked.parseInline('9) I am using __markdown__.'));
|
||||||
console.log(marked.parseInline('10) I am using __markdown__.', options));
|
console.log(marked.parseInline('10) I am using __markdown__.', options));
|
||||||
@ -97,11 +80,11 @@ const re: Rules = marked.Lexer.rules;
|
|||||||
const lexerOptions: MarkedOptions = lexer.options;
|
const lexerOptions: MarkedOptions = lexer.options;
|
||||||
|
|
||||||
const renderer = new marked.Renderer();
|
const renderer = new marked.Renderer();
|
||||||
renderer.heading = (text, level, raw, slugger) => {
|
renderer.heading = (text, level, raw) => {
|
||||||
return text + level.toString() + slugger.slug(raw);
|
return text + level.toString();
|
||||||
};
|
};
|
||||||
renderer.hr = () => {
|
renderer.hr = () => {
|
||||||
return `<hr${renderer.options.xhtml ? '/' : ''}>\n`;
|
return `<hr>\n`;
|
||||||
};
|
};
|
||||||
renderer.checkbox = checked => {
|
renderer.checkbox = checked => {
|
||||||
return checked ? 'CHECKED' : 'UNCHECKED';
|
return checked ? 'CHECKED' : 'UNCHECKED';
|
||||||
@ -111,7 +94,7 @@ class ExtendedRenderer extends marked.Renderer {
|
|||||||
code = (code: string, language: string | undefined, isEscaped: boolean): string => super.code(code, language, isEscaped);
|
code = (code: string, language: string | undefined, isEscaped: boolean): string => super.code(code, language, isEscaped);
|
||||||
blockquote = (quote: string): string => super.blockquote(quote);
|
blockquote = (quote: string): string => super.blockquote(quote);
|
||||||
html = (html: string): string => super.html(html);
|
html = (html: string): string => super.html(html);
|
||||||
heading = (text: string, level: 1 | 2 | 3 | 4 | 5 | 6, raw: string, slugger: Slugger): string => super.heading(text, level, raw, slugger);
|
heading = (text: string, level: 1 | 2 | 3 | 4 | 5 | 6, raw: string): string => super.heading(text, level, raw);
|
||||||
hr = (): string => super.hr();
|
hr = (): string => super.hr();
|
||||||
list = (body: string, ordered: boolean, start: number): string => super.list(body, ordered, start);
|
list = (body: string, ordered: boolean, start: number): string => super.list(body, ordered, start);
|
||||||
listitem = (text: string, task: boolean, checked: boolean): string => super.listitem(text, task, checked);
|
listitem = (text: string, task: boolean, checked: boolean): string => super.listitem(text, task, checked);
|
||||||
@ -149,10 +132,6 @@ console.log(parser.parse(parseTestTokens));
|
|||||||
console.log(marked.Parser.parse(parseTestTokens));
|
console.log(marked.Parser.parse(parseTestTokens));
|
||||||
const parserOptions: MarkedOptions = parser.options;
|
const parserOptions: MarkedOptions = parser.options;
|
||||||
|
|
||||||
const slugger = new marked.Slugger();
|
|
||||||
console.log(slugger.slug('Test Slug'));
|
|
||||||
console.log(slugger.slug('Test Slug', { dryrun: true }));
|
|
||||||
|
|
||||||
marked.use({ renderer }, { tokenizer });
|
marked.use({ renderer }, { tokenizer });
|
||||||
|
|
||||||
marked.use({
|
marked.use({
|
||||||
@ -270,17 +249,11 @@ const asyncMarked: string = await marked(md, { async: true });
|
|||||||
const promiseMarked: Promise<string> = marked(md, { async: true });
|
const promiseMarked: Promise<string> = marked(md, { async: true });
|
||||||
const notAsyncMarked: string = marked(md, { async: false });
|
const notAsyncMarked: string = marked(md, { async: false });
|
||||||
const defaultMarked: string = marked(md);
|
const defaultMarked: string = marked(md);
|
||||||
expectType<void>(marked(md, (_: any, res: string | undefined) => { res; }));
|
|
||||||
expectType<void>(marked(md, { async: true }, (_: any, res: string | undefined) => { res; }));
|
|
||||||
expectType<void>(marked(md, { async: false }, (_: any, res: string | undefined) => { res; }));
|
|
||||||
|
|
||||||
const asyncMarkedParse: string = await marked.parse(md, { async: true });
|
const asyncMarkedParse: string = await marked.parse(md, { async: true });
|
||||||
const promiseMarkedParse: Promise<string> = marked.parse(md, { async: true, headerIds: false });
|
const promiseMarkedParse: Promise<string> = marked.parse(md, { async: true });
|
||||||
const notAsyncMarkedParse: string = marked.parse(md, { async: false });
|
const notAsyncMarkedParse: string = marked.parse(md, { async: false });
|
||||||
const defaultMarkedParse: string = marked.parse(md);
|
const defaultMarkedParse: string = marked.parse(md);
|
||||||
expectType<void>(marked.parse(md, (_: any, res: string | undefined) => { res; }));
|
|
||||||
expectType<void>(marked(md, { async: true }, (_: any, res: string | undefined) => { res; }));
|
|
||||||
expectType<void>(marked(md, { async: false }, (_: any, res: string | undefined) => { res; }));
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Tests for List and ListItem
|
// Tests for List and ListItem
|
||||||
@ -330,9 +303,6 @@ const tokens4 = lexer2.lex('# test');
|
|||||||
const parser2 = new Parser();
|
const parser2 = new Parser();
|
||||||
console.log(parser2.parse(tokens4));
|
console.log(parser2.parse(tokens4));
|
||||||
|
|
||||||
const slugger2 = new Slugger();
|
|
||||||
console.log(slugger2.slug('Test Slug'));
|
|
||||||
|
|
||||||
marked.use({ renderer: new Renderer() });
|
marked.use({ renderer: new Renderer() });
|
||||||
marked.use({ renderer: new TextRenderer() });
|
marked.use({ renderer: new TextRenderer() });
|
||||||
marked.use({ tokenizer: new Tokenizer() });
|
marked.use({ tokenizer: new Tokenizer() });
|
||||||
|
@ -34,13 +34,13 @@ describe('Hooks', () => {
|
|||||||
marked.use({
|
marked.use({
|
||||||
hooks: {
|
hooks: {
|
||||||
preprocess(markdown) {
|
preprocess(markdown) {
|
||||||
this.options.headerIds = false;
|
this.options.breaks = true;
|
||||||
return markdown;
|
return markdown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const html = marked('# test');
|
const html = marked('line1\nline2');
|
||||||
expect(html.trim()).toBe('<h1>test</h1>');
|
expect(html.trim()).toBe('<p>line1<br>line2</p>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should preprocess options async', async() => {
|
it('should preprocess options async', async() => {
|
||||||
@ -49,13 +49,13 @@ describe('Hooks', () => {
|
|||||||
hooks: {
|
hooks: {
|
||||||
async preprocess(markdown) {
|
async preprocess(markdown) {
|
||||||
await timeout();
|
await timeout();
|
||||||
this.options.headerIds = false;
|
this.options.breaks = true;
|
||||||
return markdown;
|
return markdown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const html = await marked('# test');
|
const html = await marked('line1\nline2');
|
||||||
expect(html.trim()).toBe('<h1>test</h1>');
|
expect(html.trim()).toBe('<p>line1<br>line2</p>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should postprocess html', () => {
|
it('should postprocess html', () => {
|
||||||
|
@ -794,27 +794,6 @@ paragraph
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sanitize', () => {
|
|
||||||
expectTokens({
|
|
||||||
md: '<div>html</div>',
|
|
||||||
options: { sanitize: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
raw: '<div>html</div>',
|
|
||||||
pre: false,
|
|
||||||
block: true,
|
|
||||||
text: '<div>html</div>',
|
|
||||||
tokens: [{
|
|
||||||
type: 'text',
|
|
||||||
raw: '<div>html</div>',
|
|
||||||
text: '<div>html</div>'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('def', () => {
|
describe('def', () => {
|
||||||
@ -894,23 +873,6 @@ paragraph
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('html sanitize', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: '<div>html</div>',
|
|
||||||
options: { sanitize: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: '<div>html</div>',
|
|
||||||
inLink: false,
|
|
||||||
inRawBlock: false,
|
|
||||||
block: false,
|
|
||||||
text: '<div>html</div>'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('link', () => {
|
it('link', () => {
|
||||||
expectInlineTokens({
|
expectInlineTokens({
|
||||||
md: '[link](https://example.com)',
|
md: '[link](https://example.com)',
|
||||||
@ -1205,7 +1167,7 @@ paragraph
|
|||||||
it('autolink email', () => {
|
it('autolink email', () => {
|
||||||
expectInlineTokens({
|
expectInlineTokens({
|
||||||
md: '<test@example.com>',
|
md: '<test@example.com>',
|
||||||
options: { mangle: false },
|
options: {},
|
||||||
tokens: [
|
tokens: [
|
||||||
{
|
{
|
||||||
type: 'link',
|
type: 'link',
|
||||||
@ -1220,28 +1182,6 @@ paragraph
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('autolink mangle email', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: '<test@example.com>',
|
|
||||||
options: { mangle: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'link',
|
|
||||||
raw: '<test@example.com>',
|
|
||||||
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|
||||||
href: jasmine.stringMatching(/^mailto:(&#x?[0-9a-f]+;)+$/),
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|
||||||
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('url', () => {
|
it('url', () => {
|
||||||
expectInlineTokens({
|
expectInlineTokens({
|
||||||
md: 'https://example.com',
|
md: 'https://example.com',
|
||||||
@ -1262,7 +1202,7 @@ paragraph
|
|||||||
it('url email', () => {
|
it('url email', () => {
|
||||||
expectInlineTokens({
|
expectInlineTokens({
|
||||||
md: 'test@example.com',
|
md: 'test@example.com',
|
||||||
options: { gfm: true, mangle: false },
|
options: { gfm: true },
|
||||||
tokens: [
|
tokens: [
|
||||||
{
|
{
|
||||||
type: 'link',
|
type: 'link',
|
||||||
@ -1276,28 +1216,6 @@ paragraph
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('url mangle email', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: 'test@example.com',
|
|
||||||
options: { gfm: true, mangle: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'link',
|
|
||||||
raw: 'test@example.com',
|
|
||||||
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|
||||||
href: jasmine.stringMatching(/^mailto:(&#x?[0-9a-f]+;)+$/),
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|
||||||
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('text', () => {
|
it('text', () => {
|
||||||
@ -1312,78 +1230,6 @@ paragraph
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('smartypants', () => {
|
|
||||||
it('single quotes', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: "'single quotes'",
|
|
||||||
options: { smartypants: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: "'single quotes'",
|
|
||||||
text: '‘single quotes’'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('double quotes', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: '"double quotes"',
|
|
||||||
options: { smartypants: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: '"double quotes"',
|
|
||||||
text: '“double quotes”'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ellipses', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: 'ellipses...',
|
|
||||||
options: { smartypants: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: 'ellipses...',
|
|
||||||
text: 'ellipses…'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('en-dash', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: 'en--dash',
|
|
||||||
options: { smartypants: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: 'en--dash',
|
|
||||||
text: 'en–dash'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('em-dash', () => {
|
|
||||||
expectInlineTokens({
|
|
||||||
md: 'em---dash',
|
|
||||||
options: { smartypants: true },
|
|
||||||
tokens: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
raw: 'em---dash',
|
|
||||||
text: 'em—dash'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
import { _Slugger } from '../../src/Slugger.js';
|
|
||||||
|
|
||||||
describe('Test slugger functionality', () => {
|
|
||||||
it('should use lowercase slug', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('Test')).toBe('test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be unique to avoid collisions 1280', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('test')).toBe('test');
|
|
||||||
expect(slugger.slug('test')).toBe('test-1');
|
|
||||||
expect(slugger.slug('test')).toBe('test-2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be unique when slug ends with number', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('test 1')).toBe('test-1');
|
|
||||||
expect(slugger.slug('test')).toBe('test');
|
|
||||||
expect(slugger.slug('test')).toBe('test-2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be unique when slug ends with hyphen number', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('foo')).toBe('foo');
|
|
||||||
expect(slugger.slug('foo')).toBe('foo-1');
|
|
||||||
expect(slugger.slug('foo 1')).toBe('foo-1-1');
|
|
||||||
expect(slugger.slug('foo-1')).toBe('foo-1-2');
|
|
||||||
expect(slugger.slug('foo')).toBe('foo-2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow non-latin chars', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('привет')).toBe('привет');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove ampersands 857', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('This & That Section')).toBe('this--that-section');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove periods', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('file.txt')).toBe('filetxt');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove html tags', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('<em>html</em>')).toBe('html');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not increment seen when using dryrun option', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('<h1>This Section</h1>', { dryrun: true })).toBe('this-section');
|
|
||||||
expect(slugger.slug('<h1>This Section</h1>')).toBe('this-section');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still return the next unique id when using dryrun', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('<h1>This Section</h1>')).toBe('this-section');
|
|
||||||
expect(slugger.slug('<h1>This Section</h1>', { dryrun: true })).toBe('this-section-1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be repeatable in a sequence', () => {
|
|
||||||
const slugger = new _Slugger();
|
|
||||||
expect(slugger.slug('foo')).toBe('foo');
|
|
||||||
expect(slugger.slug('foo')).toBe('foo-1');
|
|
||||||
expect(slugger.slug('foo')).toBe('foo-2');
|
|
||||||
expect(slugger.slug('foo', { dryrun: true })).toBe('foo-3');
|
|
||||||
expect(slugger.slug('foo', { dryrun: true })).toBe('foo-3');
|
|
||||||
expect(slugger.slug('foo')).toBe('foo-3');
|
|
||||||
expect(slugger.slug('foo')).toBe('foo-4');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,21 +1,6 @@
|
|||||||
import { marked, Renderer, Slugger, lexer, parseInline, use, getDefaults, walkTokens, defaults, setOptions } from '../../src/marked.js';
|
import { marked, Renderer, lexer, parseInline, use, getDefaults, walkTokens, defaults, setOptions } from '../../src/marked.js';
|
||||||
import { timeout } from './utils.js';
|
import { timeout } from './utils.js';
|
||||||
|
|
||||||
describe('Test heading ID functionality', () => {
|
|
||||||
it('should add id attribute', () => {
|
|
||||||
const renderer = new Renderer({ ...defaults, headerIds: true });
|
|
||||||
const slugger = new Slugger();
|
|
||||||
const header = renderer.heading('test', 1, 'test', slugger);
|
|
||||||
expect(header).toBe('<h1 id="test">test</h1>\n');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should NOT add id attribute when options set false', () => {
|
|
||||||
const renderer = new Renderer({ headerIds: false });
|
|
||||||
const header = renderer.heading('test', 1, 'test');
|
|
||||||
expect(header).toBe('<h1>test</h1>\n');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Test paragraph token type', () => {
|
describe('Test paragraph token type', () => {
|
||||||
it('should use the "paragraph" type on top level', () => {
|
it('should use the "paragraph" type on top level', () => {
|
||||||
const md = 'A Paragraph.\n\n> A blockquote\n\n- list item\n';
|
const md = 'A Paragraph.\n\n> A blockquote\n\n- list item\n';
|
||||||
@ -227,9 +212,9 @@ describe('use extension', () => {
|
|||||||
return `<u>${token.text}</u>\n`;
|
return `<u>${token.text}</u>\n`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
use({ sanitize: true, silent: true, extensions: [extension] });
|
use({ silent: true, extensions: [extension] });
|
||||||
const html = marked(':test:\ntest\n<div></div>');
|
const html = marked(':test:\ntest\n<div></div>');
|
||||||
expect(html).toBe('<u>test</u>\n<p>test</p>\n<p><div></div></p>\n');
|
expect(html).toBe('<u>test</u>\n<p>test</p>\n<div></div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle renderers that return false', () => {
|
it('should handle renderers that return false', () => {
|
||||||
@ -456,8 +441,7 @@ describe('use extension', () => {
|
|||||||
if (token.text === `used ${name}`) {
|
if (token.text === `used ${name}`) {
|
||||||
token.text += ' walked';
|
token.text += ' walked';
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
headerIds: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,8 +467,7 @@ describe('use extension', () => {
|
|||||||
renderer(token) {
|
renderer(token) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}],
|
}]
|
||||||
headerIds: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,8 +619,7 @@ used extension2 walked</p>
|
|||||||
token.tokens.pop();
|
token.tokens.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
headerIds: false
|
|
||||||
};
|
};
|
||||||
use(styleTags);
|
use(styleTags);
|
||||||
const html = marked('This is a *paragraph* with blue text. {blue}\n'
|
const html = marked('This is a *paragraph* with blue text. {blue}\n'
|
||||||
@ -695,28 +677,13 @@ used extension2 walked</p>
|
|||||||
expect(walked).toBe(2);
|
expect(walked).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use walkTokens in async', (done) => {
|
|
||||||
let walked = 0;
|
|
||||||
const extension = {
|
|
||||||
walkTokens(token) {
|
|
||||||
walked++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
use({ silent: true });
|
|
||||||
use(extension);
|
|
||||||
marked('text', () => {
|
|
||||||
expect(walked).toBe(2);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use options from extension', () => {
|
it('should use options from extension', () => {
|
||||||
const extension = {
|
const extension = {
|
||||||
headerIds: false
|
breaks: true
|
||||||
};
|
};
|
||||||
use(extension);
|
use(extension);
|
||||||
const html = marked('# heading');
|
const html = marked('line1\nline2');
|
||||||
expect(html).toBe('<h1>heading</h1>\n');
|
expect(html).toBe('<p>line1<br>line2</p>\n');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call all walkTokens in reverse order', () => {
|
it('should call all walkTokens in reverse order', () => {
|
||||||
@ -831,100 +798,6 @@ paragraph
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('async highlight', () => {
|
|
||||||
let highlight, markdown;
|
|
||||||
beforeEach(() => {
|
|
||||||
marked.use({ silent: true });
|
|
||||||
highlight = jasmine.createSpy('highlight', (text, lang, callback) => {
|
|
||||||
setImmediate(() => {
|
|
||||||
callback(null, `async ${text || ''}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
markdown = `
|
|
||||||
\`\`\`lang1
|
|
||||||
text 1
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
> \`\`\`lang2
|
|
||||||
> text 2
|
|
||||||
> \`\`\`
|
|
||||||
|
|
||||||
- \`\`\`lang3
|
|
||||||
text 3
|
|
||||||
\`\`\`
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should highlight codeblocks async', (done) => {
|
|
||||||
highlight.and.callThrough();
|
|
||||||
|
|
||||||
marked(markdown, { highlight }, (err, html) => {
|
|
||||||
if (err) {
|
|
||||||
fail(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(html).toBe(`<pre><code class="language-lang1">async text 1
|
|
||||||
</code></pre>
|
|
||||||
<blockquote>
|
|
||||||
<pre><code class="language-lang2">async text 2
|
|
||||||
</code></pre>
|
|
||||||
</blockquote>
|
|
||||||
<ul>
|
|
||||||
<li><pre><code class="language-lang3">async text 3
|
|
||||||
</code></pre>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
`);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call callback for each error in highlight', (done) => {
|
|
||||||
highlight.and.callFake((text, lang, callback) => {
|
|
||||||
callback(new Error('highlight error'));
|
|
||||||
});
|
|
||||||
|
|
||||||
let numErrors = 0;
|
|
||||||
marked(markdown, { highlight }, (err, html) => {
|
|
||||||
expect(html).toContain('An error occurred:');
|
|
||||||
|
|
||||||
if (err || html.includes('An error occurred:')) {
|
|
||||||
numErrors++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numErrors === 3) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should highlight codeblocks when not async', (done) => {
|
|
||||||
highlight.and.callFake((text, lang, callback) => {
|
|
||||||
callback(null, `async ${text || ''}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
marked(markdown, { highlight }, (err, html) => {
|
|
||||||
if (err) {
|
|
||||||
fail(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(html).toBe(`<pre><code class="language-lang1">async text 1
|
|
||||||
</code></pre>
|
|
||||||
<blockquote>
|
|
||||||
<pre><code class="language-lang2">async text 2
|
|
||||||
</code></pre>
|
|
||||||
</blockquote>
|
|
||||||
<ul>
|
|
||||||
<li><pre><code class="language-lang3">async text 3
|
|
||||||
</code></pre>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
`);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('walkTokens', () => {
|
describe('walkTokens', () => {
|
||||||
it('should walk over every token', () => {
|
it('should walk over every token', () => {
|
||||||
const markdown = `
|
const markdown = `
|
||||||
|
4
test/update-specs.js
vendored
4
test/update-specs.js
vendored
@ -73,6 +73,6 @@ const commonmarkDir = resolve(__dirname, './specs/commonmark');
|
|||||||
const gfmDir = resolve(__dirname, './specs/gfm');
|
const gfmDir = resolve(__dirname, './specs/gfm');
|
||||||
removeFiles(commonmarkDir);
|
removeFiles(commonmarkDir);
|
||||||
removeFiles(gfmDir);
|
removeFiles(gfmDir);
|
||||||
updateCommonmark(commonmarkDir, { gfm: false, pedantic: false, headerIds: false });
|
updateCommonmark(commonmarkDir, { gfm: false, pedantic: false });
|
||||||
updateCommonmark(gfmDir, { gfm: true, pedantic: false, headerIds: false });
|
updateCommonmark(gfmDir, { gfm: true, pedantic: false });
|
||||||
updateGfm(gfmDir);
|
updateGfm(gfmDir);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user