From f9328cccd56002e00736c457963afdedc2231715 Mon Sep 17 00:00:00 2001
From: Evan Jacobs
Date: Thu, 11 Apr 2024 14:54:42 -0400
Subject: [PATCH] fix: adjusted block html regex to avoid perf issues
Closes #546
Thank you @devbrains-com for contributing the basis of this fix!
---
.changeset/quiet-boxes-flow.md | 5 ++
index.compiler.spec.tsx | 148 +++++++++++++++++++++++++++++++++
index.tsx | 2 +-
3 files changed, 154 insertions(+), 1 deletion(-)
create mode 100644 .changeset/quiet-boxes-flow.md
diff --git a/.changeset/quiet-boxes-flow.md b/.changeset/quiet-boxes-flow.md
new file mode 100644
index 00000000..965975cd
--- /dev/null
+++ b/.changeset/quiet-boxes-flow.md
@@ -0,0 +1,5 @@
+---
+"markdown-to-jsx": patch
+---
+
+Improved block html detection regex to handle certain edge cases that cause extreme slowness. Thank you @devbrains-com for the basis for this fix 🤝
diff --git a/index.compiler.spec.tsx b/index.compiler.spec.tsx
index 53950e80..9626aaa6 100644
--- a/index.compiler.spec.tsx
+++ b/index.compiler.spec.tsx
@@ -3442,6 +3442,154 @@ Item detail
`)
})
+
+ it('#546 perf regression test, self-closing block + block HTML causes exponential degradation', () => {
+ render(
+ compiler(
+ `
+
+You can have anything here. But it's best if the self-closing tag also appears in the document as a pair tag multiple times. We have found it when compiling a table with spans that had a self-closing span at the top.
+
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+no
+
+Each span you copy above increases the time it takes by 2. Also, writing text here increases the time.`.trim()
+ )
+ )
+
+ expect(root.innerHTML).toMatchInlineSnapshot(`
+
+
+
+
+ You can have anything here. But it's best if the self-closing tag also appears in the document as a pair tag multiple times. We have found it when compiling a table with spans that had a self-closing span at the top.
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ no
+
+
+ Each span you copy above increases the time it takes by 2. Also, writing text here increases the time.
+
+
+ `)
+ })
})
describe('horizontal rules', () => {
diff --git a/index.tsx b/index.tsx
index 4b6a9a74..733a6bc3 100644
--- a/index.tsx
+++ b/index.tsx
@@ -254,7 +254,7 @@ const HEADING_SETEXT_R = /^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/
* \n*
*/
const HTML_BLOCK_ELEMENT_R =
- /^ *(?!<[a-z][^ >/]* ?\/>)<([a-z][^ >/]*) ?([^>]*)>\n?(\s*(?:<\1[^>]*?>[\s\S]*?<\/\1>|(?!<\1\b)[\s\S])*?)<\/\1>(?!<\/\1>)\n*/i
+ /^ *(?!<[a-z][^ >/]* ?\/>)<([a-z][^ >/]*) ?((?:[^>]*[^/])?)>\n?(\s*(?:<\1[^>]*?>[\s\S]*?<\/\1>|(?!<\1\b)[\s\S])*?)<\/\1>(?!<\/\1>)\n*/i
const HTML_CHAR_CODE_R = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/gi