Files
SnapOtter/scripts/generate-conversion-seo.mjs
T
SnapOtterandGitHub 63a03d26f2 feat: pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization
Lands five integrated branches: pipeline templates (#355), analytics opt-out (#354), 83 conversion presets bringing the catalog to 240 tools (#356), self-hosted positioning (#353), and e2e modernization (#351).

Integration fixes: aligned stale web analytics tests with the opt-out/allow-list model, closed 3 CodeQL incomplete-sanitization alerts in the i18n generator, resolved settings/index/docs/format-matrix conflicts, and corrected tool counts to 240.
2026-06-28 18:57:53 +08:00

80 lines
4.3 KiB
JavaScript

import { readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { CONVERSION_PRESETS } from "../packages/shared/src/conversion-presets.ts";
const __dirname = dirname(fileURLToPath(import.meta.url));
const SEO = join(__dirname, "../apps/landing/src/data/tool-seo.ts");
const BEGIN = " // BEGIN conversion-presets (generated by scripts/generate-conversion-seo.mjs)";
const END = " // END conversion-presets";
// Per-preset honest overrides for conversions whose result is an approximation
// rather than a faithful copy, so the SEO copy sets correct expectations.
const OVERRIDES = {
"eps-to-svg": (j) => ` ${j("eps-to-svg")}: {
searchTitle: ${j("EPS to SVG Converter Online Free")},
longDescription: ${j("Convert EPS files to SVG by tracing the artwork into vector paths. This works best for logos, icons, and line art. Complex EPS files with gradients, photographic content, or fine detail can lose fidelity, because the result is a traced approximation rather than a one-to-one copy of the original vectors. Runs on your own SnapOtter instance, never uploaded to a third party.")},
useCases: [
${j("Trace an EPS logo or icon into a clean, scalable SVG")},
${j("Convert simple EPS line art for the web without Illustrator")},
${j("Batch convert many EPS files to traced SVG at once")},
],
features: [
${j("Traces EPS artwork into SVG vector paths (not a 1:1 vector copy)")},
${j("Best results on logos, icons, and line art")},
${j("Batch processing for multiple files")},
${j("Private: runs on your own instance, no third-party upload")},
],
faqs: [
{ q: ${j("Does this preserve the original EPS vectors exactly?")}, a: ${j("No. It renders the EPS and traces the result into new SVG paths. Simple line art and logos convert cleanly, but complex EPS with gradients, effects, or embedded images can lose detail. For a faithful vector copy, keep the original EPS or use a dedicated vector editor.")} },
{ q: ${j("How do I convert EPS to SVG?")}, a: ${j("Upload your EPS file, then download the traced SVG. SnapOtter processes it on your instance.")} },
{ q: ${j("Are my files private?")}, a: ${j("Yes. Files are processed on your own server and are not sent to any third party.")} },
],
},`,
};
function entry(p) {
const F = p.from;
const T = p.to;
const j = (s) => JSON.stringify(s);
if (OVERRIDES[p.id]) return OVERRIDES[p.id](j);
return ` ${j(p.id)}: {
searchTitle: ${j(`${F} to ${T} Converter Online Free`)},
longDescription: ${j(`Convert ${F} files to ${T} online, free and private. Your files are processed on your own SnapOtter instance, never uploaded to a third party. Batch convert multiple ${F} files to ${T} at once.`)},
useCases: [
${j(`Convert a ${F} file to ${T} without installing software`)},
${j(`Batch convert many ${F} files to ${T} at once`)},
${j(`Prepare ${T} files for apps that do not accept ${F}`)},
],
features: [
${j(`${F} to ${T} conversion in your browser`)},
${j("Batch processing for multiple files")},
${j("Private: runs on your own instance, no third-party upload")},
${j("Free and unlimited on self-hosted SnapOtter")},
],
faqs: [
{ q: ${j(`How do I convert ${F} to ${T}?`)}, a: ${j(`Upload your ${F} file, then download the converted ${T}. SnapOtter processes it on your instance.`)} },
{ q: ${j(`Is ${F} to ${T} conversion free?`)}, a: ${j("Yes. Self-hosted SnapOtter has no limits or watermarks.")} },
{ q: ${j("Are my files private?")}, a: ${j("Yes. Files are processed on your own server and are not sent to any third party.")} },
],
},`;
}
function esc(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function main() {
let src = readFileSync(SEO, "utf8");
const gen = [BEGIN, ...CONVERSION_PRESETS.map(entry), END].join("\n");
if (src.includes(BEGIN)) {
src = src.replace(new RegExp(`${esc(BEGIN)}[\\s\\S]*?${esc(END)}`), gen);
} else {
// Insert right after `export const TOOL_SEO: Record<string, ToolSeo> = {`.
src = src.replace(/(export const TOOL_SEO: Record<string, ToolSeo> = \{\n)/, `$1${gen}\n`);
}
writeFileSync(SEO, src);
console.log(`Injected ${CONVERSION_PRESETS.length} SEO entries`);
}
main();