Skip to content

Commit

Permalink
Merge pull request #654 from robertKozik/multiple-quote
Browse files Browse the repository at this point in the history
  • Loading branch information
blimpich authored Feb 26, 2024
2 parents e4c35b7 + ff37799 commit 6fa01a6
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
59 changes: 58 additions & 1 deletion __tests__/ExpensiMark-HTML-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1828,4 +1828,61 @@ test('Test italic/bold/strikethrough markdown to keep consistency', () => {
testString = '~This~is~strikethrough~test~~~~';
resultString = '<del>This~is~strikethrough~test</del>~~~';
expect(parser.replace(testString)).toBe(resultString);
});
});


describe('multi-level blockquote', () => {
test('test max level of blockquote (3)', () => {
const quoteTestStartString = '>>>>> Hello world';
const quoteTestReplacedString = '<blockquote><blockquote><blockquote>&gt;&gt; Hello world</blockquote></blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});
test('multi-level blockquote with single space', () => {
const quoteTestStartString = '> > > Hello world';
const quoteTestReplacedString = '<blockquote><blockquote><blockquote>Hello world</blockquote></blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});
test('multi-level blockquote with multiple spaces', () => {
const quoteTestStartString = '> > > Hello world';
const quoteTestReplacedString = '<blockquote><blockquote><blockquote>Hello world</blockquote></blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});

test('multi-level blockquote with mixed spaces', () => {
const quoteTestStartString = '> > > Hello world';
const quoteTestReplacedString = '<blockquote><blockquote><blockquote>Hello world</blockquote></blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});

test('multi-level blockquote with diffrent syntax', () => {
const quoteTestStartString = '> > _Hello_ *world*';
const quoteTestReplacedString = '<blockquote><blockquote><em>Hello</em> <strong>world</strong></blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});

test('multi-level blockquote with nested heading', () => {
const quoteTestStartString = '> > # Hello world';
const quoteTestReplacedString = '<blockquote><blockquote><h1>Hello world</h1></blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});

test('multiline multi-level blockquote', () => {
const quoteTestStartString = '> > Hello my\n> > beautiful\n> > world\n';
const quoteTestReplacedString = '<blockquote><blockquote>Hello my<br />beautiful<br />world</blockquote></blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});

test('multiline blockquote with diffrent levels', () => {
const quoteTestStartString = '> > > Hello my\n> > beautiful\n> world\n';
const quoteTestReplacedString = '<blockquote><blockquote><blockquote>Hello my</blockquote>beautiful</blockquote>world</blockquote>';

expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString);
});
});
36 changes: 30 additions & 6 deletions lib/ExpensiMark.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,22 @@ export default class ExpensiMark {
// To do this we need to parse body of the quote without first space
let isStartingWithSpace = false;
const textToReplace = g1.replace(/^&gt;( )?/gm, (match, g2) => {
isStartingWithSpace = !!g2;
return '';
if (shouldKeepRawInput) {
isStartingWithSpace = !!g2;
return '';
}
return match;
});
const replacedText = this.replace(textToReplace, {filterRules: ['heading1'], shouldEscapeText: false, shouldKeepRawInput});
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) {
filterRules.push('quote');
this.currentQuoteDepth++;
}

const replacedText = this.replace(textToReplace, {filterRules, shouldEscapeText: false, shouldKeepRawInput});
this.currentQuoteDepth = 1;
return `<blockquote>${isStartingWithSpace ? ' ' : ''}${replacedText}</blockquote>`;
},
},
Expand Down Expand Up @@ -464,7 +476,19 @@ export default class ExpensiMark {
* The list of rules that have to be applied when shouldKeepWhitespace flag is true.
* @type {Object[]}
*/
this.shouldKeepWhitespaceRules = this.rules.filter(rule => !this.whitespaceRulesToDisable.includes(rule.name)).map(rule => rule.name);
this.shouldKeepWhitespaceRules = this.rules.filter(rule => !this.whitespaceRulesToDisable.includes(rule.name));

/**
* maxQuoteDepth is the maximum depth of nested quotes that we want to support.
* @type {Number}
*/
this.maxQuoteDepth = 3;

/**
* currentQuoteDepth is the current depth of nested quotes that we are processing.
* @type {Number}
*/
this.currentQuoteDepth = 0;
}

/**
Expand All @@ -481,8 +505,8 @@ export default class ExpensiMark {
replace(text, {filterRules = [], shouldEscapeText = true, shouldKeepRawInput = false} = {}) {
// This ensures that any html the user puts into the comment field shows as raw html
let replacedText = shouldEscapeText ? _.escape(text) : text;
const excludeRules = shouldKeepRawInput ? _.union(this.shouldKeepWhitespaceRules, filterRules) : filterRules;
const rules = _.isEmpty(excludeRules) ? this.rules : _.filter(this.rules, rule => _.contains(excludeRules, rule.name));
const enabledRules = shouldKeepRawInput ? this.shouldKeepWhitespaceRules : this.rules;
const rules = _.isEmpty(filterRules) ? enabledRules : _.filter(this.rules, rule => _.contains(filterRules, rule.name));

try {
rules.forEach((rule) => {
Expand Down

0 comments on commit 6fa01a6

Please sign in to comment.