Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | /** * WP GFM Renderer - SSR Client * * Handles client-side complement for Server-Side Rendering * - Sends rendered Mermaid SVG to server for caching * - Detects and processes SSR-pending elements * * @package WpGfmRenderer * @since 2.0.0 */ /* global wpGfmConfig */ (function() { 'use strict'; // Wait for wpGfmConfig configuration to be available if (typeof wpGfmConfig === 'undefined') { console.warn('[GFMR SSR] wpGfmConfig configuration not found'); return; } /** * Save Mermaid SVG to server cache * * @param {string} diagramId - Diagram identifier (content hash) * @param {string} theme - Theme identifier * @param {string} bgColor - Background color * @param {string} svg - SVG content */ function saveMermaidSvgToCache(diagramId, theme, bgColor, svg) { // Only send if user is logged in (admin preview scenario) // Check if SSR nonce is available (indicates user can cache) if (!wpGfmConfig.mermaidSsrNonce) { console.log('[GFMR SSR] Skip SVG caching - no nonce available (user likely not logged in)'); return; } const data = new URLSearchParams({ action: 'gfmr_save_mermaid_svg', nonce: wpGfmConfig.mermaidSsrNonce, diagram_id: diagramId, theme: theme, bg_color: bgColor, svg: svg }); // Use WordPress AJAX URL if available, fallback to standard path const ajaxUrl = wpGfmConfig.ajaxUrl || '/wp-admin/admin-ajax.php'; fetch(ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: data }) .then(response => response.json()) .then(result => { if (result.success) { console.log('[GFMR SSR] Mermaid SVG cached:', diagramId); } else { console.warn('[GFMR SSR] Failed to cache Mermaid SVG:', result.data?.message); } }) .catch(error => { console.error('[GFMR SSR] Error caching Mermaid SVG:', error); }); } /** * Process SSR-pending Mermaid diagrams * * Waits for Mermaid to render, then sends SVG to server */ function processSsrPendingDiagrams() { const pendingDiagrams = document.querySelectorAll('.gfmr-mermaid-container[data-ssr="pending"]'); if (pendingDiagrams.length === 0) { return; } console.log('[GFMR SSR] Found', pendingDiagrams.length, 'SSR-pending diagrams'); // Set up MutationObserver to detect when Mermaid rendering completes pendingDiagrams.forEach(container => { const diagramId = container.getAttribute('data-diagram-id'); const theme = container.getAttribute('data-theme') || 'default'; const bgColor = container.getAttribute('data-mermaid-bg-color') || 'transparent'; // Create observer to watch for SVG insertion const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeName === 'SVG') { // SVG was rendered const svg = node.outerHTML; // Send to server for caching saveMermaidSvgToCache(diagramId, theme, bgColor, svg); // Mark as processed container.setAttribute('data-ssr', 'cached'); // Disconnect observer observer.disconnect(); } }); }); }); // Start observing observer.observe(container, { childList: true, subtree: true }); // Set timeout to disconnect observer after 30 seconds setTimeout(() => { observer.disconnect(); if (container.getAttribute('data-ssr') === 'pending') { console.warn('[GFMR SSR] Timeout waiting for Mermaid render:', diagramId); container.setAttribute('data-ssr', 'failed'); } }, 30000); }); } /** * Initialize SSR client */ function init() { // Wait for DOM to be ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); return; } console.log('[GFMR SSR] Initializing SSR client'); // Process SSR-pending diagrams processSsrPendingDiagrams(); // Re-process if new content is dynamically added const contentObserver = new MutationObserver((mutations) => { let hasNewDiagrams = false; mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === 1) { // Element node if (node.matches && node.matches('.gfmr-mermaid-container[data-ssr="pending"]')) { hasNewDiagrams = true; } else if (node.querySelector) { const pending = node.querySelector('.gfmr-mermaid-container[data-ssr="pending"]'); if (pending) { hasNewDiagrams = true; } } } }); }); if (hasNewDiagrams) { console.log('[GFMR SSR] Detected new SSR-pending diagrams'); processSsrPendingDiagrams(); } }); // Observe document body for dynamic content contentObserver.observe(document.body, { childList: true, subtree: true }); } // Start initialization init(); })(); |