waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
/* ============================================
   UTILITY FUNCTIONS
   Helper functions used across modules
   ============================================ */

// === Debounce ===
function debounce(fn, delay) {
    let timeoutId;
    return function (...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => fn.apply(this, args), delay);
    };
}

// === Throttle ===
function throttle(fn, limit) {
    let inThrottle;
    return function (...args) {
        if (!inThrottle) {
            fn.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

// === Escape HTML ===
function escapeHtml(str) {
    if (!str) return '';
    const div = document.createElement('div');
    div.textContent = str;
    return div.innerHTML;
}

// === Copy to Clipboard ===
async function copyToClipboard(text, button) {
    try {
        await navigator.clipboard.writeText(text);
        if (button) {
            button.classList.add('copied');
            setTimeout(() => button.classList.remove('copied'), 2000);
        }
        showToast('Copied!', 'Text copied to clipboard', 'success');
        return true;
    } catch (err) {
        console.error('Failed to copy:', err);
        showToast('Copy Failed', 'Unable to copy to clipboard', 'error');
        return false;
    }
}

// === Create Element Helper ===
function createElement(tag, className, attributes = {}) {
    const el = document.createElement(tag);
    if (className) el.className = className;
    Object.entries(attributes).forEach(([key, value]) => {
        if (key === 'textContent') {
            el.textContent = value;
        } else if (key === 'innerHTML') {
            el.innerHTML = value;
        } else if (key.startsWith('data-')) {
            el.setAttribute(key, value);
        } else {
            el[key] = value;
        }
    });
    return el;
}

// === Format Code for Display ===
function formatCode(code, language = 'rust') {
    // Basic syntax highlighting (Prism handles the rest)
    return code;
}

// === Highlight Search Match ===
function highlightMatch(text, query) {
    if (!query || !text) return escapeHtml(text);
    const escaped = escapeHtml(text);
    const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');
    return escaped.replace(regex, '<mark>$1</mark>');
}

// === Escape RegExp ===
function escapeRegExp(str) {
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

// === Plural Helper ===
function plural(count, singular, pluralForm) {
    return count === 1 ? singular : (pluralForm || singular + 's');
}

// === Generate Unique ID ===
function generateId(prefix = 'id') {
    return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}

// === Get Category from Code ===
function getCategoryFromCode(code) {
    if (!code) return 'Unknown';
    // Extract category prefix (e.g., "E" from "E0001", "AUTH" from "AUTH_001")
    const match = code.match(/^([A-Z]+)/);
    return match ? match[1] : 'Other';
}

// === Parse Error Code Parts ===
function parseErrorCode(code) {
    if (!code) return { prefix: '', number: '' };
    const match = code.match(/^([A-Z_]+)(\d+)$/);
    if (match) {
        return { prefix: match[1], number: match[2] };
    }
    return { prefix: code, number: '' };
}

// === Scroll to Element ===
function scrollToElement(element, options = {}) {
    const defaults = {
        behavior: 'smooth',
        block: 'center',
        inline: 'nearest'
    };
    element.scrollIntoView({ ...defaults, ...options });
}

// === Local Storage Helpers ===
const Storage = {
    get(key, defaultValue = null) {
        try {
            const item = localStorage.getItem(key);
            return item ? JSON.parse(item) : defaultValue;
        } catch {
            return defaultValue;
        }
    },
    
    set(key, value) {
        try {
            localStorage.setItem(key, JSON.stringify(value));
            return true;
        } catch {
            return false;
        }
    },
    
    remove(key) {
        try {
            localStorage.removeItem(key);
            return true;
        } catch {
            return false;
        }
    }
};