marked 0.6.3 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/marked +19 -19
- package/lib/marked.esm.js +1849 -0
- package/lib/marked.js +1553 -1463
- package/man/marked.1 +1 -4
- package/man/marked.1.txt +4 -7
- package/marked.min.js +2 -2
- package/package.json +35 -23
- package/src/InlineLexer.js +293 -0
- package/src/Lexer.js +402 -0
- package/src/Parser.js +206 -0
- package/src/Renderer.js +164 -0
- package/src/Slugger.js +33 -0
- package/src/TextRenderer.js +42 -0
- package/src/defaults.js +30 -0
- package/src/helpers.js +243 -0
- package/src/marked.js +150 -0
- package/src/rules.js +266 -0
package/src/Renderer.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
const { defaults } = require('./defaults.js');
|
|
2
|
+
const {
|
|
3
|
+
cleanUrl,
|
|
4
|
+
escape
|
|
5
|
+
} = require('./helpers.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Renderer
|
|
9
|
+
*/
|
|
10
|
+
module.exports = class Renderer {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options || defaults;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
code(code, infostring, escaped) {
|
|
16
|
+
const lang = (infostring || '').match(/\S*/)[0];
|
|
17
|
+
if (this.options.highlight) {
|
|
18
|
+
const out = this.options.highlight(code, lang);
|
|
19
|
+
if (out != null && out !== code) {
|
|
20
|
+
escaped = true;
|
|
21
|
+
code = out;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!lang) {
|
|
26
|
+
return '<pre><code>'
|
|
27
|
+
+ (escaped ? code : escape(code, true))
|
|
28
|
+
+ '</code></pre>';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return '<pre><code class="'
|
|
32
|
+
+ this.options.langPrefix
|
|
33
|
+
+ escape(lang, true)
|
|
34
|
+
+ '">'
|
|
35
|
+
+ (escaped ? code : escape(code, true))
|
|
36
|
+
+ '</code></pre>\n';
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
blockquote(quote) {
|
|
40
|
+
return '<blockquote>\n' + quote + '</blockquote>\n';
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
html(html) {
|
|
44
|
+
return html;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
heading(text, level, raw, slugger) {
|
|
48
|
+
if (this.options.headerIds) {
|
|
49
|
+
return '<h'
|
|
50
|
+
+ level
|
|
51
|
+
+ ' id="'
|
|
52
|
+
+ this.options.headerPrefix
|
|
53
|
+
+ slugger.slug(raw)
|
|
54
|
+
+ '">'
|
|
55
|
+
+ text
|
|
56
|
+
+ '</h'
|
|
57
|
+
+ level
|
|
58
|
+
+ '>\n';
|
|
59
|
+
}
|
|
60
|
+
// ignore IDs
|
|
61
|
+
return '<h' + level + '>' + text + '</h' + level + '>\n';
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
hr() {
|
|
65
|
+
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
list(body, ordered, start) {
|
|
69
|
+
const type = ordered ? 'ol' : 'ul',
|
|
70
|
+
startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
|
|
71
|
+
return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
listitem(text) {
|
|
75
|
+
return '<li>' + text + '</li>\n';
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
checkbox(checked) {
|
|
79
|
+
return '<input '
|
|
80
|
+
+ (checked ? 'checked="" ' : '')
|
|
81
|
+
+ 'disabled="" type="checkbox"'
|
|
82
|
+
+ (this.options.xhtml ? ' /' : '')
|
|
83
|
+
+ '> ';
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
paragraph(text) {
|
|
87
|
+
return '<p>' + text + '</p>\n';
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
table(header, body) {
|
|
91
|
+
if (body) body = '<tbody>' + body + '</tbody>';
|
|
92
|
+
|
|
93
|
+
return '<table>\n'
|
|
94
|
+
+ '<thead>\n'
|
|
95
|
+
+ header
|
|
96
|
+
+ '</thead>\n'
|
|
97
|
+
+ body
|
|
98
|
+
+ '</table>\n';
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
tablerow(content) {
|
|
102
|
+
return '<tr>\n' + content + '</tr>\n';
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
tablecell(content, flags) {
|
|
106
|
+
const type = flags.header ? 'th' : 'td';
|
|
107
|
+
const tag = flags.align
|
|
108
|
+
? '<' + type + ' align="' + flags.align + '">'
|
|
109
|
+
: '<' + type + '>';
|
|
110
|
+
return tag + content + '</' + type + '>\n';
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// span level renderer
|
|
114
|
+
strong(text) {
|
|
115
|
+
return '<strong>' + text + '</strong>';
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
em(text) {
|
|
119
|
+
return '<em>' + text + '</em>';
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
codespan(text) {
|
|
123
|
+
return '<code>' + text + '</code>';
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
br() {
|
|
127
|
+
return this.options.xhtml ? '<br/>' : '<br>';
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
del(text) {
|
|
131
|
+
return '<del>' + text + '</del>';
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
link(href, title, text) {
|
|
135
|
+
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
136
|
+
if (href === null) {
|
|
137
|
+
return text;
|
|
138
|
+
}
|
|
139
|
+
let out = '<a href="' + escape(href) + '"';
|
|
140
|
+
if (title) {
|
|
141
|
+
out += ' title="' + title + '"';
|
|
142
|
+
}
|
|
143
|
+
out += '>' + text + '</a>';
|
|
144
|
+
return out;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
image(href, title, text) {
|
|
148
|
+
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
149
|
+
if (href === null) {
|
|
150
|
+
return text;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let out = '<img src="' + href + '" alt="' + text + '"';
|
|
154
|
+
if (title) {
|
|
155
|
+
out += ' title="' + title + '"';
|
|
156
|
+
}
|
|
157
|
+
out += this.options.xhtml ? '/>' : '>';
|
|
158
|
+
return out;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
text(text) {
|
|
162
|
+
return text;
|
|
163
|
+
};
|
|
164
|
+
};
|
package/src/Slugger.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slugger generates header id
|
|
3
|
+
*/
|
|
4
|
+
module.exports = class Slugger {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.seen = {};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Convert string to unique id
|
|
11
|
+
*/
|
|
12
|
+
slug(value) {
|
|
13
|
+
let slug = value
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.trim()
|
|
16
|
+
// remove html tags
|
|
17
|
+
.replace(/<[!\/a-z].*?>/ig, '')
|
|
18
|
+
// remove unwanted chars
|
|
19
|
+
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
|
|
20
|
+
.replace(/\s/g, '-');
|
|
21
|
+
|
|
22
|
+
if (this.seen.hasOwnProperty(slug)) {
|
|
23
|
+
const originalSlug = slug;
|
|
24
|
+
do {
|
|
25
|
+
this.seen[originalSlug]++;
|
|
26
|
+
slug = originalSlug + '-' + this.seen[originalSlug];
|
|
27
|
+
} while (this.seen.hasOwnProperty(slug));
|
|
28
|
+
}
|
|
29
|
+
this.seen[slug] = 0;
|
|
30
|
+
|
|
31
|
+
return slug;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextRenderer
|
|
3
|
+
* returns only the textual part of the token
|
|
4
|
+
*/
|
|
5
|
+
module.exports = class TextRenderer {
|
|
6
|
+
// no need for block level renderers
|
|
7
|
+
strong(text) {
|
|
8
|
+
return text;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
em(text) {
|
|
12
|
+
return text;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
codespan(text) {
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
del(text) {
|
|
20
|
+
return text;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
html(text) {
|
|
24
|
+
return text;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
text(text) {
|
|
28
|
+
return text;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
link(href, title, text) {
|
|
32
|
+
return '' + text;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
image(href, title, text) {
|
|
36
|
+
return '' + text;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
br() {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
};
|
package/src/defaults.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function getDefaults() {
|
|
2
|
+
return {
|
|
3
|
+
baseUrl: null,
|
|
4
|
+
breaks: false,
|
|
5
|
+
gfm: true,
|
|
6
|
+
headerIds: true,
|
|
7
|
+
headerPrefix: '',
|
|
8
|
+
highlight: null,
|
|
9
|
+
langPrefix: 'language-',
|
|
10
|
+
mangle: true,
|
|
11
|
+
pedantic: false,
|
|
12
|
+
renderer: null,
|
|
13
|
+
sanitize: false,
|
|
14
|
+
sanitizer: null,
|
|
15
|
+
silent: false,
|
|
16
|
+
smartLists: false,
|
|
17
|
+
smartypants: false,
|
|
18
|
+
xhtml: false
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function changeDefaults(newDefaults) {
|
|
23
|
+
module.exports.defaults = newDefaults;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
defaults: getDefaults(),
|
|
28
|
+
getDefaults,
|
|
29
|
+
changeDefaults
|
|
30
|
+
};
|
package/src/helpers.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers
|
|
3
|
+
*/
|
|
4
|
+
const escapeTest = /[&<>"']/;
|
|
5
|
+
const escapeReplace = /[&<>"']/g;
|
|
6
|
+
const escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
|
|
7
|
+
const escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
|
|
8
|
+
const escapeReplacements = {
|
|
9
|
+
'&': '&',
|
|
10
|
+
'<': '<',
|
|
11
|
+
'>': '>',
|
|
12
|
+
'"': '"',
|
|
13
|
+
"'": '''
|
|
14
|
+
};
|
|
15
|
+
const getEscapeReplacement = (ch) => escapeReplacements[ch];
|
|
16
|
+
function escape(html, encode) {
|
|
17
|
+
if (encode) {
|
|
18
|
+
if (escapeTest.test(html)) {
|
|
19
|
+
return html.replace(escapeReplace, getEscapeReplacement);
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
if (escapeTestNoEncode.test(html)) {
|
|
23
|
+
return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return html;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
|
|
31
|
+
|
|
32
|
+
function unescape(html) {
|
|
33
|
+
// explicitly match decimal, hex, and named HTML entities
|
|
34
|
+
return html.replace(unescapeTest, (_, n) => {
|
|
35
|
+
n = n.toLowerCase();
|
|
36
|
+
if (n === 'colon') return ':';
|
|
37
|
+
if (n.charAt(0) === '#') {
|
|
38
|
+
return n.charAt(1) === 'x'
|
|
39
|
+
? String.fromCharCode(parseInt(n.substring(2), 16))
|
|
40
|
+
: String.fromCharCode(+n.substring(1));
|
|
41
|
+
}
|
|
42
|
+
return '';
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const caret = /(^|[^\[])\^/g;
|
|
47
|
+
function edit(regex, opt) {
|
|
48
|
+
regex = regex.source || regex;
|
|
49
|
+
opt = opt || '';
|
|
50
|
+
const obj = {
|
|
51
|
+
replace: (name, val) => {
|
|
52
|
+
val = val.source || val;
|
|
53
|
+
val = val.replace(caret, '$1');
|
|
54
|
+
regex = regex.replace(name, val);
|
|
55
|
+
return obj;
|
|
56
|
+
},
|
|
57
|
+
getRegex: () => {
|
|
58
|
+
return new RegExp(regex, opt);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return obj;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const nonWordAndColonTest = /[^\w:]/g;
|
|
65
|
+
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
|
|
66
|
+
function cleanUrl(sanitize, base, href) {
|
|
67
|
+
if (sanitize) {
|
|
68
|
+
let prot;
|
|
69
|
+
try {
|
|
70
|
+
prot = decodeURIComponent(unescape(href))
|
|
71
|
+
.replace(nonWordAndColonTest, '')
|
|
72
|
+
.toLowerCase();
|
|
73
|
+
} catch (e) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (base && !originIndependentUrl.test(href)) {
|
|
81
|
+
href = resolveUrl(base, href);
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
href = encodeURI(href).replace(/%25/g, '%');
|
|
85
|
+
} catch (e) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return href;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const baseUrls = {};
|
|
92
|
+
const justDomain = /^[^:]+:\/*[^/]*$/;
|
|
93
|
+
const protocol = /^([^:]+:)[\s\S]*$/;
|
|
94
|
+
const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
|
|
95
|
+
|
|
96
|
+
function resolveUrl(base, href) {
|
|
97
|
+
if (!baseUrls[' ' + base]) {
|
|
98
|
+
// we can ignore everything in base after the last slash of its path component,
|
|
99
|
+
// but we might need to add _that_
|
|
100
|
+
// https://tools.ietf.org/html/rfc3986#section-3
|
|
101
|
+
if (justDomain.test(base)) {
|
|
102
|
+
baseUrls[' ' + base] = base + '/';
|
|
103
|
+
} else {
|
|
104
|
+
baseUrls[' ' + base] = rtrim(base, '/', true);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
base = baseUrls[' ' + base];
|
|
108
|
+
const relativeBase = base.indexOf(':') === -1;
|
|
109
|
+
|
|
110
|
+
if (href.substring(0, 2) === '//') {
|
|
111
|
+
if (relativeBase) {
|
|
112
|
+
return href;
|
|
113
|
+
}
|
|
114
|
+
return base.replace(protocol, '$1') + href;
|
|
115
|
+
} else if (href.charAt(0) === '/') {
|
|
116
|
+
if (relativeBase) {
|
|
117
|
+
return href;
|
|
118
|
+
}
|
|
119
|
+
return base.replace(domain, '$1') + href;
|
|
120
|
+
} else {
|
|
121
|
+
return base + href;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const noopTest = { exec: function noopTest() {} };
|
|
126
|
+
|
|
127
|
+
function merge(obj) {
|
|
128
|
+
let i = 1,
|
|
129
|
+
target,
|
|
130
|
+
key;
|
|
131
|
+
|
|
132
|
+
for (; i < arguments.length; i++) {
|
|
133
|
+
target = arguments[i];
|
|
134
|
+
for (key in target) {
|
|
135
|
+
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|
136
|
+
obj[key] = target[key];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return obj;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function splitCells(tableRow, count) {
|
|
145
|
+
// ensure that every cell-delimiting pipe has a space
|
|
146
|
+
// before it to distinguish it from an escaped pipe
|
|
147
|
+
const row = tableRow.replace(/\|/g, (match, offset, str) => {
|
|
148
|
+
let escaped = false,
|
|
149
|
+
curr = offset;
|
|
150
|
+
while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
|
|
151
|
+
if (escaped) {
|
|
152
|
+
// odd number of slashes means | is escaped
|
|
153
|
+
// so we leave it alone
|
|
154
|
+
return '|';
|
|
155
|
+
} else {
|
|
156
|
+
// add space before unescaped |
|
|
157
|
+
return ' |';
|
|
158
|
+
}
|
|
159
|
+
}),
|
|
160
|
+
cells = row.split(/ \|/);
|
|
161
|
+
let i = 0;
|
|
162
|
+
|
|
163
|
+
if (cells.length > count) {
|
|
164
|
+
cells.splice(count);
|
|
165
|
+
} else {
|
|
166
|
+
while (cells.length < count) cells.push('');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (; i < cells.length; i++) {
|
|
170
|
+
// leading or trailing whitespace is ignored per the gfm spec
|
|
171
|
+
cells[i] = cells[i].trim().replace(/\\\|/g, '|');
|
|
172
|
+
}
|
|
173
|
+
return cells;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
|
|
177
|
+
// /c*$/ is vulnerable to REDOS.
|
|
178
|
+
// invert: Remove suffix of non-c chars instead. Default falsey.
|
|
179
|
+
function rtrim(str, c, invert) {
|
|
180
|
+
const l = str.length;
|
|
181
|
+
if (l === 0) {
|
|
182
|
+
return '';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Length of suffix matching the invert condition.
|
|
186
|
+
let suffLen = 0;
|
|
187
|
+
|
|
188
|
+
// Step left until we fail to match the invert condition.
|
|
189
|
+
while (suffLen < l) {
|
|
190
|
+
const currChar = str.charAt(l - suffLen - 1);
|
|
191
|
+
if (currChar === c && !invert) {
|
|
192
|
+
suffLen++;
|
|
193
|
+
} else if (currChar !== c && invert) {
|
|
194
|
+
suffLen++;
|
|
195
|
+
} else {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return str.substr(0, l - suffLen);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function findClosingBracket(str, b) {
|
|
204
|
+
if (str.indexOf(b[1]) === -1) {
|
|
205
|
+
return -1;
|
|
206
|
+
}
|
|
207
|
+
const l = str.length;
|
|
208
|
+
let level = 0,
|
|
209
|
+
i = 0;
|
|
210
|
+
for (; i < l; i++) {
|
|
211
|
+
if (str[i] === '\\') {
|
|
212
|
+
i++;
|
|
213
|
+
} else if (str[i] === b[0]) {
|
|
214
|
+
level++;
|
|
215
|
+
} else if (str[i] === b[1]) {
|
|
216
|
+
level--;
|
|
217
|
+
if (level < 0) {
|
|
218
|
+
return i;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return -1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function checkSanitizeDeprecation(opt) {
|
|
226
|
+
if (opt && opt.sanitize && !opt.silent) {
|
|
227
|
+
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');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
module.exports = {
|
|
232
|
+
escape,
|
|
233
|
+
unescape,
|
|
234
|
+
edit,
|
|
235
|
+
cleanUrl,
|
|
236
|
+
resolveUrl,
|
|
237
|
+
noopTest,
|
|
238
|
+
merge,
|
|
239
|
+
splitCells,
|
|
240
|
+
rtrim,
|
|
241
|
+
findClosingBracket,
|
|
242
|
+
checkSanitizeDeprecation
|
|
243
|
+
};
|
package/src/marked.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const Lexer = require('./Lexer.js');
|
|
2
|
+
const Parser = require('./Parser.js');
|
|
3
|
+
const Renderer = require('./Renderer.js');
|
|
4
|
+
const TextRenderer = require('./TextRenderer.js');
|
|
5
|
+
const InlineLexer = require('./InlineLexer.js');
|
|
6
|
+
const Slugger = require('./Slugger.js');
|
|
7
|
+
const {
|
|
8
|
+
merge,
|
|
9
|
+
checkSanitizeDeprecation,
|
|
10
|
+
escape
|
|
11
|
+
} = require('./helpers.js');
|
|
12
|
+
const {
|
|
13
|
+
getDefaults,
|
|
14
|
+
changeDefaults,
|
|
15
|
+
defaults
|
|
16
|
+
} = require('./defaults.js');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Marked
|
|
20
|
+
*/
|
|
21
|
+
function marked(src, opt, callback) {
|
|
22
|
+
// throw error in case of non string input
|
|
23
|
+
if (typeof src === 'undefined' || src === null) {
|
|
24
|
+
throw new Error('marked(): input parameter is undefined or null');
|
|
25
|
+
}
|
|
26
|
+
if (typeof src !== 'string') {
|
|
27
|
+
throw new Error('marked(): input parameter is of type '
|
|
28
|
+
+ Object.prototype.toString.call(src) + ', string expected');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (callback || typeof opt === 'function') {
|
|
32
|
+
if (!callback) {
|
|
33
|
+
callback = opt;
|
|
34
|
+
opt = null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
opt = merge({}, marked.defaults, opt || {});
|
|
38
|
+
checkSanitizeDeprecation(opt);
|
|
39
|
+
const highlight = opt.highlight;
|
|
40
|
+
let tokens,
|
|
41
|
+
pending,
|
|
42
|
+
i = 0;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
tokens = Lexer.lex(src, opt);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
return callback(e);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pending = tokens.length;
|
|
51
|
+
|
|
52
|
+
const done = function(err) {
|
|
53
|
+
if (err) {
|
|
54
|
+
opt.highlight = highlight;
|
|
55
|
+
return callback(err);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let out;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
out = Parser.parse(tokens, opt);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
err = e;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
opt.highlight = highlight;
|
|
67
|
+
|
|
68
|
+
return err
|
|
69
|
+
? callback(err)
|
|
70
|
+
: callback(null, out);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (!highlight || highlight.length < 3) {
|
|
74
|
+
return done();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
delete opt.highlight;
|
|
78
|
+
|
|
79
|
+
if (!pending) return done();
|
|
80
|
+
|
|
81
|
+
for (; i < tokens.length; i++) {
|
|
82
|
+
(function(token) {
|
|
83
|
+
if (token.type !== 'code') {
|
|
84
|
+
return --pending || done();
|
|
85
|
+
}
|
|
86
|
+
return highlight(token.text, token.lang, function(err, code) {
|
|
87
|
+
if (err) return done(err);
|
|
88
|
+
if (code == null || code === token.text) {
|
|
89
|
+
return --pending || done();
|
|
90
|
+
}
|
|
91
|
+
token.text = code;
|
|
92
|
+
token.escaped = true;
|
|
93
|
+
--pending || done();
|
|
94
|
+
});
|
|
95
|
+
})(tokens[i]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
opt = merge({}, marked.defaults, opt || {});
|
|
102
|
+
checkSanitizeDeprecation(opt);
|
|
103
|
+
return Parser.parse(Lexer.lex(src, opt), opt);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
|
106
|
+
if ((opt || marked.defaults).silent) {
|
|
107
|
+
return '<p>An error occurred:</p><pre>'
|
|
108
|
+
+ escape(e.message + '', true)
|
|
109
|
+
+ '</pre>';
|
|
110
|
+
}
|
|
111
|
+
throw e;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Options
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
marked.options =
|
|
120
|
+
marked.setOptions = function(opt) {
|
|
121
|
+
merge(marked.defaults, opt);
|
|
122
|
+
changeDefaults(marked.defaults);
|
|
123
|
+
return marked;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
marked.getDefaults = getDefaults;
|
|
127
|
+
|
|
128
|
+
marked.defaults = defaults;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Expose
|
|
132
|
+
*/
|
|
133
|
+
|
|
134
|
+
marked.Parser = Parser;
|
|
135
|
+
marked.parser = Parser.parse;
|
|
136
|
+
|
|
137
|
+
marked.Renderer = Renderer;
|
|
138
|
+
marked.TextRenderer = TextRenderer;
|
|
139
|
+
|
|
140
|
+
marked.Lexer = Lexer;
|
|
141
|
+
marked.lexer = Lexer.lex;
|
|
142
|
+
|
|
143
|
+
marked.InlineLexer = InlineLexer;
|
|
144
|
+
marked.inlineLexer = InlineLexer.output;
|
|
145
|
+
|
|
146
|
+
marked.Slugger = Slugger;
|
|
147
|
+
|
|
148
|
+
marked.parse = marked;
|
|
149
|
+
|
|
150
|
+
module.exports = marked;
|