marked 0.8.0 → 1.1.0
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 +2 -2
- package/lib/marked.esm.js +1370 -833
- package/lib/marked.js +1731 -1021
- package/marked.min.js +2 -2
- package/package.json +15 -14
- package/src/Lexer.js +314 -282
- package/src/Parser.js +206 -157
- package/src/Renderer.js +21 -21
- package/src/Slugger.js +4 -1
- package/src/TextRenderer.js +4 -0
- package/src/Tokenizer.js +633 -0
- package/src/defaults.js +2 -0
- package/src/marked.js +124 -42
- package/src/rules.js +34 -7
- package/src/InlineLexer.js +0 -293
package/src/marked.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const Lexer = require('./Lexer.js');
|
|
2
2
|
const Parser = require('./Parser.js');
|
|
3
|
+
const Tokenizer = require('./Tokenizer.js');
|
|
3
4
|
const Renderer = require('./Renderer.js');
|
|
4
5
|
const TextRenderer = require('./TextRenderer.js');
|
|
5
|
-
const InlineLexer = require('./InlineLexer.js');
|
|
6
6
|
const Slugger = require('./Slugger.js');
|
|
7
7
|
const {
|
|
8
8
|
merge,
|
|
@@ -28,18 +28,17 @@ function marked(src, opt, callback) {
|
|
|
28
28
|
+ Object.prototype.toString.call(src) + ', string expected');
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
if (typeof opt === 'function') {
|
|
32
|
+
callback = opt;
|
|
33
|
+
opt = null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
opt = merge({}, marked.defaults, opt || {});
|
|
37
|
+
checkSanitizeDeprecation(opt);
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
checkSanitizeDeprecation(opt);
|
|
39
|
+
if (callback) {
|
|
39
40
|
const highlight = opt.highlight;
|
|
40
|
-
let tokens
|
|
41
|
-
pending,
|
|
42
|
-
i = 0;
|
|
41
|
+
let tokens;
|
|
43
42
|
|
|
44
43
|
try {
|
|
45
44
|
tokens = Lexer.lex(src, opt);
|
|
@@ -47,20 +46,15 @@ function marked(src, opt, callback) {
|
|
|
47
46
|
return callback(e);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
pending = tokens.length;
|
|
51
|
-
|
|
52
49
|
const done = function(err) {
|
|
53
|
-
if (err) {
|
|
54
|
-
opt.highlight = highlight;
|
|
55
|
-
return callback(err);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
50
|
let out;
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
if (!err) {
|
|
53
|
+
try {
|
|
54
|
+
out = Parser.parse(tokens, opt);
|
|
55
|
+
} catch (e) {
|
|
56
|
+
err = e;
|
|
57
|
+
}
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
opt.highlight = highlight;
|
|
@@ -76,34 +70,45 @@ function marked(src, opt, callback) {
|
|
|
76
70
|
|
|
77
71
|
delete opt.highlight;
|
|
78
72
|
|
|
79
|
-
if (!
|
|
73
|
+
if (!tokens.length) return done();
|
|
80
74
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
75
|
+
let pending = 0;
|
|
76
|
+
marked.walkTokens(tokens, function(token) {
|
|
77
|
+
if (token.type === 'code') {
|
|
78
|
+
pending++;
|
|
79
|
+
highlight(token.text, token.lang, function(err, code) {
|
|
80
|
+
if (err) {
|
|
81
|
+
return done(err);
|
|
82
|
+
}
|
|
83
|
+
if (code != null && code !== token.text) {
|
|
84
|
+
token.text = code;
|
|
85
|
+
token.escaped = true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
pending--;
|
|
89
|
+
if (pending === 0) {
|
|
90
|
+
done();
|
|
90
91
|
}
|
|
91
|
-
token.text = code;
|
|
92
|
-
token.escaped = true;
|
|
93
|
-
--pending || done();
|
|
94
92
|
});
|
|
95
|
-
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (pending === 0) {
|
|
97
|
+
done();
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
return;
|
|
99
101
|
}
|
|
102
|
+
|
|
100
103
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
const tokens = Lexer.lex(src, opt);
|
|
105
|
+
if (opt.walkTokens) {
|
|
106
|
+
marked.walkTokens(tokens, opt.walkTokens);
|
|
107
|
+
}
|
|
108
|
+
return Parser.parse(tokens, opt);
|
|
104
109
|
} catch (e) {
|
|
105
110
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
|
106
|
-
if (
|
|
111
|
+
if (opt.silent) {
|
|
107
112
|
return '<p>An error occurred:</p><pre>'
|
|
108
113
|
+ escape(e.message + '', true)
|
|
109
114
|
+ '</pre>';
|
|
@@ -127,6 +132,84 @@ marked.getDefaults = getDefaults;
|
|
|
127
132
|
|
|
128
133
|
marked.defaults = defaults;
|
|
129
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Use Extension
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
marked.use = function(extension) {
|
|
140
|
+
const opts = merge({}, extension);
|
|
141
|
+
if (extension.renderer) {
|
|
142
|
+
const renderer = marked.defaults.renderer || new Renderer();
|
|
143
|
+
for (const prop in extension.renderer) {
|
|
144
|
+
const prevRenderer = renderer[prop];
|
|
145
|
+
renderer[prop] = (...args) => {
|
|
146
|
+
let ret = extension.renderer[prop].apply(renderer, args);
|
|
147
|
+
if (ret === false) {
|
|
148
|
+
ret = prevRenderer.apply(renderer, args);
|
|
149
|
+
}
|
|
150
|
+
return ret;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
opts.renderer = renderer;
|
|
154
|
+
}
|
|
155
|
+
if (extension.tokenizer) {
|
|
156
|
+
const tokenizer = marked.defaults.tokenizer || new Tokenizer();
|
|
157
|
+
for (const prop in extension.tokenizer) {
|
|
158
|
+
const prevTokenizer = tokenizer[prop];
|
|
159
|
+
tokenizer[prop] = (...args) => {
|
|
160
|
+
let ret = extension.tokenizer[prop].apply(tokenizer, args);
|
|
161
|
+
if (ret === false) {
|
|
162
|
+
ret = prevTokenizer.apply(tokenizer, args);
|
|
163
|
+
}
|
|
164
|
+
return ret;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
opts.tokenizer = tokenizer;
|
|
168
|
+
}
|
|
169
|
+
if (extension.walkTokens) {
|
|
170
|
+
const walkTokens = marked.defaults.walkTokens;
|
|
171
|
+
opts.walkTokens = (token) => {
|
|
172
|
+
extension.walkTokens(token);
|
|
173
|
+
if (walkTokens) {
|
|
174
|
+
walkTokens(token);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
marked.setOptions(opts);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Run callback for every token
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
marked.walkTokens = function(tokens, callback) {
|
|
186
|
+
for (const token of tokens) {
|
|
187
|
+
callback(token);
|
|
188
|
+
switch (token.type) {
|
|
189
|
+
case 'table': {
|
|
190
|
+
for (const cell of token.tokens.header) {
|
|
191
|
+
marked.walkTokens(cell, callback);
|
|
192
|
+
}
|
|
193
|
+
for (const row of token.tokens.cells) {
|
|
194
|
+
for (const cell of row) {
|
|
195
|
+
marked.walkTokens(cell, callback);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case 'list': {
|
|
201
|
+
marked.walkTokens(token.items, callback);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
default: {
|
|
205
|
+
if (token.tokens) {
|
|
206
|
+
marked.walkTokens(token.tokens, callback);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
130
213
|
/**
|
|
131
214
|
* Expose
|
|
132
215
|
*/
|
|
@@ -140,8 +223,7 @@ marked.TextRenderer = TextRenderer;
|
|
|
140
223
|
marked.Lexer = Lexer;
|
|
141
224
|
marked.lexer = Lexer.lex;
|
|
142
225
|
|
|
143
|
-
marked.
|
|
144
|
-
marked.inlineLexer = InlineLexer.output;
|
|
226
|
+
marked.Tokenizer = Tokenizer;
|
|
145
227
|
|
|
146
228
|
marked.Slugger = Slugger;
|
|
147
229
|
|
package/src/rules.js
CHANGED
|
@@ -10,7 +10,7 @@ const {
|
|
|
10
10
|
const block = {
|
|
11
11
|
newline: /^\n+/,
|
|
12
12
|
code: /^( {4}[^\n]+\n*)+/,
|
|
13
|
-
fences: /^ {0,3}(`{3,}|~{3,})([
|
|
13
|
+
fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
|
|
14
14
|
hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
|
|
15
15
|
heading: /^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,
|
|
16
16
|
blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
|
|
@@ -69,10 +69,10 @@ block.html = edit(block.html, 'i')
|
|
|
69
69
|
|
|
70
70
|
block.paragraph = edit(block._paragraph)
|
|
71
71
|
.replace('hr', block.hr)
|
|
72
|
-
.replace('heading', ' {0,3}#{1,6}
|
|
72
|
+
.replace('heading', ' {0,3}#{1,6} ')
|
|
73
73
|
.replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
|
|
74
74
|
.replace('blockquote', ' {0,3}>')
|
|
75
|
-
.replace('fences', ' {0,3}(?:`{3,}|~{3,})[
|
|
75
|
+
.replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
|
|
76
76
|
.replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
77
77
|
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
|
|
78
78
|
.replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
|
|
@@ -93,10 +93,36 @@ block.normal = merge({}, block);
|
|
|
93
93
|
*/
|
|
94
94
|
|
|
95
95
|
block.gfm = merge({}, block.normal, {
|
|
96
|
-
nptable:
|
|
97
|
-
|
|
96
|
+
nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
|
|
97
|
+
+ ' *([-:]+ *\\|[-| :]*)' // Align
|
|
98
|
+
+ '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)', // Cells
|
|
99
|
+
table: '^ *\\|(.+)\\n' // Header
|
|
100
|
+
+ ' *\\|?( *[-:]+[-| :]*)' // Align
|
|
101
|
+
+ '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
|
|
98
102
|
});
|
|
99
103
|
|
|
104
|
+
block.gfm.nptable = edit(block.gfm.nptable)
|
|
105
|
+
.replace('hr', block.hr)
|
|
106
|
+
.replace('heading', ' {0,3}#{1,6} ')
|
|
107
|
+
.replace('blockquote', ' {0,3}>')
|
|
108
|
+
.replace('code', ' {4}[^\\n]')
|
|
109
|
+
.replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
|
|
110
|
+
.replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
111
|
+
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
|
|
112
|
+
.replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
|
|
113
|
+
.getRegex();
|
|
114
|
+
|
|
115
|
+
block.gfm.table = edit(block.gfm.table)
|
|
116
|
+
.replace('hr', block.hr)
|
|
117
|
+
.replace('heading', ' {0,3}#{1,6} ')
|
|
118
|
+
.replace('blockquote', ' {0,3}>')
|
|
119
|
+
.replace('code', ' {4}[^\\n]')
|
|
120
|
+
.replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
|
|
121
|
+
.replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
|
|
122
|
+
.replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
|
|
123
|
+
.replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
|
|
124
|
+
.getRegex();
|
|
125
|
+
|
|
100
126
|
/**
|
|
101
127
|
* Pedantic grammar (original John Gruber's loose markdown specification)
|
|
102
128
|
*/
|
|
@@ -143,7 +169,7 @@ const inline = {
|
|
|
143
169
|
reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
|
|
144
170
|
nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
|
|
145
171
|
strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,
|
|
146
|
-
em: /^_([^\s_])_(?!_)
|
|
172
|
+
em: /^_([^\s_])_(?!_)|^_([^\s_<][\s\S]*?[^\s_])_(?!_|[^\s,punctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\s,punctuation])|^\*([^\s*<\[])\*(?!\*)|^\*([^\s<"][\s\S]*?[^\s\[\*])\*(?![\]`punctuation])|^\*([^\s*"<\[][\s\S]*[^\s])\*(?!\*)/,
|
|
147
173
|
code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
|
|
148
174
|
br: /^( {2,}|\\)\n(?!\s*$)/,
|
|
149
175
|
del: noopTest,
|
|
@@ -152,7 +178,8 @@ const inline = {
|
|
|
152
178
|
|
|
153
179
|
// list of punctuation marks from common mark spec
|
|
154
180
|
// without ` and ] to workaround Rule 17 (inline code blocks/links)
|
|
155
|
-
|
|
181
|
+
// without , to work around example 393
|
|
182
|
+
inline._punctuation = '!"#$%&\'()*+\\-./:;<=>?@\\[^_{|}~';
|
|
156
183
|
inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex();
|
|
157
184
|
|
|
158
185
|
inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
|
package/src/InlineLexer.js
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
const Renderer = require('./Renderer.js');
|
|
2
|
-
const { defaults } = require('./defaults.js');
|
|
3
|
-
const { inline } = require('./rules.js');
|
|
4
|
-
const {
|
|
5
|
-
findClosingBracket,
|
|
6
|
-
escape
|
|
7
|
-
} = require('./helpers.js');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Inline Lexer & Compiler
|
|
11
|
-
*/
|
|
12
|
-
module.exports = class InlineLexer {
|
|
13
|
-
constructor(links, options) {
|
|
14
|
-
this.options = options || defaults;
|
|
15
|
-
this.links = links;
|
|
16
|
-
this.rules = inline.normal;
|
|
17
|
-
this.options.renderer = this.options.renderer || new Renderer();
|
|
18
|
-
this.renderer = this.options.renderer;
|
|
19
|
-
this.renderer.options = this.options;
|
|
20
|
-
|
|
21
|
-
if (!this.links) {
|
|
22
|
-
throw new Error('Tokens array requires a `links` property.');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (this.options.pedantic) {
|
|
26
|
-
this.rules = inline.pedantic;
|
|
27
|
-
} else if (this.options.gfm) {
|
|
28
|
-
if (this.options.breaks) {
|
|
29
|
-
this.rules = inline.breaks;
|
|
30
|
-
} else {
|
|
31
|
-
this.rules = inline.gfm;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Expose Inline Rules
|
|
38
|
-
*/
|
|
39
|
-
static get rules() {
|
|
40
|
-
return inline;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Static Lexing/Compiling Method
|
|
45
|
-
*/
|
|
46
|
-
static output(src, links, options) {
|
|
47
|
-
const inline = new InlineLexer(links, options);
|
|
48
|
-
return inline.output(src);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Lexing/Compiling
|
|
53
|
-
*/
|
|
54
|
-
output(src) {
|
|
55
|
-
let out = '',
|
|
56
|
-
link,
|
|
57
|
-
text,
|
|
58
|
-
href,
|
|
59
|
-
title,
|
|
60
|
-
cap,
|
|
61
|
-
prevCapZero;
|
|
62
|
-
|
|
63
|
-
while (src) {
|
|
64
|
-
// escape
|
|
65
|
-
if (cap = this.rules.escape.exec(src)) {
|
|
66
|
-
src = src.substring(cap[0].length);
|
|
67
|
-
out += escape(cap[1]);
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// tag
|
|
72
|
-
if (cap = this.rules.tag.exec(src)) {
|
|
73
|
-
if (!this.inLink && /^<a /i.test(cap[0])) {
|
|
74
|
-
this.inLink = true;
|
|
75
|
-
} else if (this.inLink && /^<\/a>/i.test(cap[0])) {
|
|
76
|
-
this.inLink = false;
|
|
77
|
-
}
|
|
78
|
-
if (!this.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
|
|
79
|
-
this.inRawBlock = true;
|
|
80
|
-
} else if (this.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
|
|
81
|
-
this.inRawBlock = false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
src = src.substring(cap[0].length);
|
|
85
|
-
out += this.options.sanitize
|
|
86
|
-
? this.options.sanitizer
|
|
87
|
-
? this.options.sanitizer(cap[0])
|
|
88
|
-
: escape(cap[0])
|
|
89
|
-
: cap[0];
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// link
|
|
94
|
-
if (cap = this.rules.link.exec(src)) {
|
|
95
|
-
const lastParenIndex = findClosingBracket(cap[2], '()');
|
|
96
|
-
if (lastParenIndex > -1) {
|
|
97
|
-
const start = cap[0].indexOf('!') === 0 ? 5 : 4;
|
|
98
|
-
const linkLen = start + cap[1].length + lastParenIndex;
|
|
99
|
-
cap[2] = cap[2].substring(0, lastParenIndex);
|
|
100
|
-
cap[0] = cap[0].substring(0, linkLen).trim();
|
|
101
|
-
cap[3] = '';
|
|
102
|
-
}
|
|
103
|
-
src = src.substring(cap[0].length);
|
|
104
|
-
this.inLink = true;
|
|
105
|
-
href = cap[2];
|
|
106
|
-
if (this.options.pedantic) {
|
|
107
|
-
link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
|
|
108
|
-
|
|
109
|
-
if (link) {
|
|
110
|
-
href = link[1];
|
|
111
|
-
title = link[3];
|
|
112
|
-
} else {
|
|
113
|
-
title = '';
|
|
114
|
-
}
|
|
115
|
-
} else {
|
|
116
|
-
title = cap[3] ? cap[3].slice(1, -1) : '';
|
|
117
|
-
}
|
|
118
|
-
href = href.trim().replace(/^<([\s\S]*)>$/, '$1');
|
|
119
|
-
out += this.outputLink(cap, {
|
|
120
|
-
href: InlineLexer.escapes(href),
|
|
121
|
-
title: InlineLexer.escapes(title)
|
|
122
|
-
});
|
|
123
|
-
this.inLink = false;
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// reflink, nolink
|
|
128
|
-
if ((cap = this.rules.reflink.exec(src))
|
|
129
|
-
|| (cap = this.rules.nolink.exec(src))) {
|
|
130
|
-
src = src.substring(cap[0].length);
|
|
131
|
-
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
|
|
132
|
-
link = this.links[link.toLowerCase()];
|
|
133
|
-
if (!link || !link.href) {
|
|
134
|
-
out += cap[0].charAt(0);
|
|
135
|
-
src = cap[0].substring(1) + src;
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
this.inLink = true;
|
|
139
|
-
out += this.outputLink(cap, link);
|
|
140
|
-
this.inLink = false;
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// strong
|
|
145
|
-
if (cap = this.rules.strong.exec(src)) {
|
|
146
|
-
src = src.substring(cap[0].length);
|
|
147
|
-
out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1]));
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// em
|
|
152
|
-
if (cap = this.rules.em.exec(src)) {
|
|
153
|
-
src = src.substring(cap[0].length);
|
|
154
|
-
out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// code
|
|
159
|
-
if (cap = this.rules.code.exec(src)) {
|
|
160
|
-
src = src.substring(cap[0].length);
|
|
161
|
-
out += this.renderer.codespan(escape(cap[2].trim(), true));
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// br
|
|
166
|
-
if (cap = this.rules.br.exec(src)) {
|
|
167
|
-
src = src.substring(cap[0].length);
|
|
168
|
-
out += this.renderer.br();
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// del (gfm)
|
|
173
|
-
if (cap = this.rules.del.exec(src)) {
|
|
174
|
-
src = src.substring(cap[0].length);
|
|
175
|
-
out += this.renderer.del(this.output(cap[1]));
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// autolink
|
|
180
|
-
if (cap = this.rules.autolink.exec(src)) {
|
|
181
|
-
src = src.substring(cap[0].length);
|
|
182
|
-
if (cap[2] === '@') {
|
|
183
|
-
text = escape(this.mangle(cap[1]));
|
|
184
|
-
href = 'mailto:' + text;
|
|
185
|
-
} else {
|
|
186
|
-
text = escape(cap[1]);
|
|
187
|
-
href = text;
|
|
188
|
-
}
|
|
189
|
-
out += this.renderer.link(href, null, text);
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// url (gfm)
|
|
194
|
-
if (!this.inLink && (cap = this.rules.url.exec(src))) {
|
|
195
|
-
if (cap[2] === '@') {
|
|
196
|
-
text = escape(cap[0]);
|
|
197
|
-
href = 'mailto:' + text;
|
|
198
|
-
} else {
|
|
199
|
-
// do extended autolink path validation
|
|
200
|
-
do {
|
|
201
|
-
prevCapZero = cap[0];
|
|
202
|
-
cap[0] = this.rules._backpedal.exec(cap[0])[0];
|
|
203
|
-
} while (prevCapZero !== cap[0]);
|
|
204
|
-
text = escape(cap[0]);
|
|
205
|
-
if (cap[1] === 'www.') {
|
|
206
|
-
href = 'http://' + text;
|
|
207
|
-
} else {
|
|
208
|
-
href = text;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
src = src.substring(cap[0].length);
|
|
212
|
-
out += this.renderer.link(href, null, text);
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// text
|
|
217
|
-
if (cap = this.rules.text.exec(src)) {
|
|
218
|
-
src = src.substring(cap[0].length);
|
|
219
|
-
if (this.inRawBlock) {
|
|
220
|
-
out += this.renderer.text(this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0]);
|
|
221
|
-
} else {
|
|
222
|
-
out += this.renderer.text(escape(this.smartypants(cap[0])));
|
|
223
|
-
}
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (src) {
|
|
228
|
-
throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return out;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
static escapes(text) {
|
|
236
|
-
return text ? text.replace(InlineLexer.rules._escapes, '$1') : text;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Compile Link
|
|
241
|
-
*/
|
|
242
|
-
outputLink(cap, link) {
|
|
243
|
-
const href = link.href,
|
|
244
|
-
title = link.title ? escape(link.title) : null;
|
|
245
|
-
|
|
246
|
-
return cap[0].charAt(0) !== '!'
|
|
247
|
-
? this.renderer.link(href, title, this.output(cap[1]))
|
|
248
|
-
: this.renderer.image(href, title, escape(cap[1]));
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Smartypants Transformations
|
|
253
|
-
*/
|
|
254
|
-
smartypants(text) {
|
|
255
|
-
if (!this.options.smartypants) return text;
|
|
256
|
-
return text
|
|
257
|
-
// em-dashes
|
|
258
|
-
.replace(/---/g, '\u2014')
|
|
259
|
-
// en-dashes
|
|
260
|
-
.replace(/--/g, '\u2013')
|
|
261
|
-
// opening singles
|
|
262
|
-
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
|
263
|
-
// closing singles & apostrophes
|
|
264
|
-
.replace(/'/g, '\u2019')
|
|
265
|
-
// opening doubles
|
|
266
|
-
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
|
267
|
-
// closing doubles
|
|
268
|
-
.replace(/"/g, '\u201d')
|
|
269
|
-
// ellipses
|
|
270
|
-
.replace(/\.{3}/g, '\u2026');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Mangle Links
|
|
275
|
-
*/
|
|
276
|
-
mangle(text) {
|
|
277
|
-
if (!this.options.mangle) return text;
|
|
278
|
-
const l = text.length;
|
|
279
|
-
let out = '',
|
|
280
|
-
i = 0,
|
|
281
|
-
ch;
|
|
282
|
-
|
|
283
|
-
for (; i < l; i++) {
|
|
284
|
-
ch = text.charCodeAt(i);
|
|
285
|
-
if (Math.random() > 0.5) {
|
|
286
|
-
ch = 'x' + ch.toString(16);
|
|
287
|
-
}
|
|
288
|
-
out += '&#' + ch + ';';
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return out;
|
|
292
|
-
}
|
|
293
|
-
};
|