master
1import fs from 'node:fs'
2import path from 'node:path'
3import { Badge } from './badges.js'
4import { quoteAttr } from './utils.js'
5import { log } from './log.js'
6
7const START_MARK = '<!-- my-badges start -->'
8const END_MARK = '<!-- my-badges end -->'
9const BADGE_SIZE = 64
10
11export function updateReadme(
12 badges: Badge[],
13 size: number | string,
14 repoDir: string,
15) {
16 const readmeFilename = detectReadmeFilename(repoDir)
17 const readmeContent = fs.readFileSync(readmeFilename, 'utf8')
18
19 const content = generateReadme(readmeContent, badges, size)
20 fs.writeFileSync(readmeFilename, content)
21}
22
23function detectReadmeFilename(cwd: string): string {
24 const file = ['README.md', 'readme.md']
25 .map((f) => path.resolve(cwd, f))
26 .find((f) => fs.existsSync(f))
27 if (!file) throw new Error('Cannot find README.md')
28
29 return file
30}
31
32export function generateReadme(
33 content: string,
34 badges: Badge[],
35 size: number | string = BADGE_SIZE,
36) {
37 log.info('Updating README.md...')
38
39 const start = content.indexOf(START_MARK)
40 const end = content.indexOf(END_MARK)
41 if ((start === -1 && end !== -1) || (start !== -1 && end === -1))
42 throw new Error(
43 'Invalid README.md: both or none of the marks should be present',
44 )
45
46 if (start > end)
47 throw new Error('Invalid README.md: start mark should be before end mark')
48
49 const badgesHtml = badges
50 .map((badge) => {
51 const desc = quoteAttr(badge.desc)
52 // prettier-ignore
53 return `<a href="my-badges/${badge.id}.md"><img src="${badge.image}" alt="${desc}" title="${desc}" width="${parseInt(size + '')}"></a>`
54 })
55 .join('\n')
56
57 if (end === -1 && start === -1)
58 return `${START_MARK}
59${badgesHtml}
60${END_MARK}
61
62${content}`
63
64 return `${content.slice(0, start)}${START_MARK}
65${badgesHtml}
66${END_MARK}${content.slice(end + END_MARK.length)}`
67}