@mridang/webhint-hint-plumbline 0.12.0 → 0.14.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.
@@ -5,6 +5,11 @@ import { registrableDomain } from '../../lib/headers/registrable-domain.js';
5
5
  import { reportingFindings } from '../../lib/headers/reporting.js';
6
6
  import { reportFindings } from './shared.js';
7
7
  const join = (values, separator) => values.length > 0 ? values.join(separator) : null;
8
+ /** Whether the response came through Cloudflare, by its `server` or `cf-ray` header. */
9
+ function viaCloudflare(headers) {
10
+ return (headerValues(headers, 'cf-ray').length > 0 ||
11
+ headerValues(headers, 'server').some((value) => value.toLowerCase().includes('cloudflare')));
12
+ }
8
13
  /**
9
14
  * Violation and error reports sent to third parties (Webbkoll's
10
15
  * `external_report`). A Content-Security-Policy or
@@ -37,6 +42,7 @@ export default defineHint({
37
42
  csp: join(headerValues(page.headers, 'content-security-policy'), '; '),
38
43
  cspReportOnly: join(headerValues(page.headers, 'content-security-policy-report-only'), '; '),
39
44
  nel: nel[0] ?? null,
45
+ cloudflare: viaCloudflare(page.headers),
40
46
  reportTo: join(headerValues(page.headers, 'report-to'), ', '),
41
47
  }), {
42
48
  lines: [
@@ -1 +1 @@
1
- {"version":3,"file":"csp-reporting.js","sourceRoot":"","sources":["../../../src/hints/headers/csp-reporting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,IAAI,GAAG,CAAC,MAAgB,EAAE,SAAiB,EAAiB,EAAE,CAClE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAEpD;;;;;;;;GAQG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,8BAA8B;IACpC,WAAW,EACT,uFAAuF;IACzF,QAAQ,EAAE,QAAQ,CAAC,QAAQ;IAC3B,MAAM,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,SAAS,CAAC;IACnD,SAAS,EAAE,sCAAsC;IACjD,KAAK,CAAC,OAAO;QACX,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9C,cAAc,CACZ,IAAI,EACJ,iBAAiB,CAAC;gBAChB,WAAW,EAAE,iBAAiB,CAAC,IAAI,CAAC;gBACpC,8DAA8D;gBAC9D,GAAG,EAAE,IAAI,CACP,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAyB,CAAC,EACrD,IAAI,CACL;gBACD,aAAa,EAAE,IAAI,CACjB,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,qCAAqC,CAAC,EACjE,IAAI,CACL;gBACD,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI;gBACnB,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC;aAC9D,CAAC,EACF;gBACE,KAAK,EAAE;oBACL,yBAAyB;oBACzB,qCAAqC;oBACrC,WAAW;oBACX,KAAK;iBACN,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,CAClC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAC/B,CACF;aACF,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"csp-reporting.js","sourceRoot":"","sources":["../../../src/hints/headers/csp-reporting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,IAAI,GAAG,CAAC,MAAgB,EAAE,SAAiB,EAAiB,EAAE,CAClE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAEpD,wFAAwF;AACxF,SAAS,aAAa,CAAC,OAA2C;IAChE,OAAO,CACL,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;QAC1C,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7C,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAC3C,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,8BAA8B;IACpC,WAAW,EACT,uFAAuF;IACzF,QAAQ,EAAE,QAAQ,CAAC,QAAQ;IAC3B,MAAM,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,SAAS,CAAC;IACnD,SAAS,EAAE,sCAAsC;IACjD,KAAK,CAAC,OAAO;QACX,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9C,cAAc,CACZ,IAAI,EACJ,iBAAiB,CAAC;gBAChB,WAAW,EAAE,iBAAiB,CAAC,IAAI,CAAC;gBACpC,8DAA8D;gBAC9D,GAAG,EAAE,IAAI,CACP,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAyB,CAAC,EACrD,IAAI,CACL;gBACD,aAAa,EAAE,IAAI,CACjB,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,qCAAqC,CAAC,EACjE,IAAI,CACL;gBACD,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI;gBACnB,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;gBACvC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC;aAC9D,CAAC,EACF;gBACE,KAAK,EAAE;oBACL,yBAAyB;oBACzB,qCAAqC;oBACrC,WAAW;oBACX,KAAK;iBACN,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,CAClC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAC/B,CACF;aACF,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -2,7 +2,10 @@
2
2
  * Permissions-Policy parsing and the OWASP Secure Headers Project check.
3
3
  *
4
4
  * OSHP expects the header to switch off 28 features with an empty allowlist
5
- * (`feature=()`), and `sync-xhr` may also be limited to `(self)`.
5
+ * (`feature=()`). Any of them may also be limited to `(self)`: a site that
6
+ * needs one of its own features (a copy button, voice input, fullscreen) keeps
7
+ * it, and `(self)` still keeps embedded third parties from using it. An
8
+ * allowlist that names other origins, or `*`, or is missing, still fails.
6
9
  */
