diff --git a/__tests__/empty-line-around-blockquotes.test.ts b/__tests__/empty-line-around-blockquotes.test.ts index c6e3d21f..70fa4d1a 100644 --- a/__tests__/empty-line-around-blockquotes.test.ts +++ b/__tests__/empty-line-around-blockquotes.test.ts @@ -23,7 +23,7 @@ ruleTest({ `, }, { // accounts for https://github.com/platers/obsidian-linter/issues/668 - testname: 'Make sure that consecutive blockquotes are not merged when multiple blank lines are between them', + testName: 'Make sure that consecutive blockquotes are not merged when multiple blank lines are between them', before: dedent` > [!quote] title 1 > the quote 1 @@ -90,5 +90,41 @@ ruleTest({ > The quote 3 `, }, + { // accounts for https://github.com/platers/obsidian-linter/issues/684 + testName: 'Make sure that consecutive blockquotes do not get merged when the first one ends with an empty blockquote line', + before: dedent` + > [!FAQ] Title + > + ${''} + > [!NOTES] Title + > Content + `, + after: dedent` + > [!FAQ] Title + > + ${''} + > [!NOTES] Title + > Content + `, + }, + { // accounts for https://github.com/platers/obsidian-linter/issues/684 + testName: 'Make sure that consecutive blockquotes do not get merged when the second one starts with an empty blockquote line', + before: dedent` + > [!FAQ] Title + > Content here + ${''} + > + > [!NOTES] Title + > Content + `, + after: dedent` + > [!FAQ] Title + > Content here + ${''} + > + > [!NOTES] Title + > Content + `, + }, ], }); diff --git a/src/utils/strings.ts b/src/utils/strings.ts index 939d0efb..5490779e 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -92,21 +92,33 @@ function makeSureContentHasASingleEmptyLineBeforeItUnlessItStartsAFileForBlockqu let index = startOfContent; let startOfNewContent = startOfContent; let lineNestingLevel = 0; + let foundABlankLine = false; + let previousChar = ''; while (index >= 0) { const currentChar = text.charAt(index); if (currentChar.trim() !== '' && currentChar !== '>') { break; // if non-whitespace, non-gt-bracket is encountered, then the line has content } else if (currentChar === '>') { + // if we go from having a blank line at any point to then having more blockquote content we know we have encountered another blockquote + if (foundABlankLine) { + break; + } + lineNestingLevel++; } else if (currentChar === '\n') { if (lineNestingLevel === 0 || lineNestingLevel === nestingLevel || (lineNestingLevel + 1) === nestingLevel) { startOfNewContent = index; lineNestingLevel = 0; + + if (previousChar === '\n') { + foundABlankLine = true; + } } else { break; } } index--; + previousChar = currentChar; } if (index < 0 || startOfNewContent === 0) { @@ -169,11 +181,18 @@ function makeSureContentHasASingleEmptyLineAfterItUnlessItEndsAFileForBlockquote let endOfNewContent = endOfContent; let isFirstNewLine = true; let lineNestingLevel = 0; + let foundABlankLine = false; + let previousChar = ''; while (index < text.length) { const currentChar = text.charAt(index); if (currentChar.trim() !== '' && currentChar !== '>') { break; // if non-whitespace is encountered, then the line has content } else if (currentChar === '>') { + // if we go from having a blank line at any point to then having more blockquote content we know we have encountered another blockquote + if (foundABlankLine) { + break; + } + lineNestingLevel++; } else if (currentChar === '\n') { if (lineNestingLevel === 0 || lineNestingLevel === nestingLevel || (lineNestingLevel + 1) === nestingLevel) { @@ -183,11 +202,17 @@ function makeSureContentHasASingleEmptyLineAfterItUnlessItEndsAFileForBlockquote } else { endOfNewContent = index; } + + if (previousChar === '\n') { + foundABlankLine = true; + } } else { break; } } index++; + + previousChar = currentChar; } if (index === text.length || endOfNewContent === text.length - 1) {