41 lines
1.6 KiB
JavaScript
41 lines
1.6 KiB
JavaScript
export function esc(s) {
|
|
return (s == null ? '' : String(s))
|
|
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
.replace(/"/g, '"').replace(/'/g, ''');
|
|
}
|
|
|
|
export function stripTags(html) {
|
|
if (!html) return '';
|
|
var d = document.createElement('div');
|
|
d.innerHTML = html;
|
|
return (d.textContent || d.innerText || '').replace(/\s+/g, ' ').trim();
|
|
}
|
|
|
|
export function formatWhen(iso) {
|
|
if (!iso) return '';
|
|
var d = new Date(iso);
|
|
if (isNaN(d.getTime())) return '';
|
|
var now = new Date();
|
|
var sameDay = d.toDateString() === now.toDateString();
|
|
if (sameDay) return d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
|
|
return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: d.getFullYear() === now.getFullYear() ? undefined : 'numeric' });
|
|
}
|
|
|
|
// Sanitize via DOMPurify (loaded from cdnjs in index.html, also used by
|
|
// learningHub.js). If DOMPurify fails to load, render as plain text.
|
|
export function sanitizeHtml(html) {
|
|
if (!window.DOMPurify || typeof window.DOMPurify.sanitize !== 'function') {
|
|
console.warn('[notes] DOMPurify unavailable - rendering as plain text.');
|
|
var d = document.createElement('div');
|
|
d.textContent = String(html == null ? '' : html);
|
|
return d.innerHTML;
|
|
}
|
|
return window.DOMPurify.sanitize(html, {
|
|
ALLOWED_TAGS: ['p','br','strong','em','b','i','u','s','h2','h3','h4',
|
|
'ul','ol','li','a','blockquote','code','pre','hr'],
|
|
ALLOWED_ATTR: ['href','target','rel'],
|
|
ADD_ATTR: ['target'],
|
|
FORBID_ATTR: ['style','onerror','onload','onclick','onmouseover'],
|
|
ALLOW_DATA_ATTR: false
|
|
});
|
|
}
|