fixing rolodex and search

This commit is contained in:
HotSwapp
2025-08-11 21:58:25 -05:00
parent 278eb7c5d4
commit c76b68d009
25 changed files with 1651 additions and 915 deletions

View File

@@ -12,20 +12,20 @@
const TYPE_CLASSES = {
success: {
container: 'border-success-200 dark:border-success-800',
icon: 'fa-solid fa-circle-check text-success-600 dark:text-success-400'
container: 'border-green-300 dark:border-green-500 bg-green-50 dark:bg-green-800',
icon: 'fa-solid fa-circle-check text-green-600 dark:text-green-300'
},
danger: {
container: 'border-danger-200 dark:border-danger-800',
icon: 'fa-solid fa-triangle-exclamation text-danger-600 dark:text-danger-400'
container: 'border-red-300 dark:border-red-500 bg-red-50 dark:bg-red-800',
icon: 'fa-solid fa-triangle-exclamation text-red-600 dark:text-red-300'
},
warning: {
container: 'border-warning-200 dark:border-warning-800',
icon: 'fa-solid fa-triangle-exclamation text-warning-600 dark:text-warning-400'
container: 'border-yellow-300 dark:border-yellow-500 bg-yellow-50 dark:bg-yellow-800',
icon: 'fa-solid fa-triangle-exclamation text-yellow-600 dark:text-yellow-300'
},
info: {
container: 'border-info-200 dark:border-info-800',
icon: 'fa-solid fa-circle-info text-info-600 dark:text-info-400'
container: 'border-blue-300 dark:border-blue-500 bg-blue-50 dark:bg-blue-800',
icon: 'fa-solid fa-circle-info text-blue-600 dark:text-blue-300'
}
};
@@ -34,6 +34,30 @@
return TYPE_ALIASES[key] || 'info';
}
// ---- DOMPurify Lazy Loader ------------------------------------------------
// Delegated sanitizer: uses shared htmlSanitizer if available, else performs a minimal fallback
function sanitizeHTML(dirty) {
if (window.htmlSanitizer && typeof window.htmlSanitizer.sanitize === 'function') {
return window.htmlSanitizer.sanitize(dirty);
}
// Minimal inline fallback to guarantee some protection until sanitizer.js loads
const temp = document.createElement('div');
temp.innerHTML = dirty;
temp.querySelectorAll('script, style').forEach((el) => el.remove());
temp.querySelectorAll('*').forEach((el) => {
Array.from(el.attributes).forEach((attr) => {
const name = attr.name;
const value = attr.value;
if (/^on/i.test(name)) el.removeAttribute(name);
if ((name === 'href' || name === 'src') && value && value.trim().toLowerCase().startsWith('javascript:')) {
el.removeAttribute(name);
}
});
});
return temp.innerHTML;
}
function getOrCreateContainer(containerId = 'notification-container') {
let container = document.getElementById(containerId);
if (!container) {
@@ -63,7 +87,7 @@
const container = getOrCreateContainer(containerId);
const wrapper = document.createElement('div');
wrapper.className = `alert-notification max-w-sm w-[22rem] bg-white dark:bg-neutral-800 border rounded-lg shadow-lg p-4 transition-all duration-300 translate-x-4 opacity-0 ${
wrapper.className = `alert-notification max-w-sm w-[22rem] border-2 rounded-lg shadow-xl p-4 transition-all duration-300 translate-x-4 opacity-0 ${
(TYPE_CLASSES[tone] || TYPE_CLASSES.info).container
}`;
wrapper.setAttribute('role', role);
@@ -84,17 +108,17 @@
if (title) {
const titleEl = document.createElement('p');
titleEl.className = 'text-sm font-semibold text-neutral-900 dark:text-neutral-100';
titleEl.className = 'text-sm font-bold text-neutral-900 dark:text-white';
titleEl.textContent = String(title);
content.appendChild(titleEl);
}
const text = document.createElement('div');
text.className = 'text-xs mt-1 text-neutral-800 dark:text-neutral-200';
text.className = 'text-sm mt-1 font-semibold text-neutral-900 dark:text-white';
if (message instanceof Node) {
text.appendChild(message);
} else if (html) {
text.innerHTML = String(message || '');
text.innerHTML = sanitizeHTML(String(message || ''));
} else {
text.textContent = String(message || '');
}
@@ -177,7 +201,10 @@
error: (message, options = {}) => show(message, 'danger', options),
warning: (message, options = {}) => show(message, 'warning', options),
info: (message, options = {}) => show(message, 'info', options),
getOrCreateContainer
getOrCreateContainer,
// Internal: exposed for unit testing only (non-enumerable by default prototype iteration)
_sanitize: sanitizeHTML,
_ensureDOMPurifyLoaded: () => window.htmlSanitizer ? window.htmlSanitizer.ensureDOMPurifyLoaded() : Promise.resolve(null)
};
// Expose globally