Files
kashilo/js/utils/helpers.js

78 lines
2.4 KiB
JavaScript

/**
* Utility helper functions
* @module utils/helpers
*/
/**
* Escape HTML special characters to prevent XSS
* Use for any user-generated content rendered via innerHTML
* @param {string} str - Untrusted string
* @returns {string} Escaped string safe for innerHTML
* @example
* escapeHTML('<script>alert("XSS")</script>') // '&lt;script&gt;...'
*/
export function escapeHTML(str) {
if (str === null || str === undefined) return '';
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
/**
* Format relative time (e.g., "vor 2 Stunden", "2 hours ago")
* Uses Intl.RelativeTimeFormat for localization
* @param {Date|string} date - Date to format
* @param {string} [locale='de'] - Locale code
* @returns {string} Relative time string
* @example
* formatRelativeTime(new Date(Date.now() - 3600000), 'de') // 'vor 1 Stunde'
*/
export function formatRelativeTime(date, locale = 'de') {
const now = new Date();
const then = new Date(date);
const diffMs = now - then;
const diffSec = Math.floor(diffMs / 1000);
const diffMin = Math.floor(diffSec / 60);
const diffHour = Math.floor(diffMin / 60);
const diffDay = Math.floor(diffHour / 24);
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
if (diffDay > 0) return rtf.format(-diffDay, 'day');
if (diffHour > 0) return rtf.format(-diffHour, 'hour');
if (diffMin > 0) return rtf.format(-diffMin, 'minute');
return rtf.format(-diffSec, 'second');
}
/**
* Debounce function calls
* @param {Function} fn - Function to debounce
* @param {number} [delay=300] - Delay in ms
* @returns {Function} Debounced function
* @example
* const debouncedSearch = debounce((q) => search(q), 500)
*/
export function debounce(fn, delay = 300) {
let timeoutId
return function (...args) {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => fn.apply(this, args), delay)
}
}
/**
* Truncate string with ellipsis
* @param {string} str - String to truncate
* @param {number} [maxLength=100] - Maximum length
* @returns {string} Truncated string
* @example
* truncate('Hello World', 5) // 'Hell…'
*/
export function truncate(str, maxLength = 100) {
if (!str || str.length <= maxLength) return str;
return str.slice(0, maxLength - 1) + '…';
}