diff --git a/src/formatters/helpers/getEndOfSection.test.ts b/src/formatters/helpers/getEndOfSection.test.ts index 0cdff94..bd9bd1a 100644 --- a/src/formatters/helpers/getEndOfSection.test.ts +++ b/src/formatters/helpers/getEndOfSection.test.ts @@ -7,7 +7,7 @@ test("getEndOfSection - find the end of a section", () => { "", "## Section 1", // target (2) "Content 1", // result (3) - "", + "", "## Section 2", "Content 2", "", @@ -85,7 +85,7 @@ test("getEndOfSection - find end of section with higher level section", () => { "", "## Section 2", "Content 2", // result (6) - "", + "", "# Title 2", "Content 3", ]; @@ -96,14 +96,14 @@ test("getEndOfSection - find end of section with higher level section", () => { }); test("getEndOfSection - find end of section with no headings", () => { - const lines = [ - "Content 1", - "", - "Content 2", // target (2) - "Content 3", // result (3) - "", - "Content 4" - ]; + const lines = [ + "Content 1", + "", + "Content 2", // target (2) + "Content 3", // result (3) + "", + "Content 4", + ]; const targetLine = 2; const result = getEndOfSection(lines, targetLine); @@ -127,7 +127,7 @@ test("getEndOfSection - find end of section with top level heading and only sub "", "## Topic B", "content b1", // result (14) - "", + "", "", ]; @@ -145,7 +145,7 @@ test("getEndOfSection - target isn't heading", () => { "content a1", // target (3) "content a2", "content a3", // result (5) - "", + "", "---", "Thematic break", "1", @@ -165,42 +165,76 @@ test("getEndOfSection - target isn't heading", () => { }); test("getEndOfSection - target is heading, should not consider subsections", () => { - const lines = [ - "# Notes", - "", - "## Topic A", // target (2) - "content a1", - "content a2", - "content a3", // result (5) - "## Topic B", - "content b1", - "", - "", - ]; - - const targetLine = 2; - - const result = getEndOfSection(lines, targetLine, false); - expect(result).toBe(5); + const lines = [ + "# Notes", + "", + "## Topic A", // target (2) + "content a1", + "content a2", + "content a3", // result (5) + "## Topic B", + "content b1", + "", + "", + ]; + + const targetLine = 2; + + const result = getEndOfSection(lines, targetLine, false); + expect(result).toBe(5); }); test("getEndOfSection - target is heading, should consider subsections", () => { - const lines = [ - "# Notes", // target (0) - "", - "## Topic A", - "content a1", - "## Topic B", - "content b1", - "### contentA", - "content", - "#### contentB", - "content", - "content", // target (10) - ]; - - const targetLine = 0; - - const result = getEndOfSection(lines, targetLine, true); - expect(result).toBe(10); -}); \ No newline at end of file + const lines = [ + "# Notes", // target (0) + "", + "## Topic A", + "content a1", + "## Topic B", + "content b1", + "### contentA", + "content", + "#### contentB", + "content", + "content", // target (10) + ]; + + const targetLine = 0; + + const result = getEndOfSection(lines, targetLine, true); + expect(result).toBe(10); +}); + +test("getEndOfSection - Capture to first line, shoudlConsiderSubsections ON", () => { + const lines = [ + "# Meeting Notes", // target (0) + "", + "### Topic A", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet commodo mi, nec consequat tellus.", + "", + "### Topic B", + "Aliquam erat volutpat. Nullam fringilla, enim eu volutpat congue, odio elit imperdiet felis, non congue est justo cursus dui.", // result (6) + ]; + + const targetLine = 0; + + const result = getEndOfSection(lines, targetLine, true); + expect(result).toBe(6); +}); + +test("getEndOfSection - Capture to first line, shoudlConsiderSubsections OFF", () => { + const lines = [ + "# Meeting Notes", // target (0) + "", // result (1) + "### Topic A", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet commodo mi, nec consequat tellus.", + "", + "### Topic B", + "Aliquam erat volutpat. Nullam fringilla, enim eu volutpat congue, odio elit imperdiet felis, non congue est justo cursus dui.", + ]; + + const targetLine = 0; + + const result = getEndOfSection(lines, targetLine, false); + expect(result).toBe(1); +}); diff --git a/src/formatters/helpers/getEndOfSection.ts b/src/formatters/helpers/getEndOfSection.ts index d053c09..d9ddcd4 100644 --- a/src/formatters/helpers/getEndOfSection.ts +++ b/src/formatters/helpers/getEndOfSection.ts @@ -69,7 +69,7 @@ export default function getEndOfSection( const endOfSectionLineIdx = getEndOfSectionLineByHeadings( targetHeading as Heading, headings, - lastLineInBodyIdx, + lines, shouldConsiderSubsections ); @@ -78,11 +78,16 @@ export default function getEndOfSection( endOfSectionLineIdx, (str: string) => str.trim() !== "" ); - + if (lastNonEmptyLineInSectionIdx !== null) { - if (lastNonEmptyLineInSectionIdx + 1 === lastLineInBodyIdx) { - return endOfSectionLineIdx; - } + if (lastNonEmptyLineInSectionIdx + 1 === lastLineInBodyIdx) { + return endOfSectionLineIdx; + } + + if (lastNonEmptyLineInSectionIdx === 0) { + return lastNonEmptyLineInSectionIdx + 1; + } + return lastNonEmptyLineInSectionIdx; } @@ -92,13 +97,14 @@ export default function getEndOfSection( function getEndOfSectionLineByHeadings( targetHeading: Heading, headings: Heading[], - lastLineInBodyIdx: number, + lines: string[], shouldConsiderSubsections: boolean ): number { const targetHeadingIdx = headings.findIndex((heading) => isSameHeading(heading, targetHeading) ); const targetHeadingIsLastHeading = targetHeadingIdx === headings.length - 1; + const lastLineInBodyIdx = lines.length - 1; if (targetHeadingIsLastHeading) { return lastLineInBodyIdx; @@ -126,6 +132,15 @@ function getEndOfSectionLineByHeadings( return headings[targetHeadingIdx + 1].line; } + if (!shouldConsiderSubsections && !foundHigherOrSameLevelHeading) { + const nextHeading = findNextHeading(targetHeading.line, headings); + if (nextHeading === null) { + return lastLineInBodyIdx; + } + + return nextHeading; + } + // There are no higher level sections, but there may be more sections. return lastLineInBodyIdx; } @@ -151,6 +166,17 @@ function findNextHigherOrSameLevelHeading( return [nextSameOrHigherLevelHeadingIdx, true]; } +function findNextHeading( + fromIdxInBody: number, + headings: Heading[] +): number | null { + const nextheading = headings.findIndex( + (heading) => heading.line > fromIdxInBody + ); + + return nextheading === -1 ? null : nextheading; +} + function findPriorIdx( items: T[], fromIdx: number,