mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-09-08 19:07:38 +02:00
208 lines
5.6 KiB
JavaScript
208 lines
5.6 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import { execFileSync } from 'child_process';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const DIST_DIR = path.resolve(__dirname, '../dist');
|
|
const LOCALES_DIR = path.resolve(__dirname, '../public/locales');
|
|
const SITE_URL = (process.env.SITE_URL || 'https://www.bentopdf.com').replace(
|
|
/\/+$/,
|
|
''
|
|
);
|
|
const EXCLUDED_PAGES = new Set(['404', 'wasm-settings']);
|
|
|
|
const languages = fs.readdirSync(LOCALES_DIR).filter((file) => {
|
|
return fs.statSync(path.join(LOCALES_DIR, file)).isDirectory();
|
|
});
|
|
|
|
const PRIORITY_MAP = {
|
|
index: 1.0,
|
|
tools: 0.9,
|
|
'pdf-converter': 0.9,
|
|
'pdf-editor': 0.9,
|
|
'pdf-security': 0.9,
|
|
'pdf-merge-split': 0.9,
|
|
'merge-pdf': 0.9,
|
|
'split-pdf': 0.9,
|
|
'compress-pdf': 0.9,
|
|
'edit-pdf': 0.9,
|
|
'word-to-pdf': 0.9,
|
|
'excel-to-pdf': 0.9,
|
|
'powerpoint-to-pdf': 0.9,
|
|
'jpg-to-pdf': 0.9,
|
|
'pdf-to-word': 0.9,
|
|
'unlock-pdf': 0.9,
|
|
'protect-pdf': 0.9,
|
|
'pdf-to-excel': 0.9,
|
|
'pdf-to-jpg': 0.9,
|
|
'compress-pdf-to-100kb': 0.8,
|
|
'compress-pdf-to-200kb': 0.8,
|
|
'compress-pdf-to-500kb': 0.8,
|
|
'compress-pdf-to-1mb': 0.8,
|
|
'compress-pdf-to-2mb': 0.8,
|
|
'compress-pdf-for-email': 0.8,
|
|
about: 0.8,
|
|
faq: 0.8,
|
|
contact: 0.7,
|
|
privacy: 0.5,
|
|
terms: 0.5,
|
|
licensing: 0.5,
|
|
};
|
|
|
|
function getPriority(pageName) {
|
|
return PRIORITY_MAP[pageName] || 0.7;
|
|
}
|
|
|
|
function buildUrl(lang, pageName) {
|
|
const pagePath = pageName === 'index' ? '' : pageName;
|
|
if (lang === 'en') {
|
|
return pagePath ? `${SITE_URL}/${pagePath}` : SITE_URL;
|
|
}
|
|
return pagePath ? `${SITE_URL}/${lang}/${pagePath}` : `${SITE_URL}/${lang}/`;
|
|
}
|
|
|
|
function generateSitemap() {
|
|
console.log('🗺️ Generating multilingual sitemap...');
|
|
console.log(` SITE_URL: ${SITE_URL}`);
|
|
console.log(` Languages: ${languages.join(', ')}`);
|
|
|
|
const htmlFiles = fs
|
|
.readdirSync(DIST_DIR)
|
|
.filter((file) => file.endsWith('.html'))
|
|
.map((file) => file.replace('.html', ''))
|
|
.filter((name) => !EXCLUDED_PAGES.has(name));
|
|
|
|
const projectRoot = path.resolve(__dirname, '..');
|
|
const lastModCache = new Map();
|
|
const getLastMod = (pageName) => {
|
|
if (lastModCache.has(pageName)) return lastModCache.get(pageName);
|
|
const fileName = `${pageName}.html`;
|
|
const candidates = [
|
|
path.join(projectRoot, 'src', 'pages', fileName),
|
|
path.join(projectRoot, fileName),
|
|
];
|
|
let iso = null;
|
|
for (const sourcePath of candidates) {
|
|
if (!fs.existsSync(sourcePath)) continue;
|
|
try {
|
|
const out = execFileSync(
|
|
'git',
|
|
['log', '-1', '--format=%cI', '--', sourcePath],
|
|
{ cwd: projectRoot, encoding: 'utf-8' }
|
|
).trim();
|
|
if (out) iso = out.slice(0, 10);
|
|
} catch {
|
|
iso = null;
|
|
}
|
|
if (!iso) {
|
|
try {
|
|
iso = fs.statSync(sourcePath).mtime.toISOString().slice(0, 10);
|
|
} catch {
|
|
iso = null;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (!iso) {
|
|
try {
|
|
iso = fs
|
|
.statSync(path.join(DIST_DIR, fileName))
|
|
.mtime.toISOString()
|
|
.slice(0, 10);
|
|
} catch {
|
|
iso = new Date().toISOString().slice(0, 10);
|
|
}
|
|
}
|
|
lastModCache.set(pageName, iso);
|
|
return iso;
|
|
};
|
|
|
|
let sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
|
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
|
`;
|
|
|
|
for (const pageName of htmlFiles) {
|
|
const priority = getPriority(pageName);
|
|
const url = buildUrl('en', pageName);
|
|
const lastmod = getLastMod(pageName);
|
|
|
|
sitemap += ` <url>
|
|
<loc>${url}</loc>
|
|
<lastmod>${lastmod}</lastmod>
|
|
<priority>${priority}</priority>
|
|
`;
|
|
|
|
for (const altLang of languages) {
|
|
const altUrl = buildUrl(altLang, pageName);
|
|
sitemap += ` <xhtml:link rel="alternate" hreflang="${altLang}" href="${altUrl}"/>
|
|
`;
|
|
}
|
|
|
|
const defaultUrl = buildUrl('en', pageName);
|
|
sitemap += ` <xhtml:link rel="alternate" hreflang="x-default" href="${defaultUrl}"/>
|
|
</url>
|
|
`;
|
|
}
|
|
|
|
const blogDir = path.join(DIST_DIR, 'blog');
|
|
let blogCount = 0;
|
|
if (fs.existsSync(blogDir)) {
|
|
const blogFiles = fs
|
|
.readdirSync(blogDir)
|
|
.filter((file) => file.endsWith('.html'))
|
|
.map((file) => file.replace('.html', ''));
|
|
for (const name of blogFiles) {
|
|
const url =
|
|
name === 'index' ? `${SITE_URL}/blog/` : `${SITE_URL}/blog/${name}`;
|
|
const sourcePath = path.join(projectRoot, 'blog', `${name}.html`);
|
|
let lastmod;
|
|
try {
|
|
const out = execFileSync(
|
|
'git',
|
|
['log', '-1', '--format=%cI', '--', sourcePath],
|
|
{ cwd: projectRoot, encoding: 'utf-8' }
|
|
).trim();
|
|
lastmod = out ? out.slice(0, 10) : null;
|
|
} catch {
|
|
lastmod = null;
|
|
}
|
|
if (!lastmod) {
|
|
try {
|
|
lastmod = fs.statSync(sourcePath).mtime.toISOString().slice(0, 10);
|
|
} catch {
|
|
lastmod = new Date().toISOString().slice(0, 10);
|
|
}
|
|
}
|
|
sitemap += ` <url>
|
|
<loc>${url}</loc>
|
|
<lastmod>${lastmod}</lastmod>
|
|
<priority>0.7</priority>
|
|
</url>
|
|
`;
|
|
blogCount++;
|
|
}
|
|
}
|
|
if (blogCount > 0) {
|
|
console.log(` Blog: ${blogCount} URLs added (English only)`);
|
|
}
|
|
|
|
sitemap += `</urlset>
|
|
`;
|
|
|
|
const sitemapPath = path.join(DIST_DIR, 'sitemap.xml');
|
|
fs.writeFileSync(sitemapPath, sitemap);
|
|
|
|
const publicSitemapPath = path.resolve(__dirname, '../public/sitemap.xml');
|
|
fs.writeFileSync(publicSitemapPath, sitemap);
|
|
|
|
console.log(
|
|
`✅ Sitemap generated with ${htmlFiles.length} canonical URLs (${languages.length} hreflang alternates each)`
|
|
);
|
|
}
|
|
|
|
generateSitemap();
|