@slashgear/gdpr-cookie-scanner 2.0.4 → 3.0.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.
- package/CHANGELOG.md +40 -0
- package/CLAUDE.md +1 -1
- package/README.md +5 -5
- package/dist/analyzers/compliance.d.ts.map +1 -1
- package/dist/analyzers/compliance.js +19 -9
- package/dist/analyzers/compliance.js.map +1 -1
- package/dist/classifiers/network-classifier.d.ts +1 -0
- package/dist/classifiers/network-classifier.d.ts.map +1 -1
- package/dist/classifiers/network-classifier.js +10 -1
- package/dist/classifiers/network-classifier.js.map +1 -1
- package/dist/classifiers/tracker-list.d.ts +1 -0
- package/dist/classifiers/tracker-list.d.ts.map +1 -1
- package/dist/classifiers/tracker-list.js +6 -0
- package/dist/classifiers/tracker-list.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/report/generator.d.ts.map +1 -1
- package/dist/report/generator.js +70 -33
- package/dist/report/generator.js.map +1 -1
- package/dist/scanner/network.d.ts.map +1 -1
- package/dist/scanner/network.js +1 -0
- package/dist/scanner/network.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/analyzers/compliance.ts +20 -11
- package/src/classifiers/network-classifier.ts +11 -1
- package/src/classifiers/tracker-list.ts +8 -0
- package/src/cli.ts +1 -5
- package/src/report/generator.ts +70 -36
- package/src/scanner/network.ts +1 -0
- package/src/types.ts +1 -0
- package/tests/e2e/scanner.test.ts +4 -7
- package/tests/unit/compliance.test.ts +99 -13
- package/tests/unit/network-classifier.test.ts +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @slashgear/gdpr-cookie-scanner
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- db3e538: Change the default output format from `md,pdf` to `html`.
|
|
8
|
+
|
|
9
|
+
Previously running `gdpr-scan scan <url>` with no `--format` flag produced both a Markdown bundle (3 files) and a PDF — requiring a full Playwright PDF render on every invocation. The HTML report is self-contained, opens in any browser without extra tooling, and is faster to generate, making it a better default for first-time users and CI pipelines alike. Pipelines that relied on the implicit `md` or `pdf` output must now pass `--format md,pdf` explicitly.
|
|
10
|
+
|
|
11
|
+
Also fixes the erroneous `npx` invocation in the README (issue #22): the correct command is `npx @slashgear/gdpr-cookie-scanner scan <url>`, not `npx @slashgear/gdpr-cookie-scanner gdpr-scan scan <url>`.
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- db3e538: Add `requiresConsent` field to `NetworkRequest`, mark Plausible Analytics as consent-exempt, and fix scoring for tracking-free sites.
|
|
16
|
+
|
|
17
|
+
Two related issues are fixed:
|
|
18
|
+
|
|
19
|
+
1. **Plausible Analytics false positive** — Plausible is cookieless and exempt from ePrivacy consent under CNIL guidance, but requests to `plausible.io/api/event` were matching the generic pixel pattern and penalising the score. A `requiresConsent: boolean` field is added to `NetworkRequest` (mirroring the same field on `ScannedCookie`). A new optional `consentRequired` flag on `TrackerEntry` lets known-exempt services opt out of the default consent requirement. All compliance and report logic now uses `requiresConsent` instead of testing `trackerCategory !== "cdn"` directly. Plausible Analytics is added to `TRACKER_DB` with `consentRequired: false`.
|
|
20
|
+
|
|
21
|
+
2. **Tracking-free sites capped at 97** — The "no privacy policy link on page" check deducted 3 points unconditionally, even when no consent was required. A site with no non-essential cookies or trackers now correctly scores 100/100.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 5f0e14e: Fix false non-compliance for sites with no cookies or trackers
|
|
26
|
+
|
|
27
|
+
A site with no consent modal but also no non-essential cookies and no
|
|
28
|
+
third-party trackers was previously scored 0/75 and graded F, because
|
|
29
|
+
the three consent-related dimensions (consent validity, easy refusal,
|
|
30
|
+
transparency) were zeroed out whenever no modal was detected.
|
|
31
|
+
|
|
32
|
+
GDPR and the ePrivacy Directive only require a consent mechanism when
|
|
33
|
+
the site actually uses cookies or trackers that need consent. A
|
|
34
|
+
tracking-free site has no such obligation and must now correctly receive
|
|
35
|
+
a full score (grade A) and raise no compliance issues.
|
|
36
|
+
|
|
37
|
+
The fix adds a `consentRequired` guard in `analyzeCompliance`: the
|
|
38
|
+
three modal-related dimensions are only penalised when non-essential
|
|
39
|
+
cookies or non-CDN trackers are present. The report generator
|
|
40
|
+
(executive summary, recommendations, checklist) is updated to reflect
|
|
41
|
+
the same distinction. Unit and E2E tests are updated accordingly.
|
|
42
|
+
|
|
3
43
|
## 2.0.4
|
|
4
44
|
|
|
5
45
|
### Patch Changes
|
package/CLAUDE.md
CHANGED
|
@@ -68,7 +68,7 @@ Phase 3 and 4 require two separate browser sessions so cookie state is fully iso
|
|
|
68
68
|
- **`src/classifiers/tracker-list.ts`** — Static database of tracker domains by category
|
|
69
69
|
- **`src/analyzers/compliance.ts`** — Scores 4 dimensions (0–25 each) and surfaces `DarkPatternIssue` objects: consent validity, easy refusal, transparency, cookie behavior
|
|
70
70
|
- **`src/analyzers/wording.ts`** — Text analysis of button labels and modal copy
|
|
71
|
-
- **`src/report/generator.ts`** — Renders
|
|
71
|
+
- **`src/report/generator.ts`** — Renders report files from `ScanResult` in the requested formats. The default output format is HTML. Markdown output produces 3 files: the main compliance report (`gdpr-report-*.md`), the checklist (`gdpr-checklist-*.md`), and the cookie inventory (`gdpr-cookies-*.md`); runs `oxfmt` on all generated Markdown files
|
|
72
72
|
- **`src/types.ts`** — All shared TypeScript interfaces (`ScanResult`, `ScanOptions`, `ComplianceScore`, `ConsentModal`, etc.)
|
|
73
73
|
|
|
74
74
|
### Compliance scoring
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ npx playwright install chromium
|
|
|
30
30
|
Or run without installing:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx @slashgear/gdpr-cookie-scanner
|
|
33
|
+
npx @slashgear/gdpr-cookie-scanner scan https://example.com
|
|
34
34
|
# Playwright is still required the first time:
|
|
35
35
|
npx playwright install chromium
|
|
36
36
|
```
|
|
@@ -61,7 +61,7 @@ gdpr-scan scan <url> [options]
|
|
|
61
61
|
| ------------------------ | ---------------- | ------------------------------------------------------------- |
|
|
62
62
|
| `-o, --output <dir>` | `./gdpr-reports` | Output directory for the report |
|
|
63
63
|
| `-t, --timeout <ms>` | `30000` | Navigation timeout |
|
|
64
|
-
| `-f, --format <formats>` | `
|
|
64
|
+
| `-f, --format <formats>` | `html` | Output formats: `md`, `html`, `json`, `pdf` (comma-separated) |
|
|
65
65
|
| `--no-screenshots` | — | Disable screenshot capture |
|
|
66
66
|
| `-l, --locale <locale>` | `fr-FR` | Browser locale |
|
|
67
67
|
| `-v, --verbose` | — | Show full stack trace on error |
|
|
@@ -69,7 +69,7 @@ gdpr-scan scan <url> [options]
|
|
|
69
69
|
### Examples
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
# Basic scan
|
|
72
|
+
# Basic scan — produces an HTML report by default
|
|
73
73
|
gdpr-scan scan https://example.com
|
|
74
74
|
|
|
75
75
|
# With custom output directory
|
|
@@ -78,8 +78,8 @@ gdpr-scan scan https://example.com -o ./reports
|
|
|
78
78
|
# Scan in English, without screenshots
|
|
79
79
|
gdpr-scan scan https://example.com --locale en-US --no-screenshots
|
|
80
80
|
|
|
81
|
-
# Generate
|
|
82
|
-
gdpr-scan scan https://example.com -f
|
|
81
|
+
# Generate a Markdown report instead
|
|
82
|
+
gdpr-scan scan https://example.com -f md
|
|
83
83
|
|
|
84
84
|
# Generate all formats at once
|
|
85
85
|
gdpr-scan scan https://example.com -f md,html,json,pdf
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAEZ,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAC;AAGrB,UAAU,eAAe;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,wBAAwB,EAAE,aAAa,EAAE,CAAC;IAC1C,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC3C,kBAAkB,EAAE,cAAc,EAAE,CAAC;IACrC,kBAAkB,EAAE,cAAc,EAAE,CAAC;CACtC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAEZ,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAC;AAGrB,UAAU,eAAe;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,wBAAwB,EAAE,aAAa,EAAE,CAAC;IAC1C,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC3C,kBAAkB,EAAE,cAAc,EAAE,CAAC;IACrC,kBAAkB,EAAE,cAAc,EAAE,CAAC;CACtC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,CA8MzE"}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { analyzeButtonWording, analyzeModalText } from "./wording.js";
|
|
2
2
|
export function analyzeCompliance(input) {
|
|
3
3
|
const issues = [];
|
|
4
|
+
// Determine whether a consent mechanism is actually required
|
|
5
|
+
const hasNonEssentialCookies = [
|
|
6
|
+
...input.cookiesBeforeInteraction,
|
|
7
|
+
...input.cookiesAfterAccept,
|
|
8
|
+
].some((c) => c.requiresConsent);
|
|
9
|
+
const hasNonEssentialTrackers = [
|
|
10
|
+
...input.networkBeforeInteraction,
|
|
11
|
+
...input.networkAfterAccept,
|
|
12
|
+
].some((r) => r.requiresConsent);
|
|
13
|
+
const consentRequired = hasNonEssentialCookies || hasNonEssentialTrackers;
|
|
4
14
|
// ── A. Consent validity (0-25) ────────────────────────────────
|
|
5
15
|
let consentValidity = 25;
|
|
6
|
-
if (!input.modal.detected) {
|
|
16
|
+
if (!input.modal.detected && consentRequired) {
|
|
7
17
|
issues.push({
|
|
8
18
|
type: "no-reject-button",
|
|
9
19
|
severity: "critical",
|
|
@@ -12,7 +22,7 @@ export function analyzeCompliance(input) {
|
|
|
12
22
|
});
|
|
13
23
|
consentValidity = 0;
|
|
14
24
|
}
|
|
15
|
-
else {
|
|
25
|
+
else if (input.modal.detected) {
|
|
16
26
|
// Wording analysis
|
|
17
27
|
const wordingResult = analyzeButtonWording(input.modal.buttons);
|
|
18
28
|
const textResult = analyzeModalText(input.modal.text);
|
|
@@ -38,10 +48,10 @@ export function analyzeCompliance(input) {
|
|
|
38
48
|
}
|
|
39
49
|
// ── B. Easy refusal (0-25) ────────────────────────────────────
|
|
40
50
|
let easyRefusal = 25;
|
|
41
|
-
if (!input.modal.detected) {
|
|
51
|
+
if (!input.modal.detected && consentRequired) {
|
|
42
52
|
easyRefusal = 0;
|
|
43
53
|
}
|
|
44
|
-
else {
|
|
54
|
+
else if (input.modal.detected) {
|
|
45
55
|
const acceptButton = input.modal.buttons.find((b) => b.type === "accept");
|
|
46
56
|
const rejectButton = input.modal.buttons.find((b) => b.type === "reject");
|
|
47
57
|
if (!rejectButton) {
|
|
@@ -91,10 +101,10 @@ export function analyzeCompliance(input) {
|
|
|
91
101
|
}
|
|
92
102
|
// ── C. Transparency (0-25) ────────────────────────────────────
|
|
93
103
|
let transparency = 25;
|
|
94
|
-
if (!input.modal.detected) {
|
|
104
|
+
if (!input.modal.detected && consentRequired) {
|
|
95
105
|
transparency = 0;
|
|
96
106
|
}
|
|
97
|
-
else {
|
|
107
|
+
else if (input.modal.detected) {
|
|
98
108
|
if (!input.modal.hasGranularControls) {
|
|
99
109
|
transparency -= 10;
|
|
100
110
|
}
|
|
@@ -114,8 +124,8 @@ export function analyzeCompliance(input) {
|
|
|
114
124
|
transparency -= 5;
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
|
-
// No privacy policy link anywhere on the page
|
|
118
|
-
if (!input.privacyPolicyUrl) {
|
|
127
|
+
// No privacy policy link anywhere on the page (only relevant when consent is required)
|
|
128
|
+
if (!input.privacyPolicyUrl && consentRequired) {
|
|
119
129
|
issues.push({
|
|
120
130
|
type: "missing-info",
|
|
121
131
|
severity: "warning",
|
|
@@ -149,7 +159,7 @@ export function analyzeCompliance(input) {
|
|
|
149
159
|
cookieBehavior -= Math.min(15, consentCookiesAfterReject.length * 3);
|
|
150
160
|
}
|
|
151
161
|
// Network trackers firing before interaction
|
|
152
|
-
const preInteractionTrackers = input.networkBeforeInteraction.filter((r) => r.
|
|
162
|
+
const preInteractionTrackers = input.networkBeforeInteraction.filter((r) => r.requiresConsent);
|
|
153
163
|
if (preInteractionTrackers.length > 0) {
|
|
154
164
|
issues.push({
|
|
155
165
|
type: "auto-consent",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliance.js","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAatE,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,iEAAiE;IACjE,IAAI,eAAe,GAAG,EAAE,CAAC;IAEzB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"compliance.js","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ interface NetworkClassification {
|
|
|
3
3
|
isThirdParty: boolean;
|
|
4
4
|
trackerCategory: TrackerCategory | null;
|
|
5
5
|
trackerName: string | null;
|
|
6
|
+
requiresConsent: boolean;
|
|
6
7
|
}
|
|
7
8
|
export declare function classifyNetworkRequest(url: string, resourceType: string): NetworkClassification;
|
|
8
9
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"network-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAoD/F"}
|
|
@@ -5,7 +5,12 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
5
5
|
hostname = new URL(url).hostname.replace(/^www\./, "");
|
|
6
6
|
}
|
|
7
7
|
catch {
|
|
8
|
-
return {
|
|
8
|
+
return {
|
|
9
|
+
isThirdParty: false,
|
|
10
|
+
trackerCategory: null,
|
|
11
|
+
trackerName: null,
|
|
12
|
+
requiresConsent: false,
|
|
13
|
+
};
|
|
9
14
|
}
|
|
10
15
|
// Check tracker database (exact match or suffix match)
|
|
11
16
|
for (const [domain, entry] of Object.entries(TRACKER_DB)) {
|
|
@@ -14,6 +19,7 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
14
19
|
isThirdParty: true,
|
|
15
20
|
trackerCategory: entry.category,
|
|
16
21
|
trackerName: entry.name,
|
|
22
|
+
requiresConsent: entry.consentRequired !== false && entry.category !== "cdn",
|
|
17
23
|
};
|
|
18
24
|
}
|
|
19
25
|
}
|
|
@@ -23,6 +29,7 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
23
29
|
isThirdParty: true,
|
|
24
30
|
trackerCategory: "pixel",
|
|
25
31
|
trackerName: "Tracking Pixel",
|
|
32
|
+
requiresConsent: true,
|
|
26
33
|
};
|
|
27
34
|
}
|
|
28
35
|
// Resource type heuristics
|
|
@@ -31,12 +38,14 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
31
38
|
isThirdParty: true,
|
|
32
39
|
trackerCategory: "pixel",
|
|
33
40
|
trackerName: "Tracking Pixel (image)",
|
|
41
|
+
requiresConsent: true,
|
|
34
42
|
};
|
|
35
43
|
}
|
|
36
44
|
return {
|
|
37
45
|
isThirdParty: false,
|
|
38
46
|
trackerCategory: null,
|
|
39
47
|
trackerName: null,
|
|
48
|
+
requiresConsent: false,
|
|
40
49
|
};
|
|
41
50
|
}
|
|
42
51
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-classifier.js","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"network-classifier.js","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAU/D,MAAM,UAAU,sBAAsB,CAAC,GAAW,EAAE,YAAoB;IACtE,IAAI,QAAgB,CAAC;IAErB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACzD,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,EAAE,CAAC;YAC3D,OAAO;gBACL,YAAY,EAAE,IAAI;gBAClB,eAAe,EAAE,KAAK,CAAC,QAAQ;gBAC/B,WAAW,EAAE,KAAK,CAAC,IAAI;gBACvB,eAAe,EAAE,KAAK,CAAC,eAAe,KAAK,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK;aAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5C,OAAO;YACL,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,gBAAgB;YAC7B,eAAe,EAAE,IAAI;SACtB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,YAAY,KAAK,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO;YACL,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,wBAAwB;YACrC,eAAe,EAAE,IAAI;SACtB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;QACjB,eAAe,EAAE,KAAK;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC5B,OAAO,CACL,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QACf,4CAA4C,CAAC,IAAI,CAAC,GAAG,CAAC,CACvD,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker-list.d.ts","sourceRoot":"","sources":["../../src/classifiers/tracker-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"tracker-list.d.ts","sourceRoot":"","sources":["../../src/classifiers/tracker-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAuFnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,EAQlC,CAAC"}
|
|
@@ -70,6 +70,12 @@ export const TRACKER_DB = {
|
|
|
70
70
|
"optimizely.com": { name: "Optimizely", category: "analytics" },
|
|
71
71
|
"vwo.com": { name: "VWO", category: "analytics" },
|
|
72
72
|
"app.convert.com": { name: "Convert", category: "analytics" },
|
|
73
|
+
// ── Consent-exempt analytics (CNIL ePrivacy exemption) ───────
|
|
74
|
+
"plausible.io": {
|
|
75
|
+
name: "Plausible Analytics",
|
|
76
|
+
category: "analytics",
|
|
77
|
+
consentRequired: false,
|
|
78
|
+
},
|
|
73
79
|
};
|
|
74
80
|
/**
|
|
75
81
|
* Patterns for detecting tracking pixels and beacons by URL shape.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker-list.js","sourceRoot":"","sources":["../../src/classifiers/tracker-list.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tracker-list.js","sourceRoot":"","sources":["../../src/classifiers/tracker-list.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -19,7 +19,7 @@ program
|
|
|
19
19
|
.option("--no-screenshots", "Disable screenshot capture")
|
|
20
20
|
.option("-l, --locale <locale>", "Browser locale for language detection", "fr-FR")
|
|
21
21
|
.option("-v, --verbose", "Show detailed output", false)
|
|
22
|
-
.option("-f, --format <formats>", "Output formats: md, html, json, pdf (comma-separated)", "
|
|
22
|
+
.option("-f, --format <formats>", "Output formats: md, html, json, pdf (comma-separated)", "html")
|
|
23
23
|
.action(async (url, opts) => {
|
|
24
24
|
console.log();
|
|
25
25
|
console.log(styleText(["bold", "blue"], " GDPR Cookie Scanner"));
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;KAC/C,MAAM,CAAC,oBAAoB,EAAE,iCAAiC,EAAE,gBAAgB,CAAC;KACjF,MAAM,CAAC,oBAAoB,EAAE,oCAAoC,EAAE,OAAO,CAAC;KAC3E,MAAM,CAAC,kBAAkB,EAAE,4BAA4B,CAAC;KACxD,MAAM,CAAC,uBAAuB,EAAE,uCAAuC,EAAE,OAAO,CAAC;KACjF,MAAM,CAAC,eAAe,EAAE,sBAAsB,EAAE,KAAK,CAAC;KACtD,MAAM,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAE3C,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YA2DrD,aAAa;YAkDb,YAAY;IAmC1B,OAAO,CAAC,QAAQ;IAgDhB,OAAO,CAAC,aAAa;IA6ErB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,qBAAqB;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAE3C,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YA2DrD,aAAa;YAkDb,YAAY;IAmC1B,OAAO,CAAC,QAAQ;IAgDhB,OAAO,CAAC,aAAa;IA6ErB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,qBAAqB;IAsD7B,OAAO,CAAC,iBAAiB;IA2EzB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,8BAA8B;IAiBtC,OAAO,CAAC,mBAAmB;IAgD3B,OAAO,CAAC,oBAAoB;IA+D5B,OAAO,CAAC,qBAAqB;IA6H7B,OAAO,CAAC,cAAc;CA6SvB"}
|
package/dist/report/generator.js
CHANGED
|
@@ -264,11 +264,16 @@ ${row("Cookie behavior", breakdown.cookieBehavior, 25)}
|
|
|
264
264
|
const warningCount = r.compliance.issues.filter((i) => i.severity === "warning").length;
|
|
265
265
|
const illegalPreCookies = r.cookiesBeforeInteraction.filter((c) => c.requiresConsent);
|
|
266
266
|
const persistAfterReject = r.cookiesAfterReject.filter((c) => c.requiresConsent);
|
|
267
|
-
const preInteractionTrackers = r.networkBeforeInteraction.filter((n) => n.
|
|
267
|
+
const preInteractionTrackers = r.networkBeforeInteraction.filter((n) => n.requiresConsent);
|
|
268
268
|
const lines = [];
|
|
269
|
-
|
|
269
|
+
const consentRequired = [...r.cookiesBeforeInteraction, ...r.cookiesAfterAccept].some((c) => c.requiresConsent) ||
|
|
270
|
+
[...r.networkBeforeInteraction, ...r.networkAfterAccept].some((n) => n.requiresConsent);
|
|
271
|
+
if (!r.modal.detected && consentRequired) {
|
|
270
272
|
lines.push("❌ **No consent modal detected.** The site sets cookies without requesting consent.");
|
|
271
273
|
}
|
|
274
|
+
else if (!r.modal.detected) {
|
|
275
|
+
lines.push("✅ No consent modal required — no non-essential cookies or trackers detected.");
|
|
276
|
+
}
|
|
272
277
|
else {
|
|
273
278
|
lines.push(`✅ Consent modal detected (\`${r.modal.selector}\`).`);
|
|
274
279
|
}
|
|
@@ -477,7 +482,9 @@ ${rows.join("\n")}
|
|
|
477
482
|
buildRecommendations(r) {
|
|
478
483
|
const recs = [];
|
|
479
484
|
const issues = r.compliance.issues;
|
|
480
|
-
|
|
485
|
+
const needsConsent = [...r.cookiesBeforeInteraction, ...r.cookiesAfterAccept].some((c) => c.requiresConsent) ||
|
|
486
|
+
[...r.networkBeforeInteraction, ...r.networkAfterAccept].some((n) => n.requiresConsent);
|
|
487
|
+
if (!r.modal.detected && needsConsent) {
|
|
481
488
|
recs.push("1. **Deploy a CMP solution** (e.g. Axeptio, Didomi, OneTrust, Cookiebot) that displays a consent modal before any non-essential cookie.");
|
|
482
489
|
}
|
|
483
490
|
if (issues.some((i) => i.type === "pre-ticked")) {
|
|
@@ -610,26 +617,33 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
610
617
|
const ok = "✅ Compliant";
|
|
611
618
|
const ko = "❌ Non-compliant";
|
|
612
619
|
const warn = "⚠️ Warning";
|
|
620
|
+
const na = "➖ Not applicable";
|
|
621
|
+
const consentRequired = [...r.cookiesBeforeInteraction, ...r.cookiesAfterAccept].some((c) => c.requiresConsent) ||
|
|
622
|
+
[...r.networkBeforeInteraction, ...r.networkAfterAccept].some((n) => n.requiresConsent);
|
|
623
|
+
const noModalStatus = consentRequired ? ko : na;
|
|
624
|
+
const noModalDetail = consentRequired
|
|
625
|
+
? "No consent banner detected"
|
|
626
|
+
: "Not required — no non-essential cookies or trackers";
|
|
613
627
|
const rows = [];
|
|
614
628
|
// ── A. Consent presence and validity ─────────────────────────
|
|
615
629
|
rows.push({
|
|
616
630
|
category: "Consent",
|
|
617
631
|
rule: "Consent modal detected",
|
|
618
632
|
reference: "[GDPR Art. 7](https://gdpr-info.eu/art-7-gdpr/) · [ePrivacy Dir. Art. 5(3)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32002L0058)",
|
|
619
|
-
status: r.modal.detected ? ok :
|
|
620
|
-
detail: r.modal.detected
|
|
621
|
-
? `Detected (\`${r.modal.selector}\`)`
|
|
622
|
-
: "No consent banner detected",
|
|
633
|
+
status: r.modal.detected ? ok : noModalStatus,
|
|
634
|
+
detail: r.modal.detected ? `Detected (\`${r.modal.selector}\`)` : noModalDetail,
|
|
623
635
|
});
|
|
624
636
|
const preTicked = r.modal.checkboxes.filter((c) => c.isCheckedByDefault);
|
|
625
637
|
rows.push({
|
|
626
638
|
category: "Consent",
|
|
627
639
|
rule: "No pre-ticked checkboxes",
|
|
628
640
|
reference: "[GDPR Recital 32](https://gdpr-info.eu/recitals/no-32/)",
|
|
629
|
-
status: preTicked.length === 0 ? ok : ko,
|
|
630
|
-
detail:
|
|
631
|
-
?
|
|
632
|
-
:
|
|
641
|
+
status: !r.modal.detected ? (consentRequired ? ko : na) : preTicked.length === 0 ? ok : ko,
|
|
642
|
+
detail: !r.modal.detected
|
|
643
|
+
? noModalDetail
|
|
644
|
+
: preTicked.length === 0
|
|
645
|
+
? "No pre-ticked checkbox detected"
|
|
646
|
+
: `${preTicked.length} pre-ticked box(es): ${preTicked.map((c) => c.label || c.name).join(", ")}`,
|
|
633
647
|
});
|
|
634
648
|
const misleadingAccept = getIssue("misleading-wording");
|
|
635
649
|
const acceptBtn = r.modal.buttons.find((b) => b.type === "accept");
|
|
@@ -637,13 +651,17 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
637
651
|
category: "Consent",
|
|
638
652
|
rule: "Accept button label is unambiguous",
|
|
639
653
|
reference: "[GDPR Art. 4(11)](https://gdpr-info.eu/art-4-gdpr/)",
|
|
640
|
-
status: !r.modal.detected
|
|
641
|
-
?
|
|
642
|
-
: misleadingAccept.severity === "critical"
|
|
654
|
+
status: !r.modal.detected
|
|
655
|
+
? consentRequired
|
|
643
656
|
? ko
|
|
644
|
-
:
|
|
657
|
+
: na
|
|
658
|
+
: !misleadingAccept
|
|
659
|
+
? ok
|
|
660
|
+
: misleadingAccept.severity === "critical"
|
|
661
|
+
? ko
|
|
662
|
+
: warn,
|
|
645
663
|
detail: !r.modal.detected
|
|
646
|
-
?
|
|
664
|
+
? noModalDetail
|
|
647
665
|
: acceptBtn
|
|
648
666
|
? misleadingAccept
|
|
649
667
|
? `Ambiguous label: "${acceptBtn.text}"`
|
|
@@ -657,9 +675,9 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
657
675
|
category: "Easy refusal",
|
|
658
676
|
rule: "Reject button present at first layer",
|
|
659
677
|
reference: "[CNIL Recommendation 2022](https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies)",
|
|
660
|
-
status: !r.modal.detected ? ko : noReject ? ko : ok,
|
|
678
|
+
status: !r.modal.detected ? (consentRequired ? ko : na) : noReject ? ko : ok,
|
|
661
679
|
detail: !r.modal.detected
|
|
662
|
-
?
|
|
680
|
+
? noModalDetail
|
|
663
681
|
: rejectBtn
|
|
664
682
|
? `Detected: "${rejectBtn.text}"`
|
|
665
683
|
: "No Reject button at first layer",
|
|
@@ -669,9 +687,9 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
669
687
|
category: "Easy refusal",
|
|
670
688
|
rule: "Rejecting requires no more clicks than accepting",
|
|
671
689
|
reference: "[CNIL Recommendation 2022](https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies)",
|
|
672
|
-
status: !r.modal.detected ? ko : clickIssue ? ko : ok,
|
|
690
|
+
status: !r.modal.detected ? (consentRequired ? ko : na) : clickIssue ? ko : ok,
|
|
673
691
|
detail: !r.modal.detected
|
|
674
|
-
?
|
|
692
|
+
? noModalDetail
|
|
675
693
|
: clickIssue
|
|
676
694
|
? clickIssue.evidence
|
|
677
695
|
: acceptBtn && rejectBtn
|
|
@@ -683,9 +701,9 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
683
701
|
category: "Easy refusal",
|
|
684
702
|
rule: "Size symmetry between Accept and Reject",
|
|
685
703
|
reference: "[EDPB Guidelines 03/2022](https://www.edpb.europa.eu/system/files/2022-03/edpb_03-2022_guidelines_on_dark_patterns_in_social_media_platform_interfaces_en.pdf)",
|
|
686
|
-
status: !r.modal.detected ? ko : sizeIssue ? warn : ok,
|
|
704
|
+
status: !r.modal.detected ? (consentRequired ? ko : na) : sizeIssue ? warn : ok,
|
|
687
705
|
detail: !r.modal.detected
|
|
688
|
-
?
|
|
706
|
+
? noModalDetail
|
|
689
707
|
: sizeIssue
|
|
690
708
|
? sizeIssue.evidence
|
|
691
709
|
: "Button sizes are comparable",
|
|
@@ -695,9 +713,9 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
695
713
|
category: "Easy refusal",
|
|
696
714
|
rule: "Font symmetry between Accept and Reject",
|
|
697
715
|
reference: "[EDPB Guidelines 03/2022](https://www.edpb.europa.eu/system/files/2022-03/edpb_03-2022_guidelines_on_dark_patterns_in_social_media_platform_interfaces_en.pdf)",
|
|
698
|
-
status: !r.modal.detected ? ko : nudgeIssue ? warn : ok,
|
|
716
|
+
status: !r.modal.detected ? (consentRequired ? ko : na) : nudgeIssue ? warn : ok,
|
|
699
717
|
detail: !r.modal.detected
|
|
700
|
-
?
|
|
718
|
+
? noModalDetail
|
|
701
719
|
: nudgeIssue
|
|
702
720
|
? nudgeIssue.evidence
|
|
703
721
|
: "Font sizes are comparable",
|
|
@@ -707,9 +725,15 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
707
725
|
category: "Transparency",
|
|
708
726
|
rule: "Granular controls available",
|
|
709
727
|
reference: "[EDPB Guidelines 05/2020](https://edpb.europa.eu/our-work-tools/our-documents/guidelines/guidelines-052020-consent-under-regulation-2016679_en)",
|
|
710
|
-
status: !r.modal.detected
|
|
728
|
+
status: !r.modal.detected
|
|
729
|
+
? consentRequired
|
|
730
|
+
? ko
|
|
731
|
+
: na
|
|
732
|
+
: r.modal.hasGranularControls
|
|
733
|
+
? ok
|
|
734
|
+
: warn,
|
|
711
735
|
detail: !r.modal.detected
|
|
712
|
-
?
|
|
736
|
+
? noModalDetail
|
|
713
737
|
: r.modal.hasGranularControls
|
|
714
738
|
? `${r.modal.checkboxes.length} checkbox(es) or preferences panel detected`
|
|
715
739
|
: "No granular controls (checkboxes or panel) detected",
|
|
@@ -742,9 +766,9 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
742
766
|
category: "Transparency",
|
|
743
767
|
rule: label,
|
|
744
768
|
reference: ref,
|
|
745
|
-
status: !r.modal.detected ? ko : missing ? warn : ok,
|
|
769
|
+
status: !r.modal.detected ? (consentRequired ? ko : na) : missing ? warn : ok,
|
|
746
770
|
detail: !r.modal.detected
|
|
747
|
-
?
|
|
771
|
+
? noModalDetail
|
|
748
772
|
: missing
|
|
749
773
|
? `Information absent from the modal text`
|
|
750
774
|
: "Mention found in the modal text",
|
|
@@ -754,9 +778,15 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
754
778
|
category: "Transparency",
|
|
755
779
|
rule: "Privacy policy link present in the consent modal",
|
|
756
780
|
reference: "[GDPR Art. 13](https://gdpr-info.eu/art-13-gdpr/)",
|
|
757
|
-
status: !r.modal.detected
|
|
781
|
+
status: !r.modal.detected
|
|
782
|
+
? consentRequired
|
|
783
|
+
? ko
|
|
784
|
+
: na
|
|
785
|
+
: r.modal.privacyPolicyUrl
|
|
786
|
+
? ok
|
|
787
|
+
: warn,
|
|
758
788
|
detail: !r.modal.detected
|
|
759
|
-
?
|
|
789
|
+
? noModalDetail
|
|
760
790
|
: r.modal.privacyPolicyUrl
|
|
761
791
|
? `Link found: ${r.modal.privacyPolicyUrl}`
|
|
762
792
|
: "No privacy policy link found inside the consent modal",
|
|
@@ -765,7 +795,7 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
765
795
|
category: "Transparency",
|
|
766
796
|
rule: "Privacy policy accessible from the main page",
|
|
767
797
|
reference: "[GDPR Art. 13](https://gdpr-info.eu/art-13-gdpr/)",
|
|
768
|
-
status: r.privacyPolicyUrl ? ok : warn,
|
|
798
|
+
status: r.privacyPolicyUrl ? ok : consentRequired ? warn : na,
|
|
769
799
|
detail: r.privacyPolicyUrl
|
|
770
800
|
? `Link found: ${r.privacyPolicyUrl}`
|
|
771
801
|
: "No privacy policy link found on the main page",
|
|
@@ -791,7 +821,7 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
791
821
|
? "No non-essential cookie persisting after rejection"
|
|
792
822
|
: `${persistAfterReject.length} cookie(s) persisting: ${persistAfterReject.map((c) => `\`${c.name}\``).join(", ")}`,
|
|
793
823
|
});
|
|
794
|
-
const preTrackers = r.networkBeforeInteraction.filter((req) => req.
|
|
824
|
+
const preTrackers = r.networkBeforeInteraction.filter((req) => req.requiresConsent);
|
|
795
825
|
rows.push({
|
|
796
826
|
category: "Cookie behavior",
|
|
797
827
|
rule: "No network tracker before consent",
|
|
@@ -805,6 +835,7 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
805
835
|
const conformeCount = rows.filter((r) => r.status === ok).length;
|
|
806
836
|
const nonConformeCount = rows.filter((r) => r.status === ko).length;
|
|
807
837
|
const avertissementCount = rows.filter((r) => r.status === warn).length;
|
|
838
|
+
const naCount = rows.filter((r) => r.status === na).length;
|
|
808
839
|
const lines = [];
|
|
809
840
|
lines.push(`# GDPR Compliance Checklist — ${hostname}`);
|
|
810
841
|
lines.push(`
|
|
@@ -812,7 +843,13 @@ The **Description / Purpose** column is to be filled in by the DPO or technical
|
|
|
812
843
|
> **Scanned URL:** ${r.url}
|
|
813
844
|
> **Global score:** ${r.compliance.total}/100 — Grade **${r.compliance.grade}**
|
|
814
845
|
`);
|
|
815
|
-
|
|
846
|
+
const totalsSummary = [
|
|
847
|
+
`**${conformeCount} rule(s) compliant**`,
|
|
848
|
+
`**${nonConformeCount} non-compliant**`,
|
|
849
|
+
`**${avertissementCount} warning(s)**`,
|
|
850
|
+
...(naCount > 0 ? [`**${naCount} not applicable**`] : []),
|
|
851
|
+
].join(" · ");
|
|
852
|
+
lines.push(`${totalsSummary}\n`);
|
|
816
853
|
const categories = [...new Set(rows.map((r) => r.category))];
|
|
817
854
|
for (const category of categories) {
|
|
818
855
|
lines.push(`## ${category}\n`);
|