diff --git a/src/index.ts b/src/index.ts index cb72d79..101f746 100644 --- a/src/index.ts +++ b/src/index.ts @@ -801,8 +801,32 @@ export function mergeAgentsFiles(agentsFiles: string[]): string { for (const [, section] of Object.entries(allSections)) { result.push(`${'#'.repeat(section.level)} ${section.title}`); result.push(''); - for (const content of section.contents) { + for (let i = 0; i < section.contents.length; i++) { + const content = section.contents[i]; + const nextContent = section.contents[i + 1]; + result.push(content); + + if (nextContent) { + const lastNewLineIndex = content.lastIndexOf('\n'); + const lastLine = + lastNewLineIndex === -1 + ? content + : content.substring(lastNewLineIndex + 1); + + const firstNewLineIndex = nextContent.indexOf('\n'); + const nextFirstLine = + firstNewLineIndex === -1 + ? nextContent + : nextContent.substring(0, firstNewLineIndex); + + // If both blocks are part of an unordered list (starting with '- '), + // skip the newline to merge them. + if (lastLine.startsWith('- ') && nextFirstLine.startsWith('- ')) { + continue; + } + } + result.push(''); } } diff --git a/test/agents.test.ts b/test/agents.test.ts index f6ff2eb..b215d5d 100644 --- a/test/agents.test.ts +++ b/test/agents.test.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { assert, beforeEach, expect, test } from '@rstest/core'; -import { create } from '../src'; +import { create, mergeAgentsFiles } from '../src'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const fixturesDir = path.join(__dirname, 'fixtures', 'agents-md'); @@ -233,3 +233,97 @@ test('should merge top-level sections from AGENTS.md files', async () => { " `); }); + +test('mergeAgentsFiles should handle unordered lists without extra newline', () => { + const file1 = ` +## Tools + +- item 1 +- item 2 +`; + const file2 = ` +## Tools + +- item 3 +`; + + const merged = mergeAgentsFiles([file1, file2]); + + expect(merged).toMatchInlineSnapshot(` + "## Tools + + - item 1 + - item 2 + - item 3" + `); +}); + +test('mergeAgentsFiles should still add newline for non-list content', () => { + const file1 = ` +## Tools + +Some intro text. +`; + const file2 = ` +## Tools + +More text. +`; + + const merged = mergeAgentsFiles([file1, file2]); + + expect(merged).toMatchInlineSnapshot(` + "## Tools + + Some intro text. + + More text." + `); +}); + +test('mergeAgentsFiles should not skip newline for horizontal rules (---)', () => { + const file1 = ` +## Tools + +--- +`; + const file2 = ` +## Tools + +- item 1 +`; + + const merged = mergeAgentsFiles([file1, file2]); + + expect(merged).toMatchInlineSnapshot(` + "## Tools + + --- + + - item 1" + `); +}); + +test('mergeAgentsFiles should add newline when paragraph is followed by list', () => { + const file1 = ` +## Tools + +Some intro text. +`; + const file2 = ` +## Tools + +- item 1 +`; + + const merged = mergeAgentsFiles([file1, file2]); + + // Revised requirement: Paragraph followed by list SHOULD have a newline. + expect(merged).toMatchInlineSnapshot(` + "## Tools + + Some intro text. + + - item 1" + `); +});