7
10
  import { type Finding } from './finding.js';
8
11
  /** Features that must be `()`, in the order OSHP lists them. */
@@ -2,7 +2,10 @@
2
2
  * Permissions-Policy parsing and the OWASP Secure Headers Project check.
3
3
  *
4
4
  * OSHP expects the header to switch off 28 features with an empty allowlist
5
- * (`feature=()`), and `sync-xhr` may also be limited to `(self)`.
5
+ * (`feature=()`). Any of them may also be limited to `(self)`: a site that
6
+ * needs one of its own features (a copy button, voice input, fullscreen) keeps
7
+ * it, and `(self)` still keeps embedded third parties from using it. An
8
+ * allowlist that names other origins, or `*`, or is missing, still fails.
6
9
  */
7
10
  import { finding } from './finding.js';
8
11
  /** Features that must be `()`, in the order OSHP lists them. */
@@ -88,6 +91,10 @@ export function parsePermissionsPolicy(value) {
88
91
  }
89
92
  return policy;
90
93
  }
94
+ /** Whether an allowlist keeps a feature from third parties: empty, or this origin only. */
95
+ function isClosed(allowlist) {
96
+ return allowlist === '()' || allowlist === '(self)';
97
+ }
91
98
  /** Findings for the OWASP rule; `value` is null when no header was sent. */
92
99
  export function permissionsPolicyFindings(value) {
93
100
  if (value === null) {
@@ -96,16 +103,15 @@ export function permissionsPolicyFindings(value) {
96
103
  ];
97
104
  }
98
105
  const policy = parsePermissionsPolicy(value);
99
- const failing = DISABLED_FEATURES.filter((feature) => policy.get(feature) !== '()');
100
- const syncXhr = policy.get('sync-xhr');
101
- if (syncXhr !== '()' && syncXhr !== '(self)') {
106
+ const failing = DISABLED_FEATURES.filter((feature) => !isClosed(policy.get(feature)));
107
+ if (!isClosed(policy.get('sync-xhr'))) {
102
108
  failing.push('sync-xhr');
103
109
  }
104
110
  if (failing.length === 0) {
105
111
  return [];
106
112
  }
107
113
  return [
108
- finding('error', `The 'Permissions-Policy' header should disable these features with an empty allowlist (for example 'camera=()'; 'sync-xhr' may also be '(self)'): ${failing.join(', ')}.`),
114
+ finding('error', `The 'Permissions-Policy' header should disable these features with an empty allowlist (for example 'camera=()'), or limit them to this origin with '(self)': ${failing.join(', ')}.`),
109
115
  ];
110
116
  }
111
117
  //# sourceMappingURL=permissions-policy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions-policy.js","sourceRoot":"","sources":["../../../src/lib/headers/permissions-policy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions-policy.js","sourceRoot":"","sources":["../../../src/lib/headers/permissions-policy.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ export interface ReportingInput {
7
7
  nel: string | null;
8
8
  /** Raw `Report-To` header: a comma separated list of JSON groups. */
9
9
  reportTo: string | null;
10
+ /** The response came through Cloudflare (its `server` or `cf-ray` header). */
11
+ cloudflare?: boolean;
10
12
  }
