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/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 (callback || typeof opt === 'function') {
32
- if (!callback) {
33
- callback = opt;
34
- opt = null;
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
- opt = merge({}, marked.defaults, opt || {});
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
- try {
61
- out = Parser.parse(tokens, opt);
62
- } catch (e) {
63
- err = e;
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 (!pending) return done();
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
- 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]);
98
+ if (pending === 0) {
99
+ done();
96
100
  }
97
101
 
98
102
  return;
99
103
  }
104
+
100
105
  try {
101
- opt = merge({}, marked.defaults, opt || {});
102
- checkSanitizeDeprecation(opt);
103
- return Parser.parse(Lexer.lex(src, opt), opt);
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 ((opt || marked.defaults).silent) {
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.InlineLexer = InlineLexer;
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
- strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,
172
- em: /^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,
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 ` and ] to workaround Rule 17 (inline code blocks/links)
181
- inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~';
182
- inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex();
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: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
226
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
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(),
@@ -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
- };