euparliamentmonitor 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +1005 -0
- package/SECURITY.md +151 -0
- package/package.json +131 -0
- package/scripts/constants/committee-indicator-map.d.ts +199 -0
- package/scripts/constants/committee-indicator-map.d.ts.map +1 -0
- package/scripts/constants/committee-indicator-map.js +1224 -0
- package/scripts/constants/committee-indicator-map.js.map +1 -0
- package/scripts/constants/config.d.ts +38 -0
- package/scripts/constants/config.d.ts.map +1 -0
- package/scripts/constants/config.js +66 -0
- package/scripts/constants/config.js.map +1 -0
- package/scripts/constants/language-articles.d.ts +84 -0
- package/scripts/constants/language-articles.d.ts.map +1 -0
- package/scripts/constants/language-articles.js +6771 -0
- package/scripts/constants/language-articles.js.map +1 -0
- package/scripts/constants/language-core.d.ts +38 -0
- package/scripts/constants/language-core.d.ts.map +1 -0
- package/scripts/constants/language-core.js +90 -0
- package/scripts/constants/language-core.js.map +1 -0
- package/scripts/constants/language-ui.d.ts +82 -0
- package/scripts/constants/language-ui.d.ts.map +1 -0
- package/scripts/constants/language-ui.js +889 -0
- package/scripts/constants/language-ui.js.map +1 -0
- package/scripts/constants/languages.d.ts +14 -0
- package/scripts/constants/languages.d.ts.map +1 -0
- package/scripts/constants/languages.js +15 -0
- package/scripts/constants/languages.js.map +1 -0
- package/scripts/generators/analysis-builders.d.ts +266 -0
- package/scripts/generators/analysis-builders.d.ts.map +1 -0
- package/scripts/generators/analysis-builders.js +2903 -0
- package/scripts/generators/analysis-builders.js.map +1 -0
- package/scripts/generators/breaking-content.d.ts +45 -0
- package/scripts/generators/breaking-content.d.ts.map +1 -0
- package/scripts/generators/breaking-content.js +530 -0
- package/scripts/generators/breaking-content.js.map +1 -0
- package/scripts/generators/committee-helpers.d.ts +54 -0
- package/scripts/generators/committee-helpers.d.ts.map +1 -0
- package/scripts/generators/committee-helpers.js +154 -0
- package/scripts/generators/committee-helpers.js.map +1 -0
- package/scripts/generators/dashboard-content.d.ts +95 -0
- package/scripts/generators/dashboard-content.d.ts.map +1 -0
- package/scripts/generators/dashboard-content.js +630 -0
- package/scripts/generators/dashboard-content.js.map +1 -0
- package/scripts/generators/deep-analysis-content.d.ts +23 -0
- package/scripts/generators/deep-analysis-content.d.ts.map +1 -0
- package/scripts/generators/deep-analysis-content.js +831 -0
- package/scripts/generators/deep-analysis-content.js.map +1 -0
- package/scripts/generators/mindmap-content.d.ts +55 -0
- package/scripts/generators/mindmap-content.d.ts.map +1 -0
- package/scripts/generators/mindmap-content.js +512 -0
- package/scripts/generators/mindmap-content.js.map +1 -0
- package/scripts/generators/motions-content.d.ts +50 -0
- package/scripts/generators/motions-content.d.ts.map +1 -0
- package/scripts/generators/motions-content.js +391 -0
- package/scripts/generators/motions-content.js.map +1 -0
- package/scripts/generators/news-enhanced.d.ts +14 -0
- package/scripts/generators/news-enhanced.d.ts.map +1 -0
- package/scripts/generators/news-enhanced.js +169 -0
- package/scripts/generators/news-enhanced.js.map +1 -0
- package/scripts/generators/news-indexes.d.ts +31 -0
- package/scripts/generators/news-indexes.d.ts.map +1 -0
- package/scripts/generators/news-indexes.js +410 -0
- package/scripts/generators/news-indexes.js.map +1 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts +352 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/fetch-stage.js +1522 -0
- package/scripts/generators/pipeline/fetch-stage.js.map +1 -0
- package/scripts/generators/pipeline/generate-stage.d.ts +43 -0
- package/scripts/generators/pipeline/generate-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/generate-stage.js +204 -0
- package/scripts/generators/pipeline/generate-stage.js.map +1 -0
- package/scripts/generators/pipeline/output-stage.d.ts +48 -0
- package/scripts/generators/pipeline/output-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/output-stage.js +145 -0
- package/scripts/generators/pipeline/output-stage.js.map +1 -0
- package/scripts/generators/pipeline/transform-stage.d.ts +57 -0
- package/scripts/generators/pipeline/transform-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/transform-stage.js +111 -0
- package/scripts/generators/pipeline/transform-stage.js.map +1 -0
- package/scripts/generators/propositions-content.d.ts +29 -0
- package/scripts/generators/propositions-content.d.ts.map +1 -0
- package/scripts/generators/propositions-content.js +90 -0
- package/scripts/generators/propositions-content.js.map +1 -0
- package/scripts/generators/sankey-content.d.ts +45 -0
- package/scripts/generators/sankey-content.d.ts.map +1 -0
- package/scripts/generators/sankey-content.js +227 -0
- package/scripts/generators/sankey-content.js.map +1 -0
- package/scripts/generators/sitemap.d.ts +66 -0
- package/scripts/generators/sitemap.d.ts.map +1 -0
- package/scripts/generators/sitemap.js +562 -0
- package/scripts/generators/sitemap.js.map +1 -0
- package/scripts/generators/strategies/article-strategy.d.ts +146 -0
- package/scripts/generators/strategies/article-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/article-strategy.js +4 -0
- package/scripts/generators/strategies/article-strategy.js.map +1 -0
- package/scripts/generators/strategies/breaking-news-strategy.d.ts +64 -0
- package/scripts/generators/strategies/breaking-news-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/breaking-news-strategy.js +246 -0
- package/scripts/generators/strategies/breaking-news-strategy.js.map +1 -0
- package/scripts/generators/strategies/committee-reports-strategy.d.ts +93 -0
- package/scripts/generators/strategies/committee-reports-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/committee-reports-strategy.js +447 -0
- package/scripts/generators/strategies/committee-reports-strategy.js.map +1 -0
- package/scripts/generators/strategies/month-ahead-strategy.d.ts +60 -0
- package/scripts/generators/strategies/month-ahead-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/month-ahead-strategy.js +175 -0
- package/scripts/generators/strategies/month-ahead-strategy.js.map +1 -0
- package/scripts/generators/strategies/monthly-review-strategy.d.ts +66 -0
- package/scripts/generators/strategies/monthly-review-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/monthly-review-strategy.js +204 -0
- package/scripts/generators/strategies/monthly-review-strategy.js.map +1 -0
- package/scripts/generators/strategies/motions-strategy.d.ts +61 -0
- package/scripts/generators/strategies/motions-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/motions-strategy.js +215 -0
- package/scripts/generators/strategies/motions-strategy.js.map +1 -0
- package/scripts/generators/strategies/propositions-strategy.d.ts +60 -0
- package/scripts/generators/strategies/propositions-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/propositions-strategy.js +257 -0
- package/scripts/generators/strategies/propositions-strategy.js.map +1 -0
- package/scripts/generators/strategies/week-ahead-strategy.d.ts +57 -0
- package/scripts/generators/strategies/week-ahead-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/week-ahead-strategy.js +178 -0
- package/scripts/generators/strategies/week-ahead-strategy.js.map +1 -0
- package/scripts/generators/strategies/weekly-review-strategy.d.ts +63 -0
- package/scripts/generators/strategies/weekly-review-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/weekly-review-strategy.js +211 -0
- package/scripts/generators/strategies/weekly-review-strategy.js.map +1 -0
- package/scripts/generators/swot-content.d.ts +42 -0
- package/scripts/generators/swot-content.d.ts.map +1 -0
- package/scripts/generators/swot-content.js +366 -0
- package/scripts/generators/swot-content.js.map +1 -0
- package/scripts/generators/week-ahead-content.d.ts +103 -0
- package/scripts/generators/week-ahead-content.d.ts.map +1 -0
- package/scripts/generators/week-ahead-content.js +610 -0
- package/scripts/generators/week-ahead-content.js.map +1 -0
- package/scripts/index.d.ts +40 -0
- package/scripts/index.d.ts.map +1 -0
- package/scripts/index.js +53 -0
- package/scripts/index.js.map +1 -0
- package/scripts/mcp/ep-mcp-client.d.ts +471 -0
- package/scripts/mcp/ep-mcp-client.d.ts.map +1 -0
- package/scripts/mcp/ep-mcp-client.js +734 -0
- package/scripts/mcp/ep-mcp-client.js.map +1 -0
- package/scripts/mcp/mcp-connection.d.ts +264 -0
- package/scripts/mcp/mcp-connection.d.ts.map +1 -0
- package/scripts/mcp/mcp-connection.js +790 -0
- package/scripts/mcp/mcp-connection.js.map +1 -0
- package/scripts/mcp/mcp-health.d.ts +75 -0
- package/scripts/mcp/mcp-health.d.ts.map +1 -0
- package/scripts/mcp/mcp-health.js +78 -0
- package/scripts/mcp/mcp-health.js.map +1 -0
- package/scripts/mcp/mcp-retry.d.ts +94 -0
- package/scripts/mcp/mcp-retry.d.ts.map +1 -0
- package/scripts/mcp/mcp-retry.js +127 -0
- package/scripts/mcp/mcp-retry.js.map +1 -0
- package/scripts/mcp/wb-mcp-client.d.ts +38 -0
- package/scripts/mcp/wb-mcp-client.d.ts.map +1 -0
- package/scripts/mcp/wb-mcp-client.js +112 -0
- package/scripts/mcp/wb-mcp-client.js.map +1 -0
- package/scripts/templates/article-template.d.ts +9 -0
- package/scripts/templates/article-template.d.ts.map +1 -0
- package/scripts/templates/article-template.js +378 -0
- package/scripts/templates/article-template.js.map +1 -0
- package/scripts/templates/section-builders.d.ts +28 -0
- package/scripts/templates/section-builders.d.ts.map +1 -0
- package/scripts/templates/section-builders.js +142 -0
- package/scripts/templates/section-builders.js.map +1 -0
- package/scripts/types/analysis.d.ts +115 -0
- package/scripts/types/analysis.d.ts.map +1 -0
- package/scripts/types/analysis.js +4 -0
- package/scripts/types/analysis.js.map +1 -0
- package/scripts/types/common.d.ts +584 -0
- package/scripts/types/common.d.ts.map +1 -0
- package/scripts/types/common.js +96 -0
- package/scripts/types/common.js.map +1 -0
- package/scripts/types/generation.d.ts +104 -0
- package/scripts/types/generation.d.ts.map +1 -0
- package/scripts/types/generation.js +4 -0
- package/scripts/types/generation.js.map +1 -0
- package/scripts/types/index.d.ts +24 -0
- package/scripts/types/index.d.ts.map +1 -0
- package/scripts/types/index.js +16 -0
- package/scripts/types/index.js.map +1 -0
- package/scripts/types/intelligence.d.ts +129 -0
- package/scripts/types/intelligence.d.ts.map +1 -0
- package/scripts/types/intelligence.js +4 -0
- package/scripts/types/intelligence.js.map +1 -0
- package/scripts/types/mcp.d.ts +418 -0
- package/scripts/types/mcp.d.ts.map +1 -0
- package/scripts/types/mcp.js +4 -0
- package/scripts/types/mcp.js.map +1 -0
- package/scripts/types/parliament.d.ts +388 -0
- package/scripts/types/parliament.d.ts.map +1 -0
- package/scripts/types/parliament.js +4 -0
- package/scripts/types/parliament.js.map +1 -0
- package/scripts/types/quality.d.ts +114 -0
- package/scripts/types/quality.d.ts.map +1 -0
- package/scripts/types/quality.js +4 -0
- package/scripts/types/quality.js.map +1 -0
- package/scripts/types/stakeholder.d.ts +88 -0
- package/scripts/types/stakeholder.d.ts.map +1 -0
- package/scripts/types/stakeholder.js +16 -0
- package/scripts/types/stakeholder.js.map +1 -0
- package/scripts/types/visualization.d.ts +708 -0
- package/scripts/types/visualization.d.ts.map +1 -0
- package/scripts/types/visualization.js +4 -0
- package/scripts/types/visualization.js.map +1 -0
- package/scripts/types/world-bank.d.ts +85 -0
- package/scripts/types/world-bank.d.ts.map +1 -0
- package/scripts/types/world-bank.js +4 -0
- package/scripts/types/world-bank.js.map +1 -0
- package/scripts/utils/article-category.d.ts +18 -0
- package/scripts/utils/article-category.d.ts.map +1 -0
- package/scripts/utils/article-category.js +49 -0
- package/scripts/utils/article-category.js.map +1 -0
- package/scripts/utils/article-quality-scorer.d.ts +87 -0
- package/scripts/utils/article-quality-scorer.d.ts.map +1 -0
- package/scripts/utils/article-quality-scorer.js +1048 -0
- package/scripts/utils/article-quality-scorer.js.map +1 -0
- package/scripts/utils/content-metadata.d.ts +34 -0
- package/scripts/utils/content-metadata.d.ts.map +1 -0
- package/scripts/utils/content-metadata.js +249 -0
- package/scripts/utils/content-metadata.js.map +1 -0
- package/scripts/utils/content-validator.d.ts +94 -0
- package/scripts/utils/content-validator.d.ts.map +1 -0
- package/scripts/utils/content-validator.js +489 -0
- package/scripts/utils/content-validator.js.map +1 -0
- package/scripts/utils/copy-test-reports.d.ts +9 -0
- package/scripts/utils/copy-test-reports.d.ts.map +1 -0
- package/scripts/utils/copy-test-reports.js +508 -0
- package/scripts/utils/copy-test-reports.js.map +1 -0
- package/scripts/utils/file-utils.d.ts +144 -0
- package/scripts/utils/file-utils.d.ts.map +1 -0
- package/scripts/utils/file-utils.js +374 -0
- package/scripts/utils/file-utils.js.map +1 -0
- package/scripts/utils/fix-articles.d.ts +27 -0
- package/scripts/utils/fix-articles.d.ts.map +1 -0
- package/scripts/utils/fix-articles.js +510 -0
- package/scripts/utils/fix-articles.js.map +1 -0
- package/scripts/utils/generate-docs-index.d.ts +8 -0
- package/scripts/utils/generate-docs-index.d.ts.map +1 -0
- package/scripts/utils/generate-docs-index.js +275 -0
- package/scripts/utils/generate-docs-index.js.map +1 -0
- package/scripts/utils/html-sanitize.d.ts +18 -0
- package/scripts/utils/html-sanitize.d.ts.map +1 -0
- package/scripts/utils/html-sanitize.js +57 -0
- package/scripts/utils/html-sanitize.js.map +1 -0
- package/scripts/utils/intelligence-analysis.d.ts +173 -0
- package/scripts/utils/intelligence-analysis.d.ts.map +1 -0
- package/scripts/utils/intelligence-analysis.js +936 -0
- package/scripts/utils/intelligence-analysis.js.map +1 -0
- package/scripts/utils/intelligence-index.d.ts +126 -0
- package/scripts/utils/intelligence-index.d.ts.map +1 -0
- package/scripts/utils/intelligence-index.js +731 -0
- package/scripts/utils/intelligence-index.js.map +1 -0
- package/scripts/utils/metadata-utils.d.ts +14 -0
- package/scripts/utils/metadata-utils.d.ts.map +1 -0
- package/scripts/utils/metadata-utils.js +18 -0
- package/scripts/utils/metadata-utils.js.map +1 -0
- package/scripts/utils/news-metadata.d.ts +47 -0
- package/scripts/utils/news-metadata.d.ts.map +1 -0
- package/scripts/utils/news-metadata.js +259 -0
- package/scripts/utils/news-metadata.js.map +1 -0
- package/scripts/utils/validate-articles.d.ts +2 -0
- package/scripts/utils/validate-articles.d.ts.map +1 -0
- package/scripts/utils/validate-articles.js +284 -0
- package/scripts/utils/validate-articles.js.map +1 -0
- package/scripts/utils/validate-ep-api.d.ts +51 -0
- package/scripts/utils/validate-ep-api.d.ts.map +1 -0
- package/scripts/utils/validate-ep-api.js +160 -0
- package/scripts/utils/validate-ep-api.js.map +1 -0
- package/scripts/utils/world-bank-data.d.ts +84 -0
- package/scripts/utils/world-bank-data.d.ts.map +1 -0
- package/scripts/utils/world-bank-data.js +311 -0
- package/scripts/utils/world-bank-data.js.map +1 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
/**
|
|
5
|
+
* @module Generators/Sitemap
|
|
6
|
+
* @description Generates sitemap.xml and multi-language sitemap HTML pages
|
|
7
|
+
* for all news articles, index pages, and documentation files.
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path, { resolve } from 'path';
|
|
11
|
+
import { pathToFileURL } from 'url';
|
|
12
|
+
import { NEWS_DIR, BASE_URL, PROJECT_ROOT } from '../constants/config.js';
|
|
13
|
+
import { ALL_LANGUAGES, LANGUAGE_NAMES, LANGUAGE_FLAGS, PAGE_TITLES, PAGE_DESCRIPTIONS, SKIP_LINK_TEXTS, HEADER_SUBTITLE_LABELS, getLocalizedString, getTextDirection, } from '../constants/languages.js';
|
|
14
|
+
import { getNewsArticles, getModifiedDate, parseArticleFilename, formatSlug, extractArticleMeta, escapeHTML, } from '../utils/file-utils.js';
|
|
15
|
+
/** Absolute docs directory under project root */
|
|
16
|
+
const DOCS_DIR = path.join(PROJECT_ROOT, 'docs');
|
|
17
|
+
/**
|
|
18
|
+
* Recursively collect all HTML files under a directory, returning paths
|
|
19
|
+
* relative to the project root.
|
|
20
|
+
*
|
|
21
|
+
* @param dir - Directory to scan
|
|
22
|
+
* @param rootDir - Project root for computing relative paths
|
|
23
|
+
* @returns Array of relative paths (e.g. "docs/api/index.html")
|
|
24
|
+
*/
|
|
25
|
+
export function collectDocsHtmlFiles(dir, rootDir = PROJECT_ROOT) {
|
|
26
|
+
const results = [];
|
|
27
|
+
if (!fs.existsSync(dir)) {
|
|
28
|
+
return results;
|
|
29
|
+
}
|
|
30
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const fullPath = path.join(dir, entry.name);
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
results.push(...collectDocsHtmlFiles(fullPath, rootDir));
|
|
35
|
+
}
|
|
36
|
+
else if (entry.isFile() && entry.name.endsWith('.html')) {
|
|
37
|
+
results.push(path.relative(rootDir, fullPath).replace(/\\/g, '/'));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return results.sort();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate sitemap XML including index pages, news articles, sitemap HTML pages,
|
|
44
|
+
* and documentation files from the docs/ folder.
|
|
45
|
+
*
|
|
46
|
+
* @param articles - List of article filenames
|
|
47
|
+
* @param docsFiles - Relative paths to docs HTML files (e.g. "docs/api/index.html")
|
|
48
|
+
* @returns Complete sitemap XML string
|
|
49
|
+
*/
|
|
50
|
+
export function generateSitemap(articles, docsFiles = []) {
|
|
51
|
+
const urls = [];
|
|
52
|
+
const today = new Date().toISOString().split('T')[0];
|
|
53
|
+
// Add home pages for each language
|
|
54
|
+
for (const lang of ALL_LANGUAGES) {
|
|
55
|
+
const filename = lang === 'en' ? 'index.html' : `index-${lang}.html`;
|
|
56
|
+
urls.push({
|
|
57
|
+
loc: `${BASE_URL}/${filename}`,
|
|
58
|
+
lastmod: today,
|
|
59
|
+
changefreq: 'daily',
|
|
60
|
+
priority: '1.0',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Add sitemap HTML pages for each language
|
|
64
|
+
for (const lang of ALL_LANGUAGES) {
|
|
65
|
+
const filename = lang === 'en' ? 'sitemap.html' : `sitemap_${lang}.html`;
|
|
66
|
+
urls.push({
|
|
67
|
+
loc: `${BASE_URL}/${filename}`,
|
|
68
|
+
lastmod: today,
|
|
69
|
+
changefreq: 'daily',
|
|
70
|
+
priority: '0.5',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// Add RSS feed
|
|
74
|
+
urls.push({
|
|
75
|
+
loc: `${BASE_URL}/rss.xml`,
|
|
76
|
+
lastmod: today,
|
|
77
|
+
changefreq: 'daily',
|
|
78
|
+
priority: '0.5',
|
|
79
|
+
});
|
|
80
|
+
// Add news articles
|
|
81
|
+
for (const article of articles) {
|
|
82
|
+
const filepath = path.join(NEWS_DIR, article);
|
|
83
|
+
const lastmod = getModifiedDate(filepath);
|
|
84
|
+
urls.push({
|
|
85
|
+
loc: `${BASE_URL}/news/${article}`,
|
|
86
|
+
lastmod,
|
|
87
|
+
changefreq: 'monthly',
|
|
88
|
+
priority: '0.8',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// Add docs HTML files
|
|
92
|
+
for (const relPath of docsFiles) {
|
|
93
|
+
const fullPath = path.join(PROJECT_ROOT, relPath);
|
|
94
|
+
let lastmod = today;
|
|
95
|
+
try {
|
|
96
|
+
lastmod = getModifiedDate(fullPath);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Use today if file stat fails
|
|
100
|
+
}
|
|
101
|
+
urls.push({
|
|
102
|
+
loc: `${BASE_URL}/${relPath.replace(/\\/g, '/')}`,
|
|
103
|
+
lastmod,
|
|
104
|
+
changefreq: 'weekly',
|
|
105
|
+
priority: '0.3',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
109
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
110
|
+
${urls
|
|
111
|
+
.map((url) => ` <url>
|
|
112
|
+
<loc>${url.loc}</loc>
|
|
113
|
+
<lastmod>${url.lastmod}</lastmod>
|
|
114
|
+
<changefreq>${url.changefreq}</changefreq>
|
|
115
|
+
<priority>${url.priority}</priority>
|
|
116
|
+
</url>`)
|
|
117
|
+
.join('\n')}
|
|
118
|
+
</urlset>`;
|
|
119
|
+
}
|
|
120
|
+
/** Default sitemap title used as English fallback */
|
|
121
|
+
const DEFAULT_SITEMAP_TITLE = 'Sitemap';
|
|
122
|
+
/** Sitemap page titles per language */
|
|
123
|
+
const SITEMAP_TITLES = {
|
|
124
|
+
en: DEFAULT_SITEMAP_TITLE,
|
|
125
|
+
sv: 'Webbplatskarta',
|
|
126
|
+
da: DEFAULT_SITEMAP_TITLE,
|
|
127
|
+
no: 'Nettstedskart',
|
|
128
|
+
fi: 'Sivukartta',
|
|
129
|
+
de: 'Seitenübersicht',
|
|
130
|
+
fr: 'Plan du site',
|
|
131
|
+
es: 'Mapa del sitio',
|
|
132
|
+
nl: DEFAULT_SITEMAP_TITLE,
|
|
133
|
+
ar: 'خريطة الموقع',
|
|
134
|
+
he: 'מפת אתר',
|
|
135
|
+
ja: 'サイトマップ',
|
|
136
|
+
ko: '사이트맵',
|
|
137
|
+
zh: '网站地图',
|
|
138
|
+
};
|
|
139
|
+
/** Sitemap section headings per language */
|
|
140
|
+
const SITEMAP_SECTIONS = {
|
|
141
|
+
en: { news: 'News Articles', docs: 'Documentation', pages: 'Pages' },
|
|
142
|
+
sv: { news: 'Nyhetsartiklar', docs: 'Dokumentation', pages: 'Sidor' },
|
|
143
|
+
da: { news: 'Nyhedsartikler', docs: 'Dokumentation', pages: 'Sider' },
|
|
144
|
+
no: { news: 'Nyhetsartikler', docs: 'Dokumentasjon', pages: 'Sider' },
|
|
145
|
+
fi: { news: 'Uutisartikkelit', docs: 'Dokumentaatio', pages: 'Sivut' },
|
|
146
|
+
de: { news: 'Nachrichtenartikel', docs: 'Dokumentation', pages: 'Seiten' },
|
|
147
|
+
fr: { news: 'Articles de presse', docs: 'Documentation', pages: 'Pages' },
|
|
148
|
+
es: { news: 'Artículos de noticias', docs: 'Documentación', pages: 'Páginas' },
|
|
149
|
+
nl: { news: 'Nieuwsartikelen', docs: 'Documentatie', pages: "Pagina's" },
|
|
150
|
+
ar: { news: 'مقالات إخبارية', docs: 'التوثيق', pages: 'الصفحات' },
|
|
151
|
+
he: { news: 'מאמרי חדשות', docs: 'תיעוד', pages: 'דפים' },
|
|
152
|
+
ja: { news: 'ニュース記事', docs: 'ドキュメント', pages: 'ページ' },
|
|
153
|
+
ko: { news: '뉴스 기사', docs: '문서', pages: '페이지' },
|
|
154
|
+
zh: { news: '新闻文章', docs: '文档', pages: '页面' },
|
|
155
|
+
};
|
|
156
|
+
/** Documentation section labels per language */
|
|
157
|
+
const DOCS_LABELS = {
|
|
158
|
+
en: {
|
|
159
|
+
api: 'API Documentation',
|
|
160
|
+
coverage: 'Code Coverage',
|
|
161
|
+
testResults: 'Test Results',
|
|
162
|
+
docsHome: 'Documentation Home',
|
|
163
|
+
},
|
|
164
|
+
sv: {
|
|
165
|
+
api: 'API-dokumentation',
|
|
166
|
+
coverage: 'Kodtäckning',
|
|
167
|
+
testResults: 'Testresultat',
|
|
168
|
+
docsHome: 'Dokumentationsstart',
|
|
169
|
+
},
|
|
170
|
+
da: {
|
|
171
|
+
api: 'API-dokumentation',
|
|
172
|
+
coverage: 'Kodedækning',
|
|
173
|
+
testResults: 'Testresultater',
|
|
174
|
+
docsHome: 'Dokumentationsstart',
|
|
175
|
+
},
|
|
176
|
+
no: {
|
|
177
|
+
api: 'API-dokumentasjon',
|
|
178
|
+
coverage: 'Kodedekning',
|
|
179
|
+
testResults: 'Testresultater',
|
|
180
|
+
docsHome: 'Dokumentasjonsstart',
|
|
181
|
+
},
|
|
182
|
+
fi: {
|
|
183
|
+
api: 'API-dokumentaatio',
|
|
184
|
+
coverage: 'Koodikattavuus',
|
|
185
|
+
testResults: 'Testitulokset',
|
|
186
|
+
docsHome: 'Dokumentaation etusivu',
|
|
187
|
+
},
|
|
188
|
+
de: {
|
|
189
|
+
api: 'API-Dokumentation',
|
|
190
|
+
coverage: 'Codeabdeckung',
|
|
191
|
+
testResults: 'Testergebnisse',
|
|
192
|
+
docsHome: 'Dokumentationsstart',
|
|
193
|
+
},
|
|
194
|
+
fr: {
|
|
195
|
+
api: 'Documentation API',
|
|
196
|
+
coverage: 'Couverture du code',
|
|
197
|
+
testResults: 'Résultats des tests',
|
|
198
|
+
docsHome: 'Accueil documentation',
|
|
199
|
+
},
|
|
200
|
+
es: {
|
|
201
|
+
api: 'Documentación API',
|
|
202
|
+
coverage: 'Cobertura de código',
|
|
203
|
+
testResults: 'Resultados de pruebas',
|
|
204
|
+
docsHome: 'Inicio de documentación',
|
|
205
|
+
},
|
|
206
|
+
nl: {
|
|
207
|
+
api: 'API-documentatie',
|
|
208
|
+
coverage: 'Codedekking',
|
|
209
|
+
testResults: 'Testresultaten',
|
|
210
|
+
docsHome: 'Documentatiestart',
|
|
211
|
+
},
|
|
212
|
+
ar: {
|
|
213
|
+
api: 'وثائق API',
|
|
214
|
+
coverage: 'تغطية الكود',
|
|
215
|
+
testResults: 'نتائج الاختبار',
|
|
216
|
+
docsHome: 'الصفحة الرئيسية للتوثيق',
|
|
217
|
+
},
|
|
218
|
+
he: {
|
|
219
|
+
api: 'תיעוד API',
|
|
220
|
+
coverage: 'כיסוי קוד',
|
|
221
|
+
testResults: 'תוצאות בדיקות',
|
|
222
|
+
docsHome: 'דף הבית של התיעוד',
|
|
223
|
+
},
|
|
224
|
+
ja: {
|
|
225
|
+
api: 'APIドキュメント',
|
|
226
|
+
coverage: 'コードカバレッジ',
|
|
227
|
+
testResults: 'テスト結果',
|
|
228
|
+
docsHome: 'ドキュメントホーム',
|
|
229
|
+
},
|
|
230
|
+
ko: {
|
|
231
|
+
api: 'API 문서',
|
|
232
|
+
coverage: '코드 커버리지',
|
|
233
|
+
testResults: '테스트 결과',
|
|
234
|
+
docsHome: '문서 홈',
|
|
235
|
+
},
|
|
236
|
+
zh: { api: 'API 文档', coverage: '代码覆盖率', testResults: '测试结果', docsHome: '文档首页' },
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Get the sitemap HTML filename for a given language code.
|
|
240
|
+
*
|
|
241
|
+
* @param lang - Language code
|
|
242
|
+
* @returns Filename string
|
|
243
|
+
*/
|
|
244
|
+
export function getSitemapFilename(lang) {
|
|
245
|
+
return lang === 'en' ? 'sitemap.html' : `sitemap_${lang}.html`;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get the index filename for a given language code.
|
|
249
|
+
*
|
|
250
|
+
* @param lang - Language code
|
|
251
|
+
* @returns Filename string
|
|
252
|
+
*/
|
|
253
|
+
function getIndexFilename(lang) {
|
|
254
|
+
return lang === 'en' ? 'index.html' : `index-${lang}.html`;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Build compact language switcher nav HTML for sitemap pages.
|
|
258
|
+
*
|
|
259
|
+
* @param currentLang - Active language code
|
|
260
|
+
* @returns HTML string
|
|
261
|
+
*/
|
|
262
|
+
function buildSitemapLangSwitcher(currentLang) {
|
|
263
|
+
return ALL_LANGUAGES.map((code) => {
|
|
264
|
+
const flag = getLocalizedString(LANGUAGE_FLAGS, code);
|
|
265
|
+
const name = getLocalizedString(LANGUAGE_NAMES, code);
|
|
266
|
+
const active = code === currentLang ? ' active' : '';
|
|
267
|
+
const ariaCurrent = code === currentLang ? ' aria-current="page"' : '';
|
|
268
|
+
const href = getSitemapFilename(code);
|
|
269
|
+
return `<a href="${href}" class="lang-link${active}" hreflang="${code}" title="${escapeHTML(name)}"${ariaCurrent}>${flag} ${code.toUpperCase()}</a>`;
|
|
270
|
+
}).join('\n ');
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Build the footer language grid for sitemap pages.
|
|
274
|
+
*
|
|
275
|
+
* @param currentLang - Active language code
|
|
276
|
+
* @returns HTML string
|
|
277
|
+
*/
|
|
278
|
+
function buildSitemapFooterLanguageGrid(currentLang) {
|
|
279
|
+
return ALL_LANGUAGES.map((code) => {
|
|
280
|
+
const flag = getLocalizedString(LANGUAGE_FLAGS, code);
|
|
281
|
+
const name = getLocalizedString(LANGUAGE_NAMES, code);
|
|
282
|
+
const href = getSitemapFilename(code);
|
|
283
|
+
const active = code === currentLang ? ' class="active"' : '';
|
|
284
|
+
return `<a href="${href}"${active} hreflang="${code}">${flag} ${escapeHTML(name)}</a>`;
|
|
285
|
+
}).join('\n ');
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Generate a sitemap HTML page for a specific language.
|
|
289
|
+
* Lists all articles for that language with titles and descriptions,
|
|
290
|
+
* plus a high-level documentation section.
|
|
291
|
+
*
|
|
292
|
+
* @param lang - Language code
|
|
293
|
+
* @param articleInfos - Article info (title/description) for this language
|
|
294
|
+
* @param hasDocsDir - Whether the docs directory exists
|
|
295
|
+
* @returns Complete HTML document string
|
|
296
|
+
*/
|
|
297
|
+
export function generateSitemapHTML(lang, articleInfos, hasDocsDir = false) {
|
|
298
|
+
const sitemapTitle = SITEMAP_TITLES[lang] ?? SITEMAP_TITLES['en'] ?? DEFAULT_SITEMAP_TITLE;
|
|
299
|
+
const pageTitle = `${getLocalizedString(PAGE_TITLES, lang).split(' - ')[0]} - ${sitemapTitle}`;
|
|
300
|
+
const description = getLocalizedString(PAGE_DESCRIPTIONS, lang);
|
|
301
|
+
const skipLinkText = getLocalizedString(SKIP_LINK_TEXTS, lang);
|
|
302
|
+
const dir = getTextDirection(lang);
|
|
303
|
+
const year = new Date().getFullYear();
|
|
304
|
+
const sections = SITEMAP_SECTIONS[lang] ?? SITEMAP_SECTIONS['en'];
|
|
305
|
+
const docsLabels = DOCS_LABELS[lang] ?? DOCS_LABELS['en'];
|
|
306
|
+
const heroTitle = getLocalizedString(PAGE_TITLES, lang).split(' - ')[0] ?? '';
|
|
307
|
+
const headerSubtitle = escapeHTML(getLocalizedString(HEADER_SUBTITLE_LABELS, lang));
|
|
308
|
+
// Pages section
|
|
309
|
+
const pagesSection = ALL_LANGUAGES.map((code) => {
|
|
310
|
+
const name = getLocalizedString(LANGUAGE_NAMES, code);
|
|
311
|
+
const flag = getLocalizedString(LANGUAGE_FLAGS, code);
|
|
312
|
+
const href = getIndexFilename(code);
|
|
313
|
+
return ` <li><a href="${href}">${flag} ${escapeHTML(name)}</a></li>`;
|
|
314
|
+
}).join('\n');
|
|
315
|
+
// News articles section
|
|
316
|
+
const articlesSection = articleInfos.length === 0
|
|
317
|
+
? ''
|
|
318
|
+
: articleInfos
|
|
319
|
+
.map((a) => ` <li>
|
|
320
|
+
<a href="news/${escapeHTML(a.filename)}">${escapeHTML(a.title)}</a>
|
|
321
|
+
<span class="sitemap-date">${escapeHTML(a.date)}</span>${a.description ? `\n <p class="sitemap-desc">${escapeHTML(a.description)}</p>` : ''}
|
|
322
|
+
</li>`)
|
|
323
|
+
.join('\n');
|
|
324
|
+
// Documentation section (high-level links)
|
|
325
|
+
const docsSection = hasDocsDir
|
|
326
|
+
? `
|
|
327
|
+
<section class="sitemap-section">
|
|
328
|
+
<h2><span aria-hidden="true">📚</span> ${escapeHTML(sections.docs)}</h2>
|
|
329
|
+
<ul class="sitemap-list">
|
|
330
|
+
<li><a href="docs/index.html">${escapeHTML(docsLabels.docsHome)}</a></li>
|
|
331
|
+
<li><a href="docs/api/index.html">${escapeHTML(docsLabels.api)}</a></li>
|
|
332
|
+
<li><a href="docs/coverage/index.html">${escapeHTML(docsLabels.coverage)}</a></li>
|
|
333
|
+
<li><a href="docs/test-results/index.html">${escapeHTML(docsLabels.testResults)}</a></li>
|
|
334
|
+
</ul>
|
|
335
|
+
</section>`
|
|
336
|
+
: '';
|
|
337
|
+
return `<!DOCTYPE html>
|
|
338
|
+
<html lang="${lang}" dir="${dir}">
|
|
339
|
+
<head>
|
|
340
|
+
<meta charset="UTF-8">
|
|
341
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
342
|
+
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
|
343
|
+
<meta name="referrer" content="no-referrer">
|
|
344
|
+
<title>${escapeHTML(pageTitle)}</title>
|
|
345
|
+
<meta name="description" content="${escapeHTML(description)}">
|
|
346
|
+
<meta property="og:type" content="website">
|
|
347
|
+
<meta property="og:title" content="${escapeHTML(sitemapTitle)}">
|
|
348
|
+
<meta property="og:description" content="${escapeHTML(description)}">
|
|
349
|
+
<meta property="og:site_name" content="EU Parliament Monitor">
|
|
350
|
+
<meta property="og:locale" content="${lang}">
|
|
351
|
+
<meta property="og:image" content="https://hack23.github.io/euparliamentmonitor/images/og-image.jpg">
|
|
352
|
+
<meta property="og:image:width" content="1200">
|
|
353
|
+
<meta property="og:image:height" content="630">
|
|
354
|
+
<!-- Favicons -->
|
|
355
|
+
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
356
|
+
<link rel="icon" type="image/png" sizes="32x32" href="images/favicon-32x32.png">
|
|
357
|
+
<link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png">
|
|
358
|
+
<link rel="apple-touch-icon" sizes="180x180" href="images/apple-touch-icon.png">
|
|
359
|
+
<link rel="manifest" href="site.webmanifest">
|
|
360
|
+
<meta name="theme-color" content="#003399">
|
|
361
|
+
<link rel="stylesheet" href="styles.css">
|
|
362
|
+
</head>
|
|
363
|
+
<body>
|
|
364
|
+
<a href="#main" class="skip-link">${escapeHTML(skipLinkText)}</a>
|
|
365
|
+
|
|
366
|
+
<header class="site-header" role="banner">
|
|
367
|
+
<div class="site-header__inner">
|
|
368
|
+
<a href="${getIndexFilename(lang)}" class="site-header__brand" aria-label="${escapeHTML(heroTitle)}">
|
|
369
|
+
<picture class="site-header__logo-picture">
|
|
370
|
+
<source srcset="images/favicon-96x96.webp" type="image/webp">
|
|
371
|
+
<img class="site-header__logo" src="images/favicon-96x96.png" alt="" width="96" height="96" aria-hidden="true">
|
|
372
|
+
</picture>
|
|
373
|
+
<span>
|
|
374
|
+
<span class="site-header__title">${escapeHTML(heroTitle)}</span>
|
|
375
|
+
<span class="site-header__subtitle">${headerSubtitle}</span>
|
|
376
|
+
</span>
|
|
377
|
+
</a>
|
|
378
|
+
</div>
|
|
379
|
+
</header>
|
|
380
|
+
|
|
381
|
+
<nav class="language-switcher" role="navigation" aria-label="Language selection">
|
|
382
|
+
${buildSitemapLangSwitcher(lang)}
|
|
383
|
+
</nav>
|
|
384
|
+
|
|
385
|
+
<main id="main" class="site-main">
|
|
386
|
+
<h1>${escapeHTML(sitemapTitle)}</h1>
|
|
387
|
+
|
|
388
|
+
<section class="sitemap-section">
|
|
389
|
+
<h2><span aria-hidden="true">🏠</span> ${escapeHTML(sections.pages)}</h2>
|
|
390
|
+
<ul class="sitemap-list">
|
|
391
|
+
${pagesSection}
|
|
392
|
+
</ul>
|
|
393
|
+
</section>
|
|
394
|
+
${docsSection}
|
|
395
|
+
<section class="sitemap-section">
|
|
396
|
+
<h2><span aria-hidden="true">📰</span> ${escapeHTML(sections.news)}</h2>
|
|
397
|
+
<ul class="sitemap-list">
|
|
398
|
+
${articlesSection}
|
|
399
|
+
</ul>
|
|
400
|
+
</section>
|
|
401
|
+
</main>
|
|
402
|
+
|
|
403
|
+
<footer class="site-footer" role="contentinfo">
|
|
404
|
+
<div class="footer-content">
|
|
405
|
+
<div class="footer-section">
|
|
406
|
+
<h3>About EU Parliament Monitor</h3>
|
|
407
|
+
<p>European Parliament Intelligence Platform — monitoring political activity with systematic transparency. Powered by European Parliament open data.</p>
|
|
408
|
+
</div>
|
|
409
|
+
<div class="footer-section">
|
|
410
|
+
<h3>Quick Links</h3>
|
|
411
|
+
<ul>
|
|
412
|
+
<li><a href="${getIndexFilename(lang)}">Home</a></li>
|
|
413
|
+
<li><a href="rss.xml">RSS Feed</a></li>
|
|
414
|
+
<li><a href="https://github.com/Hack23/euparliamentmonitor">GitHub Repository</a></li>
|
|
415
|
+
<li><a href="https://github.com/Hack23/euparliamentmonitor/blob/main/LICENSE">Apache-2.0 License</a></li>
|
|
416
|
+
<li><a href="https://www.europarl.europa.eu/">European Parliament</a></li>
|
|
417
|
+
</ul>
|
|
418
|
+
</div>
|
|
419
|
+
<div class="footer-section">
|
|
420
|
+
<h3>Built by Hack23 AB</h3>
|
|
421
|
+
<ul>
|
|
422
|
+
<li><a href="https://hack23.com">hack23.com</a></li>
|
|
423
|
+
<li><a href="https://www.linkedin.com/company/hack23">LinkedIn</a></li>
|
|
424
|
+
<li><a href="https://github.com/Hack23/ISMS-PUBLIC">Security & Privacy Policy</a></li>
|
|
425
|
+
<li><a href="mailto:james@hack23.com">Contact</a></li>
|
|
426
|
+
</ul>
|
|
427
|
+
</div>
|
|
428
|
+
<div class="footer-section">
|
|
429
|
+
<h3>Languages</h3>
|
|
430
|
+
<div class="language-grid">
|
|
431
|
+
${buildSitemapFooterLanguageGrid(lang)}
|
|
432
|
+
</div>
|
|
433
|
+
</div>
|
|
434
|
+
</div>
|
|
435
|
+
<div class="footer-bottom">
|
|
436
|
+
<p>© 2008-${year} <a href="https://hack23.com">Hack23 AB</a> (Org.nr 5595347807) | Gothenburg, Sweden</p>
|
|
437
|
+
</div>
|
|
438
|
+
</footer>
|
|
439
|
+
</body>
|
|
440
|
+
</html>`;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Escape special XML characters in text content.
|
|
444
|
+
*
|
|
445
|
+
* @param str - Raw string to escape for XML
|
|
446
|
+
* @returns XML-safe string
|
|
447
|
+
*/
|
|
448
|
+
function escapeXML(str) {
|
|
449
|
+
return str
|
|
450
|
+
.replace(/&/g, '&')
|
|
451
|
+
.replace(/</g, '<')
|
|
452
|
+
.replace(/>/g, '>')
|
|
453
|
+
.replace(/"/g, '"')
|
|
454
|
+
.replace(/'/g, ''');
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Generate RSS 2.0 XML feed with all news articles across all languages.
|
|
458
|
+
* Articles are sorted newest-first. Each item includes the article language.
|
|
459
|
+
*
|
|
460
|
+
* @param articleInfos - Article metadata sorted newest first
|
|
461
|
+
* @returns Complete RSS 2.0 XML string
|
|
462
|
+
*/
|
|
463
|
+
export function generateRssFeed(articleInfos) {
|
|
464
|
+
const buildDate = new Date().toUTCString();
|
|
465
|
+
const items = articleInfos
|
|
466
|
+
.map((item) => ` <item>
|
|
467
|
+
<title>${escapeXML(item.title)}</title>
|
|
468
|
+
<link>${escapeXML(item.link)}</link>
|
|
469
|
+
<description>${escapeXML(item.description)}</description>
|
|
470
|
+
<pubDate>${item.pubDate}</pubDate>
|
|
471
|
+
<guid isPermaLink="true">${escapeXML(item.link)}</guid>
|
|
472
|
+
<dc:language>${escapeXML(item.lang)}</dc:language>
|
|
473
|
+
</item>`)
|
|
474
|
+
.join('\n');
|
|
475
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
476
|
+
<!-- SPDX-FileCopyrightText: 2024-2026 Hack23 AB -->
|
|
477
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
478
|
+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
479
|
+
<channel>
|
|
480
|
+
<title>EU Parliament Monitor</title>
|
|
481
|
+
<link>${BASE_URL}</link>
|
|
482
|
+
<description>European Parliament Intelligence Platform — monitoring political activity with systematic transparency.</description>
|
|
483
|
+
<language>en</language>
|
|
484
|
+
<lastBuildDate>${buildDate}</lastBuildDate>
|
|
485
|
+
<atom:link href="${BASE_URL}/rss.xml" rel="self" type="application/rss+xml"/>
|
|
486
|
+
${items}
|
|
487
|
+
</channel>
|
|
488
|
+
</rss>`;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Main execution - generates sitemap.xml, multi-language sitemap HTML pages, and rss.xml.
|
|
492
|
+
*/
|
|
493
|
+
function main() {
|
|
494
|
+
console.log('🗺️ Generating sitemap...');
|
|
495
|
+
const articles = getNewsArticles();
|
|
496
|
+
console.log(`📊 Found ${articles.length} articles`);
|
|
497
|
+
// Collect docs HTML files
|
|
498
|
+
const docsFiles = collectDocsHtmlFiles(DOCS_DIR);
|
|
499
|
+
console.log(`📚 Found ${docsFiles.length} docs files`);
|
|
500
|
+
const sitemap = generateSitemap(articles, docsFiles);
|
|
501
|
+
const filepath = path.join(PROJECT_ROOT, 'sitemap.xml');
|
|
502
|
+
fs.writeFileSync(filepath, sitemap, 'utf-8');
|
|
503
|
+
const totalUrls = articles.length + ALL_LANGUAGES.length + ALL_LANGUAGES.length + docsFiles.length + 1;
|
|
504
|
+
console.log(`✅ Generated sitemap.xml with ${totalUrls} URLs`);
|
|
505
|
+
// Build article metadata map for sitemap HTML pages and RSS,
|
|
506
|
+
// pre-grouped by language for O(N) iteration
|
|
507
|
+
const articlesByLang = new Map();
|
|
508
|
+
const rssItems = [];
|
|
509
|
+
for (const lang of ALL_LANGUAGES) {
|
|
510
|
+
articlesByLang.set(lang, []);
|
|
511
|
+
}
|
|
512
|
+
for (const filename of articles) {
|
|
513
|
+
const parsed = parseArticleFilename(filename);
|
|
514
|
+
if (parsed) {
|
|
515
|
+
const meta = extractArticleMeta(path.join(NEWS_DIR, filename));
|
|
516
|
+
const info = {
|
|
517
|
+
filename: parsed.filename,
|
|
518
|
+
date: parsed.date,
|
|
519
|
+
title: meta.title || formatSlug(parsed.slug),
|
|
520
|
+
description: meta.description,
|
|
521
|
+
};
|
|
522
|
+
const bucket = articlesByLang.get(parsed.lang);
|
|
523
|
+
if (bucket) {
|
|
524
|
+
bucket.push(info);
|
|
525
|
+
}
|
|
526
|
+
rssItems.push({
|
|
527
|
+
title: info.title,
|
|
528
|
+
link: `${BASE_URL}/news/${info.filename}`,
|
|
529
|
+
description: info.description || info.title,
|
|
530
|
+
pubDate: new Date(parsed.date).toUTCString(),
|
|
531
|
+
lang: parsed.lang,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
// Check if docs directory exists
|
|
536
|
+
const hasDocsDir = fs.existsSync(DOCS_DIR);
|
|
537
|
+
// Generate sitemap HTML for each language
|
|
538
|
+
let htmlGenerated = 0;
|
|
539
|
+
for (const lang of ALL_LANGUAGES) {
|
|
540
|
+
const langArticles = articlesByLang.get(lang) || [];
|
|
541
|
+
// Sort newest first
|
|
542
|
+
langArticles.sort((a, b) => b.date.localeCompare(a.date));
|
|
543
|
+
const html = generateSitemapHTML(lang, langArticles, hasDocsDir);
|
|
544
|
+
const sitemapFilename = getSitemapFilename(lang);
|
|
545
|
+
const sitemapPath = path.join(PROJECT_ROOT, sitemapFilename);
|
|
546
|
+
fs.writeFileSync(sitemapPath, html, 'utf-8');
|
|
547
|
+
console.log(` ✅ Generated ${sitemapFilename} (${langArticles.length} articles)`);
|
|
548
|
+
htmlGenerated++;
|
|
549
|
+
}
|
|
550
|
+
console.log(`✅ Generated ${htmlGenerated} sitemap HTML files`);
|
|
551
|
+
// Sort RSS items newest first using numeric timestamps
|
|
552
|
+
rssItems.sort((a, b) => Date.parse(b.pubDate) - Date.parse(a.pubDate));
|
|
553
|
+
const rss = generateRssFeed(rssItems);
|
|
554
|
+
const rssPath = path.join(PROJECT_ROOT, 'rss.xml');
|
|
555
|
+
fs.writeFileSync(rssPath, rss, 'utf-8');
|
|
556
|
+
console.log(`✅ Generated rss.xml with ${rssItems.length} items`);
|
|
557
|
+
}
|
|
558
|
+
// Only run main when executed directly (not when imported)
|
|
559
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
|
|
560
|
+
main();
|
|
561
|
+
}
|
|
562
|
+
//# sourceMappingURL=sitemap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../../src/generators/sitemap.ts"],"names":[],"mappings":"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"}
|