Skip to content

Commit 9397604

Browse files
committed
Improve perf of blockSkip on modern engines
RegExp lookbehind assertions are supported in Safari >= 16.5. But the lookbehind-less version has a performance penalty. So having a fallback keeps support for older Safari versions while maintaining performance for modern engines.
1 parent aebb5a0 commit 9397604

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

src/Lexer.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,10 @@ export class _Lexer<ParserOutput = string, RendererOutput = string> {
320320
}
321321

322322
// Mask out other blocks
323+
let offset;
323324
while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
324-
if (match[2]) {
325-
maskedSrc = maskedSrc.slice(0, match.indices![2][0]) + '[' + 'a'.repeat(match[2].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
326-
} else {
327-
maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
328-
}
325+
offset = match[2] ? match[2].length : 0;
326+
maskedSrc = maskedSrc.slice(0, match.index + offset) + '[' + 'a'.repeat(match[0].length - offset - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
329327
}
330328

331329
// Mask out blocks from extensions

src/rules.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ function edit(regex: string | RegExp, opt = '') {
1616
return obj;
1717
}
1818

19+
const supportsLookbehind = (() => {
20+
try {
21+
// eslint-disable-next-line prefer-regex-literals
22+
return !!new RegExp('(?<=1)(?<!1)');
23+
} catch {
24+
return false;
25+
}
26+
})();
27+
1928
export const other = {
2029
codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
2130
outputLinkReplace: /\\([\[\]])/g,
@@ -267,9 +276,10 @@ const _punctuationOrSpaceGfmStrongEm = /(?!~)[\s\p{P}\p{S}]/u;
267276
const _notPunctuationOrSpaceGfmStrongEm = /(?:[^\s\p{P}\p{S}]|~)/u;
268277

269278
// sequences em should skip over [title](link), `code`, <html>
270-
const blockSkip = edit(/link|code|html/, 'dg')
279+
const blockSkip = edit(/link|precode-code|html/, 'g')
271280
.replace('link', /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/)
272-
.replace('code', /(?:^^|[^`])((?<b>`+)[^`]+\k<b>(?!`))/)
281+
.replace('precode-', supportsLookbehind ? '(?<!`)()' : '(^^|[^`])')
282+
.replace('code', /(?<b>`+)[^`]+\k<b>(?!`)/)
273283
.replace('html', /<(?! )[^<>]*?>/)
274284
.getRegex();
275285

0 commit comments

Comments
 (0)