@accesslint/cli 0.2.1 → 0.3.1
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/audit.d.ts +12 -0
- package/dist/audit.js +47 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +4 -4
- package/dist/format.d.ts +4 -0
- package/dist/inline-css.d.ts +1 -0
- package/dist/inline-css.js +81 -0
- package/dist/input.d.ts +1 -0
- package/package.json +8 -2
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type AuditResult } from "@accesslint/core";
|
|
2
|
+
export interface AuditOptions {
|
|
3
|
+
includeAAA?: boolean;
|
|
4
|
+
componentMode?: boolean;
|
|
5
|
+
disabledRules?: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Returns true if the HTML looks like a fragment/component rather than a full
|
|
9
|
+
* document (i.e. it lacks a doctype or <html> tag).
|
|
10
|
+
*/
|
|
11
|
+
export declare function isHTMLFragment(html: string): boolean;
|
|
12
|
+
export declare function audit(html: string, options?: AuditOptions): AuditResult;
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/audit.ts
|
|
2
|
+
import { JSDOM, VirtualConsole } from "jsdom";
|
|
3
|
+
import {
|
|
4
|
+
runAudit,
|
|
5
|
+
configureRules
|
|
6
|
+
} from "@accesslint/core";
|
|
7
|
+
function isHTMLFragment(html) {
|
|
8
|
+
const prefix = html.slice(0, 1000);
|
|
9
|
+
return !(/<!doctype\s/i.test(prefix) || /<html[\s>]/i.test(prefix));
|
|
10
|
+
}
|
|
11
|
+
var globalsRegistered = false;
|
|
12
|
+
function ensureGlobals(window) {
|
|
13
|
+
if (globalsRegistered)
|
|
14
|
+
return;
|
|
15
|
+
for (const key of Object.getOwnPropertyNames(window)) {
|
|
16
|
+
if (key in globalThis)
|
|
17
|
+
continue;
|
|
18
|
+
const desc = Object.getOwnPropertyDescriptor(window, key);
|
|
19
|
+
if (!desc || typeof desc.value !== "function")
|
|
20
|
+
continue;
|
|
21
|
+
try {
|
|
22
|
+
globalThis[key] = desc.value;
|
|
23
|
+
} catch {}
|
|
24
|
+
}
|
|
25
|
+
globalsRegistered = true;
|
|
26
|
+
}
|
|
27
|
+
function audit(html, options = {}) {
|
|
28
|
+
const config = {
|
|
29
|
+
componentMode: options.componentMode ?? false
|
|
30
|
+
};
|
|
31
|
+
if (options.includeAAA)
|
|
32
|
+
config.includeAAA = true;
|
|
33
|
+
if (options.disabledRules?.length)
|
|
34
|
+
config.disabledRules = options.disabledRules;
|
|
35
|
+
configureRules(config);
|
|
36
|
+
const virtualConsole = new VirtualConsole;
|
|
37
|
+
const dom = new JSDOM(html, { pretendToBeVisual: true, virtualConsole });
|
|
38
|
+
ensureGlobals(dom.window);
|
|
39
|
+
const result = runAudit(dom.window.document);
|
|
40
|
+
result.violations = result.violations.map(({ element: _el, ...rest }) => rest);
|
|
41
|
+
dom.window.close();
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
isHTMLFragment,
|
|
46
|
+
audit
|
|
47
|
+
};
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
CHANGED
|
@@ -7766,11 +7766,11 @@ function ensureGlobals(window) {
|
|
|
7766
7766
|
globalsRegistered = true;
|
|
7767
7767
|
}
|
|
7768
7768
|
function audit(html, options = {}) {
|
|
7769
|
-
const config = {
|
|
7769
|
+
const config = {
|
|
7770
|
+
componentMode: options.componentMode ?? false
|
|
7771
|
+
};
|
|
7770
7772
|
if (options.includeAAA)
|
|
7771
7773
|
config.includeAAA = true;
|
|
7772
|
-
if (options.componentMode)
|
|
7773
|
-
config.componentMode = true;
|
|
7774
7774
|
if (options.disabledRules?.length)
|
|
7775
7775
|
config.disabledRules = options.disabledRules;
|
|
7776
7776
|
Bn(config);
|
|
@@ -7778,7 +7778,7 @@ function audit(html, options = {}) {
|
|
|
7778
7778
|
const dom = new JSDOM2(html, { pretendToBeVisual: true, virtualConsole });
|
|
7779
7779
|
ensureGlobals(dom.window);
|
|
7780
7780
|
const result = Gn(dom.window.document);
|
|
7781
|
-
result.violations = result.violations.map(({ element, ...rest }) => rest);
|
|
7781
|
+
result.violations = result.violations.map(({ element: _el, ...rest }) => rest);
|
|
7782
7782
|
dom.window.close();
|
|
7783
7783
|
return result;
|
|
7784
7784
|
}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function inlineCSS(html: string, baseURL: string): Promise<string>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// src/inline-css.ts
|
|
2
|
+
import { JSDOM } from "jsdom";
|
|
3
|
+
async function fetchCSS(url) {
|
|
4
|
+
try {
|
|
5
|
+
const res = await fetch(url);
|
|
6
|
+
if (!res.ok) {
|
|
7
|
+
console.warn(`Warning: failed to fetch stylesheet ${url}: ${res.status}`);
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return res.text();
|
|
11
|
+
} catch (err) {
|
|
12
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
13
|
+
console.warn(`Warning: failed to fetch stylesheet ${url}: ${msg}`);
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function resolveImports(css, baseURL) {
|
|
18
|
+
const importPattern = /@import\s+(?:url\(\s*['"]?([^'")\s]+)['"]?\s*\)|['"]([^'"]+)['""])\s*([^;]*);/g;
|
|
19
|
+
const replacements = [];
|
|
20
|
+
for (const m of css.matchAll(importPattern)) {
|
|
21
|
+
const importURL = m[1] || m[2];
|
|
22
|
+
if (!importURL)
|
|
23
|
+
continue;
|
|
24
|
+
let resolved;
|
|
25
|
+
try {
|
|
26
|
+
resolved = new URL(importURL, baseURL).href;
|
|
27
|
+
} catch {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const imported = await fetchCSS(resolved);
|
|
31
|
+
if (imported !== null) {
|
|
32
|
+
const mediaQuery = m[3]?.trim();
|
|
33
|
+
const wrapped = mediaQuery ? `@media ${mediaQuery} {
|
|
34
|
+
${imported}
|
|
35
|
+
}` : imported;
|
|
36
|
+
replacements.push({ match: m[0], replacement: wrapped });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
let result = css;
|
|
40
|
+
for (const { match, replacement } of replacements) {
|
|
41
|
+
result = result.replace(match, replacement);
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
async function inlineCSS(html, baseURL) {
|
|
46
|
+
const dom = new JSDOM(html);
|
|
47
|
+
const doc = dom.window.document;
|
|
48
|
+
const links = doc.querySelectorAll('link[rel="stylesheet"][href]');
|
|
49
|
+
if (links.length === 0) {
|
|
50
|
+
dom.window.close();
|
|
51
|
+
return html;
|
|
52
|
+
}
|
|
53
|
+
const tasks = Array.from(links).map(async (link) => {
|
|
54
|
+
const href = link.getAttribute("href");
|
|
55
|
+
if (href.startsWith("data:"))
|
|
56
|
+
return;
|
|
57
|
+
let resolved;
|
|
58
|
+
try {
|
|
59
|
+
resolved = new URL(href, baseURL).href;
|
|
60
|
+
} catch {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const css = await fetchCSS(resolved);
|
|
64
|
+
if (css === null)
|
|
65
|
+
return;
|
|
66
|
+
const inlined = await resolveImports(css, resolved);
|
|
67
|
+
const style = doc.createElement("style");
|
|
68
|
+
style.textContent = inlined;
|
|
69
|
+
const media = link.getAttribute("media");
|
|
70
|
+
if (media)
|
|
71
|
+
style.setAttribute("media", media);
|
|
72
|
+
link.replaceWith(style);
|
|
73
|
+
});
|
|
74
|
+
await Promise.all(tasks);
|
|
75
|
+
const result = dom.serialize();
|
|
76
|
+
dom.window.close();
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
inlineCSS
|
|
81
|
+
};
|
package/dist/input.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveInput(source?: string): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accesslint/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/AccessLint/cli"
|
|
@@ -10,11 +10,15 @@
|
|
|
10
10
|
"bin": {
|
|
11
11
|
"accesslint": "./dist/cli.js"
|
|
12
12
|
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./dist/audit.js",
|
|
15
|
+
"./inline-css": "./dist/inline-css.js"
|
|
16
|
+
},
|
|
13
17
|
"files": [
|
|
14
18
|
"dist"
|
|
15
19
|
],
|
|
16
20
|
"scripts": {
|
|
17
|
-
"build": "bun build src/cli.ts --target=node --outdir=dist --external jsdom",
|
|
21
|
+
"build": "bun build src/cli.ts --target=node --outdir=dist --external jsdom && bun build src/audit.ts src/inline-css.ts --target=node --outdir=dist --external jsdom --external @accesslint/core && tsc --emitDeclarationOnly",
|
|
18
22
|
"start": "bun src/cli.ts"
|
|
19
23
|
},
|
|
20
24
|
"dependencies": {
|
|
@@ -22,6 +26,8 @@
|
|
|
22
26
|
"jsdom": "^26.0.0"
|
|
23
27
|
},
|
|
24
28
|
"devDependencies": {
|
|
29
|
+
"@types/jsdom": "^28.0.0",
|
|
30
|
+
"@types/node": "^25.3.0",
|
|
25
31
|
"citty": "^0.1.6",
|
|
26
32
|
"typescript": "^5.7.0"
|
|
27
33
|
},
|