diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 6cc6acf..0b0b6db 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -106,6 +106,7 @@ export default async function createConfigAsync() { }, plugins: [ require.resolve('./plugins/llms-txt'), + require.resolve('./plugins/og-images'), [ 'docusaurus-plugin-github-editor', { @@ -235,6 +236,8 @@ export default async function createConfigAsync() { { name: 'theme-color', content: '#D35F5F' }, { property: 'og:site_name', content: 'RaidProtect' }, { property: 'og:type', content: 'website' }, + { name: 'twitter:site', content: '@raidprotect' }, + { name: 'twitter:creator', content: '@raidprotect' }, ], docs: { versionPersistence: 'localStorage', diff --git a/package.json b/package.json index 0c8c3fb..edaffc8 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,9 @@ "@docusaurus/module-type-aliases": "^3.10.2", "@docusaurus/tsconfig": "^3.10.2", "@docusaurus/types": "^3.10.2", + "@resvg/resvg-js": "^2.6.2", + "satori": "^0.33.4", + "sharp": "^0.35.4", "typescript": "~5.6.2" }, "browserslist": { diff --git a/plugins/og-images/fonts/nohemi-700.ttf b/plugins/og-images/fonts/nohemi-700.ttf new file mode 100644 index 0000000..56caded Binary files /dev/null and b/plugins/og-images/fonts/nohemi-700.ttf differ diff --git a/plugins/og-images/fonts/objectivity-regular.otf b/plugins/og-images/fonts/objectivity-regular.otf new file mode 100644 index 0000000..9ca7971 Binary files /dev/null and b/plugins/og-images/fonts/objectivity-regular.otf differ diff --git a/plugins/og-images/index.js b/plugins/og-images/index.js new file mode 100644 index 0000000..c889483 --- /dev/null +++ b/plugins/og-images/index.js @@ -0,0 +1,376 @@ +/* Plugin Docusaurus : génère au build une image Open Graph (1200x630) par page + * de doc, de glossaire, d'article de blog et pour les pages marketing, à partir + * du titre + l'icône de la fonctionnalité (et un chiffre clé sur l'accueil), + * puis injecte og:image / twitter:image / og:type / og:image:alt dans le HTML. + * Rendu via Satori (HTML/CSS -> SVG) + resvg (SVG -> PNG) + sharp (compression). + * Tourne par locale (titres localisés). Cache persistant pour des rebuilds rapides. + * + * Build-time only : les polices TTF/OTF vivent dans ce dossier (non servies). */ + +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +const TEMPLATE_VERSION = '3'; // bump pour invalider le cache +const LOCALES = ['en', 'de', 'es', 'pt']; + +const FEATURE_ICON = { + 'raid-mode': 'iconAntiraidWhite.svg', + 'anti-spam': 'iconAntispamWhite.svg', + captcha: 'iconCaptchaWhite.svg', + 'authentication-manager': 'iconAuthManagerWhite.svg', + honeypot: 'iconHoneyPotWhite.svg', + reports: 'iconReportWhite.svg', + 'scam-images': 'iconScamLens.svg', + display: 'iconDisplayWhite.svg', + 'dm-lock': 'iconDmlockWhite.svg', + 'tag-role': 'iconTagWhite.svg', + moderation: 'iconModView.svg', + sanctions: 'iconSanctions.svg', +}; + +const CATEGORY = { + fr: {docs: 'Documentation', learn: 'Glossaire', blog: 'Blog'}, + en: {docs: 'Documentation', learn: 'Glossary', blog: 'Blog'}, + de: {docs: 'Dokumentation', learn: 'Glossar', blog: 'Blog'}, + es: {docs: 'Documentación', learn: 'Glosario', blog: 'Blog'}, + pt: {docs: 'Documentação', learn: 'Glossário', blog: 'Blog'}, +}; + +const TAGLINE = { + fr: 'Bot Discord de modération et de protection', + en: 'Discord moderation & protection bot', + de: 'Discord-Bot für Moderation und Schutz', + es: 'Bot de moderación y protección para Discord', + pt: 'Bot de moderação e proteção para Discord', +}; + +// Chiffre clé de l'accueil (aligné sur le count par défaut du site). +const STAT = { + fr: '400 000+ serveurs · 55M+ membres protégés', + en: '400,000+ servers · 55M+ protected members', + de: '400.000+ Server · 55M+ geschützte Mitglieder', + es: '400 000+ servidores · 55M+ miembros protegidos', + pt: '400.000+ servidores · 55M+ membros protegidos', +}; + +// Pages marketing (chemins relatifs à l'outDir de la locale). +const MARKETING = [ + 'premium.html', + 'business.html', + 'communities/games.html', + 'communities/creators.html', +]; + +// Pages commerciales : titre + points mis en avant (au lieu du simple titre). +const HIGHLIGHTS = { + 'premium.html': { + pill: 'Premium', + title: { + fr: 'Poussez RaidProtect plus loin', + en: 'Push RaidProtect further', + de: 'Holen Sie mehr aus RaidProtect', + es: 'Lleva RaidProtect más lejos', + pt: 'Leve o RaidProtect além', + }, + points: { + fr: ['Sanctions à votre vocabulaire', 'Anti-raid en mode expulsion', 'Limites étendues sur vos modules', 'Accès anticipé aux nouveautés'], + en: ['Sanctions in your own words', 'Kick-mode anti-raid', 'Higher limits on your modules', 'Early access to new features'], + de: ['Sanktionen in Ihren Worten', 'Anti-Raid im Kick-Modus', 'Höhere Limits für Ihre Module', 'Früher Zugang zu Neuheiten'], + es: ['Sanciones a tu medida', 'Anti-raid en modo expulsión', 'Límites ampliados en tus módulos', 'Acceso anticipado a novedades'], + pt: ['Sanções no seu vocabulário', 'Anti-raid em modo expulsão', 'Limites ampliados nos seus módulos', 'Acesso antecipado às novidades'], + }, + }, + 'business.html': { + pill: 'Business', + title: { + fr: 'RaidProtect pour les entreprises', + en: 'RaidProtect for companies', + de: 'RaidProtect für Unternehmen', + es: 'RaidProtect para empresas', + pt: 'RaidProtect para empresas', + }, + points: { + fr: ['Modérateurs professionnels', 'Instance dédiée et isolée', 'Conformité RGPD assumée', 'Audit et suivi humain'], + en: ['Professional moderators', 'Dedicated, isolated instance', 'GDPR compliant', 'Expert audit & human follow-up'], + de: ['Professionelle Moderatoren', 'Dedizierte, isolierte Instanz', 'DSGVO-konform', 'Experten-Audit & menschliche Betreuung'], + es: ['Moderadores profesionales', 'Instancia dedicada y aislada', 'Cumplimiento del RGPD', 'Auditoría y seguimiento humano'], + pt: ['Moderadores profissionais', 'Instância dedicada e isolada', 'Conformidade com o RGPD', 'Auditoria e acompanhamento humano'], + }, + }, +}; + +function walk(dir) { + const out = []; + if (!fs.existsSync(dir)) return out; + for (const e of fs.readdirSync(dir, {withFileTypes: true})) { + const full = path.join(dir, e.name); + if (e.isDirectory()) out.push(...walk(full)); + else if (e.name.endsWith('.html')) out.push(full); + } + return out; +} + +const isVersionSegment = (seg) => seg === 'beta' || /^\d+\.\d+/.test(seg); + +const decode = (s) => + s + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, "'") + .replace(/'/g, "'"); + +function extractTitle(html) { + const m = html.match(/]*>([^<]*)<\/title>/i); + if (!m) return null; + return decode(m[1]).replace(/\s*\|\s*RaidProtect\s*$/, '').trim(); +} + +const el = (type, style, children) => ({type, props: {style, ...(children !== undefined ? {children} : {})}}); + +module.exports = function ogImagesPlugin(context) { + const {currentLocale, defaultLocale} = context.i18n; + const localePrefix = currentLocale === defaultLocale ? '' : `/${currentLocale}`; + const cat = CATEGORY[currentLocale] || CATEGORY[defaultLocale] || CATEGORY.fr; + const tagline = TAGLINE[currentLocale] || TAGLINE[defaultLocale] || TAGLINE.fr; + const stat = STAT[currentLocale] || STAT[defaultLocale] || STAT.fr; + const iconsDir = path.join(context.siteDir, 'static/img/icons'); + const cacheDir = path.join(context.siteDir, 'node_modules/.cache/og-images'); + + return { + name: 'og-images', + async postBuild({siteConfig, outDir}) { + const satori = (await import('satori')).default; + const {Resvg} = require('@resvg/resvg-js'); + const sharp = require('sharp'); + + const fonts = [ + {name: 'Nohemi', data: fs.readFileSync(path.join(__dirname, 'fonts/nohemi-700.ttf')), weight: 700, style: 'normal'}, + {name: 'Objectivity', data: fs.readFileSync(path.join(__dirname, 'fonts/objectivity-regular.otf')), weight: 400, style: 'normal'}, + ]; + + const iconCache = {}; + const iconDataUri = (file) => { + if (!file) return null; + if (file in iconCache) return iconCache[file]; + try { + const svg = fs.readFileSync(path.join(iconsDir, file), 'utf8'); + const png = new Resvg(svg, {fitTo: {mode: 'width', value: 180}}).render().asPng(); + iconCache[file] = `data:image/png;base64,${Buffer.from(png).toString('base64')}`; + } catch { + iconCache[file] = null; + } + return iconCache[file]; + }; + + let logoUri = null; + try { + const logoSvg = fs.readFileSync(path.join(iconsDir, 'extend_logo.svg'), 'utf8'); + const logoPng = new Resvg(logoSvg, {fitTo: {mode: 'width', value: 660}}).render().asPng(); + logoUri = `data:image/png;base64,${Buffer.from(logoPng).toString('base64')}`; + } catch { + logoUri = null; + } + + // Coche rouge pour les points mis en avant (premium/business). + const checkSvg = + ''; + const checkUri = `data:image/png;base64,${Buffer.from( + new Resvg(checkSvg, {fitTo: {mode: 'width', value: 56}}).render().asPng(), + ).toString('base64')}`; + + // Collecte des pages + leur type. + const pages = []; + const add = (file, kind) => { + const rel = path.relative(outDir, file).split(path.sep).join('/'); + pages.push({file, rel, kind}); + }; + for (const file of walk(path.join(outDir, 'docs'))) { + const rel = path.relative(outDir, file).split(path.sep).join('/'); + const segs = rel.split('/'); + if (LOCALES.includes(segs[0])) continue; + if (isVersionSegment((segs[1] || '').replace(/\.html$/, ''))) continue; + if (/^docs\/edit(\.html)?$/.test(rel) || /\/tags\//.test(rel) || /(^|\/)404/.test(rel)) continue; + add(file, 'docs'); + } + for (const file of walk(path.join(outDir, 'learn'))) { + const rel = path.relative(outDir, file).split(path.sep).join('/'); + if (LOCALES.includes(rel.split('/')[0])) continue; + if (/\/tags\//.test(rel)) continue; + add(file, 'learn'); + } + // Le blog est volontairement exclu : chaque article a sa propre image + // (frontmatter `image:`), qu'on ne doit pas écraser. + add(path.join(outDir, 'index.html'), 'home'); + for (const rel of MARKETING) { + const file = path.join(outDir, rel); + if (fs.existsSync(file)) add(file, 'marketing'); + } + + const ogDir = path.join(outDir, 'img', 'og'); + fs.mkdirSync(ogDir, {recursive: true}); + fs.mkdirSync(cacheDir, {recursive: true}); + const base = (siteConfig.url || 'https://raidprotect.bot').replace(/\/$/, '') + localePrefix; + let count = 0; + + for (const p of pages) { + if (!fs.existsSync(p.file)) continue; + const html = fs.readFileSync(p.file, 'utf8'); + let title = extractTitle(html); + if (!title) continue; + + let category = null; + let iconFile = null; + let footer = 'raidprotect.bot'; + let ogType = 'website'; + if (p.kind === 'docs') { + category = cat.docs; + ogType = 'article'; + const fm = p.rel.match(/^docs\/features\/([a-z-]+)\.html$/); + if (fm) iconFile = FEATURE_ICON[fm[1]] || null; + } else if (p.kind === 'learn') { + category = cat.learn; + ogType = 'article'; + } else if (p.kind === 'blog') { + category = cat.blog; + ogType = 'article'; + } else if (p.kind === 'home') { + title = title.replace(/^RaidProtect\s*[•·—-]\s*/, ''); + footer = stat; + } + + // Pages commerciales : titre + points mis en avant. + const hl = p.kind === 'marketing' ? HIGHLIGHTS[p.rel] : null; + const hlTitle = hl ? hl.title[currentLocale] || hl.title[defaultLocale] : null; + const hlPoints = hl ? hl.points[currentLocale] || hl.points[defaultLocale] : null; + if (hl) category = hl.pill; + + // Cache : clé sur les entrées qui influent le rendu. + const key = crypto + .createHash('sha1') + .update( + [TEMPLATE_VERSION, currentLocale, p.kind, title, iconFile || '', category || '', footer, hlTitle || '', hlPoints ? hlPoints.join('¦') : ''].join('|'), + ) + .digest('hex'); + const cachePath = path.join(cacheDir, `${key}.png`); + + let png; + if (fs.existsSync(cachePath)) { + png = fs.readFileSync(cachePath); + } else { + const icon = iconFile ? iconDataUri(iconFile) : null; + const svg = await satori( + el('div', { + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + width: '100%', + height: '100%', + padding: 72, + backgroundColor: '#111019', + backgroundImage: 'radial-gradient(1200px 630px at 100% 0%, rgba(211,95,95,0.28), rgba(17,16,25,0) 60%)', + color: '#ffffff', + fontFamily: 'Objectivity', + }, [ + el('div', {display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between'}, [ + el('div', {display: 'flex', flexDirection: 'column'}, [ + logoUri + ? {type: 'img', props: {src: logoUri, width: 330, height: 42, style: {width: 330, height: 42}}} + : el('div', {display: 'flex', fontFamily: 'Nohemi', fontSize: 34, fontWeight: 700}, 'RaidProtect'), + el('div', {display: 'flex', fontSize: 23, color: '#8f8ea0', marginTop: 16}, tagline), + ]), + ...(category + ? [el('div', { + display: 'flex', + fontSize: 22, + padding: '8px 20px', + borderRadius: 999, + color: '#cbcad6', + border: '1px solid rgba(255,255,255,0.22)', + }, category)] + : []), + ]), + el( + 'div', + {display: 'flex', flexDirection: 'column'}, + hlTitle + ? [ + el('div', { + display: 'flex', + fontFamily: 'Nohemi', + fontSize: 50, + fontWeight: 700, + lineHeight: 1.1, + marginBottom: 30, + maxWidth: 1000, + }, hlTitle), + el('div', {display: 'flex', flexDirection: 'column'}, + hlPoints.map((pt) => + el('div', {display: 'flex', alignItems: 'center', marginTop: 16, fontSize: 29, color: '#e1e0e9'}, [ + {type: 'img', props: {src: checkUri, width: 30, height: 30, style: {width: 30, height: 30, marginRight: 18}}}, + pt, + ]), + ), + ), + ] + : [ + ...(icon + ? [el('div', { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: 116, + height: 116, + borderRadius: 26, + backgroundColor: 'rgba(255,255,255,0.08)', + marginBottom: 30, + }, [{type: 'img', props: {src: icon, width: 68, height: 68, style: {width: 68, height: 68}}}])] + : []), + el('div', { + display: 'flex', + fontFamily: 'Nohemi', + fontSize: title.length > 48 ? 56 : 68, + fontWeight: 700, + lineHeight: 1.1, + maxWidth: 1000, + }, title), + ], + ), + el('div', {display: 'flex', fontSize: 26, color: '#8f8ea0'}, footer), + ]), + {width: 1200, height: 630, fonts}, + ); + const raw = new Resvg(svg).render().asPng(); + png = await sharp(raw).png({palette: true, compressionLevel: 9, effort: 8}).toBuffer(); + fs.writeFileSync(cachePath, png); + } + + const name = (p.rel === 'index.html' ? 'home' : p.rel.replace(/\.html$/, '').replace(/\//g, '-')) + '.png'; + fs.writeFileSync(path.join(ogDir, name), png); + + const url = `${base}/img/og/${name}`; + const alt = title.replace(/"/g, '"'); + let head = html + .replace(/]+property="og:image(:width|:height|:alt)?"[^>]*>/gi, '') + .replace(/]+name="twitter:image"[^>]*>/gi, '') + .replace(/]+name="twitter:card"[^>]*>/gi, '') + .replace(/]+property="og:type"[^>]*>/gi, ''); + const tags = + `` + + `` + + `` + + `` + + `` + + `` + + ``; + head = head.replace('', `${tags}`); + fs.writeFileSync(p.file, head); + count++; + } + + console.log(`[og-images] (${currentLocale}) ${count} images OG (docs, learn, marketing, accueil).`); + }, + }; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e2d6fe..ddadbfc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,15 @@ importers: '@docusaurus/types': specifier: ^3.10.2 version: 3.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@resvg/resvg-js': + specifier: ^2.6.2 + version: 2.6.2 + satori: + specifier: ^0.33.4 + version: 0.33.4 + sharp: + specifier: ^0.35.4 + version: 0.35.4 typescript: specifier: ~5.6.2 version: 5.6.3 @@ -1303,12 +1312,161 @@ packages: resolution: {integrity: sha512-xx0W3eav2uW1NRIpuHJWNwLTC15xPNjU4Uxi9NSnd3swYC96BE3vFiT93SD8s24kmAAWNwgZwfZ2fghGZ01Lcw==} engines: {node: '>=20.0'} + '@emnapi/runtime@1.11.3': + resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.35.4': + resolution: {integrity: sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.35.4': + resolution: {integrity: sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.4': + resolution: {integrity: sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==} + engines: {node: '>=20.9.0'} + os: [freebsd] + + '@img/sharp-libvips-darwin-arm64@1.3.3': + resolution: {integrity: sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.3.3': + resolution: {integrity: sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.3.3': + resolution: {integrity: sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.3.3': + resolution: {integrity: sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.3.3': + resolution: {integrity: sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.3.3': + resolution: {integrity: sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.3.3': + resolution: {integrity: sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.3.3': + resolution: {integrity: sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.3.3': + resolution: {integrity: sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.3.3': + resolution: {integrity: sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.35.4': + resolution: {integrity: sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.35.4': + resolution: {integrity: sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.35.4': + resolution: {integrity: sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.35.4': + resolution: {integrity: sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.35.4': + resolution: {integrity: sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.35.4': + resolution: {integrity: sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.35.4': + resolution: {integrity: sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.35.4': + resolution: {integrity: sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.35.4': + resolution: {integrity: sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.4': + resolution: {integrity: sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.35.4': + resolution: {integrity: sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.35.4': + resolution: {integrity: sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.35.4': + resolution: {integrity: sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1587,6 +1745,87 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@resvg/resvg-js-android-arm-eabi@2.6.2': + resolution: {integrity: sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@resvg/resvg-js-android-arm64@2.6.2': + resolution: {integrity: sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@resvg/resvg-js-darwin-arm64@2.6.2': + resolution: {integrity: sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@resvg/resvg-js-darwin-x64@2.6.2': + resolution: {integrity: sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@resvg/resvg-js-linux-arm-gnueabihf@2.6.2': + resolution: {integrity: sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@resvg/resvg-js-linux-arm64-gnu@2.6.2': + resolution: {integrity: sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@resvg/resvg-js-linux-arm64-musl@2.6.2': + resolution: {integrity: sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@resvg/resvg-js-linux-x64-gnu@2.6.2': + resolution: {integrity: sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@resvg/resvg-js-linux-x64-musl@2.6.2': + resolution: {integrity: sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@resvg/resvg-js-win32-arm64-msvc@2.6.2': + resolution: {integrity: sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@resvg/resvg-js-win32-ia32-msvc@2.6.2': + resolution: {integrity: sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@resvg/resvg-js-win32-x64-msvc@2.6.2': + resolution: {integrity: sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@resvg/resvg-js@2.6.2': + resolution: {integrity: sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==} + engines: {node: '>= 10'} + + '@shuding/opentype.js@1.4.0-beta.0': + resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} + engines: {node: '>= 8.0.0'} + hasBin: true + '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -2051,6 +2290,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@0.0.8: + resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==} + engines: {node: '>= 0.4'} + baseline-browser-mapping@2.10.0: resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} engines: {node: '>=6.0.0'} @@ -2150,6 +2393,9 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} + camelize@1.0.1: + resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} @@ -2361,18 +2607,32 @@ packages: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} + css-background-parser@0.1.0: + resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==} + css-blank-pseudo@7.0.1: resolution: {integrity: sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==} engines: {node: '>=18'} peerDependencies: postcss: ^8.4 + css-box-shadow@1.0.0-3: + resolution: {integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==} + + css-color-keywords@1.0.0: + resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} + engines: {node: '>=4'} + css-declaration-sorter@7.3.1: resolution: {integrity: sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss: ^8.0.9 + css-gradient-parser@0.0.17: + resolution: {integrity: sha512-w2Xy9UMMwlKtou0vlRnXvWglPAceXCTtcmVSo8ZBUvqCV5aXEFP/PC6d+I464810I9FT++UACwTD5511bmGPUg==} + engines: {node: '>=16'} + css-has-pseudo@7.0.3: resolution: {integrity: sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==} engines: {node: '>=18'} @@ -2428,6 +2688,9 @@ packages: css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + css-to-react-native@3.2.0: + resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + css-tree@2.2.1: resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} @@ -2558,6 +2821,10 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} @@ -2634,6 +2901,10 @@ packages: electron-to-chromium@1.5.307: resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==} + emoji-regex-xs@2.0.1: + resolution: {integrity: sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==} + engines: {node: '>=10.0.0'} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2817,6 +3088,9 @@ packages: resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==} engines: {node: '>=0.4.0'} + fflate@0.7.3: + resolution: {integrity: sha512-0Zz1jOzJWERhyhsimS54VTqOteCNwRtIlh8isdL0AXLo0g7xNTfTL7oWrkmCnPhZGocKIkWHBistBrrpoNH3aw==} + file-loader@6.2.0: resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} @@ -2955,6 +3229,9 @@ packages: handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + harfbuzzjs@0.10.0: + resolution: {integrity: sha512-SN8LVwCOzvTq3OPNd0+EAghgXugItz56wst567D1vs7LnnKGWprhi3EG58aVOBwhN8HEbQxL4I9NDWkcXUutRw==} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -3002,6 +3279,10 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + hex-rgb@4.3.0: + resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==} + engines: {node: '>=6'} + history@4.10.1: resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} @@ -3365,6 +3646,9 @@ packages: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} + linebreak@1.1.0: + resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -3832,6 +4116,9 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} + pako@0.2.9: + resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} + param-case@3.0.4: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} @@ -3839,6 +4126,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-css-color@0.2.1: + resolution: {integrity: sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg==} + parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} @@ -4573,6 +4863,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + satori@0.33.4: + resolution: {integrity: sha512-dCnaW6D/tkCJxG5UvpZPWnnvfTdGTVVSAq1tzH6xC5MeOhAeeswRcSq5zT7C6lRCdTGow9PRGus7PCzdp5JJYw==} + engines: {node: '>=16'} + sax@1.5.0: resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} engines: {node: '>=11.0.0'} @@ -4618,6 +4912,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + send@0.19.2: resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} @@ -4650,6 +4949,15 @@ packages: shallowequal@1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + sharp@0.35.4: + resolution: {integrity: sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==} + engines: {node: '>=20.9.0'} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -4763,6 +5071,9 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string.prototype.codepointat@0.2.1: + resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} + string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -4869,6 +5180,9 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -4956,6 +5270,9 @@ packages: resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} + unicode-trie@2.0.0: + resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -5191,6 +5508,9 @@ packages: resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} engines: {node: '>=12.20'} + yoga-layout@3.2.1: + resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -7395,12 +7715,123 @@ snapshots: - uglify-js - webpack-cli + '@emnapi/runtime@1.11.3': + dependencies: + tslib: 2.8.1 + optional: true + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': dependencies: '@hapi/hoek': 9.3.0 + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.3 + optional: true + + '@img/sharp-darwin-x64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.3 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.4': + dependencies: + '@img/sharp-wasm32': 0.35.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.3.3': + optional: true + + '@img/sharp-libvips-darwin-x64@1.3.3': + optional: true + + '@img/sharp-libvips-linux-arm64@1.3.3': + optional: true + + '@img/sharp-libvips-linux-arm@1.3.3': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.3.3': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.3.3': + optional: true + + '@img/sharp-libvips-linux-s390x@1.3.3': + optional: true + + '@img/sharp-libvips-linux-x64@1.3.3': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.3.3': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.3.3': + optional: true + + '@img/sharp-linux-arm64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.3 + optional: true + + '@img/sharp-linux-arm@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.3 + optional: true + + '@img/sharp-linux-ppc64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.3 + optional: true + + '@img/sharp-linux-riscv64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.3 + optional: true + + '@img/sharp-linux-s390x@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.3 + optional: true + + '@img/sharp-linux-x64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.3 + optional: true + + '@img/sharp-linuxmusl-arm64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.3 + optional: true + + '@img/sharp-linuxmusl-x64@0.35.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.3 + optional: true + + '@img/sharp-wasm32@0.35.4': + dependencies: + '@emnapi/runtime': 1.11.3 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.4': + dependencies: + '@img/sharp-wasm32': 0.35.4 + optional: true + + '@img/sharp-win32-arm64@0.35.4': + optional: true + + '@img/sharp-win32-ia32@0.35.4': + optional: true + + '@img/sharp-win32-x64@0.35.4': + optional: true + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.10 @@ -7816,6 +8247,62 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@resvg/resvg-js-android-arm-eabi@2.6.2': + optional: true + + '@resvg/resvg-js-android-arm64@2.6.2': + optional: true + + '@resvg/resvg-js-darwin-arm64@2.6.2': + optional: true + + '@resvg/resvg-js-darwin-x64@2.6.2': + optional: true + + '@resvg/resvg-js-linux-arm-gnueabihf@2.6.2': + optional: true + + '@resvg/resvg-js-linux-arm64-gnu@2.6.2': + optional: true + + '@resvg/resvg-js-linux-arm64-musl@2.6.2': + optional: true + + '@resvg/resvg-js-linux-x64-gnu@2.6.2': + optional: true + + '@resvg/resvg-js-linux-x64-musl@2.6.2': + optional: true + + '@resvg/resvg-js-win32-arm64-msvc@2.6.2': + optional: true + + '@resvg/resvg-js-win32-ia32-msvc@2.6.2': + optional: true + + '@resvg/resvg-js-win32-x64-msvc@2.6.2': + optional: true + + '@resvg/resvg-js@2.6.2': + optionalDependencies: + '@resvg/resvg-js-android-arm-eabi': 2.6.2 + '@resvg/resvg-js-android-arm64': 2.6.2 + '@resvg/resvg-js-darwin-arm64': 2.6.2 + '@resvg/resvg-js-darwin-x64': 2.6.2 + '@resvg/resvg-js-linux-arm-gnueabihf': 2.6.2 + '@resvg/resvg-js-linux-arm64-gnu': 2.6.2 + '@resvg/resvg-js-linux-arm64-musl': 2.6.2 + '@resvg/resvg-js-linux-x64-gnu': 2.6.2 + '@resvg/resvg-js-linux-x64-musl': 2.6.2 + '@resvg/resvg-js-win32-arm64-msvc': 2.6.2 + '@resvg/resvg-js-win32-ia32-msvc': 2.6.2 + '@resvg/resvg-js-win32-x64-msvc': 2.6.2 + + '@shuding/opentype.js@1.4.0-beta.0': + dependencies: + fflate: 0.7.3 + string.prototype.codepointat: 0.2.1 + '@sideway/address@4.1.5': dependencies: '@hapi/hoek': 9.3.0 @@ -8361,6 +8848,8 @@ snapshots: balanced-match@1.0.2: {} + base64-js@0.0.8: {} + baseline-browser-mapping@2.10.0: {} batch@0.6.1: {} @@ -8484,6 +8973,8 @@ snapshots: camelcase@7.0.1: {} + camelize@1.0.1: {} + caniuse-api@3.0.0: dependencies: browserslist: 4.28.1 @@ -8697,15 +9188,23 @@ snapshots: dependencies: type-fest: 1.4.0 + css-background-parser@0.1.0: {} + css-blank-pseudo@7.0.1(postcss@8.5.8): dependencies: postcss: 8.5.8 postcss-selector-parser: 7.1.1 + css-box-shadow@1.0.0-3: {} + + css-color-keywords@1.0.0: {} + css-declaration-sorter@7.3.1(postcss@8.5.8): dependencies: postcss: 8.5.8 + css-gradient-parser@0.0.17: {} + css-has-pseudo@7.0.3(postcss@8.5.8): dependencies: '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) @@ -8758,6 +9257,12 @@ snapshots: domutils: 3.2.2 nth-check: 2.1.1 + css-to-react-native@3.2.0: + dependencies: + camelize: 1.0.1 + css-color-keywords: 1.0.0 + postcss-value-parser: 4.2.0 + css-tree@2.2.1: dependencies: mdn-data: 2.0.28 @@ -8890,6 +9395,8 @@ snapshots: destroy@1.2.0: {} + detect-libc@2.1.2: {} + detect-node@2.1.0: {} detect-port@2.1.0: @@ -8990,6 +9497,8 @@ snapshots: electron-to-chromium@1.5.307: {} + emoji-regex-xs@2.0.1: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -9200,6 +9709,8 @@ snapshots: dependencies: xml-js: 1.6.11 + fflate@0.7.3: {} + file-loader@6.2.0(webpack@5.105.4): dependencies: loader-utils: 2.0.4 @@ -9344,6 +9855,8 @@ snapshots: handle-thing@2.0.1: {} + harfbuzzjs@0.10.0: {} + has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -9454,6 +9967,8 @@ snapshots: he@1.2.0: {} + hex-rgb@4.3.0: {} + history@4.10.1: dependencies: '@babel/runtime': 7.28.6 @@ -9785,6 +10300,11 @@ snapshots: lilconfig@3.1.3: {} + linebreak@1.1.0: + dependencies: + base64-js: 0.0.8 + unicode-trie: 2.0.0 + lines-and-columns@1.2.4: {} loader-runner@4.3.1: {} @@ -10531,6 +11051,8 @@ snapshots: registry-url: 6.0.1 semver: 7.7.4 + pako@0.2.9: {} + param-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -10540,6 +11062,11 @@ snapshots: dependencies: callsites: 3.1.0 + parse-css-color@0.2.1: + dependencies: + color-name: 1.1.4 + hex-rgb: 4.3.0 + parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 @@ -11409,6 +11936,22 @@ snapshots: safer-buffer@2.1.2: {} + satori@0.33.4: + dependencies: + '@shuding/opentype.js': 1.4.0-beta.0 + css-background-parser: 0.1.0 + css-box-shadow: 1.0.0-3 + css-gradient-parser: 0.0.17 + css-to-react-native: 3.2.0 + emoji-regex-xs: 2.0.1 + escape-html: 1.0.3 + fflate: 0.7.3 + harfbuzzjs: 0.10.0 + linebreak: 1.1.0 + parse-css-color: 0.2.1 + postcss-value-parser: 4.2.0 + yoga-layout: 3.2.1 + sax@1.5.0: {} scheduler@0.23.2: @@ -11452,6 +11995,8 @@ snapshots: semver@7.7.4: {} + semver@7.8.5: {} + send@0.19.2: dependencies: debug: 2.6.9 @@ -11522,6 +12067,38 @@ snapshots: shallowequal@1.1.0: {} + sharp@0.35.4: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.4 + '@img/sharp-darwin-x64': 0.35.4 + '@img/sharp-freebsd-wasm32': 0.35.4 + '@img/sharp-libvips-darwin-arm64': 1.3.3 + '@img/sharp-libvips-darwin-x64': 1.3.3 + '@img/sharp-libvips-linux-arm': 1.3.3 + '@img/sharp-libvips-linux-arm64': 1.3.3 + '@img/sharp-libvips-linux-ppc64': 1.3.3 + '@img/sharp-libvips-linux-riscv64': 1.3.3 + '@img/sharp-libvips-linux-s390x': 1.3.3 + '@img/sharp-libvips-linux-x64': 1.3.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.3 + '@img/sharp-libvips-linuxmusl-x64': 1.3.3 + '@img/sharp-linux-arm': 0.35.4 + '@img/sharp-linux-arm64': 0.35.4 + '@img/sharp-linux-ppc64': 0.35.4 + '@img/sharp-linux-riscv64': 0.35.4 + '@img/sharp-linux-s390x': 0.35.4 + '@img/sharp-linux-x64': 0.35.4 + '@img/sharp-linuxmusl-arm64': 0.35.4 + '@img/sharp-linuxmusl-x64': 0.35.4 + '@img/sharp-webcontainers-wasm32': 0.35.4 + '@img/sharp-win32-arm64': 0.35.4 + '@img/sharp-win32-ia32': 0.35.4 + '@img/sharp-win32-x64': 0.35.4 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -11650,6 +12227,8 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.2.0 + string.prototype.codepointat@0.2.1: {} + string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -11746,6 +12325,8 @@ snapshots: thunky@1.1.0: {} + tiny-inflate@1.0.3: {} + tiny-invariant@1.3.3: {} tiny-warning@1.0.3: {} @@ -11806,6 +12387,11 @@ snapshots: unicode-property-aliases-ecmascript@2.2.0: {} + unicode-trie@2.0.0: + dependencies: + pako: 0.2.9 + tiny-inflate: 1.0.3 + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -12103,4 +12689,6 @@ snapshots: yocto-queue@1.2.2: {} + yoga-layout@3.2.1: {} + zwitch@2.0.4: {}