From 6657ec6d03a630d367fbc5fc531042c8aceab07d Mon Sep 17 00:00:00 2001 From: Ned Schwartz Date: Thu, 10 Aug 2023 10:41:43 -0400 Subject: [PATCH] avoid regex for tag content footgun (#89) using regex to try to select the content fo the table was leading to runaway catastprohic backtracking. the simple solution is to just do string substring selection and insertion on the start and end tag --- src/paste-markdown-table.ts | 10 +++++++++- test/test.js | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/paste-markdown-table.ts b/src/paste-markdown-table.ts index afa5294..544ef91 100644 --- a/src/paste-markdown-table.ts +++ b/src/paste-markdown-table.ts @@ -91,6 +91,12 @@ function generateText(transfer: DataTransfer): string | undefined { const html = transfer.getData('text/html') if (!/') + if (!start || !tableCloseIndex) return + const end = html.substring(tableCloseIndex + 8) + const parser = new DOMParser() const parsedDocument = parser.parseFromString(html, 'text/html') @@ -100,5 +106,7 @@ function generateText(transfer: DataTransfer): string | undefined { const formattedTable = tableMarkdown(table) - return html.replace(//, '').replace(//, `\n${formattedTable}`) + if (!formattedTable) return + + return [start, formattedTable, end].join('').replace(//, '') } diff --git a/test/test.js b/test/test.js index f2ee67a..951d261 100644 --- a/test/test.js +++ b/test/test.js @@ -202,7 +202,7 @@ describe('paste-markdown', function () { assert.equal( textarea.value.trim(), // eslint-disable-next-line github/unescaped-html-literal - `

Here is a cool table

\n \n \n\n${tableMarkdown}\n\n\n\n

Very cool

` + `

Here is a cool table

\n \n \n${tableMarkdown}\n\n\n\n

Very cool

` ) }) @@ -225,6 +225,19 @@ describe('paste-markdown', function () { assertUnformattedPaste(textarea) }) + it('rejects malformed tables', function () { + // eslint-disable-next-line github/unescaped-html-literal, prefer-template + const html = '
' + const data = { + 'text/html': html + } + paste(textarea, data) + + // Synthetic paste events don't manipulate the DOM. A empty textarea + // means that the event handler didn't fire and normal paste happened. + assertUnformattedPaste(textarea) + }) + it('accepts x-gfm', function () { paste(textarea, {'text/plain': 'hello', 'text/x-gfm': '# hello'}) assert.include(textarea.value, '# hello')