Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions scripts/generate-skills.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,6 @@ function extractThresholds(content) {
return ''
}

// Strip internal relative links (e.g. /CoreWebVitals/LCP-Sub-Parts) from markdown link text
function cleanLinks(text) {
return text
.replace(/\[([^\]]+)\]\(\/[^)]+\)/g, '$1') // remove internal links, keep text
.replace(/\[([^\]]+)\]\((https?:[^)]+)\)/g, '[$1]($2)') // keep external links
}

// Build metadata for a single snippet JS file
function buildSnippetMeta(category, snippetFile) {
const basename = path.basename(snippetFile, '.js')
Expand Down
2 changes: 1 addition & 1 deletion scripts/install-global.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function main() {
console.log('1️⃣ Generating skills...')
try {
execSync('node scripts/generate-skills.js', { cwd: ROOT, stdio: 'inherit' })
} catch (error) {
} catch {
console.error('❌ Failed to generate skills')
process.exit(1)
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/install-skills.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function main() {
console.log('1️⃣ Generating skills...')
try {
execSync('node scripts/generate-skills.js', { cwd: ROOT, stdio: 'inherit' })
} catch (error) {
} catch {
console.error('❌ Failed to generate skills')
process.exit(1)
}
Expand Down
2 changes: 1 addition & 1 deletion snippets/Loading/Back-Forward-Cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@

// Initialize
checkRestoration();
const eligibility = testEligibility();
testEligibility();

// Display after a short delay to ensure pageshow event fires
setTimeout(() => {
Expand Down
6 changes: 4 additions & 2 deletions snippets/Loading/CSS-Media-Queries-Analysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ async function analyzeCSSMediaQueries(minWidth = 768) {
}
});
}
} catch (e) {
} catch {
// If CORS blocked, try to fetch the CSS
if (sheet.href) {
try {
const response = await fetch(sheet.href);
const cssText = await response.text();
parseMediaQueriesFromCSS(cssText, sheet.href, false);
} catch (fetchError) {
} catch {
// Silently count CORS blocked files
corsBlockedCount++;
}
Expand Down Expand Up @@ -485,6 +485,8 @@ async function analyzeCSSPerformanceImpact(minWidth = 768) {
};
}

window.analyzeCSSPerformanceImpact = analyzeCSSPerformanceImpact;

// Run with default breakpoint (768px)
(async () => {
const result = await analyzeCSSMediaQueries();
Expand Down
2 changes: 0 additions & 2 deletions snippets/Loading/Client-Side-Redirect-Detection.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,6 @@
// Recommendations
const hasDocumentNavigation = documentNavigations.length > 0;
const hasSameOriginRedirect = sameOrigin && referrerPath !== currentPath && referrerPath !== '';
const hasHighImpact = hasDocumentNavigation && documentNavigations.reduce((sum, nav) => sum + nav.duration, 0) > 1000;

if (hasDocumentNavigation || serverRedirects > 0) {
console.log('');
console.log('%c💡 Recommendations:', 'font-weight: bold;');
Expand Down
22 changes: 18 additions & 4 deletions snippets/Loading/Content-Visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function detectContentVisibility() {
if (el.id) break;
node = el.parentNode;
}
} catch (err) {
} catch {
// Do nothing...
}
return sel;
Expand Down Expand Up @@ -188,7 +188,7 @@ function analyzeContentVisibilityOpportunities(options = {}) {
if (el.id) break;
node = el.parentNode;
}
} catch (err) {}
} catch {}
return sel;
}

Expand Down Expand Up @@ -271,7 +271,13 @@ function analyzeContentVisibilityOpportunities(options = {}) {
console.log("");

// Show table without element reference
const tableData = opportunities.slice(0, 20).map(({ element, ...rest }) => rest);
const tableData = opportunities.slice(0, 20).map((opportunity) => ({
selector: opportunity.selector,
height: opportunity.height,
distanceFromViewport: opportunity.distanceFromViewport,
childElements: opportunity.childElements,
estimatedSavings: opportunity.estimatedSavings,
}));
console.table(tableData);

if (opportunities.length > 20) {
Expand Down Expand Up @@ -304,13 +310,21 @@ function analyzeContentVisibilityOpportunities(options = {}) {
console.groupEnd();

return {
opportunities: opportunities.map(({ element, ...rest }) => rest),
opportunities: opportunities.map((opportunity) => ({
selector: opportunity.selector,
height: opportunity.height,
distanceFromViewport: opportunity.distanceFromViewport,
childElements: opportunity.childElements,
estimatedSavings: opportunity.estimatedSavings,
})),
totalElements: opportunities.length,
highImpact: opportunities.filter((o) => o.estimatedSavings.startsWith("High")).length,
elements: opportunities.map((o) => o.element),
};
}

window.analyzeContentVisibilityOpportunities = analyzeContentVisibilityOpportunities;

// Run detection
(() => {
const cvResults = detectContentVisibility();
Expand Down
2 changes: 1 addition & 1 deletion snippets/Loading/Critical-CSS-Detection.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
(s) => s.href === href
);
if (sheet && sheet.cssRules) ruleCount = sheet.cssRules.length;
} catch (_) {
} catch {
corsBlocked = true;
}

Expand Down
36 changes: 29 additions & 7 deletions snippets/Loading/Find-Above-The-Fold-Lazy-Loaded-Images.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if (el.id) break;
node = el.parentNode;
}
} catch (err) {}
} catch {}
return sel;
}

