about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2025-03-15 21:08:52 -0400
committerelioat <elioat@tilde.institute>2025-03-15 21:08:52 -0400
commit7b380bc6f12771c07f7c70b6a9c747fd6703f92e (patch)
tree6e95a0e1b93a80825025bd281efe70da4488f17d
parentcd6f63bbf351e458f15613e11839bddc17bc5157 (diff)
downloadtour-7b380bc6f12771c07f7c70b6a9c747fd6703f92e.tar.gz
*
-rw-r--r--html/web-font-vacuum/app.js195
1 files changed, 85 insertions, 110 deletions
diff --git a/html/web-font-vacuum/app.js b/html/web-font-vacuum/app.js
index 2dc91ff..8a04356 100644
--- a/html/web-font-vacuum/app.js
+++ b/html/web-font-vacuum/app.js
@@ -44,6 +44,8 @@ const CORS_PROXIES = [
 
 // Keep track of which proxy worked last
 let lastWorkingProxyIndex = 0;
+let proxyFailureCount = 0;
+const MAX_PROXY_FAILURES = 3;
 
 async function fetchWithProxies(url, attempt = 0, isBinary = false) {
     // Start with the last working proxy
@@ -59,29 +61,31 @@ async function fetchWithProxies(url, attempt = 0, isBinary = false) {
             
             const fetchOptions = {
                 headers: {
-                    'Accept': isBinary ? '*/*' : 'text/html,application/xhtml+xml,text/css'
-                }
+                    'Accept': isBinary ? '*/*' : 'text/html,application/xhtml+xml,text/css',
+                    'Origin': window.location.origin
+                },
+                mode: 'cors'
             };
             
-            // For binary data, set responseType to arraybuffer if supported
-            if (isBinary) {
-                fetchOptions.mode = 'cors';
-            }
-            
             const response = await fetch(proxy.urlFormatter(url), fetchOptions);
             
             if (response.ok) {
                 lastWorkingProxyIndex = proxyIndex;
+                proxyFailureCount = 0;
                 return response;
             }
         } catch (error) {
             console.log(`Proxy ${proxy.name} failed:`, error);
-            // Continue to next proxy
+            proxyFailureCount++;
+            
+            // If we've had too many failures, wait a bit before continuing
+            if (proxyFailureCount >= MAX_PROXY_FAILURES) {
+                await new Promise(resolve => setTimeout(resolve, 1000));
+                proxyFailureCount = 0;
+            }
         }
     }
     
-    // DO NOT PASS GO! DO NOT COLLECT $200 DOLLARS
-    // All proxies failed
     throw new Error('All proxies failed to fetch the resource');
 }
 
