import fs from 'node:fs'
import path from 'node:path'
import vm from 'node:vm'
import ts from '../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/typescript.js'
const rootDir = process.cwd()
const outputDir = path.join(rootDir, 'client', 'public', 'badges')
const manifestPath = path.join(rootDir, 'server', 'src', 'config', 'badges.generated.json')
const manifestTsPath = path.join(rootDir, 'server', 'src', 'config', 'badges.generated.ts')
const sourceFiles = [
{
fileName: 'aaaa.html',
sourceId: 'core',
sourceLabel: '核心科幻'
},
{
fileName: 'bbbb.html',
sourceId: 'astro-zodiac',
sourceLabel: '星相生肖'
}
]
function writeManifestTs(manifest) {
fs.writeFileSync(
manifestTsPath,
`export const badgeCatalogData = ${JSON.stringify(manifest, null, 2)} as const\n`
)
}
const passthroughAttributes = new Set(['viewBox', 'xmlns', 'preserveAspectRatio'])
function toKebabCase(value) {
return value.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)
}
function toAttributeName(name) {
if (name === 'className') return 'class'
if (passthroughAttributes.has(name)) return name
return toKebabCase(name)
}
function escapeAttribute(value) {
return String(value)
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(//g, '>')
}
function serializeStyle(style) {
return Object.entries(style)
.map(([key, value]) => `${toKebabCase(key)}:${value}`)
.join(';')
}
function h(tag, props, ...children) {
const normalizedProps = props || {}
if (typeof tag === 'function') {
return tag({ ...normalizedProps, children })
}
const attributes = Object.entries(normalizedProps)
.filter(([, value]) => value !== null && value !== undefined && value !== false)
.map(([key, value]) => {
if (value === true) {
return toAttributeName(key)
}
const attrValue = key === 'style' && typeof value === 'object'
? serializeStyle(value)
: value
return `${toAttributeName(key)}="${escapeAttribute(attrValue)}"`
})
.join(' ')
const content = children
.flat(Infinity)
.filter(value => value !== null && value !== undefined && value !== false)
.join('')
return `<${tag}${attributes ? ` ${attributes}` : ''}>${content}${tag}>`
}
function Fragment(_props, ...children) {
return children.flat(Infinity).join('')
}
const gradients = [
{ id: 'supreme', dark: ['#2a2d3e', '#0a0a0f'], light: ['#ffffff', '#cbd5e1'] },
{ id: 'void', dark: ['#1a0033', '#05000a', '#000000'], light: ['#312e81', '#0f172a', '#020617'] },
{ id: 'ice', dark: ['#002244', '#000a1a'], light: ['#e0f2fe', '#7dd3fc'] },
{ id: 'gold', dark: ['#4a3b1c', '#1a140a'], light: ['#fef3c7', '#fbbf24'] },
{ id: 'moon', dark: ['#334155', '#0f172a'], light: ['#f8fafc', '#94a3b8'] },
{ id: 'omega', dark: ['#4a0000', '#1a0000'], light: ['#fee2e2', '#f87171'] },
{ id: 'matrix', dark: ['#003311', '#001100'], light: ['#dcfce7', '#4ade80'] },
{ id: 'platinum', dark: ['#475569', '#1e293b'], light: ['#ffffff', '#94a3b8'] },
{ id: 'nebula', dark: ['#581c87', '#831843', '#171717'], light: ['#f3e8ff', '#fbcfe8', '#cbd5e1'] },
{ id: 'aegis', dark: ['#0f172a', '#020617'], light: ['#f1f5f9', '#94a3b8'] },
{ id: 'reactor', dark: ['#14532d', '#052e16'], light: ['#dcfce7', '#4ade80'] },
{ id: 'tactical', dark: ['#450a0a', '#2a0000'], light: ['#fee2e2', '#f87171'] },
{ id: 'arcane', dark: ['#3b0764', '#17002e'], light: ['#f3e8ff', '#c084fc'] }
]
function buildDefs() {
const filters = `
`
const gradientMarkup = gradients.map(gradient => {
const buildGradient = (colors, theme) => {
const stops = colors.map((color, index) => {
const offset = colors.length === 1
? '0%'
: `${(index / (colors.length - 1)) * 100}%`
return ``
}).join('')
return `${stops}`
}
return [
buildGradient(gradient.dark, 'd'),
buildGradient(gradient.light, 'l')
].join('')
}).join('')
return `${filters}${gradientMarkup}`
}
const defsMarkup = buildDefs()
function injectDefs(svg, extraStyles = '') {
const withXmlns = svg.replace('