UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

173 lines (172 loc) • 5.96 kB
import { settings } from "../../settings.js"; import { positionHighlight } from "../utils/highlight.js"; import { closeOnOutsideClick } from "../utils/window.js"; import { rulesCategories } from "./rules/index.js"; import { DevToolbarAuditListItem } from "./ui/audit-list-item.js"; import { DevToolbarAuditListWindow } from "./ui/audit-list-window.js"; import { createAuditUI } from "./ui/audit-ui.js"; const icon = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 1 20 16" aria-hidden="true"><path fill="#fff" d="M.6 2A1.1 1.1 0 0 1 1.7.9h16.6a1.1 1.1 0 1 1 0 2.2H1.6A1.1 1.1 0 0 1 .8 2Zm1.1 7.1h6a1.1 1.1 0 0 0 0-2.2h-6a1.1 1.1 0 0 0 0 2.2ZM9.3 13H1.8a1.1 1.1 0 1 0 0 2.2h7.5a1.1 1.1 0 1 0 0-2.2Zm11.3 1.9a1.1 1.1 0 0 1-1.5 0l-1.7-1.7a4.1 4.1 0 1 1 1.6-1.6l1.6 1.7a1.1 1.1 0 0 1 0 1.6Zm-5.3-3.4a1.9 1.9 0 1 0 0-3.8 1.9 1.9 0 0 0 0 3.8Z"/></svg>'; try { customElements.define("astro-dev-toolbar-audit-window", DevToolbarAuditListWindow); customElements.define("astro-dev-toolbar-audit-list-item", DevToolbarAuditListItem); } catch { } let showState = false; var audit_default = { id: "astro:audit", name: "Audit", icon, async init(canvas, eventTarget) { let audits = []; let auditWindow = document.createElement( "astro-dev-toolbar-audit-window" ); let hasCreatedUI = false; canvas.appendChild(auditWindow); await lint(); let mutationDebounce; const observer = new MutationObserver(() => { if (mutationDebounce) { clearTimeout(mutationDebounce); } mutationDebounce = setTimeout(() => { settings.logger.verboseLog("Rerunning audit lints because the DOM has been updated."); if ("requestIdleCallback" in window) { window.requestIdleCallback( async () => { lint().then(() => { if (showState) createAuditsUI(); }); }, { timeout: 300 } ); } else { setTimeout(async () => { lint().then(() => { if (showState) createAuditsUI(); }); }, 150); } }, 250); }); setupObserver(); document.addEventListener("astro:before-preparation", () => { observer.disconnect(); }); document.addEventListener("astro:after-swap", async () => { lint(); }); document.addEventListener("astro:page-load", async () => { refreshLintPositions(); setTimeout(() => { setupObserver(); }, 100); }); eventTarget.addEventListener("app-toggled", (event) => { if (event.detail.state === true) { showState = true; createAuditsUI(); } else { showState = false; } }); closeOnOutsideClick(eventTarget, () => { const activeAudits = audits.filter((audit) => audit.card?.hasAttribute("active")); if (activeAudits.length > 0) { activeAudits.forEach((audit) => { audit.card?.toggleAttribute("active", false); }); return true; } return false; }); async function createAuditsUI() { if (hasCreatedUI) return; const fragment = document.createDocumentFragment(); for (const audit of audits) { const { card, highlight } = createAuditUI(audit, audits); audit.card = card; audit.highlight = highlight; fragment.appendChild(highlight); } auditWindow.audits = audits; canvas.appendChild(fragment); hasCreatedUI = true; } async function lint() { if (audits.length > 0) { audits.forEach((audit) => { audit.highlight?.remove(); audit.card?.remove(); }); audits = []; hasCreatedUI = false; } const selectorCache = /* @__PURE__ */ new Map(); for (const ruleCategory of rulesCategories) { for (const rule of ruleCategory.rules) { const elements = selectorCache.get(rule.selector) ?? document.querySelectorAll(rule.selector); let matches = []; if (typeof rule.match === "undefined") { matches = Array.from(elements); } else { for (const element of elements) { try { if (await rule.match(element)) { matches.push(element); } } catch (e) { settings.logger.error(`Error while running audit's match function: ${e}`); } } } for (const element of matches) { if (audits.some((audit) => audit.auditedElement === element)) continue; await createAuditProblem(rule, element); } } } eventTarget.dispatchEvent( new CustomEvent("toggle-notification", { detail: { state: audits.length > 0 } }) ); } async function createAuditProblem(rule, originalElement) { const computedStyle = window.getComputedStyle(originalElement); const targetedElement = originalElement.children[0] || originalElement; if (targetedElement.offsetParent === null || computedStyle.display === "none") { return; } if (originalElement.nodeName === "IMG" && !originalElement.complete) { return; } audits.push({ auditedElement: originalElement, rule, card: null, highlight: null }); } function refreshLintPositions() { audits.forEach(({ highlight, auditedElement }) => { const rect = auditedElement.getBoundingClientRect(); if (highlight) positionHighlight(highlight, rect); }); } ["scroll", "resize"].forEach((event) => { window.addEventListener(event, refreshLintPositions); }); function setupObserver() { observer.observe(document.body, { childList: true, subtree: true }); } } }; export { audit_default as default };