diff --git a/__tests__/ExpensiMark-HTML-test.js b/__tests__/ExpensiMark-HTML-test.js index fab1b0b8..d31b5dee 100644 --- a/__tests__/ExpensiMark-HTML-test.js +++ b/__tests__/ExpensiMark-HTML-test.js @@ -44,7 +44,7 @@ test('Test heading markdown replacement', () => { // Sections starting with > are successfully wrapped with
test('Test quote markdown replacement', () => { - const quoteTestStartString = '>This is a *quote* that started on a new line.\nHere is a >quote that did not\n```\nhere is a codefenced quote\n>it should not be quoted\n```'; + const quoteTestStartString = '> This is a *quote* that started on a new line.\nHere is a >quote that did not\n```\nhere is a codefenced quote\n>it should not be quoted\n```'; const quoteTestReplacedString = 'This is a quote that started on a new line.Here is a >quote that did not
here is a codefenced quote'; expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString); @@ -1016,7 +1016,7 @@ test('Test autolink replacement to avoid parsing nested links', () => { }); test('Test quotes markdown replacement with text matching inside and outside codefence without spaces', () => { - const testString = 'The next line should be quoted\n>Hello,I’mtext\n```\nThe next line should not be quoted\n>Hello,I’mtext\nsince its inside a codefence```'; + const testString = 'The next line should be quoted\n> Hello,I’mtext\n```\nThe next line should not be quoted\n>Hello,I’mtext\nsince its inside a codefence```'; const resultString = 'The next line should be quoted
>it should not be quoted
Hello,I’mtext
The next line should not be quoted'; @@ -1024,7 +1024,7 @@ test('Test quotes markdown replacement with text matching inside and outside cod }); test('Test quotes markdown replacement with text matching inside and outside codefence at the same line', () => { - const testString = 'The next line should be quoted\n>Hello,I’mtext\nThe next line should not be quoted\n```>Hello,I’mtext```\nsince its inside a codefence'; + const testString = 'The next line should be quoted\n> Hello,I’mtext\nThe next line should not be quoted\n```>Hello,I’mtext```\nsince its inside a codefence'; const resultString = 'The next line should be quoted
>Hello,I’mtext
since its inside a codefence
Hello,I’mtextThe next line should not be quoted
>Hello,I’mtextsince its inside a codefence'; @@ -1032,7 +1032,7 @@ test('Test quotes markdown replacement with text matching inside and outside cod }); test('Test quotes markdown replacement with text matching inside and outside codefence at the end of the text', () => { - const testString = 'The next line should be quoted\n>Hello,I’mtext\nThe next line should not be quoted\n```>Hello,I’mtext```'; + const testString = 'The next line should be quoted\n> Hello,I’mtext\nThe next line should not be quoted\n```>Hello,I’mtext```'; const resultString = 'The next line should be quoted
Hello,I’mtextThe next line should not be quoted
>Hello,I’mtext'; @@ -1040,9 +1040,9 @@ test('Test quotes markdown replacement with text matching inside and outside cod }); test('Test quotes markdown replacement with text matching inside and outside codefence with quotes at the end of the text', () => { - const testString = 'The next line should be quoted\n```>Hello,I’mtext```\nThe next line should not be quoted\n>Hello,I’mtext'; + const testString = 'The next line should be quoted\n```> Hello,I’mtext```\nThe next line should not be quoted\n> Hello,I’mtext'; - const resultString = 'The next line should be quoted
>Hello,I’mtextThe next line should not be quoted
Hello,I’mtext'; + const resultString = 'The next line should be quoted
> Hello,I’mtextThe next line should not be quoted
Hello,I’mtext'; expect(parser.replace(testString)).toBe(resultString); }); @@ -1068,31 +1068,31 @@ test('Test quotes markdown replacement with text starts with blank quote', () => }); test('Test quotes markdown replacement with quotes starts with blank quote row', () => { - const testString = '> \n>test'; + const testString = '> \n> test'; const resultString = '
test'; expect(parser.replace(testString)).toBe(resultString); }); test('Test quotes markdown replacement with quotes ends with blank quote rows', () => { - const testString = '>test\n> \n>'; + const testString = '> test\n> \n>'; const resultString = '
test'; expect(parser.replace(testString)).toBe(resultString); }); test('Test quotes markdown replacement with quotes includes a middle blank quote row', () => { - const testString = '>test\n> \n>test'; + const testString = '> test\n> \n> test'; const resultString = '
test'; expect(parser.replace(testString)).toBe(resultString); }); test('Test quotes markdown replacement with quotes includes multiple middle blank quote rows', () => { - const testString = '>test\n> \n> \n>test\ntest\n>test\n> \n> \n> \n>test'; + const testString = '> test\n> \n> \n> test\ntest\n> test\n> \n> \n> \n> test'; const resultString = '
test
testtest
test
test'; expect(parser.replace(testString)).toBe(resultString); }); test('Test quotes markdown replacement with text includes blank quotes', () => { - const testString = '> \n>quote1 line a\n> quote1 line b\ntest\n> \ntest\n>quote2 line a\n> \n> \n>quote2 line b with an empty line above'; + const testString = '> \n> quote1 line a\n> quote1 line b\ntest\n> \ntest\n> quote2 line a\n> \n> \n> quote2 line b with an empty line above'; const resultString = '
test
quote1 line atest
quote1 line b
quote2 line a'; expect(parser.replace(testString)).toBe(resultString); }); @@ -1103,6 +1103,35 @@ test('Test quotes markdown replacement with text includes multiple spaces', () = expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString); }); +test('Test markdown quotes without spaces after > should not be parsed', () => { + const testString = '>test'; + const resultString = '>test'; + expect(parser.replace(testString)).toBe(resultString); +}); +test('Test markdown quotes without spaces after > should not be parsed', () => { + const testString = '>>>test'; + const resultString = '>>>test'; + expect(parser.replace(testString)).toBe(resultString); +}); + +test('Test markdown quotes without spaces after > should not be parsed', () => { + const testString = '> >>test'; + const resultString = '
quote2 line b with an empty line above
>>test'; + expect(parser.replace(testString)).toBe(resultString); +}); + +test('Test markdown quotes without spaces after > should not be parsed', () => { + const testString = '> > > test'; + const resultString = '
'; + expect(parser.replace(testString)).toBe(resultString); +}); + +test('Test markdown quotes without spaces after > should not be parsed', () => { + const testString = '>>> test'; + const resultString = 'test
'; + expect(parser.replace(testString)).toBe(resultString); +}); + test('Single char matching', () => { const testString = ' *1* char _1_ char ~1~ char'; const resultString = ' 1 char 1 chartest
Hello world'; + const quoteTestStartString = '> Hello world'; + const quoteTestReplacedString = '
Hello world'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); @@ -1708,23 +1737,23 @@ describe('when should keep raw input flag is enabled', () => { }); test('multiple quotes', () => { - const quoteTestStartString = '>Hello my\n>beautiful\n>world\n'; - const quoteTestReplacedString = '
Hello my\n
beautiful\n
world\n'; + const quoteTestStartString = '> Hello my\n> beautiful\n> world\n'; + const quoteTestReplacedString = '
Hello my\n
beautiful\n
world\n'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); test('separate blockqoutes', () => { - const quoteTestStartString = '>Lorem ipsum\ndolor\n>sit amet'; - const quoteTestReplacedString = '
Lorem ipsum\ndolor\n
sit amet'; + const quoteTestStartString = '> Lorem ipsum\ndolor\n> sit amet'; + const quoteTestReplacedString = '
Lorem ipsum\ndolor\n
sit amet'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); describe('nested heading in blockquote', () => { test('without spaces', () => { - const quoteTestStartString = '># Hello world'; - const quoteTestReplacedString = '
'; + const quoteTestStartString = '> # Hello world'; + const quoteTestReplacedString = 'Hello world
'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); @@ -1737,8 +1766,8 @@ describe('when should keep raw input flag is enabled', () => { }); test('with multiple spaces after #', () => { - const quoteTestStartString = '># Hello world'; - const quoteTestReplacedString = 'Hello world
'; + const quoteTestStartString = '> # Hello world'; + const quoteTestReplacedString = 'Hello world
'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); @@ -1746,30 +1775,30 @@ describe('when should keep raw input flag is enabled', () => { describe('trailing whitespace after blockquote', () => { test('nothing', () => { - const quoteTestStartString = '>Hello world!'; - const quoteTestReplacedString = 'Hello world
Hello world!'; + const quoteTestStartString = '> Hello world!'; + const quoteTestReplacedString = '
Hello world!'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); test('space', () => { - const quoteTestStartString = '>Hello world '; - const quoteTestReplacedString = '
Hello world'; + const quoteTestStartString = '> Hello world '; + const quoteTestReplacedString = '
Hello world'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); test('newline', () => { - const quoteTestStartString = '>Hello world\n'; - const quoteTestReplacedString = '
Hello world\n'; + const quoteTestStartString = '> Hello world\n'; + const quoteTestReplacedString = '
Hello world\n'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); }); test('quote with other markdowns', () => { - const quoteTestStartString = '>This is a *quote* that started on a new line.\nHere is a >quote that did not\n```\nhere is a codefenced quote\n>it should not be quoted\n```'; - const quoteTestReplacedString = '
This is a quote that started on a new line.\nHere is a >quote that did not\n
here is a codefenced quote\n>it should not be quoted\n'; + const quoteTestStartString = '> This is a *quote* that started on a new line.\nHere is a >quote that did not\n```\nhere is a codefenced quote\n>it should not be quoted\n```'; + const quoteTestReplacedString = '
This is a quote that started on a new line.\nHere is a >quote that did not\n
here is a codefenced quote\n>it should not be quoted\n'; expect(parser.replace(quoteTestStartString, {shouldKeepRawInput: true})).toBe(quoteTestReplacedString); }); diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index f6dc6b69..4b8a7eb2 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -246,7 +246,7 @@ export default class ExpensiMark { // block quotes naturally appear on their own line. Blockquotes should not appear in code fences or // inline code blocks. A single prepending space should be stripped if it exists process: (textToProcess, replacement, shouldKeepRawInput = false) => { - const regex = /^> *(?! )(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]+)/gm; + const regex = /^(?:>)+ +(?! )(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]+)/gm; const replaceFunction = (g1) => replacement(g1, shouldKeepRawInput); if (shouldKeepRawInput) { return textToProcess.replace(regex, replaceFunction); @@ -268,7 +268,7 @@ export default class ExpensiMark { const filterRules = ['heading1']; // if we don't reach the max quote depth we allow the recursive call to process possible quote - if (this.currentQuoteDepth < this.maxQuoteDepth - 1) { + if (this.currentQuoteDepth < this.maxQuoteDepth - 1 || isStartingWithSpace) { filterRules.push('quote'); this.currentQuoteDepth++; }