Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 7x | /**
* @module generate-news-indexes/template/client-script-runtime/helpers
* @description Pure utility helpers (XSS escape, safe href, i18n template
* interpolation) — emitted as a string fragment into the inline `<script>`
* body. Keep small: this is a CSP-relevant surface per
* `Secure_Development_Policy.md`.
*
* @author Hack23 AB
* @license Apache-2.0
*/
/** Helper functions (escape / safe href / i18n template). */
export const HELPER_FUNCTIONS = `
// HTML-escape helper to prevent XSS when interpolating article fields into innerHTML
function esc(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
}
function safeHref(slug) {
var s = String(slug);
// Allow relative HTML paths including subdirectory articles (e.g. "2026-05-04-election-cycle/current-en.html").
// Block control chars, backslashes, and protocol-relative URLs.
if (!s || /[\\\\\\x00-\\x1F\\x7F]/.test(s) || s.indexOf('//') === 0) {
return '#';
}
if (!/^[A-Za-z0-9._/-]+\\.html$/.test(s)) {
return '#';
}
return esc(s);
}
function i18nShowing(shown, total) {
var template;
if (i18nShowingConfig && typeof i18nShowingConfig === 'object') {
if (shown === 1 && Object.prototype.hasOwnProperty.call(i18nShowingConfig, 'one')) {
template = i18nShowingConfig.one;
} else if (Object.prototype.hasOwnProperty.call(i18nShowingConfig, 'other')) {
template = i18nShowingConfig.other;
} else {
template = String(i18nShowingConfig);
}
} else {
template = i18nShowingConfig || '';
}
if (typeof template !== 'string') {
template = String(template);
}
return template
.replace('{shown}', String(shown))
.replace('{total}', String(total));
}
`;
|