import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; const root = dirname(fileURLToPath(import.meta.url)); const distHtml = join(root, 'dist', 'index.html'); const { origin, routes } = JSON.parse( readFileSync(join(root, 'src', 'seo.routes.json'), 'utf8'), ); const faq = JSON.parse(readFileSync(join(root, 'src', 'faq.json'), 'utf8')); const CHROME_STORE = 'https://chromewebstore.google.com/detail/bagpcheidbkfgijnnmolnkgagibbjfnk'; const VSCODE_MARKETPLACE = 'https://marketplace.visualstudio.com/items?itemName=JuanKibin.lexai-vscode'; const REPO = 'https://git.juankibin.space/kibin/LexAI'; const homeDescription = routes.find((r) => r.path === '/')?.description ?? ''; function softwareGraph() { return { '@type': 'SoftwareApplication', name: 'LexAI', applicationCategory: 'BrowserApplication', applicationSubCategory: 'Writing assistance', operatingSystem: 'Chrome, VS Code, Windows, macOS, Linux', url: `${origin}/`, downloadUrl: [CHROME_STORE, VSCODE_MARKETPLACE], license: `${REPO}/src/branch/main/LICENSE`, sameAs: [REPO, CHROME_STORE, VSCODE_MARKETPLACE], offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' }, }; } function jsonLd(route) { const url = route.path === '/' ? `${origin}/` : `${origin}${route.path}`; const graph = [ { '@type': 'WebSite', name: 'LexAI', url: `${origin}/`, description: homeDescription, }, softwareGraph(), ]; if (route.path === '/') { graph.push({ '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.q, acceptedAnswer: { '@type': 'Answer', text: item.a }, })), }); } else { graph.push({ '@type': 'BreadcrumbList', itemListElement: [ { '@type': 'ListItem', position: 1, name: 'Home', item: `${origin}/` }, { '@type': 'ListItem', position: 2, name: route.title, item: url }, ], }); } return JSON.stringify({ '@context': 'https://schema.org', '@graph': graph }); } function apply(html, { title, description, url, robots, ld }) { let out = html; out = out.replace(/