@accesslint/cli 0.2.0 → 0.3.0

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.
@@ -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
+ if (options.includeAAA)
30
+ config.includeAAA = true;
31
+ if (options.componentMode)
32
+ config.componentMode = 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
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js CHANGED
@@ -7745,6 +7745,10 @@ function Gn(e2) {
7745
7745
  var jn = new Map(Ze.map((e2) => [e2.id, e2]));
7746
7746
 
7747
7747
  // src/audit.ts
7748
+ function isHTMLFragment(html) {
7749
+ const prefix = html.slice(0, 1000);
7750
+ return !(/<!doctype\s/i.test(prefix) || /<html[\s>]/i.test(prefix));
7751
+ }
7748
7752
  var globalsRegistered = false;
7749
7753
  function ensureGlobals(window) {
7750
7754
  if (globalsRegistered)
@@ -7774,7 +7778,7 @@ function audit(html, options = {}) {
7774
7778
  const dom = new JSDOM2(html, { pretendToBeVisual: true, virtualConsole });
7775
7779
  ensureGlobals(dom.window);
7776
7780
  const result = Gn(dom.window.document);
7777
- result.violations = result.violations.map(({ element, ...rest }) => rest);
7781
+ result.violations = result.violations.map(({ element: _el, ...rest }) => rest);
7778
7782
  dom.window.close();
7779
7783
  return result;
7780
7784
  }
@@ -7852,11 +7856,6 @@ var main = defineCommand({
7852
7856
  description: "Include AAA-level rules",
7853
7857
  default: false
7854
7858
  },
7855
- "component-mode": {
7856
- type: "boolean",
7857
- description: "Exclude page-level rules",
7858
- default: false
7859
- },
7860
7859
  disable: {
7861
7860
  type: "string",
7862
7861
  alias: "d",
@@ -7869,7 +7868,7 @@ var main = defineCommand({
7869
7868
  const disabledRules = args.disable ? args.disable.split(",").map((s2) => s2.trim()) : undefined;
7870
7869
  const result = audit(html, {
7871
7870
  includeAAA: args["include-aaa"],
7872
- componentMode: args["component-mode"],
7871
+ componentMode: isHTMLFragment(html),
7873
7872
  disabledRules
7874
7873
  });
7875
7874
  console.log(format(result, args.format));
@@ -0,0 +1,4 @@
1
+ import type { AuditResult } from "@accesslint/core";
2
+ export declare function formatText(result: AuditResult): string;
3
+ export declare function formatJSON(result: AuditResult): string;
4
+ export declare function format(result: AuditResult, fmt: string): string;
@@ -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
+ };
@@ -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.2.0",
3
+ "version": "0.3.0",
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
  },