Skip to content

Commit 70e5d94

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 70e5d94

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-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: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ 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+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
24+
} catch(error) {
25+
return false;
26+
}
27+
})();
28+
1929
export const other = {
2030
codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
2131
outputLinkReplace: /\\([\[\]])/g,
@@ -267,9 +277,10 @@ const _punctuationOrSpaceGfmStrongEm = /(?!~)[\s\p{P}\p{S}]/u;
267277
const _notPunctuationOrSpaceGfmStrongEm = /(?:[^\s\p{P}\p{S}]|~)/u;
268278

269279
// sequences em should skip over [title](link), `code`, <html>
270-
const blockSkip = edit(/link|code|html/, 'dg')
280+
const blockSkip = edit(/link|precode-code|html/, 'g')
271281
.replace('link', /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/)
272-
.replace('code', /(?:^^|[^`])((?<b>`+)[^`]+\k<b>(?!`))/)
282+
.replace('precode-', supportsLookbehind ? '(?<!`)()' : '(^^|[^`])')
283+
.replace('code', /(?<b>`+)[^`]+\k<b>(?!`)/)
273284
.replace('html', /<(?! )[^<>]*?>/)
274285
.getRegex();
275286

0 commit comments

Comments
 (0)