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}