Expand Down Expand Up @@ -54,7 +54,7 @@
if (entry && entry.transferSize) {
return (entry.transferSize / 1024).toFixed(1) + " KB";
}
} catch (err) {}
} catch {}
return null;
}

Expand Down Expand Up @@ -189,10 +189,19 @@

// Table of all problematic images
console.group("📋 Lazy Loaded Images in Viewport");
const tableData = results.lazyImages.map(({ element, area, position, ...rest }) => ({
...rest,
top: position.top + "px",
isLcpCandidate: rest.isLcpCandidate ? "⚠️ YES" : "no"
const tableData = results.lazyImages.map((image) => ({
selector: image.selector,
lazyType: image.lazyType,
dimensions: image.dimensions,
top: image.position.top + "px",
distanceFromEdge: image.distanceFromEdge,
src: image.src,
srcset: image.srcset,
sizes: image.sizes,
alt: image.alt,
fetchPriority: image.fetchPriority,
fileSize: image.fileSize,
isLcpCandidate: image.isLcpCandidate ? "⚠️ YES" : "no",
}));
console.table(tableData);
console.groupEnd();
Expand Down Expand Up @@ -233,7 +242,20 @@
withDataSrc: results.summary.withDataSrc,
lcpAffected: results.summary.lcpAffected,
},
items: results.lazyImages.map(({ element, area, ...rest }) => rest),
items: results.lazyImages.map((image) => ({
selector: image.selector,
lazyType: image.lazyType,
dimensions: image.dimensions,
position: image.position,
distanceFromEdge: image.distanceFromEdge,
src: image.src,
srcset: image.srcset,
sizes: image.sizes,
alt: image.alt,
fetchPriority: image.fetchPriority,
fileSize: image.fileSize,
isLcpCandidate: image.isLcpCandidate,
})),
issues: [
...(results.summary.lcpAffected ? [{ severity: "error", message: 'LCP candidate image has lazy loading — remove loading="lazy" and add fetchpriority="high"' }] : []),
...(results.lazyImages.filter(i => !i.isLcpCandidate).length > 0 ? [{ severity: "warning", message: `${results.lazyImages.filter(i => !i.isLcpCandidate).length} above-fold image(s) have lazy loading — remove loading="lazy"` }] : []),
Expand Down
12 changes: 9 additions & 3 deletions snippets/Loading/Find-Images-With-Lazy-and-Fetchpriority.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if (el.id) break;
node = el.parentNode;
}
} catch (err) {}
} catch {}
return sel;
}

Expand Down Expand Up @@ -87,12 +87,18 @@
});

console.log("%c📋 Conflicting Elements:", "font-weight: bold;");
console.table(tableData.map(({ element, ...rest }) => rest));
console.table(tableData.map((item) => ({
selector: item.selector,
dimensions: item.dimensions,
inViewport: item.inViewport,
isLcpCandidate: item.isLcpCandidate,
src: item.src,
})));

// Elements for inspection
console.log("");
console.log("%c🔎 Elements for inspection:", "font-weight: bold;");
tableData.forEach(({ element, selector, isLcpCandidate }, i) => {
tableData.forEach(({ element, isLcpCandidate }, i) => {
const marker = isLcpCandidate === "⚠️ Yes" ? " 🚨 LCP" : "";
console.log(`${i + 1}.${marker}`, element);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if (el.id) break;
node = el.parentNode;
}
} catch (err) {}
} catch {}
return sel;
}

