{# Master Feature Loader - Manages all optional features efficiently #} {# Usage: {% include "../../includes/features/feature-loader.html" %} #} {# Features can be enabled via: 1. Template variables: {% set enable_code_highlighting = true %} 2. Module fields: {{ module.features.code_highlighting }} 3. Page meta: {{ content.meta_description contains "code-highlight" }} 4. Auto-detection based on content #} {# Auto-detect features if not explicitly set #} {% set auto_detect = auto_detect|default(true) %} {% if auto_detect %} {# Auto-detect code highlighting need #} {% if not enable_code_highlighting is defined %} {% set enable_code_highlighting = false %} {% if content.post_body %} {% if ' // Feature detection and lazy loading manager (function() { 'use strict'; // Track loaded features to prevent duplicates window.loadedFeatures = window.loadedFeatures || new Set(); // Feature configuration const features = { codeHighlighting: { enabled: {{ enable_code_highlighting|lower }}, selectors: ['pre code', '.highlight-code', '[class*="language-"]'], loaded: false }, qrCode: { enabled: {{ enable_qr_code|lower }}, selectors: ['.qr-code-container', '[data-qr-content]', '#qr-generator-widget'], loaded: false }, charts: { enabled: {{ enable_charts|lower }}, selectors: ['.chart-container', 'canvas[data-chart]', '[data-chart-config]', '#chart-builder'], loaded: false }, pdfExport: { enabled: {{ enable_pdf_export|lower }}, selectors: ['.generate-pdf', '[data-pdf-export]', '#pdf-toolbar'], loaded: false }, accordionEnhancement: { enabled: {{ enable_accordion_js|lower }}, selectors: ['[data-exclusive]', '.accordion-group[data-exclusive]'], loaded: false, script: '{{ get_asset_url("../../js/components/accordion.js") }}' } }; // Check if any feature elements exist on the page function checkForFeatures() { Object.keys(features).forEach(featureName => { const feature = features[featureName]; if (!feature.enabled || feature.loaded) return; const hasElements = feature.selectors.some(selector => document.querySelector(selector) !== null ); if (hasElements) { loadFeature(featureName); } }); } // Load a specific feature function loadFeature(featureName) { if (window.loadedFeatures.has(featureName)) return; window.loadedFeatures.add(featureName); features[featureName].loaded = true; // Dispatch custom event for feature loading window.dispatchEvent(new CustomEvent('featureLoading', { detail: { feature: featureName } })); // Load accordion enhancement script if needed if (featureName === 'accordionEnhancement' && features.accordionEnhancement.script) { const script = document.createElement('script'); script.src = features.accordionEnhancement.script; script.async = true; script.onload = function() { console.log('Accordion enhancement loaded'); }; document.body.appendChild(script); } console.log(`Loading feature: ${featureName}`); } // Monitor DOM changes for dynamically added content if ('MutationObserver' in window) { const observer = new MutationObserver((mutations) => { let shouldCheck = false; mutations.forEach(mutation => { if (mutation.addedNodes.length > 0) { shouldCheck = true; } }); if (shouldCheck) { // Debounce the check clearTimeout(window.featureCheckTimeout); window.featureCheckTimeout = setTimeout(checkForFeatures, 100); } }); // Start observing once DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { childList: true, subtree: true }); checkForFeatures(); }); } else { observer.observe(document.body, { childList: true, subtree: true }); checkForFeatures(); } } else { // Fallback for older browsers if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', checkForFeatures); } else { checkForFeatures(); } } // Public API for manually loading features window.loadFeature = loadFeature; window.features = features; })(); {# Include individual feature files based on what's enabled #} {# These files contain their own lazy loading logic #} {% if enable_code_highlighting %} {% include "./code-highlighting.html" %} {% endif %} {% if enable_qr_code %} {% include "./qr-code.html" %} {% endif %} {% if enable_charts %} {% include "./charts.html" %} {% endif %} {% if enable_pdf_export %} {% include "./pdf-generator.html" %} {% endif %} {# Feature status indicator for debugging (only in preview mode) #} {% if request.query_dict.hs_preview %}
Features:
Code: {{ enable_code_highlighting|default(false) ? '✓' : '✗' }}
QR: {{ enable_qr_code|default(false) ? '✓' : '✗' }}
Charts: {{ enable_charts|default(false) ? '✓' : '✗' }}
PDF: {{ enable_pdf_export|default(false) ? '✓' : '✗' }}
Accordion JS: {{ enable_accordion_js|default(false) ? '✓' : '✗' }}
{% endif %}