Sitemap - przywrócenie

This commit is contained in:
dm
2025-12-21 18:17:14 +01:00
parent 0d967ea6c8
commit 12be46d038
5 changed files with 189 additions and 50 deletions

View File

@@ -1,5 +1,5 @@
title: Możliwości telewizji JAMBOX title: Możliwości telewizji JAMBOX
description: Funkcje i udogodnienia dostępne w JAMBOX. description: Poznaj funkcje i udogodnienia dostępne na dekoderach telewizji JAMBOX.
sections: sections:
- title: CatchUp - Archiwum TV - title: CatchUp - Archiwum TV
image: https://www.jambox.pl/sites/default/files/jambox-kyanit-catchup1.png image: https://www.jambox.pl/sites/default/files/jambox-kyanit-catchup1.png

View File

@@ -52,6 +52,7 @@ const jsonExtra = meta.extraSchema ? JSON.stringify(meta.extraSchema) : null;
/> />
<link rel="canonical" href={meta.canonical} /> <link rel="canonical" href={meta.canonical} />
<link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml" />
<!-- OpenGraph --> <!-- OpenGraph -->
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />

View File

@@ -396,3 +396,90 @@ export function getRequiredEnv(key: string): string {
return value; return value;
} }
// ==================== SITEMAP HELPERS ====================
export type SitemapUrl = {
loc: string;
lastmod?: string;
changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
priority?: number;
};
/**
* Generuje sitemap XML z listy URL-i
* @param urls - Tablica URL-i do sitemap
* @returns String z XML sitemap
*
* @example
* const urls = [
* { loc: 'https://example.com/', priority: 1.0, changefreq: 'daily' },
* { loc: 'https://example.com/about', priority: 0.8, changefreq: 'monthly' }
* ];
* const xml = generateSitemapXml(urls);
*/
export function generateSitemapXml(urls: SitemapUrl[]): string {
const urlEntries = urls.map(url => {
const parts = [
' <url>',
` <loc>${url.loc}</loc>`,
];
if (url.lastmod) {
parts.push(` <lastmod>${url.lastmod}</lastmod>`);
}
if (url.changefreq) {
parts.push(` <changefreq>${url.changefreq}</changefreq>`);
}
if (url.priority !== undefined) {
parts.push(` <priority>${url.priority.toFixed(1)}</priority>`);
}
parts.push(' </url>');
return parts.join('\n');
}).join('\n');
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urlEntries}
</urlset>`;
}
/**
* Automatyczne określenie changefreq na podstawie ścieżki URL
* @param path - Ścieżka URL (np. "/internet-swiatlowodowy")
* @returns Częstotliwość zmian
*
* @example
* inferChangeFreq('/') // => 'daily'
* inferChangeFreq('/dokumenty/regulamin') // => 'yearly'
*/
export function inferChangeFreq(path: string): SitemapUrl['changefreq'] {
if (path === '/') return 'daily';
if (path.includes('/internet-') || path.includes('/telefon')) return 'weekly';
if (path.includes('/mapa-zasiegu') || path.includes('/kontakt')) return 'monthly';
if (path.includes('/dokumenty')) return 'yearly';
if (path.includes('/premium')) return 'monthly';
return 'weekly';
}
/**
* Automatyczne określenie priority na podstawie ścieżki URL
* @param path - Ścieżka URL
* @returns Priorytet (0.0 - 1.0)
*
* @example
* inferPriority('/') // => 1.0
* inferPriority('/dokumenty/polityka-prywatnosci') // => 0.5
*/
export function inferPriority(path: string): number {
if (path === '/') return 1.0;
if (path.includes('/internet-') || path.includes('/telefon')) return 0.9;
if (path.includes('/mapa-zasiegu') || path.includes('/kontakt')) return 0.8;
if (path.includes('/premium')) return 0.7;
if (path.includes('/telewizja-mozliwosci')) return 0.7;
if (path.includes('/dokumenty')) return 0.5;
return 0.7;
}

View File

@@ -1,49 +0,0 @@
import { globby } from 'globby';
export async function GET() {
const base = "https://www.fuz.pl";
// Pobieramy wszystkie pliki .astro
const files = await globby([
"src/pages/**/*.astro",
"!src/pages/_*.astro", // pomiń pliki zaczynające się od _
"!src/pages/**/[...*", // pomiń catch-all
"!src/pages/**/[**", // pomiń dynamiczne parametry
"!src/pages/sitemap.xml.js", // pomiń samą sitemapę
"!src/pages/api/**" // pomiń API endpoints
]);
// Konwersja ścieżek plikowych → URL-e
const urls = files.map((file) => {
let url = file
.replace("src/pages", "")
.replace(".astro", "");
// obsługa index: /index.astro → /
if (url.endsWith("/index")) {
url = url.replace("/index", "");
}
return url;
});
const body = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls
.map((url) => {
return `
<url>
<loc>${base}${url}</loc>
<changefreq>weekly</changefreq>
<priority>${url === "/" ? "1.0" : "0.8"}</priority>
</url>`;
})
.join("")}
</urlset>`;
return new Response(body, {
headers: {
"Content-Type": "application/xml",
},
});
}

100
src/pages/sitemap.xml.ts Normal file
View File

@@ -0,0 +1,100 @@
import type { APIRoute } from 'astro';
import {
getEnv,
generateSitemapXml,
inferChangeFreq,
inferPriority,
type SitemapUrl
} from '../lib/astro-helpers';
import { listDocuments } from '../lib/documents';
/**
* Dynamiczny sitemap generator
* GET /sitemap.xml
*/
export const GET: APIRoute = async ({ site }) => {
const base = site?.toString().replace(/\/$/, '') ||
getEnv('PUBLIC_SITE_URL') ||
"https://www.fuz.pl";
const now = new Date().toISOString();
const urls: SitemapUrl[] = [];
// ========================================
// STATYCZNE STRONY
// ========================================
const staticPages = [
'/',
'/internet-swiatlowodowy',
'/internet-telewizja',
'/telefon',
'/mapa-zasiegu',
'/kontakt',
'/dokumenty',
'/premium',
'/telewizja-mozliwosci',
];
staticPages.forEach(path => {
urls.push({
loc: `${base}${path}`,
lastmod: now,
changefreq: inferChangeFreq(path),
priority: inferPriority(path),
});
});
// ========================================
// DYNAMICZNE STRONY: Dokumenty
// ========================================
try {
const docs = listDocuments();
docs
.filter(d => d.visible === true)
.forEach(d => {
const path = `/dokumenty/${d.slug}`;
urls.push({
loc: `${base}${path}`,
lastmod: now,
changefreq: 'yearly',
priority: 0.5,
});
});
} catch (e) {
console.warn('⚠️ Sitemap: Could not load documents:', e);
}
// ========================================
// DYNAMICZNE STRONY: Premium packages (opcjonalnie)
// ========================================
// TODO: Jeśli masz dynamiczne pakiety premium, dodaj tutaj:
/*
try {
const packages = await loadPremiumPackages();
packages.forEach(p => {
urls.push({
loc: `${base}/premium/${p.tid}`,
lastmod: now,
changefreq: 'monthly',
priority: 0.7,
});
});
} catch (e) {
console.warn('⚠️ Sitemap: Could not load premium packages:', e);
}
*/
// ========================================
// GENERUJ XML
// ========================================
const sitemap = generateSitemapXml(urls);
return new Response(sitemap, {
status: 200,
headers: {
'Content-Type': 'application/xml; charset=utf-8',
'Cache-Control': 'public, max-age=3600', // 1h cache
},
});
};