Skip to content

Commit

Permalink
fix a perf issue in the new bold and emphasis regexes
Browse files Browse the repository at this point in the history
  • Loading branch information
quantizor committed Jul 10, 2018
1 parent 8cc1741 commit c1fe1eb
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 27 deletions.
31 changes: 31 additions & 0 deletions __snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`markdown-to-jsx compiler #190 perf regression 1`] = `
<span data-reactroot>
Lorum
<em>
ipsum
</em>
:
<a href
style="float: right;"
>
<small>
foo
</small>
</a>
<span style="float: right;">
<small>
&amp;nbsp;
</small>
</span>
<a href
style="float: right;"
>
<small>
bar
</small>
</a>
</span>
`;

exports[`markdown-to-jsx compiler GFM tables should handle a basic table 1`] = `
<table data-reactroot>
Expand Down
63 changes: 36 additions & 27 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,19 @@ const TABLE_ROW_SPLIT = / *\| */;
/**
* Bolding requires the same character to be used twice, so we do a detect for which
* one is in use, then double-check it's used a second time and then twice at the end.
*
* Bits of the mega regex:
*
* |[^`~()\[\]<>]*? ignore normal stuff
* |(?:.*?([`~]).*?\3.*?)* ignore stuff in backticks & tildes
* |(?:.*?\([^)]*?\).*?)* ignore stuff in parens
* |(?:.*?\[[^\]]*?\].*?)* ignore stuff in square brackets
* |(?:.*?<.*?>.*?)* ignore stuff in angle brackets
*
*/
const TEXT_BOLD_R = /^([*_])\1((?:(?:.*?([`~]).*?\3.*?)*|(?:.*?[\[(<].*?[\])>].*?)*|.+?)\1?)\1{2}/;
const TEXT_EMPHASIZED_R = /^([*_])((?:.*?([`~]).*?\3.*?)*|(?:.*?[\[(<].*?[\])>].*?)*|.+?)\1/;
const TEXT_STRIKETHROUGHED_R = /^~~((?:.*?([`~]).*?\2.*?)*|(?:.*?[\[(<].*?[\])>].*?)*|.+?)~~/;
const TEXT_BOLD_R = /^([*_])\1((?:[^`~()\[\]<>]*?|(?:.*?([`~]).*?\3.*?)*|(?:.*?\([^)]*?\).*?)*|(?:.*?\[[^\]]*?\].*?)*|(?:.*?<.*?>.*?)*|[^\1]*?)\1?)\1{2}/;
const TEXT_EMPHASIZED_R = /^([*_])((?:[^`~()\[\]<>]*?|(?:.*?([`~]).*?\3.*?)*|(?:.*?\([^)]*?\).*?)*|(?:.*?\[[^\]]*?\].*?)*|(?:.*?<.*?>.*?)*|[^\1]*?))\1/;
const TEXT_STRIKETHROUGHED_R = /^~~((?:.*?([`~]).*?\2.*?)*|(?:.*?<.*?>.*?)*|.+?)~~/;

const TEXT_ESCAPED_R = /^\\([^0-9A-Za-z\s])/;
const TEXT_PLAIN_R = /^[\s\S]+?(?=[^0-9A-Z\s\u00c0-\uffff]|\d+\.|\n\n| {2,}\n|\w+:\S|$)/i;
Expand Down Expand Up @@ -1505,37 +1514,37 @@ export function compiler(markdown, options) {
},
};

Object.keys(rules).forEach(key => {
let { match, parse } = rules[key];
// Object.keys(rules).forEach(key => {
// let { match, parse } = rules[key];

rules[key].match = (...args) => {
const start = performance.now();
const result = match(...args);
const delta = performance.now() - start;
// rules[key].match = (...args) => {
// const start = performance.now();
// const result = match(...args);
// const delta = performance.now() - start;

if (delta > 5)
console.warn(
`Slow match for ${key}: ${delta.toFixed(3)}ms, input: ${
args[0]
}`
);
// if (delta > 5)
// console.warn(
// `Slow match for ${key}: ${delta.toFixed(3)}ms, input: ${
// args[0]
// }`
// );

return result;
};
// return result;
// };

rules[key].parse = (...args) => {
const start = performance.now();
const result = parse(...args);
const delta = performance.now() - start;
// rules[key].parse = (...args) => {
// const start = performance.now();
// const result = parse(...args);
// const delta = performance.now() - start;

if (delta > 5)
console.warn(`Slow parse for ${key}: ${delta.toFixed(3)}ms`);
// if (delta > 5)
// console.warn(`Slow parse for ${key}: ${delta.toFixed(3)}ms`);

console.log(`${key}:parse`, `${delta.toFixed(3)}ms`, args[0]);
// console.log(`${key}:parse`, `${delta.toFixed(3)}ms`, args[0]);

return result;
};
});
// return result;
// };
// });

const parser = parserFor(rules);
const emitter = reactFor(ruleOutput(rules));
Expand Down
10 changes: 10 additions & 0 deletions index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ describe('markdown-to-jsx', () => {
expect(root.innerHTML).toMatchSnapshot();
});

it('#190 perf regression', () => {
render(
compiler(
'Lorum *ipsum*: <a href="" style="float: right"><small>foo</small></a><span style="float: right"><small>&nbsp;</small></span><a href="" style="float: right"><small>bar</small></a>'
)
);

expect(root.innerHTML).toMatchSnapshot();
});

describe('inline textual elements', () => {
it('should handle emphasized text', () => {
render(compiler('*Hello.*'));
Expand Down

0 comments on commit c1fe1eb

Please sign in to comment.