Files
davila7--claude-code-templates/docs/js/utils.js
T
wehub-resource-sync bb5c75ce05
Component Security Validation / Security Audit (push) Has been cancelled
Deploy to Cloudflare Pages / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:58 +08:00

58 lines
1.8 KiB
JavaScript

// Shared Utility Functions
/**
* Escape HTML special characters to prevent XSS when injecting into innerHTML.
* Use this for any user-controlled or external data before inserting into HTML.
*/
function escapeHTML(str) {
if (typeof str !== 'string') return '';
return str
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function copyToClipboard(text, message = 'Command copied to clipboard!') {
navigator.clipboard.writeText(text).then(() => {
showNotification(message, 'success');
}).catch(err => {
console.error('Failed to copy: ', err);
showNotification('Failed to copy command', 'error');
});
}
function showNotification(message, type = 'info') {
// Remove any existing notifications first
const existingNotifications = document.querySelectorAll('.notification');
existingNotifications.forEach(notif => {
if (notif.parentNode) {
notif.parentNode.removeChild(notif);
}
});
const notification = document.createElement('div');
notification.textContent = message;
notification.className = `notification notification-${type}`;
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
color: white;
padding: 12px 24px;
border-radius: 6px;
z-index: 10000;
font-family: system-ui, -apple-system, sans-serif;
animation: slideIn 0.3s ease;
`;
document.body.appendChild(notification);
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
}, 3000);
}