BMAD-METHOD/tools/installer/core/badge.js

90 lines
2.3 KiB
JavaScript

const path = require('node:path');
const { execSync } = require('node:child_process');
const fs = require('../fs-native');
const BADGE_URL = 'https://bmad-badge.vercel.app';
const BADGE_PATTERN = /\[!\[BMAD\]\(https:\/\/bmad-badge\.vercel\.app\/[^\)]+\)\]\(https:\/\/github\.com\/bmad-code-org\/BMAD-METHOD\)/;
const README_NAMES = ['README.md', 'readme.md', 'README', 'readme'];
function resolveGitRemote(projectDir) {
try {
const raw = execSync('git remote get-url origin', {
cwd: projectDir,
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'],
}).trim();
// https://github.com/owner/repo.git
const httpsMatch = raw.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
if (httpsMatch) {
return { owner: httpsMatch[1], repo: httpsMatch[2] };
}
} catch {
// no git remote
}
return null;
}
async function findReadme(projectDir) {
for (const name of README_NAMES) {
const fullPath = path.join(projectDir, name);
if (await fs.pathExists(fullPath)) {
return fullPath;
}
}
return null;
}
function hasBadge(content) {
return BADGE_PATTERN.test(content);
}
function generateBadgeMarkdown(owner, repo) {
return `[![BMAD](${BADGE_URL}/${owner}/${repo}.svg)](https://github.com/bmad-code-org/BMAD-METHOD)`;
}
function injectBadge(content, owner, repo) {
const badgeLine = generateBadgeMarkdown(owner, repo);
const lines = content.split('\n');
// Find the first heading (# title)
let headingEnd = 0;
for (let i = 0; i < lines.length; i++) {
headingEnd = i + 1;
if (lines[i].startsWith('#')) break;
}
// Check if there are existing badges right after the heading
let insertAt = headingEnd;
while (insertAt < lines.length && /^\[!\[.*?\]\(.*?\)\]\(.*?\)/.test(lines[insertAt].trim())) {
insertAt++;
}
// Insert badge line
lines.splice(insertAt, 0, badgeLine);
return lines.join('\n');
}
function removeBadge(content) {
return content
.split('\n')
.filter((line) => !BADGE_PATTERN.test(line.trim()))
.join('\n');
}
function createReadmeWithBadge(owner, repo, projectName) {
const badgeLine = generateBadgeMarkdown(owner, repo);
return `# ${projectName}\n\n${badgeLine}\n`;
}
module.exports = {
resolveGitRemote,
findReadme,
hasBadge,
generateBadgeMarkdown,
injectBadge,
removeBadge,
createReadmeWithBadge,
};