diff --git a/__tests__/ExpensiMark-HTML-test.js b/__tests__/ExpensiMark-HTML-test.js index 21bc8604..7db22628 100644 --- a/__tests__/ExpensiMark-HTML-test.js +++ b/__tests__/ExpensiMark-HTML-test.js @@ -710,3 +710,17 @@ test('Test for link with no content', () => { const resultString = '[ ](www.link.com)'; expect(parser.replace(testString)).toBe(resultString); }); + +test('Test quotes markdown replacement with heading inside', () => { + let testString = '> # heading'; + expect(parser.replace(testString)).toBe('
'); + + testString = '> # heading\n> test'; + expect(parser.replace(testString)).toBe('heading
'); + + testString = '> test\n> # heading\n> test'; + expect(parser.replace(testString)).toBe('heading
test
test'); + + testString = '> # heading A\n> # heading B'; + expect(parser.replace(testString)).toBe('heading
test
'); +}); diff --git a/__tests__/ExpensiMark-HTMLToText-test.js b/__tests__/ExpensiMark-HTMLToText-test.js index 1d093bd8..baacd308 100644 --- a/__tests__/ExpensiMark-HTMLToText-test.js +++ b/__tests__/ExpensiMark-HTMLToText-test.js @@ -113,3 +113,17 @@ test('Test replacement on mixed html', () => { expect(parser.htmlToText(html)).toBe(text); }); + +test('Test new line replacement on blockquote with heading inside', () => { + let testString = 'heading A
heading B
'; + expect(parser.htmlToText(testString)).toBe('heading'); + + testString = 'heading
'; + expect(parser.htmlToText(testString)).toBe('heading\ntest'); + + testString = 'heading
test
test'; + expect(parser.htmlToText(testString)).toBe('test\n\nheading\ntest'); + + testString = 'heading
test
'; + expect(parser.htmlToText(testString)).toBe('heading A\n\nheading B'); +}); diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index 552de5ff..245460c4 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -641,3 +641,17 @@ test('Test codeFence backticks occupying a separate line while not introducing r testInput = 'heading A
heading B
'; expect(parser.htmlToMarkdown(testInput)).toBe('```\n\n\n# test\n\n```'); }); + +test('Test blockquote with h1 inside', () => { + let testString = '
# test
'; + expect(parser.htmlToMarkdown(testString)).toBe('\n> # heading\n'); + + testString = 'heading
'; + expect(parser.htmlToMarkdown(testString)).toBe('\n> # heading\n> test\n'); + + testString = 'heading
test
test'; + expect(parser.htmlToMarkdown(testString)).toBe('\n> test\n> # heading\n> test\n'); + + testString = 'heading
test
'; + expect(parser.htmlToMarkdown(testString)).toBe('\n> # heading A\n> # heading B\n'); +}); diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index a228a642..b206d306 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -167,7 +167,10 @@ export default class ExpensiMark { ); return this.modifyTextForQuote(regex, textToProcess, replacement); }, - replacement: g1 => `heading A
heading B
${g1}`, + replacement: (g1) => { + const replacedText = this.replace(g1, {filterRules: ['heading1'], shouldEscapeText: false}); + return `
${replacedText}`; + }, }, { name: 'heading1', @@ -261,7 +264,11 @@ export default class ExpensiMark { name: 'quote', regex: /\n?<(blockquote|q)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, replacement: (match, g1, g2) => { - const resultString = g2.trim().split('\n').map(m => `> ${m}`).join('\n'); + const resultString = g2.replace(/(\[block\])+/g, '\n') + .trim() + .split('\n') + .map(m => `> ${m}`) + .join('\n'); return `\n${resultString}\n`; }, }, @@ -299,6 +306,16 @@ export default class ExpensiMark { regex: /
/gi, + replacement: '
', + }, + { + name: 'blockquoteWrapHeadingClose', + regex: /<\/h1><\/blockquote>/gi, + replacement: '', + }, { name: 'blockElementOpen', regex: /(.|\s)<(blockquote|h1|pre)>/gi,