marked 0.8.1 → 1.1.1
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/lib/marked.esm.js +1475 -845
- package/lib/marked.js +1825 -1022
- package/marked.min.js +1 -1
- package/package.json +18 -16
- package/src/Lexer.js +334 -281
- 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 +659 -0
- package/src/defaults.js +2 -0
- package/src/marked.js +128 -44
- package/src/rules.js +81 -10
- 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,47 @@ function marked(src, opt, callback) {
|
|
|
76
70
|
|
|
77
71
|
delete opt.highlight;
|
|
78
72
|
|
|
79
|
-
if (!
|
|
73
|
+
if (!tokens.length) return done();
|
|
74
|
+
|
|
75
|
+
let pending = 0;
|
|
76
|
+
marked.walkTokens(tokens, function(token) {
|
|
77
|
+
if (token.type === 'code') {
|
|
78
|
+
pending++;
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
highlight(token.text, token.lang, function(err, code) {
|
|
81
|
+
if (err) {
|
|
82
|
+
return done(err);
|
|
83
|
+
}
|
|
84
|
+
if (code != null && code !== token.text) {
|
|
85
|
+
token.text = code;
|
|
86
|
+
token.escaped = true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
pending--;
|
|
90
|
+
if (pending === 0) {
|
|
91
|
+
done();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}, 0);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
80
97
|
|
|
81
|
-
|
|
82
|
-
(
|
|
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]);
|
|
98
|
+
if (pending === 0) {
|
|
99
|
+
done();
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
return;
|
|
99
103
|
}
|
|
104
|
+
|
|
100
105
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
const tokens = Lexer.lex(src, opt);
|
|
107
|
+
if (opt.walkTokens) {
|
|
108
|
+
marked.walkTokens(tokens, opt.walkTokens);
|
|
109
|
+
}
|
|
110
|
+
return Parser.parse(tokens, opt);
|
|
104
111
|
} catch (e) {
|
|
105
112
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
|
106
|
-
if (
|
|
113
|
+
if (opt.silent) {
|
|
107
114
|
return '<p>An error occurred:</p><pre>'
|
|
108
115
|
+ escape(e.message + '', true)
|
|
109
116
|
+ '</pre>';
|
|
@@ -127,6 +134,84 @@ marked.getDefaults = getDefaults;
|
|
|
127
134
|
|
|
128
135
|
marked.defaults = defaults;
|
|
129
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Use Extension
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
marked.use = function(extension) {
|
|
142
|
+
const opts = merge({}, extension);
|
|
143
|
+
if (extension.renderer) {
|
|
144
|
+
const renderer = marked.defaults.renderer || new Renderer();
|
|
145
|
+
for (const prop in extension.renderer) {
|
|
146
|
+
const prevRenderer = renderer[prop];
|
|
147
|
+
renderer[prop] = (...args) => {
|
|
148
|
+
let ret = extension.renderer[prop].apply(renderer, args);
|
|
149
|
+
if (ret === false) {
|
|
150
|
+
ret = prevRenderer.apply(renderer, args);
|
|
151
|
+
}
|
|
152
|
+
return ret;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
opts.renderer = renderer;
|
|
156
|
+
}
|
|
157
|
+
if (extension.tokenizer) {
|
|
158
|
+
const tokenizer = marked.defaults.tokenizer || new Tokenizer();
|
|
159
|
+
for (const prop in extension.tokenizer) {
|
|
160
|
+
const prevTokenizer = tokenizer[prop];
|
|
161
|
+
tokenizer[prop] = (...args) => {
|
|
162
|
+
let ret = extension.tokenizer[prop].apply(tokenizer, args);
|
|
163
|
+
if (ret === false) {
|
|
164
|
+
ret = prevTokenizer.apply(tokenizer, args);
|
|
165
|
+
}
|
|
166
|
+
return ret;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
opts.tokenizer = tokenizer;
|
|
170
|
+
}
|
|
171
|
+
if (extension.walkTokens) {
|
|
172
|
+
const walkTokens = marked.defaults.walkTokens;
|
|
173
|
+
opts.walkTokens = (token) => {
|
|
174
|
+
extension.walkTokens(token);
|
|
175
|
+
if (walkTokens) {
|
|
176
|
+
walkTokens(token);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
marked.setOptions(opts);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Run callback for every token
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
marked.walkTokens = function(tokens, callback) {
|
|
188
|
+
for (const token of tokens) {
|
|
189
|
+
callback(token);
|
|
190
|
+
switch (token.type) {
|
|
191
|
+
case 'table': {
|
|
192
|
+
for (const cell of token.tokens.header) {
|
|
193
|
+
marked.walkTokens(cell, callback);
|
|
194
|
+
}
|
|
195
|
+
for (const row of token.tokens.cells) {
|
|
196
|
+
for (const cell of row) {
|
|
197
|
+
marked.walkTokens(cell, callback);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
case 'list': {
|
|
203
|
+
marked.walkTokens(token.items, callback);
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
default: {
|
|
207
|
+
if (token.tokens) {
|
|
208
|
+
marked.walkTokens(token.tokens, callback);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
130
215
|
/**
|
|
131
216
|
* Expose
|
|
132
217
|
*/
|
|
@@ -140,8 +225,7 @@ marked.TextRenderer = TextRenderer;
|
|
|
140
225
|
marked.Lexer = Lexer;
|
|
141
226
|
marked.lexer = Lexer.lex;
|
|
142
227
|
|
|
143
|
-
marked.
|
|
144
|
-
marked.inlineLexer = InlineLexer.output;
|
|
228
|
+
marked.Tokenizer = Tokenizer;
|
|
145
229
|
|
|
146
230
|
marked.Slugger = Slugger;
|
|
147
231
|
|
package/src/rules.js
CHANGED
|
@@ -42,7 +42,7 @@ block.def = edit(block.def)
|
|
|
42
42
|
.replace('title', block._title)
|
|
43
43
|
.getRegex();
|
|
44
44
|
|
|
45
|
-
block.bullet = /(?:[*+-]|\d{1,9}
|
|
45
|
+
block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
|
|
46
46
|
block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/;
|
|
47
47
|
block.item = edit(block.item, 'gm')
|
|
48
48
|
.replace(/bull/g, block.bullet)
|
|
@@ -168,18 +168,74 @@ const inline = {
|
|
|
168
168
|
link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
|
|
169
169
|
reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
|
|
170
170
|
nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
reflinkSearch: 'reflink|nolink(?!\\()',
|
|
172
|
+
strong: {
|
|
173
|
+
start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation
|
|
174
|
+
middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,
|
|
175
|
+
endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
|
|
176
|
+
endUnd: /[^\s]__(?!_)(?:(?=[punctuation\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
|
|
177
|
+
},
|
|
178
|
+
em: {
|
|
179
|
+
start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation
|
|
180
|
+
middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,
|
|
181
|
+
endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
|
|
182
|
+
endUnd: /[^\s]_(?!_)(?:(?=[punctuation\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
|
|
183
|
+
},
|
|
173
184
|
code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
|
|
174
185
|
br: /^( {2,}|\\)\n(?!\s*$)/,
|
|
175
186
|
del: noopTest,
|
|
176
|
-
text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))
|
|
187
|
+
text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/,
|
|
188
|
+
punctuation: /^([\s*punctuation])/
|
|
177
189
|
};
|
|
178
190
|
|
|
179
191
|
// list of punctuation marks from common mark spec
|
|
180
|
-
// without
|
|
181
|
-
inline._punctuation = '!"#$%&\'()
|
|
182
|
-
inline.
|
|
192
|
+
// without * and _ to workaround cases with double emphasis
|
|
193
|
+
inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
|
|
194
|
+
inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
|
|
195
|
+
|
|
196
|
+
// sequences em should skip over [title](link), `code`, <html>
|
|
197
|
+
inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
|
|
198
|
+
inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
|
|
199
|
+
|
|
200
|
+
inline.em.start = edit(inline.em.start)
|
|
201
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
202
|
+
.getRegex();
|
|
203
|
+
|
|
204
|
+
inline.em.middle = edit(inline.em.middle)
|
|
205
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
206
|
+
.replace(/overlapSkip/g, inline._overlapSkip)
|
|
207
|
+
.getRegex();
|
|
208
|
+
|
|
209
|
+
inline.em.endAst = edit(inline.em.endAst, 'g')
|
|
210
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
211
|
+
.getRegex();
|
|
212
|
+
|
|
213
|
+
inline.em.endUnd = edit(inline.em.endUnd, 'g')
|
|
214
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
215
|
+
.getRegex();
|
|
216
|
+
|
|
217
|
+
inline.strong.start = edit(inline.strong.start)
|
|
218
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
219
|
+
.getRegex();
|
|
220
|
+
|
|
221
|
+
inline.strong.middle = edit(inline.strong.middle)
|
|
222
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
223
|
+
.replace(/blockSkip/g, inline._blockSkip)
|
|
224
|
+
.getRegex();
|
|
225
|
+
|
|
226
|
+
inline.strong.endAst = edit(inline.strong.endAst, 'g')
|
|
227
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
228
|
+
.getRegex();
|
|
229
|
+
|
|
230
|
+
inline.strong.endUnd = edit(inline.strong.endUnd, 'g')
|
|
231
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
232
|
+
.getRegex();
|
|
233
|
+
|
|
234
|
+
inline.blockSkip = edit(inline._blockSkip, 'g')
|
|
235
|
+
.getRegex();
|
|
236
|
+
|
|
237
|
+
inline.overlapSkip = edit(inline._overlapSkip, 'g')
|
|
238
|
+
.getRegex();
|
|
183
239
|
|
|
184
240
|
inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
|
|
185
241
|
|
|
@@ -197,7 +253,7 @@ inline.tag = edit(inline.tag)
|
|
|
197
253
|
.replace('attribute', inline._attribute)
|
|
198
254
|
.getRegex();
|
|
199
255
|
|
|
200
|
-
inline._label = /(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
|
|
256
|
+
inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
|
|
201
257
|
inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;
|
|
202
258
|
inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
|
|
203
259
|
|
|
@@ -211,6 +267,11 @@ inline.reflink = edit(inline.reflink)
|
|
|
211
267
|
.replace('label', inline._label)
|
|
212
268
|
.getRegex();
|
|
213
269
|
|
|
270
|
+
inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
|
|
271
|
+
.replace('reflink', inline.reflink)
|
|
272
|
+
.replace('nolink', inline.nolink)
|
|
273
|
+
.getRegex();
|
|
274
|
+
|
|
214
275
|
/**
|
|
215
276
|
* Normal Inline Grammar
|
|
216
277
|
*/
|
|
@@ -222,8 +283,18 @@ inline.normal = merge({}, inline);
|
|
|
222
283
|
*/
|
|
223
284
|
|
|
224
285
|
inline.pedantic = merge({}, inline.normal, {
|
|
225
|
-
strong:
|
|
226
|
-
|
|
286
|
+
strong: {
|
|
287
|
+
start: /^__|\*\*/,
|
|
288
|
+
middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
|
|
289
|
+
endAst: /\*\*(?!\*)/g,
|
|
290
|
+
endUnd: /__(?!_)/g
|
|
291
|
+
},
|
|
292
|
+
em: {
|
|
293
|
+
start: /^_|\*/,
|
|
294
|
+
middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
|
|
295
|
+
endAst: /\*(?!\*)/g,
|
|
296
|
+
endUnd: /_(?!_)/g
|
|
297
|
+
},
|
|
227
298
|
link: edit(/^!?\[(label)\]\((.*?)\)/)
|
|
228
299
|
.replace('label', inline._label)
|
|
229
300
|
.getRegex(),
|
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.renderer.html(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
|
-
};
|