Expand Down Expand Up @@ -58,7 +58,7 @@
if (parent.matches(selector)) {
return { hidden: true, reason: selector, container: getSelector(parent) };
}
} catch (e) {}
} catch {}
}
parent = parent.parentElement;
}
Expand Down Expand Up @@ -193,7 +193,14 @@
// Below the fold images
if (results.belowFold.length > 0) {
console.group(`📍 Below The Fold (${results.belowFold.length} images)`);
const tableData = results.belowFold.slice(0, 20).map(({ element, fullSrc, ...rest }) => rest);
const tableData = results.belowFold.slice(0, 20).map((img) => ({
selector: img.selector,
src: img.src,
dimensions: img.dimensions,
size: img.size,
sizeFormatted: img.sizeFormatted,
distanceFromViewport: img.distanceFromViewport,
}));
console.table(tableData);
if (results.belowFold.length > 20) {
console.log(`... and ${results.belowFold.length - 20} more images`);
Expand All @@ -207,7 +214,15 @@
console.group(`🔒 In Hidden Containers (${results.hiddenContainers.length} images)`);
console.log("Images in tabs, modals, carousels, or other hidden elements:");
console.log("");
const tableData = results.hiddenContainers.slice(0, 15).map(({ element, fullSrc, distanceFromViewport, ...rest }) => rest);
const tableData = results.hiddenContainers.slice(0, 15).map((img) => ({
selector: img.selector,
src: img.src,
dimensions: img.dimensions,
size: img.size,
sizeFormatted: img.sizeFormatted,
hiddenReason: img.hiddenReason,
container: img.container,
}));
console.table(tableData);
if (results.hiddenContainers.length > 15) {
console.log(`... and ${results.hiddenContainers.length - 15} more images`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,6 @@
normalizeFontFamily(f.name.replace(/\.(woff2?|ttf|otf|eot)$/i, ""))
);

const loadedFamilies = uniqueLoadedFonts.map((f) =>
normalizeFontFamily(f.family)
);

const usedFamilies = usedFonts.map((f) => normalizeFontFamily(f.family));

// Fonts preloaded but not used above the fold
Expand Down
4 changes: 2 additions & 2 deletions snippets/Loading/Inline-CSS-Info-and-Size.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
contentMap.get(normalized).push(s.index);
});
const duplicates = Array.from(contentMap.entries())
.filter(([_, indices]) => indices.length > 1)
.map(([_, indices]) => indices);
.filter(([, indices]) => indices.length > 1)
.map(([, indices]) => indices);

// Rating based on total size
let rating, ratingColor;
Expand Down
4 changes: 2 additions & 2 deletions snippets/Loading/Inline-Script-Info-and-Size.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@
}
});
const duplicates = Array.from(contentMap.entries())
.filter(([_, indices]) => indices.length > 1)
.map(([_, indices]) => indices);
.filter(([, indices]) => indices.length > 1)
.map(([, indices]) => indices);

// Rating
let rating, ratingColor;
Expand Down
2 changes: 0 additions & 2 deletions snippets/Loading/JS-Execution-Time-Breakdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
const domInteractive = nav?.domInteractive || 0;
const domContentLoaded = nav?.domContentLoadedEventEnd || 0;
const loadEvent = nav?.loadEventEnd || 0;
const fetchStart = nav?.fetchStart || 0;

// 2. Script resource timing (download phase)
const scriptResources = performance
.getEntriesByType("resource")
Expand Down
4 changes: 2 additions & 2 deletions snippets/Loading/Resource-Hints-Validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,8 @@
.filter(([domain, count]) => count >= 2 && !hintedDomains.has(domain))
.sort((a, b) => b[1] - a[1]);

const topPreconnects = missingHints.filter(([_, count]) => count >= 5).slice(0, 3);
const topDnsPrefetch = missingHints.filter(([_, count]) => count >= 2 && count < 5).slice(0, 5);
const topPreconnects = missingHints.filter(([, count]) => count >= 5).slice(0, 3);
const topDnsPrefetch = missingHints.filter(([, count]) => count >= 2 && count < 5).slice(0, 5);
const shownHints = [...topPreconnects, ...topDnsPrefetch];

if (missingHints.length > 0) {
Expand Down
2 changes: 1 addition & 1 deletion snippets/Loading/SSR-Hydration-Data-Analysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
console.log("");
console.log("%c📦 Raw data object:", "font-weight: bold;");
console.log(data);
} catch (e) {
} catch {
console.log("Could not parse JSON content");
}
}
Expand Down
4 changes: 2 additions & 2 deletions snippets/Loading/Service-Worker-Analysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
' 💡 Enable with: registration.navigationPreload.enable()'
);
}
} catch (_) {
} catch {
// Access may be restricted
}
}
Expand Down Expand Up @@ -183,7 +183,7 @@
}
console.log(` Total entries: ${totalEntries}`);
}
} catch (_) {
} catch {
// Cross-origin restrictions may prevent cache access
}
}
Expand Down
12 changes: 6 additions & 6 deletions snippets/Loading/TTFB-Resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@
// Table (sorted by TTFB, slowest first)
console.log("");
console.log("%cResources (sorted by TTFB, slowest first):", "font-weight: bold;");
const tableData = resourcesData.slice(0, 25).map(({ fullUrl, ...rest }) => ({
"TTFB (ms)": rest.ttfb.toFixed(0),
"Duration (ms)": rest.duration.toFixed(0),
Type: rest.type,
"3rd Party": rest.thirdParty ? "Yes" : "",
Resource: rest.resource,
const tableData = resourcesData.slice(0, 25).map((resource) => ({
"TTFB (ms)": resource.ttfb.toFixed(0),
"Duration (ms)": resource.duration.toFixed(0),
Type: resource.type,
"3rd Party": resource.thirdParty ? "Yes" : "",
Resource: resource.resource,
}));
console.table(tableData);

Expand Down
Loading
Loading