HTML; return
$html; } // Handle potential API endpoint for error logging if ($_SERVER['REQUEST_URI'] === '/api/log-font-error' && $_SERVER['REQUEST_METHOD'] === 'POST') { $inputJSON = file_get_contents('php://input'); $errorData = json_decode($inputJSON, true); if ($errorData) { logFontError('Client-side font loading error', $errorData); } header('HTTP/1.1 204 No Content'); exit; } // Output the complete HTML echo generateHTML($config); header('Content-Type: text/html; charset=UTF-8'); // Configuration settings
$config = [ 'fontFamily' => 'Styrene', 'fontVariants' => ['B', 'LC'], 'fontFallbacks' => [ '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'sans-serif' ], 'fontPaths' => [ 'woff2' => '/static/fonts/styrene/styrene-b-lc.woff2', 'woff' => '/static/fonts/styrene/styrene-b-lc.woff', 'ttf' => '/static/fonts/styrene/styrene-b-lc.ttf' ], 'enableErrorLogging' => true, 'logFilePath' => '/var/log/font-rendering-errors.log' ]; // Font loading error tracking $fontErrors = []; /** * Log font loading errors to server log * *
@param string $message Error message *
@param array $context Additional context information *
@return void */ function logFontError($message, $context = []) { global
$config; if ($config['enableErrorLogging']) { $timestamp = date('Y-m-d H:i:s'); $contextData = json_encode($context); $logMessage = "[$timestamp] FONT ERROR: $message | Context: $contextData" . PHP_EOL; file_put_contents($config['logFilePath'], $logMessage, FILE_APPEND); } } /** * Generate font-face CSS definitions with fallbacks * *
@param array
$config Font configuration array *
@return string CSS rules for font-face */ function generateFontFaceCSS($config) {
$css = ''; foreach ($config['fontVariants'] as $variant) { $variantName =
$config['fontFamily'] . '-' . $variant;
$css .= "
@font-face {\n";
$css .= " font-family: '{$variantName}';\n";
$css .= " src: url('{$config['fontPaths']['woff2']}') format('woff2'),\n";
$css .= " url('{$config['fontPaths']['woff']}') format('woff'),\n";
$css .= " url('{$config['fontPaths']['ttf']}') format('truetype');\n";
$css .= " font-display: swap;\n";
$css .= "}\n\n"; } return
$css; } /** * Generate fallback font stack CSS * *
@param array
$config Font configuration *
@return string CSS with fallback rules */ function generateFallbackCSS($config) { $fallbacks = implode(', ', array_map(function($font) { return strpos($font, ' ') !== false ? "'$font'" :
$font; },
$config['fontFallbacks']));
$css = '';
$css .= ".tooltip, .article-header, .modal, .d-bibliography, .d-title {\n";
$css .= " font-family: '{$config['fontFamily']}', $fallbacks;\n";
$css .= "}\n\n";
$css .= ".styrene-fallback .tooltip,\n";
$css .= ".styrene-fallback .article-header,\n";
$css .= ".styrene-fallback .modal,\n";
$css .= ".styrene-fallback .d-bibliography,\n";
$css .= ".styrene-fallback .d-title {\n";
$css .= " font-family: $fallbacks;\n";
$css .= "}\n"; return
$css; } /** * Generate font loading detection JavaScript * *
@return string JavaScript for font loading detection */ function generateFontDetectionJS() {
$js = <<<EOT // Font loading error detection using Promise chain (function() { // Define our font check Promise function checkFontPromise(fontName, timeout = 3000) { return new Promise((resolve, reject) => { // First try document.fonts if available (modern browsers) if (typeof document.fonts !== 'undefined' && typeof document.fonts.check === 'function') { // Set a timeout in case font loading hangs const timeoutId = setTimeout(() => { reject(new Error(`Font loading timeout: \${fontName}`)); }, timeout); document.fonts.ready.then(() => { clearTimeout(timeoutId); if (document.fonts.check(`1em \${fontName}`)) { resolve(true); } else { reject(new Error(`Font not available: \${fontName}`)); } }).catch(err => { clearTimeout(timeoutId); reject(err); }); } else { // Fallback detection method for older browsers const testElement = document.createElement('span');
testElement.style.position = 'absolute';
testElement.style.visibility = 'hidden';
testElement.style.fontSize = '100px';
testElement.style.fontFamily = `'\${fontName}', monospace`; testElement.innerHTML = 'Test Font Loading'; document.body.appendChild(testElement); const initialWidth = testElement.offsetWidth; // Now change to just monospace and compare width
testElement.style.fontFamily = 'monospace'; const fallbackWidth = testElement.offsetWidth; // Clean up test element document.body.removeChild(testElement); // If widths are different, font likely loaded if (initialWidth !== fallbackWidth) { resolve(true); } else { reject(new Error(`Font likely not loaded: \${fontName}`)); } } }); } // Check our specific fonts Promise.allSettled([ checkFontPromise('Styrene-B'), checkFontPromise('Styrene-LC') ]).then(results => { let hasFailures = false; const errorLog = []; results.forEach((result, index) => { const fontName = index === 0 ? 'Styrene-B' : 'Styrene-LC'; if (result.status === 'rejected') { hasFailures = true; errorLog.push({ font: fontName, error: result.reason.message }); } }); // Apply fallback styling if any font failed to load if (hasFailures) { document.documentElement.classList.add('styrene-fallback'); // Log errors to console console.warn('Font loading errors detected, applied fallbacks:', errorLog); // Send error report to server if (navigator.sendBeacon) { const blob = new Blob([JSON.stringify({ errorType: 'font-loading', timestamp: new Date().toISOString(), errors: errorLog, userAgent: navigator.userAgent, url: window.location.href })], { type: 'application/json' }); navigator.sendBeacon('/api/log-font-error', blob); } } }); // Dynamic polyfill for promise.then() chain issues if (typeof Promise.prototype._originalThen === 'undefined') { Promise.prototype._originalThen = Promise.prototype.then; Promise.prototype.then = function(onFulfilled, onRejected) { // Wrap callbacks to prevent chain breaking on errors const wrappedOnFulfilled = onFulfilled ? function(value) { try { return onFulfilled(value); } catch (e) { console.error('Error in promise chain:', e); // Return a valid promise to continue chain return Promise.resolve({ error: e, originalValue: value, recoveryAttempted: true }); } } : undefined; const wrappedOnRejected = onRejected ? function(reason) { try { return onRejected(reason); } catch (e) { console.error('Error in promise rejection handler:', e); // Return a valid promise to continue chain return Promise.resolve({ error: e, originalReason: reason, recoveryAttempted: true }); } } : undefined; return this._originalThen(wrappedOnFulfilled, wrappedOnRejected); }; } })(); EOT; return
$js; } // Generate complete HTML output function generateHTML($config) { $fontFaceCSS = generateFontFaceCSS($config); $fallbackCSS = generateFallbackCSS($config); $fontDetectionJS = generateFontDetectionJS();
$html = <<<HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ChatGPT Font Rendering Fix</title> <style> /* Font definitions */ $fontFaceCSS /* Fallback mechanisms */ $fallbackCSS /* Additional styles for demo */ body { font-family: system-ui, sans-serif; line-height: 1.5; max-width: 800px; margin: 0 auto; padding: 20px; } .article-header { font-size: 24px; margin-bottom: 20px; } .tooltip { background:
#f5f5f5; padding: 10px; border-radius: 4px; margin-bottom: 20px; } .d-title { font-size: 32px; font-weight: bold; margin-bottom: 30px; } .d-bibliography { font-size: 14px; margin-top: 40px; padding-top: 20px; border-top: 1px solid
#eee; } .font-test-container { margin: 40px 0; padding: 20px; border: 1px solid
#ddd; border-radius: 8px; } .font-status { margin-top: 20px; padding: 10px; background:
#eee; border-radius: 4px; } .error { color:
#c00; } .success { color:
#0a0; } </style> </head> <body> <div class="d-title">Font Rendering System with Error Handling</div> <div class="article-header">Chain-of-thought Faithfulness Test</div> <div class="tooltip tooltip-hidden"> This text should be rendered in Styrene font or fallback gracefully </div> <div class="font-test-container"> <h3>Font Loading Test</h3> <p>The text below will test if Styrene B=LC font is loading correctly:</p> <div class="article-header" id="font-test-element">Chain-of-thought Faithfulness</div> <div class="font-status" id="font-status">Checking font status...</div> </div> <div class="d-bibliography"> <p>References to chain-of-thought reasoning in language models</p> <p>[58, 59] Faithful chain-of-thought reasoning</p> </div> <script> // Font detection and error handling $fontDetectionJS // Additional test script document.addEventListener('DOMContentLoaded', function() { // Update status after font check completes setTimeout(function() { const statusElement = document.getElementById('font-status'); if (document.documentElement.classList.contains('styrene-fallback')) { statusElement.innerHTML = '<span class="error">Styrene font failed to load. Fallback fonts applied.</span>'; } else { statusElement.innerHTML = '<span class="success">Styrene font loaded successfully!</span>'; } }, 3000); // Give fonts time to load });