@navinjoseph/web-perf-core 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audits/accessibility.d.ts +10 -0
- package/dist/audits/accessibility.d.ts.map +1 -0
- package/dist/audits/accessibility.js +258 -0
- package/dist/audits/accessibility.js.map +1 -0
- package/dist/audits/best-practices.d.ts +10 -0
- package/dist/audits/best-practices.d.ts.map +1 -0
- package/dist/audits/best-practices.js +696 -0
- package/dist/audits/best-practices.js.map +1 -0
- package/dist/audits/constants.d.ts +8 -0
- package/dist/audits/constants.d.ts.map +1 -0
- package/dist/audits/constants.js +278 -0
- package/dist/audits/constants.js.map +1 -0
- package/dist/audits/performance.d.ts +11 -0
- package/dist/audits/performance.d.ts.map +1 -0
- package/dist/audits/performance.js +497 -0
- package/dist/audits/performance.js.map +1 -0
- package/dist/audits/pwa.d.ts +10 -0
- package/dist/audits/pwa.d.ts.map +1 -0
- package/dist/audits/pwa.js +396 -0
- package/dist/audits/pwa.js.map +1 -0
- package/dist/audits/security.d.ts +10 -0
- package/dist/audits/security.d.ts.map +1 -0
- package/dist/audits/security.js +249 -0
- package/dist/audits/security.js.map +1 -0
- package/dist/audits/seo.d.ts +10 -0
- package/dist/audits/seo.d.ts.map +1 -0
- package/dist/audits/seo.js +471 -0
- package/dist/audits/seo.js.map +1 -0
- package/dist/browser.d.ts +21 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +178 -0
- package/dist/browser.js.map +1 -0
- package/dist/dom-collector.d.ts +45 -0
- package/dist/dom-collector.d.ts.map +1 -0
- package/dist/dom-collector.js +173 -0
- package/dist/dom-collector.js.map +1 -0
- package/dist/formatter.d.ts +60 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +164 -0
- package/dist/formatter.js.map +1 -0
- package/dist/id-generator.d.ts +22 -0
- package/dist/id-generator.d.ts.map +1 -0
- package/dist/id-generator.js +29 -0
- package/dist/id-generator.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +41 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +194 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/reporters/html.d.ts +6 -0
- package/dist/reporters/html.d.ts.map +1 -0
- package/dist/reporters/html.js +688 -0
- package/dist/reporters/html.js.map +1 -0
- package/dist/reporters/index.d.ts +4 -0
- package/dist/reporters/index.d.ts.map +1 -0
- package/dist/reporters/index.js +17 -0
- package/dist/reporters/index.js.map +1 -0
- package/dist/reporters/json.d.ts +6 -0
- package/dist/reporters/json.d.ts.map +1 -0
- package/dist/reporters/json.js +7 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/terminal.d.ts +6 -0
- package/dist/reporters/terminal.d.ts.map +1 -0
- package/dist/reporters/terminal.js +180 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/reporters/types.d.ts +2 -0
- package/dist/reporters/types.d.ts.map +1 -0
- package/dist/reporters/types.js +2 -0
- package/dist/reporters/types.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +36 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
package/dist/browser.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { JSDOM, VirtualConsole } from "jsdom";
|
|
2
|
+
import fetch from "node-fetch";
|
|
3
|
+
/**
|
|
4
|
+
* Load a URL using jsdom with Shadow DOM support
|
|
5
|
+
*/
|
|
6
|
+
export async function loadPage(url, options = {}) {
|
|
7
|
+
const timeout = options.timeout || 10000; // 10 second default
|
|
8
|
+
const maxSize = options.maxSize || 10_000_000; // 10MB default
|
|
9
|
+
try {
|
|
10
|
+
// Create abort controller for timeout
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
13
|
+
const response = await fetch(url, {
|
|
14
|
+
headers: {
|
|
15
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
16
|
+
},
|
|
17
|
+
signal: controller.signal,
|
|
18
|
+
});
|
|
19
|
+
clearTimeout(timeoutId);
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
22
|
+
}
|
|
23
|
+
// Check content size before downloading
|
|
24
|
+
const contentLength = response.headers.get("content-length");
|
|
25
|
+
if (contentLength && parseInt(contentLength) > maxSize) {
|
|
26
|
+
throw new Error(`Page too large: ${contentLength} bytes (max: ${maxSize} bytes)`);
|
|
27
|
+
}
|
|
28
|
+
const html = await response.text();
|
|
29
|
+
// Check actual HTML size
|
|
30
|
+
if (html.length > maxSize) {
|
|
31
|
+
throw new Error(`HTML too large: ${html.length} bytes (max: ${maxSize} bytes)`);
|
|
32
|
+
}
|
|
33
|
+
// Create virtual console to suppress script errors from external scripts
|
|
34
|
+
const virtualConsole = new VirtualConsole();
|
|
35
|
+
virtualConsole.on("jsdomError", (error) => {
|
|
36
|
+
// Silently ignore JSDOM script errors from external scripts
|
|
37
|
+
// These are typically from third-party scripts that use APIs not supported by JSDOM
|
|
38
|
+
if (!error.message.includes("Could not parse CSS stylesheet")) {
|
|
39
|
+
// Only log non-CSS errors for debugging if needed
|
|
40
|
+
// console.error("JSDOM Error:", error.message);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// Create jsdom instance with Shadow DOM support
|
|
44
|
+
// Performance optimization: disable resource loading and script execution
|
|
45
|
+
// Most audits only need static HTML structure
|
|
46
|
+
const dom = new JSDOM(html, {
|
|
47
|
+
url,
|
|
48
|
+
pretendToBeVisual: true,
|
|
49
|
+
// Don't load external resources (huge perf gain) - omit resources option to disable
|
|
50
|
+
runScripts: !options.allowJs ? "outside-only" : undefined, // Only run scripts we inject (like axe-core)
|
|
51
|
+
virtualConsole,
|
|
52
|
+
beforeParse(window) {
|
|
53
|
+
// Polyfill browser APIs not supported by JSDOM
|
|
54
|
+
addBrowserPolyfills(window);
|
|
55
|
+
// Polyfill ShadowDOM if needed
|
|
56
|
+
if (!window.Element.prototype.attachShadow) {
|
|
57
|
+
window.Element.prototype.attachShadow = function () {
|
|
58
|
+
return this;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
document: dom.window.document,
|
|
65
|
+
window: dom.window,
|
|
66
|
+
html,
|
|
67
|
+
url,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
throw new Error(`Failed to load page ${url}: ${message}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get all elements including shadow DOM
|
|
77
|
+
*/
|
|
78
|
+
export function getAllElements(element) {
|
|
79
|
+
const elements = [element];
|
|
80
|
+
// Add children
|
|
81
|
+
for (const child of element.children) {
|
|
82
|
+
elements.push(...getAllElements(child));
|
|
83
|
+
}
|
|
84
|
+
// Add shadow DOM children if available
|
|
85
|
+
if (element.shadowRoot) {
|
|
86
|
+
for (const child of element.shadowRoot.children) {
|
|
87
|
+
elements.push(...getAllElements(child));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return elements;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Build selector for an element (including shadow DOM path)
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* Add polyfills for browser APIs not supported by JSDOM
|
|
97
|
+
*/
|
|
98
|
+
function addBrowserPolyfills(window) {
|
|
99
|
+
// Polyfill ReadableStream and related APIs
|
|
100
|
+
if (typeof window.ReadableStream === "undefined") {
|
|
101
|
+
window.ReadableStream = class ReadableStream {
|
|
102
|
+
constructor() {
|
|
103
|
+
// Minimal polyfill - just prevents errors
|
|
104
|
+
}
|
|
105
|
+
getReader() {
|
|
106
|
+
return {
|
|
107
|
+
read: () => Promise.resolve({ done: true, value: undefined }),
|
|
108
|
+
releaseLock: () => { },
|
|
109
|
+
closed: Promise.resolve(),
|
|
110
|
+
cancel: () => Promise.resolve(),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Polyfill WritableStream
|
|
116
|
+
if (typeof window.WritableStream === "undefined") {
|
|
117
|
+
window.WritableStream = class WritableStream {
|
|
118
|
+
constructor() { }
|
|
119
|
+
getWriter() {
|
|
120
|
+
return {
|
|
121
|
+
write: () => Promise.resolve(),
|
|
122
|
+
close: () => Promise.resolve(),
|
|
123
|
+
abort: () => Promise.resolve(),
|
|
124
|
+
closed: Promise.resolve(),
|
|
125
|
+
ready: Promise.resolve(),
|
|
126
|
+
releaseLock: () => { },
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Polyfill TransformStream
|
|
132
|
+
if (typeof window.TransformStream === "undefined") {
|
|
133
|
+
window.TransformStream = class TransformStream {
|
|
134
|
+
readable;
|
|
135
|
+
writable;
|
|
136
|
+
constructor() {
|
|
137
|
+
this.readable = new window.ReadableStream();
|
|
138
|
+
this.writable = new window.WritableStream();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Ensure window.window exists (some libraries expect this)
|
|
143
|
+
if (!window.window) {
|
|
144
|
+
window.window = window;
|
|
145
|
+
}
|
|
146
|
+
// Polyfill requestAnimationFrame if needed
|
|
147
|
+
if (!window.requestAnimationFrame) {
|
|
148
|
+
window.requestAnimationFrame = (callback) => {
|
|
149
|
+
return window.setTimeout(() => callback(Date.now()), 16);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// Polyfill cancelAnimationFrame if needed
|
|
153
|
+
if (!window.cancelAnimationFrame) {
|
|
154
|
+
window.cancelAnimationFrame = (id) => {
|
|
155
|
+
window.clearTimeout(id);
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
export function buildSelector(element) {
|
|
160
|
+
const path = [];
|
|
161
|
+
let current = element;
|
|
162
|
+
while (current && current.nodeType === 1) {
|
|
163
|
+
let selector = current.tagName.toLowerCase();
|
|
164
|
+
if (current.id) {
|
|
165
|
+
selector += `#${current.id}`;
|
|
166
|
+
}
|
|
167
|
+
else if (current.className) {
|
|
168
|
+
const classes = current.className.split(/\s+/).slice(0, 2).join(".");
|
|
169
|
+
if (classes) {
|
|
170
|
+
selector += `.${classes}`;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
path.unshift(selector);
|
|
174
|
+
current = current.parentElement;
|
|
175
|
+
}
|
|
176
|
+
return path.join(" > ");
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BrowserPage } from "./browser.js";
|
|
2
|
+
/**
|
|
3
|
+
* Cached DOM elements to avoid multiple queries
|
|
4
|
+
* This provides massive performance improvement by traversing DOM once
|
|
5
|
+
*/
|
|
6
|
+
export type CollectedElements = {
|
|
7
|
+
scripts: HTMLScriptElement[];
|
|
8
|
+
scriptsWithSrc: HTMLScriptElement[];
|
|
9
|
+
inlineScripts: HTMLScriptElement[];
|
|
10
|
+
inlineHeadScripts: HTMLScriptElement[];
|
|
11
|
+
stylesheets: HTMLLinkElement[];
|
|
12
|
+
styleLinks: HTMLLinkElement[];
|
|
13
|
+
fontLinks: HTMLLinkElement[];
|
|
14
|
+
images: HTMLImageElement[];
|
|
15
|
+
links: HTMLAnchorElement[];
|
|
16
|
+
passwordFields: HTMLInputElement[];
|
|
17
|
+
iframes: HTMLIFrameElement[];
|
|
18
|
+
metaCharset: HTMLMetaElement | null;
|
|
19
|
+
metaHttpEquiv: HTMLMetaElement | null;
|
|
20
|
+
metaRefresh: HTMLMetaElement | null;
|
|
21
|
+
metaViewport: HTMLMetaElement | null;
|
|
22
|
+
googleFontsLinks: HTMLLinkElement[];
|
|
23
|
+
googleFontsPreconnect: HTMLLinkElement | null;
|
|
24
|
+
fontPreloads: HTMLLinkElement[];
|
|
25
|
+
marquee: Element[];
|
|
26
|
+
blink: Element[];
|
|
27
|
+
font: Element[];
|
|
28
|
+
center: Element[];
|
|
29
|
+
elementsWithId: Element[];
|
|
30
|
+
allElements: Element[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Collect all DOM elements in a single traversal
|
|
34
|
+
* This is much faster than multiple querySelectorAll calls
|
|
35
|
+
*/
|
|
36
|
+
export declare function collectDOMElements(page: BrowserPage): CollectedElements;
|
|
37
|
+
/**
|
|
38
|
+
* Find render-blocking CSS stylesheets
|
|
39
|
+
*/
|
|
40
|
+
export declare function findBlockingCSS(stylesheets: HTMLLinkElement[]): HTMLLinkElement[];
|
|
41
|
+
/**
|
|
42
|
+
* Find duplicate IDs in collected elements
|
|
43
|
+
*/
|
|
44
|
+
export declare function findDuplicateIds(elementsWithId: Element[]): Map<string, Element[]>;
|
|
45
|
+
//# sourceMappingURL=dom-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-collector.d.ts","sourceRoot":"","sources":["../src/dom-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAE9B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;IAGvC,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,SAAS,EAAE,eAAe,EAAE,CAAC;IAG7B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAG3B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAG3B,cAAc,EAAE,gBAAgB,EAAE,CAAC;IAGnC,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAG7B,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,eAAe,GAAG,IAAI,CAAC;IACtC,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IAGrC,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,qBAAqB,EAAE,eAAe,GAAG,IAAI,CAAC;IAG9C,YAAY,EAAE,eAAe,EAAE,CAAC;IAGhC,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,EAAE,OAAO,EAAE,CAAC;IAGlB,cAAc,EAAE,OAAO,EAAE,CAAC;IAG1B,WAAW,EAAE,OAAO,EAAE,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAuJvE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,eAAe,EAAE,GAC7B,eAAe,EAAE,CAOnB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,OAAO,EAAE,GACxB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAsBxB"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collect all DOM elements in a single traversal
|
|
3
|
+
* This is much faster than multiple querySelectorAll calls
|
|
4
|
+
*/
|
|
5
|
+
export function collectDOMElements(page) {
|
|
6
|
+
const doc = page.document;
|
|
7
|
+
// Initialize collections
|
|
8
|
+
const collected = {
|
|
9
|
+
scripts: [],
|
|
10
|
+
scriptsWithSrc: [],
|
|
11
|
+
inlineScripts: [],
|
|
12
|
+
inlineHeadScripts: [],
|
|
13
|
+
stylesheets: [],
|
|
14
|
+
styleLinks: [],
|
|
15
|
+
fontLinks: [],
|
|
16
|
+
images: [],
|
|
17
|
+
links: [],
|
|
18
|
+
passwordFields: [],
|
|
19
|
+
iframes: [],
|
|
20
|
+
metaCharset: null,
|
|
21
|
+
metaHttpEquiv: null,
|
|
22
|
+
metaRefresh: null,
|
|
23
|
+
metaViewport: null,
|
|
24
|
+
googleFontsLinks: [],
|
|
25
|
+
googleFontsPreconnect: null,
|
|
26
|
+
fontPreloads: [],
|
|
27
|
+
marquee: [],
|
|
28
|
+
blink: [],
|
|
29
|
+
font: [],
|
|
30
|
+
center: [],
|
|
31
|
+
elementsWithId: [],
|
|
32
|
+
allElements: [],
|
|
33
|
+
};
|
|
34
|
+
// Single traversal of all elements
|
|
35
|
+
const allElements = doc.querySelectorAll("*");
|
|
36
|
+
collected.allElements = Array.from(allElements);
|
|
37
|
+
allElements.forEach((element) => {
|
|
38
|
+
const tagName = element.tagName.toLowerCase();
|
|
39
|
+
// Scripts
|
|
40
|
+
if (tagName === "script") {
|
|
41
|
+
const script = element;
|
|
42
|
+
collected.scripts.push(script);
|
|
43
|
+
if (script.hasAttribute("src")) {
|
|
44
|
+
collected.scriptsWithSrc.push(script);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
collected.inlineScripts.push(script);
|
|
48
|
+
if (script.closest("head")) {
|
|
49
|
+
collected.inlineHeadScripts.push(script);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Links (stylesheets, fonts, preloads)
|
|
54
|
+
else if (tagName === "link") {
|
|
55
|
+
const link = element;
|
|
56
|
+
const rel = link.getAttribute("rel");
|
|
57
|
+
const href = link.getAttribute("href") || "";
|
|
58
|
+
if (rel === "stylesheet") {
|
|
59
|
+
collected.stylesheets.push(link);
|
|
60
|
+
collected.styleLinks.push(link);
|
|
61
|
+
// Font links
|
|
62
|
+
if (href.includes("font")) {
|
|
63
|
+
collected.fontLinks.push(link);
|
|
64
|
+
}
|
|
65
|
+
// Google Fonts
|
|
66
|
+
if (href.includes("fonts.googleapis.com")) {
|
|
67
|
+
collected.googleFontsLinks.push(link);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Font preloads
|
|
71
|
+
if (rel === "preload" && link.getAttribute("as") === "font") {
|
|
72
|
+
collected.fontPreloads.push(link);
|
|
73
|
+
}
|
|
74
|
+
// Google Fonts preconnect
|
|
75
|
+
if (rel === "preconnect" &&
|
|
76
|
+
(href.includes("fonts.googleapis.com") ||
|
|
77
|
+
href.includes("fonts.gstatic.com"))) {
|
|
78
|
+
collected.googleFontsPreconnect = link;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Images
|
|
82
|
+
else if (tagName === "img") {
|
|
83
|
+
collected.images.push(element);
|
|
84
|
+
}
|
|
85
|
+
// Anchors
|
|
86
|
+
else if (tagName === "a") {
|
|
87
|
+
collected.links.push(element);
|
|
88
|
+
}
|
|
89
|
+
// Iframes
|
|
90
|
+
else if (tagName === "iframe") {
|
|
91
|
+
collected.iframes.push(element);
|
|
92
|
+
}
|
|
93
|
+
// Input fields
|
|
94
|
+
else if (tagName === "input") {
|
|
95
|
+
const input = element;
|
|
96
|
+
if (input.type === "password") {
|
|
97
|
+
collected.passwordFields.push(input);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Meta tags
|
|
101
|
+
else if (tagName === "meta") {
|
|
102
|
+
const meta = element;
|
|
103
|
+
const charset = meta.getAttribute("charset");
|
|
104
|
+
const httpEquiv = meta.getAttribute("http-equiv");
|
|
105
|
+
const name = meta.getAttribute("name");
|
|
106
|
+
if (charset) {
|
|
107
|
+
collected.metaCharset = meta;
|
|
108
|
+
}
|
|
109
|
+
if (httpEquiv === "Content-Type") {
|
|
110
|
+
collected.metaHttpEquiv = meta;
|
|
111
|
+
}
|
|
112
|
+
if (httpEquiv === "refresh") {
|
|
113
|
+
collected.metaRefresh = meta;
|
|
114
|
+
}
|
|
115
|
+
if (name === "viewport") {
|
|
116
|
+
collected.metaViewport = meta;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Deprecated elements
|
|
120
|
+
else if (tagName === "marquee") {
|
|
121
|
+
collected.marquee.push(element);
|
|
122
|
+
}
|
|
123
|
+
else if (tagName === "blink") {
|
|
124
|
+
collected.blink.push(element);
|
|
125
|
+
}
|
|
126
|
+
else if (tagName === "font") {
|
|
127
|
+
collected.font.push(element);
|
|
128
|
+
}
|
|
129
|
+
else if (tagName === "center") {
|
|
130
|
+
collected.center.push(element);
|
|
131
|
+
}
|
|
132
|
+
// Elements with IDs
|
|
133
|
+
if (element.hasAttribute("id")) {
|
|
134
|
+
collected.elementsWithId.push(element);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return collected;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Find render-blocking CSS stylesheets
|
|
141
|
+
*/
|
|
142
|
+
export function findBlockingCSS(stylesheets) {
|
|
143
|
+
return stylesheets.filter((link) => {
|
|
144
|
+
const media = link.getAttribute("media");
|
|
145
|
+
const disabled = link.hasAttribute("disabled");
|
|
146
|
+
// Blocking if no media attribute (or media="all") and not disabled
|
|
147
|
+
return !disabled && (!media || media === "all" || media === "screen");
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Find duplicate IDs in collected elements
|
|
152
|
+
*/
|
|
153
|
+
export function findDuplicateIds(elementsWithId) {
|
|
154
|
+
const idCount = new Map();
|
|
155
|
+
elementsWithId.forEach((element) => {
|
|
156
|
+
const id = element.getAttribute("id");
|
|
157
|
+
if (id) {
|
|
158
|
+
if (!idCount.has(id)) {
|
|
159
|
+
idCount.set(id, []);
|
|
160
|
+
}
|
|
161
|
+
idCount.get(id).push(element);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
// Filter to only duplicates
|
|
165
|
+
const duplicates = new Map();
|
|
166
|
+
idCount.forEach((elements, id) => {
|
|
167
|
+
if (elements.length > 1) {
|
|
168
|
+
duplicates.set(id, elements);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
return duplicates;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=dom-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-collector.js","sourceRoot":"","sources":["../src/dom-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Issue, PendingCheck, Summary, AuditReport } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Format audit results into a complete audit report
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatResults(url: string, startTime: number, endTime: number, allIssues: Issue[], allPassed: PendingCheck[], allIncomplete?: Issue[]): AuditReport;
|
|
6
|
+
/**
|
|
7
|
+
* Generate summary statistics from issues
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateSummary(issues: Issue[]): Summary;
|
|
10
|
+
/**
|
|
11
|
+
* Merge multiple audit results into a single array
|
|
12
|
+
*/
|
|
13
|
+
export declare function mergeAuditResults(results: Array<{
|
|
14
|
+
issues: Issue[];
|
|
15
|
+
passed: PendingCheck[];
|
|
16
|
+
}>): {
|
|
17
|
+
issues: Issue[];
|
|
18
|
+
passed: PendingCheck[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Apply threshold checking to determine if audit passed
|
|
22
|
+
*/
|
|
23
|
+
export declare function checkThresholds(summary: Summary, thresholds?: {
|
|
24
|
+
critical?: number;
|
|
25
|
+
serious?: number;
|
|
26
|
+
moderate?: number;
|
|
27
|
+
minor?: number;
|
|
28
|
+
}): {
|
|
29
|
+
passed: boolean;
|
|
30
|
+
violations: string[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Sort issues by severity and then by category
|
|
34
|
+
*/
|
|
35
|
+
export declare function sortIssues(issues: Issue[]): Issue[];
|
|
36
|
+
/**
|
|
37
|
+
* Group issues by category
|
|
38
|
+
*/
|
|
39
|
+
export declare function groupByCategory(issues: Issue[]): Record<string, Issue[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Group issues by severity
|
|
42
|
+
*/
|
|
43
|
+
export declare function groupBySeverity(issues: Issue[]): Record<string, Issue[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Filter issues by severity
|
|
46
|
+
*/
|
|
47
|
+
export declare function filterBySeverity(issues: Issue[], severities: Array<"critical" | "serious" | "moderate" | "minor">): Issue[];
|
|
48
|
+
/**
|
|
49
|
+
* Filter issues by category
|
|
50
|
+
*/
|
|
51
|
+
export declare function filterByCategory(issues: Issue[], categories: string[]): Issue[];
|
|
52
|
+
/**
|
|
53
|
+
* Get top N issues by severity
|
|
54
|
+
*/
|
|
55
|
+
export declare function getTopIssues(issues: Issue[], count: number): Issue[];
|
|
56
|
+
/**
|
|
57
|
+
* Calculate percentage of passed checks
|
|
58
|
+
*/
|
|
59
|
+
export declare function calculatePassRate(passed: number, total: number): number;
|
|
60
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvE;;GAEG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,KAAK,EAAE,EAClB,SAAS,EAAE,YAAY,EAAE,EACzB,aAAa,GAAE,KAAK,EAAO,GAC1B,WAAW,CAeb;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAmCxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,GAC1D;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,CAU7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CA+C3C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAanD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAWxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAaxE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,KAAK,EAAE,EACf,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC,GAC/D,KAAK,EAAE,CAET;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,KAAK,EAAE,EACf,UAAU,EAAE,MAAM,EAAE,GACnB,KAAK,EAAE,CAET;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,CAEpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGvE"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format audit results into a complete audit report
|
|
3
|
+
*/
|
|
4
|
+
export function formatResults(url, startTime, endTime, allIssues, allPassed, allIncomplete = []) {
|
|
5
|
+
const duration = endTime - startTime;
|
|
6
|
+
// Generate summary statistics
|
|
7
|
+
const summary = generateSummary(allIssues);
|
|
8
|
+
return {
|
|
9
|
+
url,
|
|
10
|
+
timestamp: startTime,
|
|
11
|
+
duration,
|
|
12
|
+
issues: allIssues,
|
|
13
|
+
passed: allPassed,
|
|
14
|
+
incomplete: allIncomplete,
|
|
15
|
+
summary,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate summary statistics from issues
|
|
20
|
+
*/
|
|
21
|
+
export function generateSummary(issues) {
|
|
22
|
+
const summary = {
|
|
23
|
+
total: issues.length,
|
|
24
|
+
bySeverity: {
|
|
25
|
+
critical: 0,
|
|
26
|
+
serious: 0,
|
|
27
|
+
moderate: 0,
|
|
28
|
+
minor: 0,
|
|
29
|
+
},
|
|
30
|
+
byCategory: {
|
|
31
|
+
images: 0,
|
|
32
|
+
interactive: 0,
|
|
33
|
+
forms: 0,
|
|
34
|
+
color: 0,
|
|
35
|
+
document: 0,
|
|
36
|
+
structure: 0,
|
|
37
|
+
aria: 0,
|
|
38
|
+
technical: 0,
|
|
39
|
+
},
|
|
40
|
+
passed: 0,
|
|
41
|
+
};
|
|
42
|
+
// Count by severity
|
|
43
|
+
issues.forEach((issue) => {
|
|
44
|
+
summary.bySeverity[issue.severity]++;
|
|
45
|
+
});
|
|
46
|
+
// Count by category
|
|
47
|
+
issues.forEach((issue) => {
|
|
48
|
+
if (issue.category in summary.byCategory) {
|
|
49
|
+
summary.byCategory[issue.category]++;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return summary;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Merge multiple audit results into a single array
|
|
56
|
+
*/
|
|
57
|
+
export function mergeAuditResults(results) {
|
|
58
|
+
const allIssues = [];
|
|
59
|
+
const allPassed = [];
|
|
60
|
+
results.forEach((result) => {
|
|
61
|
+
allIssues.push(...result.issues);
|
|
62
|
+
allPassed.push(...result.passed);
|
|
63
|
+
});
|
|
64
|
+
return { issues: allIssues, passed: allPassed };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Apply threshold checking to determine if audit passed
|
|
68
|
+
*/
|
|
69
|
+
export function checkThresholds(summary, thresholds) {
|
|
70
|
+
if (!thresholds) {
|
|
71
|
+
return { passed: true, violations: [] };
|
|
72
|
+
}
|
|
73
|
+
const violations = [];
|
|
74
|
+
if (thresholds.critical !== undefined &&
|
|
75
|
+
summary.bySeverity.critical > thresholds.critical) {
|
|
76
|
+
violations.push(`Critical issues: ${summary.bySeverity.critical} (threshold: ${thresholds.critical})`);
|
|
77
|
+
}
|
|
78
|
+
if (thresholds.serious !== undefined &&
|
|
79
|
+
summary.bySeverity.serious > thresholds.serious) {
|
|
80
|
+
violations.push(`Serious issues: ${summary.bySeverity.serious} (threshold: ${thresholds.serious})`);
|
|
81
|
+
}
|
|
82
|
+
if (thresholds.moderate !== undefined &&
|
|
83
|
+
summary.bySeverity.moderate > thresholds.moderate) {
|
|
84
|
+
violations.push(`Moderate issues: ${summary.bySeverity.moderate} (threshold: ${thresholds.moderate})`);
|
|
85
|
+
}
|
|
86
|
+
if (thresholds.minor !== undefined &&
|
|
87
|
+
summary.bySeverity.minor > thresholds.minor) {
|
|
88
|
+
violations.push(`Minor issues: ${summary.bySeverity.minor} (threshold: ${thresholds.minor})`);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
passed: violations.length === 0,
|
|
92
|
+
violations,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Sort issues by severity and then by category
|
|
97
|
+
*/
|
|
98
|
+
export function sortIssues(issues) {
|
|
99
|
+
const severityOrder = { critical: 0, serious: 1, moderate: 2, minor: 3 };
|
|
100
|
+
return issues.slice().sort((a, b) => {
|
|
101
|
+
// First sort by severity
|
|
102
|
+
const severityDiff = severityOrder[a.severity] - severityOrder[b.severity];
|
|
103
|
+
if (severityDiff !== 0) {
|
|
104
|
+
return severityDiff;
|
|
105
|
+
}
|
|
106
|
+
// Then by category
|
|
107
|
+
return a.category.localeCompare(b.category);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Group issues by category
|
|
112
|
+
*/
|
|
113
|
+
export function groupByCategory(issues) {
|
|
114
|
+
const grouped = {};
|
|
115
|
+
issues.forEach((issue) => {
|
|
116
|
+
if (!grouped[issue.category]) {
|
|
117
|
+
grouped[issue.category] = [];
|
|
118
|
+
}
|
|
119
|
+
grouped[issue.category].push(issue);
|
|
120
|
+
});
|
|
121
|
+
return grouped;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Group issues by severity
|
|
125
|
+
*/
|
|
126
|
+
export function groupBySeverity(issues) {
|
|
127
|
+
const grouped = {
|
|
128
|
+
critical: [],
|
|
129
|
+
serious: [],
|
|
130
|
+
moderate: [],
|
|
131
|
+
minor: [],
|
|
132
|
+
};
|
|
133
|
+
issues.forEach((issue) => {
|
|
134
|
+
grouped[issue.severity].push(issue);
|
|
135
|
+
});
|
|
136
|
+
return grouped;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Filter issues by severity
|
|
140
|
+
*/
|
|
141
|
+
export function filterBySeverity(issues, severities) {
|
|
142
|
+
return issues.filter((issue) => severities.includes(issue.severity));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Filter issues by category
|
|
146
|
+
*/
|
|
147
|
+
export function filterByCategory(issues, categories) {
|
|
148
|
+
return issues.filter((issue) => categories.includes(issue.category));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get top N issues by severity
|
|
152
|
+
*/
|
|
153
|
+
export function getTopIssues(issues, count) {
|
|
154
|
+
return sortIssues(issues).slice(0, count);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Calculate percentage of passed checks
|
|
158
|
+
*/
|
|
159
|
+
export function calculatePassRate(passed, total) {
|
|
160
|
+
if (total === 0)
|
|
161
|
+
return 100;
|
|
162
|
+
return Math.round((passed / total) * 100);
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"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"}
|