Skip to content

Commit

Permalink
Merge pull request #385 from mateusbra/markdown-quote
Browse files Browse the repository at this point in the history
Changes in quotes
  • Loading branch information
roryabraham authored Jun 24, 2021
2 parents c3465bf + a5fc132 commit 717d9c8
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 2 deletions.
32 changes: 32 additions & 0 deletions __tests__/ExpensiMark-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,35 @@ test('Test HTML string with seperate closing tags (<br></br>) to markdown ', ()
const resultString = 'Hello\nWorld,\nWelcome\nTo\nExpensify';
expect(parser.htmlToMarkdown(testString)).toBe(resultString);
});

test('Test quotes markdown replacement with text matching inside and outside codefence without spaces', () => {
const testString = 'The next line should be quoted\n&gt;Hello,I’mtext\n```\nThe next line should not be quoted\n&gt;Hello,I’mtext\nsince its inside a codefence```';

const resultString = 'The next line should be quoted<br><blockquote>Hello,I’mtext</blockquote><pre>The&#32;next&#32;line&#32;should&#32;not&#32;be&#32;quoted<br>&gt;Hello,I’mtext<br>since&#32;its&#32;inside&#32;a&#32;codefence</pre>';

expect(parser.replace(testString)).toBe(resultString);
});

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&gt;Hello,I’mtext\nThe next line should not be quoted\n```&gt;Hello,I’mtext```\nsince its inside a codefence';

const resultString = 'The next line should be quoted<br><blockquote>Hello,I’mtext</blockquote>The next line should not be quoted<br><pre>&gt;Hello,I’mtext</pre><br>since its inside a codefence';

expect(parser.replace(testString)).toBe(resultString);
});

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&gt;Hello,I’mtext\nThe next line should not be quoted\n```&gt;Hello,I’mtext```';

const resultString = 'The next line should be quoted<br><blockquote>Hello,I’mtext</blockquote>The next line should not be quoted<br><pre>&gt;Hello,I’mtext</pre>';

expect(parser.replace(testString)).toBe(resultString);
});

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```&gt;Hello,I’mtext```\nThe next line should not be quoted\n&gt;Hello,I’mtext';

const resultString = 'The next line should be quoted<br><pre>&gt;Hello,I’mtext</pre><br>The next line should not be quoted<br><blockquote>Hello,I’mtext</blockquote>';

expect(parser.replace(testString)).toBe(resultString);
});
91 changes: 89 additions & 2 deletions lib/ExpensiMark.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,13 @@ export default class ExpensiMark {
// We also want to capture a blank line before or after the quote so that we do not add extra spaces.
// 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
regex: /\n?^&gt; ?(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]+)\n?/gm,
replacement: '<blockquote>$1</blockquote>'
process: (textToProcess, replacement) => {
const regex = new RegExp(
/\n?^&gt; ?(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]+)\n?/gm
);
return this.modifyTextForQuote(regex, textToProcess, replacement);
},
replacement: g1 => `<blockquote>${g1}</blockquote>`,
},
{
name: 'newline',
Expand Down Expand Up @@ -285,4 +290,86 @@ export default class ExpensiMark {
});
return generatedMarkdown;
}

/**
* Modify text for Quotes replacing chevrons with html elements
*
* @param {RegExp} regex
* @param {String} textToCheck
* @param {Function} replacement
*
* @returns {String}
*/

modifyTextForQuote(regex, textToCheck, replacement) {
let replacedText = '';
let textToFormat = '';
const match = textToCheck.match(regex);

// If there's matches we need to modify the quotes
if (match !== null) {
let insideCodefence = false;

// Split the textToCheck in lines
const textSplitted = textToCheck.split('\n');

for (let i = 0; i < textSplitted.length; i++) {
if (!insideCodefence) {
// We need to know when there is a start of codefence so we dont quote
insideCodefence = Str.contains(textSplitted[i], '<pre>');
}

// We only want to modify lines starting with &gt; that is not codefence
if (Str.startsWith(textSplitted[i], '&gt;') && !insideCodefence) {
// Avoid blank lines starting with &gt;
if (textSplitted[i].trim() !== '&gt;') {
textSplitted[i] = textSplitted[i].substr(4).trim();
textSplitted[i] = textSplitted[i].trim();
textToFormat += `${textSplitted[i]}\n`;

// We need ensure that index i-1 >= 0
} else if (i > 0) {
// Certificate that we will have only one blank row
if (textSplitted[i - 1].trim() !== '') {
textSplitted[i] = textSplitted[i].substr(4).trim();
textSplitted[i] = textSplitted[i].trim();
textToFormat += `${textSplitted[i]}\n`;
}
}
} else {
// Make sure we will only modify if we have Text needed to be formatted for quote
if (textToFormat !== '') {
textToFormat = textToFormat.replace(/\n$/, '');
replacedText += replacement(textToFormat);
textToFormat = '';
}

// We dont want a \n after the textSplitted if it is the last row
if (i === textSplitted.length - 1) {
replacedText += `${textSplitted[i]}`;
} else {
replacedText += `${textSplitted[i]}\n`;
}

// We need to know when we are not inside codefence anymore
if (insideCodefence) {
insideCodefence = !Str.contains(textSplitted[i], '</pre>');
}
}
}

// When loop ends we need the last quote to be formatted if we have quotes at last rows
if (textToFormat !== '') {
textToFormat = textToFormat.replace(/\n$/, '');
replacedText += replacement(textToFormat);
}

// Replace all the blank lines between quotes, if there are only blank lines between them
replacedText = replacedText.replace(/(<\/blockquote>((\s*)+)<blockquote>)/g, '</blockquote><blockquote>');
} else {
// If we doesn't have matches make sure the function will return the same textToCheck
replacedText = textToCheck;
}
return replacedText;
}
}

0 comments on commit 717d9c8

Please sign in to comment.