@@ -350,7 +354,7 @@ document.addEventListener('DOMContentLoaded', () => {
             if (fontUrls.size === 0) {
                 resultsDiv.innerHTML = '<p>No web fonts (WOFF/TTF/WOFF2/OTF) were found on this page.</p>';
             } else {
-                displayFontUrls(Array.from(fontUrls));
+                displayFontUrls(fontUrls);
             }
 
         } catch (error) {
@@ -372,78 +376,71 @@ document.addEventListener('DOMContentLoaded', () => {
             const response = await fetchWithProxies(cssUrl);
             const css = await response.text();
             
-            // Use the CSS URL as the base URL for resolving font URLs
+            // Extract font URLs from the CSS content
+            extractFontUrlsFromCss(css, cssUrl, fontUrls);
         } catch (error) {
             console.error(`Error processing CSS from ${cssUrl}:`, error);
         }
     }
 
     /**
-     * Extracts font URLs from CSS by the power of regex.
-     * - Font URLs
-     * - Font family names
-     * - Full CSS rules for reference
+     * Extracts font URLs from CSS content
      * 
-     * @param {string} css - The CSS content to parse
-     * @param {string} baseUrl - Base URL for resolving relative paths
+     * @param {string} css - The CSS content to process
+     * @param {string} cssUrl - The URL of the CSS file (for resolving relative paths)
      * @param {Set} fontUrls - Set to store found font URLs
      */
-    function extractFontUrlsFromCss(css, baseUrl, fontUrls) {
+    function extractFontUrlsFromCss(css, cssUrl, fontUrls) {
+        // Get the base URL for resolving relative paths
+        const baseUrl = new URL(cssUrl).origin;
+        
+        // Match @font-face blocks
         const fontFaceRegex = /@font-face\s*{[^}]*}/g;
         const urlRegex = /url\(['"]?([^'"\)]+)['"]?\)/g;
-        const fontFamilyRegex = /font-family\s*:\s*['"]?([^'";]+)['"]?/;
+        const fontFamilyRegex = /font-family\s*:\s*['"]?([^'";]*)['"]?/;
         
-        let fontFaceRules = css.match(fontFaceRegex) || [];
-        
-        fontFaceRules.forEach(rule => {
-            let urls = [];
-            let match;
-            
-            // Extract URLs from the rule
-            while ((match = urlRegex.exec(rule)) !== null) {
-                let fontUrl = match[1].trim();
-                
-                // Handle relative URLs
-                if (!fontUrl.startsWith('http') && !fontUrl.startsWith('data:')) {
-                    fontUrl = new URL(fontUrl, baseUrl).href;
-                }
-                
-                // Check if it's a font file
-                if (fontUrl.match(/\.(woff2?|ttf|otf|eot)($|\?)/i)) {
-                    urls.push(fontUrl);
-                }
-            }
+        let fontFaceMatch;
+        while ((fontFaceMatch = fontFaceRegex.exec(css)) !== null) {
+            const fontFaceBlock = fontFaceMatch[0];
             
             // Extract font-family name
-            const familyMatch = rule.match(fontFamilyRegex);
-            const familyName = familyMatch ? familyMatch[1].trim() : 'Unknown Font';            
-            const cleanRule = rule.replace(/\s+/g, ' ').trim();
+            const familyMatch = fontFaceBlock.match(fontFamilyRegex);
+            const fontFamily = familyMatch ? familyMatch[1].trim() : 'Unknown Font';
             
-            urls.forEach(url => {
-                const filename = url.split('/').pop().split('?')[0];
-                fontUrls.add({
-                    url,
-                    family: familyName,
-                    filename,
-                    cssRule: cleanRule
-                });
-            });
-        });
-        
-        // Also look for other font references in the CSS
-        const fontRegex = /font(-family)?\s*:\s*['"]?([^'";]+)['"]?/g;
-        while ((match = fontRegex.exec(css)) !== null) {
-            if (!match[0].includes('@font-face')) {
-                const rule = match[0].trim();
-                const context = css.substring(Math.max(0, match.index - 50), 
-                                           Math.min(css.length, match.index + rule.length + 50));
-                
-                // Store the context for any existing font entries that match the family
-                const fontFamily = match[2].split(',')[0].trim();
-                for (let fontData of fontUrls) {
-                    if (fontData.family === fontFamily) {
-                        fontData.usageExample = context.trim();
+            // Extract all URLs from this @font-face block
+            let urlMatch;
+            while ((urlMatch = urlRegex.exec(fontFaceBlock)) !== null) {
+                try {
+                    let fontUrl = urlMatch[1].trim();
+                    
+                    // Skip data: URLs
+                    if (fontUrl.startsWith('data:')) {
+                        console.log('Skipping data: URL font');
+                        continue;
                     }
+                    
+                    // Only process known font file types
+                    if (!fontUrl.match(/\.(woff2?|ttf|otf|eot)(\?.*)?$/i)) {
+                        continue;
+                    }
+                    
+                    // Resolve relative URLs
+                    if (fontUrl.startsWith('//')) {
+                        fontUrl = 'https:' + fontUrl;
+                    } else if (!fontUrl.startsWith('http')) {
+                        fontUrl = new URL(fontUrl, cssUrl).href;
+                    }
+                    
+                    const filename = fontUrl.split('/').pop().split('?')[0];
+                    console.log(`Found font in CSS: ${fontUrl} (${fontFamily})`);
+                    
+                    fontUrls.add({
+                        url: fontUrl,
+                        family: fontFamily,
+                        filename: filename
+                    });
+                } catch (error) {
+                    console.error('Error processing font URL:', urlMatch[1], error);
                 }
             }
         }
@@ -461,51 +458,27 @@ document.addEventListener('DOMContentLoaded', () => {
      */
     function extractDirectFontLinks(doc, baseUrl, fontUrls) {
         // Check for preload links
-        doc.querySelectorAll('link[rel="preload"][as="font"]').forEach(link => {
-            const href = link.getAttribute('href');
-            if (href && href.match(/\.(woff|woff2|ttf|otf)(\?.*)?$/i)) {
-                try {
-                    const absoluteUrl = new URL(href, baseUrl).href;
-                    const filename = href.split('/').pop().split('?')[0];
-                    
-                    // Try to get font-family from the link
-                    let fontFamilyName = 'Unknown Font';
-                    if (link.dataset.fontFamily) {
-                        fontFamilyName = link.dataset.fontFamily;
-                    }
-                    
-                    console.log(`Found preloaded font: ${absoluteUrl} (${fontFamilyName})`);
-                    fontUrls.add({
-                        url: absoluteUrl,
-                        family: fontFamilyName,
-                        filename: filename
-                    });
-                } catch (error) {
-                    console.error('Error resolving font URL:', href, error);
-                }
-            }
-        });
-        
-        // Check for any links that might be fonts
-        doc.querySelectorAll('a[href]').forEach(link => {
+        doc.querySelectorAll('link[rel="preload"][as="font"], link[rel="stylesheet"]').forEach(link => {
             const href = link.getAttribute('href');
-            if (href && href.match(/\.(woff|woff2|ttf|otf)(\?.*)?$/i)) {
+            if (href && href.match(/\.(woff|woff2|ttf|otf|css)(\?.*)?$/i)) {
                 try {
                     const absoluteUrl = new URL(href, baseUrl).href;
-                    const filename = href.split('/').pop().split('?')[0];
-                    
-                    // Use link text as potential font name if available
-                    let fontFamilyName = link.textContent.trim() || 'Unknown Font';
-                    if (fontFamilyName === filename) {
-                        fontFamilyName = 'Unknown Font';
+                    if (href.match(/\.css(\?.*)?$/i)) {
+                        processCssUrl(absoluteUrl, fontUrls, baseUrl);
+                    } else {
+                        const filename = href.split('/').pop().split('?')[0];
+                        let fontFamilyName = 'Unknown Font';
+                        if (link.dataset.fontFamily) {
+                            fontFamilyName = link.dataset.fontFamily;
+                        }
+                        
+                        console.log(`Found preloaded font: ${absoluteUrl} (${fontFamilyName})`);
+                        fontUrls.add({
+                            url: absoluteUrl,
+                            family: fontFamilyName,
+                            filename: filename
+                        });
                     }
-                    
-                    console.log(`Found linked font: ${absoluteUrl} (${fontFamilyName})`);
-                    fontUrls.add({
-                        url: absoluteUrl,
-                        family: fontFamilyName,
-                        filename: filename
-                    });
                 } catch (error) {
                     console.error('Error resolving font URL:', href, error);
                 }
@@ -529,7 +502,10 @@ document.addEventListener('DOMContentLoaded', () => {
         const resultsDiv = document.getElementById('results');
         resultsDiv.innerHTML = '';
 
-        if (urls.size === 0) {
+        // Convert urls to array if it's a Set, or use as is if already array
+        const fontsArray = Array.isArray(urls) ? urls : Array.from(urls);
+        
+        if (fontsArray.length === 0) {
             resultsDiv.innerHTML = '<p>No fonts found on this webpage.</p>';
             return;
         }
@@ -541,7 +517,6 @@ document.addEventListener('DOMContentLoaded', () => {
         container.style.maxWidth = '800px';
         container.style.margin = '0 auto';
 
-        const fontsArray = Array.from(urls);
         const shouldAutoPreview = fontsArray.length < 4;
 
         for (let fontData of fontsArray) {