diff --git a/tools/installer/core/badge.js b/tools/installer/core/badge.js index 7c1274779..af2ae11af 100644 --- a/tools/installer/core/badge.js +++ b/tools/installer/core/badge.js @@ -9,6 +9,12 @@ const BADGE_PATTERN = new RegExp( ); const README_NAMES = ['README.md', 'readme.md', 'README', 'readme']; +/** + * Resolve owner and repo from the project's git remote origin URL. + * Supports HTTPS and SSH formats. + * @param {string} projectDir - Project root directory + * @returns {{ owner: string, repo: string } | null} Parsed owner/repo or null + */ function resolveGitRemote(projectDir) { try { const raw = execSync('git remote get-url origin', { @@ -17,7 +23,6 @@ function resolveGitRemote(projectDir) { stdio: ['pipe', 'pipe', 'pipe'], }).trim(); - // https://github.com/owner/repo.git const httpsMatch = raw.match(/github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?\/?$/i); if (httpsMatch) { return { owner: httpsMatch[1], repo: httpsMatch[2] }; @@ -28,6 +33,12 @@ function resolveGitRemote(projectDir) { return null; } +/** + * Find the first README file in the project directory. + * Checks common README naming variants (case-insensitive). + * @param {string} projectDir - Project root directory + * @returns {Promise} Absolute path to README or null + */ async function findReadme(projectDir) { for (const name of README_NAMES) { const fullPath = path.join(projectDir, name); @@ -38,14 +49,33 @@ async function findReadme(projectDir) { return null; } +/** + * Check whether the content already contains a BMAD badge. + * @param {string} content - README file content + * @returns {boolean} True if badge is present + */ function hasBadge(content) { return BADGE_PATTERN.test(content); } +/** + * Generate the BMAD badge markdown line. + * @param {string} owner - Repository owner + * @param {string} repo - Repository name + * @returns {string} Badge markdown string + */ function generateBadgeMarkdown(owner, repo) { return `[![BMAD](${BADGE_URL}/${owner}/${repo}.svg)](https://github.com/bmad-code-org/BMAD-METHOD)`; } +/** + * Inject the BMAD badge into README content. + * Places the badge after the first heading, alongside any existing badges. + * @param {string} content - Original README content + * @param {string} owner - Repository owner + * @param {string} repo - Repository name + * @returns {string} Updated README content with badge + */ function injectBadge(content, owner, repo) { const badgeLine = generateBadgeMarkdown(owner, repo); @@ -64,11 +94,15 @@ function injectBadge(content, owner, repo) { insertAt++; } - // Insert badge line lines.splice(insertAt, 0, badgeLine); return lines.join('\n'); } +/** + * Remove the BMAD badge from README content. + * @param {string} content - README file content + * @returns {string} Cleaned README content without the badge line + */ function removeBadge(content) { return content .split('\n') @@ -76,6 +110,13 @@ function removeBadge(content) { .join('\n'); } +/** + * Create a minimal README.md content with project heading and BMAD badge. + * @param {string} owner - Repository owner + * @param {string} repo - Repository name + * @param {string} projectName - Project name for the heading + * @returns {string} New README content + */ function createReadmeWithBadge(owner, repo, projectName) { const badgeLine = generateBadgeMarkdown(owner, repo); return `# ${projectName}\n\n${badgeLine}\n`;