11
13
  export interface ExternalReports {
12
14
  cspReportUri?: string[];
@@ -5,10 +5,32 @@
5
5
  * the browser to send reports, with the visitor's URL and details, to the
6
6
  * endpoint; when that endpoint is on another registrable domain, visitor data
7
7
  * leaves the site.
8
+ *
9
+ * One exception: a site served through Cloudflare gets a `NEL` header and a
10
+ * `Report-To` group injected by Cloudflare itself, pointing at
11
+ * `*.nel.cloudflare.com`. The site's owner did not choose that endpoint and
12
+ * cannot remove it without switching Network Error Logging off in their
13
+ * Cloudflare account, so it is the hosting platform's own reporting and not
14
+ * a third party they added. It is skipped when the response shows it came
15
+ * through Cloudflare; the same endpoint on any other site is still reported.
8
16
  */
9
17
  import { parseCspLoose } from './csp.js';
10
18
  import { finding } from './finding.js';
11
19
  import { isThirdParty } from './registrable-domain.js';
20
+ /** Cloudflare's own Network Error Logging collector, injected on proxied sites. */
21
+ const CLOUDFLARE_NEL = /(^|\.)nel\.cloudflare\.com$/i;
22
+ /** Whether an endpoint is Cloudflare's injected collector on a site served by Cloudflare. */
23
+ function isPlatformEndpoint(url, cloudflare) {
24
+ if (!cloudflare) {
25
+ return false;
26
+ }
27
+ try {
28
+ return CLOUDFLARE_NEL.test(new URL(url).hostname);
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
12
34
  function parseGroups(reportTo) {
13
35
  try {
14
36
  const parsed = JSON.parse(`[${reportTo}]`);
@@ -19,7 +41,7 @@ function parseGroups(reportTo) {
19
41
  }
20
42
  }
21
43
  /** Third-party endpoint URLs of the named group of a `Report-To` header. */
22
- function thirdPartyEndpoints(groups, name, registrable) {
44
+ function thirdPartyEndpoints(groups, name, registrable, cloudflare) {
23
45
  const urls = [];
24
46
  for (const group of groups) {
25
47
  if (group?.group !== name || !Array.isArray(group.endpoints)) {
@@ -27,7 +49,8 @@ function thirdPartyEndpoints(groups, name, registrable) {
27
49
  }
28
50
  for (const endpoint of group.endpoints) {
29
51
  const url = typeof endpoint?.url === 'string' ? endpoint.url : '';
30
- if (isThirdParty(url, registrable)) {
52
+ if (isThirdParty(url, registrable) &&
53
+ !isPlatformEndpoint(url, cloudflare)) {
31
54
  urls.push(url);
32
55
  }
33
56
  }
@@ -40,7 +63,8 @@ export function externalReports(input) {
40
63
  const csp = parseCspLoose(input.csp);
41
64
  const reportOnly = parseCspLoose(input.cspReportOnly);
42
65
  const groups = input.reportTo === null ? null : parseGroups(input.reportTo);
43
- const reportUri = (policy) => (policy.get('report-uri') ?? []).filter((url) => isThirdParty(url, input.registrable));
66
+ const reportUri = (policy) => (policy.get('report-uri') ?? []).filter((url) => isThirdParty(url, input.registrable) &&
67
+ !isPlatformEndpoint(url, input.cloudflare));
44
68
  const uriHeader = reportUri(csp);
45
69
  if (uriHeader.length > 0) {
46
70
  found.cspReportUri = uriHeader;
@@ -52,14 +76,14 @@ export function externalReports(input) {
52
76
  if (groups) {
53
77
  const toHeader = csp.get('report-to')?.[0];
54
78
  if (toHeader !== undefined) {
55
- const urls = thirdPartyEndpoints(groups, toHeader, input.registrable);
79
+ const urls = thirdPartyEndpoints(groups, toHeader, input.registrable, input.cloudflare);
56
80
  if (urls.length > 0) {
57
81
  found.cspReportTo = urls;
58
82
  }
59
83
  }
60
84
  const toReportOnly = reportOnly.get('report-to')?.[0];
61
85
  if (toReportOnly !== undefined) {
62
- const urls = thirdPartyEndpoints(groups, toReportOnly, input.registrable);
86
+ const urls = thirdPartyEndpoints(groups, toReportOnly, input.registrable, input.cloudflare);
63
87
  if (urls.length > 0) {
64
88
  found.cspReportOnlyReportTo = urls;
65
89
  }
@@ -68,7 +92,7 @@ export function externalReports(input) {
68
92
  try {
69
93
  const nel = JSON.parse(input.nel);
70
94
  if (nel && typeof nel === 'object' && 'report_to' in nel) {
71
- const urls = thirdPartyEndpoints(groups, nel.report_to, input.registrable);
95
+ const urls = thirdPartyEndpoints(groups, nel.report_to, input.registrable, input.cloudflare);
72
96
  if (urls.length > 0) {
73
97
  found.nel = urls;
74
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reporting.js","sourceRoot":"","sources":["../../../src/lib/headers/reporting.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reporting.js","sourceRoot":"","sources":["../../../src/lib/headers/reporting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { EphemeralKey } from './evaluate.js';
2
+ import type { TlsConnect } from './client.js';
3
+ /** The certificate facts the prober reads, named as Node names them. */
4
+ export interface RemoteCertificate {
5
+ subject: Record<string, string>;
6
+ issuer: Record<string, string>;
7
+ subjectaltname: string;
8
+ valid_from: string;
9
+ valid_to: string;
10
+ serialNumber: string;
11
+ fingerprint256: string;
12
+ keyType: string;
13
+ bits?: number;
14
+ asn1Curve?: string;
15
+ signatureAlgorithm: string;
16
+ /** Where the issuer's certificate and an OCSP answer can be had, as Node names the keys. */
17
+ infoAccess?: Record<string, string[]>;
18
+ }
19
+ /** What the prober answers. */
20
+ export interface RemoteHandshake {
21
+ protocol: string;
22
+ cipher: {
23
+ name: string;
24
+ standardName: string;
25
+ };
26
+ authorized: boolean;
27
+ authorizationError: string | null;
28
+ ephemeral: EphemeralKey | null;
29
+ /** DER, base64, leaf first. */
30
+ chain: string[] | null;
31
+ certificates: RemoteCertificate[] | null;
32
+ /** DER, base64. */
33
+ ocsp: string | null;
34
+ compression?: boolean;
35
+ }
36
+ /** What is asked of the prober. */
37
+ export interface RemoteRequest {
38
+ host: string;
39
+ port: number;
40
+ starttls?: 'smtp';
41
+ minVersion?: string;
42
+ maxVersion?: string;
43
+ /** An OpenSSL cipher list. */
44
+ ciphers?: string;
45
+ /** An OpenSSL signature algorithm list. */
46
+ sigalgs?: string;
47
+ /** Colon separated key exchange groups. */
48
+ ecdhCurve?: string;
49
+ requestOCSP?: boolean;
50
+ }
51
+ /** Makes one request to the prober; rejects when the handshake failed. */
52
+ export type RemoteCall = (request: RemoteRequest) => Promise<RemoteHandshake>;
53
+ /** A `TlsConnect` that asks the prober. */
54
+ export declare function remoteConnect(call: RemoteCall): TlsConnect;
@@ -0,0 +1,54 @@
1
+ import { TLS_VERSIONS } from './constants.js';
2
+ /** The base64 text as bytes. */
3
+ function bytesOf(base64) {
4
+ return Buffer.from(base64, 'base64');
5
+ }
6
+ /** The leaf certificate as Node shows it, from what the prober read. */
7
+ function peerOf(certs, chain) {
8
+ const leaf = certs[0];
9
+ return {
10
+ subject: leaf?.subject ?? {},
11
+ issuer: leaf?.issuer ?? {},
12
+ subjectaltname: leaf?.subjectaltname,
13
+ valid_from: leaf?.valid_from,
14
+ valid_to: leaf?.valid_to,
15
+ serialNumber: leaf?.serialNumber,
16
+ fingerprint256: leaf?.fingerprint256,
17
+ bits: leaf?.bits,
18
+ asn1Curve: leaf?.asn1Curve,
19
+ infoAccess: leaf?.infoAccess,
20
+ raw: chain[0],
21
+ };
22
+ }
23
+ /** A `TlsConnect` that asks the prober. */
24
+ export function remoteConnect(call) {
25
+ return async (target, options) => {
26
+ const answer = await call({
27
+ host: target.host,
28
+ port: target.port,
29
+ ...(target.starttls ? { starttls: target.starttls } : {}),
30
+ ...(options.minVersion ? { minVersion: options.minVersion } : {}),
31
+ ...(options.maxVersion ? { maxVersion: options.maxVersion } : {}),
32
+ ...(options.ciphers ? { ciphers: options.ciphers } : {}),
33
+ ...(options.sigalgs ? { sigalgs: options.sigalgs } : {}),
34
+ ...(options.ecdhCurve ? { ecdhCurve: options.ecdhCurve } : {}),
35
+ ...(options.requestOCSP ? { requestOCSP: true } : {}),
36
+ });
37
+ const chain = (answer.chain ?? []).map(bytesOf);
38
+ const protocol = TLS_VERSIONS.includes(answer.protocol)
39
+ ? answer.protocol
40
+ : null;
41
+ const result = {
42
+ protocol,
43
+ cipher: answer.cipher,
44
+ ephemeral: answer.ephemeral,
45
+ authorized: answer.authorized,
46
+ authorizationError: answer.authorizationError,
47
+ chain,
48
+ peerCertificate: peerOf(answer.certificates ?? [], chain),
49
+ ocspResponse: answer.ocsp ? bytesOf(answer.ocsp) : null,
50
+ };
51
+ return result;
52
+ };
53
+ }
54
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../src/lib/tls/remote.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,YAAY,EAAmB,MAAM,gBAAgB,CAAC;AAuD/D,gCAAgC;AAChC,SAAS,OAAO,CAAC,MAAc;IAC7B,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,wEAAwE;AACxE,SAAS,MAAM,CACb,KAAmC,EACnC,KAAwB;IAExB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,OAAO;QACL,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,EAAE;QAC5B,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE;QAC1B,cAAc,EAAE,IAAI,EAAE,cAAc;QACpC,UAAU,EAAE,IAAI,EAAE,UAAU;QAC5B,QAAQ,EAAE,IAAI,EAAE,QAAQ;QACxB,YAAY,EAAE,IAAI,EAAE,YAAY;QAChC,cAAc,EAAE,IAAI,EAAE,cAAc;QACpC,IAAI,EAAE,IAAI,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI,EAAE,SAAS;QAC1B,UAAU,EAAE,IAAI,EAAE,UAAU;QAC5B,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;KACgB,CAAC;AAClC,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;YACxB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAI,YAAkC,CAAC,QAAQ,CAC3D,MAAM,CAAC,QAAQ,CAChB;YACC,CAAC,CAAE,MAAM,CAAC,QAAuB;YACjC,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,MAAM,GAAgB;YAC1B,QAAQ;YACR,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC7C,KAAK;YACL,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,KAAK,CAAC;YACzD,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SACxD,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * What the hints take from webhint's core at run time, for a runtime that
3
+ * cannot load the core (a Cloudflare Worker: the core reads files and loads
4
+ * packages by name). The hints only need the scope names; the rest of webhint
5
+ * is types. `package.json` points `#hint` here under the `workerd` condition.
6
+ */
7
+ /** Where a hint applies: the site, a local project, or either. Same values as webhint's. */
8
+ export declare enum HintScope {
9
+ local = "local",
10
+ site = "site",
11
+ any = "any"
12
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * What the hints take from webhint's core at run time, for a runtime that
3
+ * cannot load the core (a Cloudflare Worker: the core reads files and loads
4
+ * packages by name). The hints only need the scope names; the rest of webhint
5
+ * is types. `package.json` points `#hint` here under the `workerd` condition.
6
+ */
7
+ /** Where a hint applies: the site, a local project, or either. Same values as webhint's. */
8
+ export var HintScope;
9
+ (function (HintScope) {
10
+ HintScope["local"] = "local";
11
+ HintScope["site"] = "site";
12
+ HintScope["any"] = "any";
13
+ })(HintScope || (HintScope = {}));
14
+ //# sourceMappingURL=hint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hint.js","sourceRoot":"","sources":["../../src/worker/hint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,4FAA4F;AAC5F,MAAM,CAAN,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,4BAAe,CAAA;IACf,0BAAa,CAAA;IACb,wBAAW,CAAA;AACb,CAAC,EAJW,SAAS,KAAT,SAAS,QAIpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mridang/webhint-hint-plumbline",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "prepack": "tsc --build",
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "imports": {
19
19
  "#hint": {
20
+ "workerd": "./dist/worker/hint.js",
20
21
  "default": "hint"
21
22
  },
22
23
  "#net": {