marked 2.0.4 → 2.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/lib/marked.esm.js +225 -64
- package/lib/marked.js +313 -94
- package/marked.min.js +1 -1
- package/package.json +13 -13
- package/src/Lexer.js +67 -7
- package/src/Parser.js +25 -2
- package/src/Tokenizer.js +15 -14
- package/src/defaults.js +1 -0
- package/src/marked.js +112 -36
- package/src/rules.js +4 -4
package/src/marked.js
CHANGED
|
@@ -51,6 +51,9 @@ function marked(src, opt, callback) {
|
|
|
51
51
|
|
|
52
52
|
if (!err) {
|
|
53
53
|
try {
|
|
54
|
+
if (opt.walkTokens) {
|
|
55
|
+
marked.walkTokens(tokens, opt.walkTokens);
|
|
56
|
+
}
|
|
54
57
|
out = Parser.parse(tokens, opt);
|
|
55
58
|
} catch (e) {
|
|
56
59
|
err = e;
|
|
@@ -138,46 +141,114 @@ marked.defaults = defaults;
|
|
|
138
141
|
* Use Extension
|
|
139
142
|
*/
|
|
140
143
|
|
|
141
|
-
marked.use = function(
|
|
142
|
-
const opts = merge({},
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
marked.use = function(...args) {
|
|
145
|
+
const opts = merge({}, ...args);
|
|
146
|
+
const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
|
|
147
|
+
let hasExtensions;
|
|
148
|
+
|
|
149
|
+
args.forEach((pack) => {
|
|
150
|
+
// ==-- Parse "addon" extensions --== //
|
|
151
|
+
if (pack.extensions) {
|
|
152
|
+
hasExtensions = true;
|
|
153
|
+
pack.extensions.forEach((ext) => {
|
|
154
|
+
if (!ext.name) {
|
|
155
|
+
throw new Error('extension name required');
|
|
151
156
|
}
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
if (ext.renderer) { // Renderer extensions
|
|
158
|
+
const prevRenderer = extensions.renderers?.[ext.name];
|
|
159
|
+
if (prevRenderer) {
|
|
160
|
+
// Replace extension with func to run new extension but fall back if false
|
|
161
|
+
extensions.renderers[ext.name] = function(...args) {
|
|
162
|
+
let ret = ext.renderer.apply(this, args);
|
|
163
|
+
if (ret === false) {
|
|
164
|
+
ret = prevRenderer.apply(this, args);
|
|
165
|
+
}
|
|
166
|
+
return ret;
|
|
167
|
+
};
|
|
168
|
+
} else {
|
|
169
|
+
extensions.renderers[ext.name] = ext.renderer;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (ext.tokenizer) { // Tokenizer Extensions
|
|
173
|
+
if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
|
|
174
|
+
throw new Error("extension level must be 'block' or 'inline'");
|
|
175
|
+
}
|
|
176
|
+
if (extensions[ext.level]) {
|
|
177
|
+
extensions[ext.level].unshift(ext.tokenizer);
|
|
178
|
+
} else {
|
|
179
|
+
extensions[ext.level] = [ext.tokenizer];
|
|
180
|
+
}
|
|
181
|
+
if (ext.start) { // Function to check for start of token
|
|
182
|
+
if (ext.level === 'block') {
|
|
183
|
+
if (extensions.startBlock) {
|
|
184
|
+
extensions.startBlock.push(ext.start);
|
|
185
|
+
} else {
|
|
186
|
+
extensions.startBlock = [ext.start];
|
|
187
|
+
}
|
|
188
|
+
} else if (ext.level === 'inline') {
|
|
189
|
+
if (extensions.startInline) {
|
|
190
|
+
extensions.startInline.push(ext.start);
|
|
191
|
+
} else {
|
|
192
|
+
extensions.startInline = [ext.start];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (ext.childTokens) { // Child tokens to be visited by walkTokens
|
|
198
|
+
extensions.childTokens[ext.name] = ext.childTokens;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
154
201
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
ret
|
|
202
|
+
|
|
203
|
+
// ==-- Parse "overwrite" extensions --== //
|
|
204
|
+
if (pack.renderer) {
|
|
205
|
+
const renderer = marked.defaults.renderer || new Renderer();
|
|
206
|
+
for (const prop in pack.renderer) {
|
|
207
|
+
const prevRenderer = renderer[prop];
|
|
208
|
+
// Replace renderer with func to run extension, but fall back if false
|
|
209
|
+
renderer[prop] = (...args) => {
|
|
210
|
+
let ret = pack.renderer[prop].apply(renderer, args);
|
|
211
|
+
if (ret === false) {
|
|
212
|
+
ret = prevRenderer.apply(renderer, args);
|
|
213
|
+
}
|
|
214
|
+
return ret;
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
opts.renderer = renderer;
|
|
218
|
+
}
|
|
219
|
+
if (pack.tokenizer) {
|
|
220
|
+
const tokenizer = marked.defaults.tokenizer || new Tokenizer();
|
|
221
|
+
for (const prop in pack.tokenizer) {
|
|
222
|
+
const prevTokenizer = tokenizer[prop];
|
|
223
|
+
// Replace tokenizer with func to run extension, but fall back if false
|
|
224
|
+
tokenizer[prop] = (...args) => {
|
|
225
|
+
let ret = pack.tokenizer[prop].apply(tokenizer, args);
|
|
226
|
+
if (ret === false) {
|
|
227
|
+
ret = prevTokenizer.apply(tokenizer, args);
|
|
228
|
+
}
|
|
229
|
+
return ret;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
opts.tokenizer = tokenizer;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ==-- Parse WalkTokens extensions --== //
|
|
236
|
+
if (pack.walkTokens) {
|
|
237
|
+
const walkTokens = marked.defaults.walkTokens;
|
|
238
|
+
opts.walkTokens = (token) => {
|
|
239
|
+
pack.walkTokens.call(this, token);
|
|
240
|
+
if (walkTokens) {
|
|
241
|
+
walkTokens(token);
|
|
165
242
|
}
|
|
166
|
-
return ret;
|
|
167
243
|
};
|
|
168
244
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
walkTokens(token);
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
marked.setOptions(opts);
|
|
245
|
+
|
|
246
|
+
if (hasExtensions) {
|
|
247
|
+
opts.extensions = extensions;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
marked.setOptions(opts);
|
|
251
|
+
});
|
|
181
252
|
};
|
|
182
253
|
|
|
183
254
|
/**
|
|
@@ -204,7 +275,12 @@ marked.walkTokens = function(tokens, callback) {
|
|
|
204
275
|
break;
|
|
205
276
|
}
|
|
206
277
|
default: {
|
|
207
|
-
if (token.
|
|
278
|
+
if (marked.defaults?.extensions?.childTokens?.[token.type]) { // Walk any extensions
|
|
279
|
+
marked.defaults?.extensions.childTokens[token.type].forEach(function(childTokens) {
|
|
280
|
+
marked.walkTokens(token[childTokens], callback);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (token.tokens && !marked.defaults?.extensions?.childTokens[token.type]) {
|
|
208
284
|
marked.walkTokens(token.tokens, callback);
|
|
209
285
|
}
|
|
210
286
|
}
|
package/src/rules.js
CHANGED
|
@@ -176,9 +176,9 @@ const inline = {
|
|
|
176
176
|
emStrong: {
|
|
177
177
|
lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
|
|
178
178
|
// (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left. (5) and (6) can be either Left or Right.
|
|
179
|
-
// () Skip other delimiter (1) #***
|
|
180
|
-
rDelimAst: /\_\_[^_]*?\*[^_]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
|
|
181
|
-
rDelimUnd: /\*\*[
|
|
179
|
+
// () Skip other delimiter (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
|
|
180
|
+
rDelimAst: /\_\_[^_*]*?\*[^_*]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
|
|
181
|
+
rDelimUnd: /\*\*[^_*]*?\_[^_*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
|
|
182
182
|
},
|
|
183
183
|
code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
|
|
184
184
|
br: /^( {2,}|\\)\n(?!\s*$)/,
|
|
@@ -286,7 +286,7 @@ inline.gfm = merge({}, inline.normal, {
|
|
|
286
286
|
url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
|
|
287
287
|
_backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
|
|
288
288
|
del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
|
|
289
|
-
text: /^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))
|
|
289
|
+
text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
|
|
290
290
|
});
|
|
291
291
|
|
|
292
292
|
inline.gfm.url = edit(inline.gfm.url, 'i')
|