@ecomconsult/consentkit 0.5.7 → 0.5.9
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/README.md +43 -1
- package/npm/core.cjs +3 -0
- package/npm/core.mjs +4 -0
- package/npm/index.cjs +3 -0
- package/npm/index.d.ts +67 -1
- package/npm/index.mjs +4 -0
- package/npm/internal-stub.mjs +11 -1
- package/npm/react.mjs +10 -1
- package/package.json +3 -2
- package/src/ck-core.js +470 -14
- package/src/ck-debug.js +273 -3
- package/src/ck-locales.js +6 -0
- package/src/ck-saas.js +33 -0
- package/src/ck-ui.js +550 -43
package/README.md
CHANGED
|
@@ -199,6 +199,7 @@ Pass any subset to `init()`. Nested objects merge with the defaults.
|
|
|
199
199
|
| `blocking.placeholders` | `boolean` | `true` | v0.5.7. Draw a card in place of an embed held back before consent — see [Placeholders for blocked embeds](#placeholders-for-blocked-embeds). `false` restores the pre-0.5.7 behaviour: the frame is still blocked, just invisible |
|
|
200
200
|
| `hostdb` | `Record<string, Category>` | — | Extra `host: category` pairs merged into the tracker database, applied before the initial scan. SaaS mode fills this from the service; `ConsentKit._extendHostDb()` does the same at any later point |
|
|
201
201
|
| `cookieTable` | `CkCookieTableEntry[]` | `[]` | Declared cookies, listed per category in the panel |
|
|
202
|
+
| `services` | `CkService[]` | `[]` | v0.5.8. Third-party services the site declares. Each gets its own toggle inside its category group in the panel, and can be refused individually — see [Services](#services). At most 50 |
|
|
202
203
|
|
|
203
204
|
`cookieTable` entries:
|
|
204
205
|
|
|
@@ -206,6 +207,45 @@ Pass any subset to `init()`. Nested objects merge with the defaults.
|
|
|
206
207
|
{ name: '_ga', category: 'analytics', vendor: 'Google', purpose: 'Visit statistics', expiry: '2 years' }
|
|
207
208
|
```
|
|
208
209
|
|
|
210
|
+
### Services
|
|
211
|
+
|
|
212
|
+
**v0.5.8.** A `services` row names one third party: where its resources come
|
|
213
|
+
from, which cookies it sets and what it is for. The preferences panel lists it
|
|
214
|
+
inside its category group with **its own toggle**, so a visitor can accept
|
|
215
|
+
analytics in general and still refuse one particular service.
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
services: [{
|
|
219
|
+
id: 'hotjar', // stable, ^[a-z0-9-]{1,64}$
|
|
220
|
+
name: 'Hotjar',
|
|
221
|
+
vendor: 'Hotjar Ltd',
|
|
222
|
+
category: 'analytics',
|
|
223
|
+
hosts: ['hotjar.com'], // suffix-matched, like the tracker database
|
|
224
|
+
paths: ['/hotjar-'], // optional, substring-matched
|
|
225
|
+
cookies: ['_hjSession', '_hjSessionUser'], // names; matched against cookieTable
|
|
226
|
+
privacyUrl: 'https://www.hotjar.com/privacy/', // http(s) only
|
|
227
|
+
purpose: { ru: '…', ro: '…', en: 'Records how visitors move around the page.' },
|
|
228
|
+
enabled: true // false: not shown, not blocked separately
|
|
229
|
+
}]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
What the toggle does:
|
|
233
|
+
|
|
234
|
+
- **Group off** — every service of that group is off and blocked, as before.
|
|
235
|
+
- **Group on** — the services come back, *except* the ones the visitor switched
|
|
236
|
+
off by hand. A refusal survives the group being switched off and on again.
|
|
237
|
+
- A refused service's resources are held back exactly as if its category had no
|
|
238
|
+
consent, and its cookies are deleted exactly as on a category withdrawal.
|
|
239
|
+
- The «Allow and show» button on a blocked embed's placeholder grants the
|
|
240
|
+
category **and** clears the refusal on that frame's service.
|
|
241
|
+
|
|
242
|
+
`hosts` need not already be in the tracker database: `init()` folds them into
|
|
243
|
+
the block map under the row's own category, so a service host ConsentKit has
|
|
244
|
+
never heard of is still held back.
|
|
245
|
+
|
|
246
|
+
Refusals are stored in `ck_consent` as `services: { '<id>': false }` — denials
|
|
247
|
+
only. An id absent from the map is allowed, subject to its category.
|
|
248
|
+
|
|
209
249
|
### Button appearance
|
|
210
250
|
|
|
211
251
|
Each of the three banner buttons can be styled independently:
|
|
@@ -361,9 +401,10 @@ All methods are safe to call at any time and never throw.
|
|
|
361
401
|
|---|---|---|
|
|
362
402
|
| `init(config?)` | `CkState` | Idempotent. Restores stored consent, then dispatches `ck:init`. Calling again merges config only |
|
|
363
403
|
| `allowed(category)` | `boolean` | `necessary` is always `true` |
|
|
404
|
+
| `allowedService(id)` | `boolean` | v0.5.8. May this one declared service run? True when its category is granted **and** the visitor has not refused it individually. An id the config does not declare is `true` |
|
|
364
405
|
| `getState()` | `CkState` | A fresh object on every call |
|
|
365
406
|
| `accept('all')` | `CkState` | Grants everything. `method: 'accept_all'` |
|
|
366
|
-
| `accept({ ... })` | `CkState` | Per-category choice. `method: 'custom'`. Omitted categories stay denied |
|
|
407
|
+
| `accept({ ... })` | `CkState` | Per-category choice. `method: 'custom'`. Omitted categories stay denied. v0.5.8: an optional `services: { '<id>': false }` replaces the stored refusals wholesale; omit it to leave them untouched |
|
|
367
408
|
| `rejectAll()` | `CkState` | Denies every opt-in category. `method: 'reject_all'` |
|
|
368
409
|
| `withdraw()` | `CkState` | Clears storage and known cookies, sends GCM `denied`, resets to `decided: false` |
|
|
369
410
|
| `show()` | `void` | Opens the preferences panel |
|
|
@@ -381,6 +422,7 @@ All methods are safe to call at any time and never throw.
|
|
|
381
422
|
ts: null, // ISO timestamp
|
|
382
423
|
policyVersion: '1',
|
|
383
424
|
categories: { necessary: true, functional: false, analytics: false, marketing: false },
|
|
425
|
+
services: {}, // v0.5.8. Per-service refusals ONLY: { hotjar: false }
|
|
384
426
|
method: null // 'accept_all' | 'reject_all' | 'custom'
|
|
385
427
|
}
|
|
386
428
|
```
|
package/npm/core.cjs
CHANGED
|
@@ -25,6 +25,9 @@ function createStub() {
|
|
|
25
25
|
config: {},
|
|
26
26
|
init: function () { return undecidedState(); },
|
|
27
27
|
allowed: function (cat) { return cat === 'necessary'; },
|
|
28
|
+
// v0.5.8 (SPEC V1.12 §3). `true`: a stub means the engine never attached
|
|
29
|
+
// and withholds nothing, so it must not claim a refusal it cannot enforce.
|
|
30
|
+
allowedService: function () { return true; },
|
|
28
31
|
getState: undecidedState,
|
|
29
32
|
accept: function () { return undecidedState(); },
|
|
30
33
|
rejectAll: function () { return undecidedState(); },
|
package/npm/core.mjs
CHANGED
|
@@ -23,6 +23,10 @@ export default ConsentKit;
|
|
|
23
23
|
export const {
|
|
24
24
|
init,
|
|
25
25
|
allowed,
|
|
26
|
+
// v0.5.8 (SPEC V1.12 §3): «may this ONE declared service run?» — the category
|
|
27
|
+
// check plus the visitor's per-service refusal, which getState() alone cannot
|
|
28
|
+
// reconstruct. Part of the public surface, so it is a named import too.
|
|
29
|
+
allowedService,
|
|
26
30
|
getState,
|
|
27
31
|
accept,
|
|
28
32
|
rejectAll,
|
package/npm/index.cjs
CHANGED
|
@@ -28,6 +28,9 @@ function createStub() {
|
|
|
28
28
|
config: {},
|
|
29
29
|
init: function () { return undecidedState(); },
|
|
30
30
|
allowed: function (cat) { return cat === 'necessary'; },
|
|
31
|
+
// v0.5.8 (SPEC V1.12 §3). `true`: a stub means the engine never attached
|
|
32
|
+
// and withholds nothing, so it must not claim a refusal it cannot enforce.
|
|
33
|
+
allowedService: function () { return true; },
|
|
31
34
|
getState: undecidedState,
|
|
32
35
|
accept: function () { return undecidedState(); },
|
|
33
36
|
rejectAll: function () { return undecidedState(); },
|
package/npm/index.d.ts
CHANGED
|
@@ -34,11 +34,26 @@ export interface CkState {
|
|
|
34
34
|
/** Policy version the decision was recorded against. */
|
|
35
35
|
policyVersion: string;
|
|
36
36
|
categories: CkCategories;
|
|
37
|
+
/**
|
|
38
|
+
* v0.5.8 (SPEC V1.12 §3). Per-service refusals, and ONLY refusals:
|
|
39
|
+
* `{ 'hotjar': false }`. An id absent from the map is allowed, subject to its
|
|
40
|
+
* category. A denial survives its category being switched off and back on.
|
|
41
|
+
*/
|
|
42
|
+
services: Record<string, false>;
|
|
37
43
|
method: CkMethod;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
/** Argument to `accept()`: `'all'`, or an explicit per-category selection. */
|
|
41
|
-
export type CkAcceptArg =
|
|
47
|
+
export type CkAcceptArg =
|
|
48
|
+
| 'all'
|
|
49
|
+
| (Partial<Record<CkOptInCategory, boolean>> & {
|
|
50
|
+
/**
|
|
51
|
+
* v0.5.8 (SPEC V1.12 §3). The FULL per-service refusal map for this
|
|
52
|
+
* decision — it replaces the stored one wholesale. Omit it to leave
|
|
53
|
+
* the existing refusals untouched.
|
|
54
|
+
*/
|
|
55
|
+
services?: Record<string, false>;
|
|
56
|
+
});
|
|
42
57
|
|
|
43
58
|
/** Banner placement. `bar` uses bottom/top; `box` uses the corner positions. */
|
|
44
59
|
export type CkLayoutType = 'bar' | 'modal' | 'box';
|
|
@@ -196,6 +211,31 @@ export interface CkCookieTableEntry {
|
|
|
196
211
|
expiry?: string;
|
|
197
212
|
}
|
|
198
213
|
|
|
214
|
+
/**
|
|
215
|
+
* v0.5.8 (SPEC V1.12 §2). One declared third-party service.
|
|
216
|
+
*
|
|
217
|
+
* `hosts` are suffix-matched (a bare domain also covers its subdomains) and
|
|
218
|
+
* `paths` are matched as case-insensitive substrings of the resolved URL —
|
|
219
|
+
* the same two rules the built-in tracker database uses.
|
|
220
|
+
*/
|
|
221
|
+
export interface CkService {
|
|
222
|
+
/** Stable kebab-case id, `^[a-z0-9-]{1,64}$`. */
|
|
223
|
+
id: string;
|
|
224
|
+
name: string;
|
|
225
|
+
vendor: string;
|
|
226
|
+
category: CkCategory;
|
|
227
|
+
hosts: string[];
|
|
228
|
+
paths?: string[];
|
|
229
|
+
/** Cookie names, matched against `cookieTable` to list them under the service. */
|
|
230
|
+
cookies: string[];
|
|
231
|
+
/** `http(s)` only; anything else is dropped rather than rendered as a link. */
|
|
232
|
+
privacyUrl?: string;
|
|
233
|
+
/** One line for the visitor, per language. Falls back to `en`. */
|
|
234
|
+
purpose?: { ru?: string; ro?: string; en?: string };
|
|
235
|
+
/** Default `true`. `false` hides the row and stops blocking it separately. */
|
|
236
|
+
enabled?: boolean;
|
|
237
|
+
}
|
|
238
|
+
|
|
199
239
|
/** Configuration accepted by `init()`. Every field is optional. */
|
|
200
240
|
export interface CkConfig {
|
|
201
241
|
/** Bump to invalidate stored decisions and re-show the banner. Default `'1'`. */
|
|
@@ -220,6 +260,17 @@ export interface CkConfig {
|
|
|
220
260
|
*/
|
|
221
261
|
hostdb?: Record<string, CkCategory>;
|
|
222
262
|
cookieTable?: CkCookieTableEntry[];
|
|
263
|
+
/**
|
|
264
|
+
* v0.5.8 (SPEC V1.12 §2/§3). The third-party services this site declares.
|
|
265
|
+
* Each row gets its own switch inside its category group in the preferences
|
|
266
|
+
* panel, and the engine can hold back that one service while the rest of the
|
|
267
|
+
* category runs. At most 50 rows; a row with `enabled: false` is neither
|
|
268
|
+
* shown nor blocked separately.
|
|
269
|
+
*
|
|
270
|
+
* `hosts` need not be in the built-in tracker database — `init()` folds them
|
|
271
|
+
* into the block map under the row's own category.
|
|
272
|
+
*/
|
|
273
|
+
services?: CkService[];
|
|
223
274
|
}
|
|
224
275
|
|
|
225
276
|
/** Detail payload of `ck:init`. */
|
|
@@ -241,6 +292,13 @@ export interface ConsentKitApi {
|
|
|
241
292
|
/** Idempotent. Restores stored state, then dispatches `ck:init`. */
|
|
242
293
|
init(config?: CkConfig): CkState;
|
|
243
294
|
allowed(category: CkCategory | string): boolean;
|
|
295
|
+
/**
|
|
296
|
+
* v0.5.8 (SPEC V1.12 §3). May this one declared service run? True when its
|
|
297
|
+
* category is granted AND the visitor has not switched it off individually —
|
|
298
|
+
* a combination `getState().categories` alone cannot reconstruct. An id the
|
|
299
|
+
* config does not declare answers `true`.
|
|
300
|
+
*/
|
|
301
|
+
allowedService(id: string): boolean;
|
|
244
302
|
getState(): CkState;
|
|
245
303
|
/** `accept('all')` grants everything; an object records `method: 'custom'`. */
|
|
246
304
|
accept(choice?: CkAcceptArg): CkState;
|
|
@@ -396,6 +454,8 @@ export { ConsentKit };
|
|
|
396
454
|
|
|
397
455
|
export declare function init(config?: CkConfig): CkState;
|
|
398
456
|
export declare function allowed(category: CkCategory | string): boolean;
|
|
457
|
+
/** v0.5.8 (SPEC V1.12 §3). */
|
|
458
|
+
export declare function allowedService(id: string): boolean;
|
|
399
459
|
export declare function getState(): CkState;
|
|
400
460
|
export declare function accept(choice?: CkAcceptArg): CkState;
|
|
401
461
|
export declare function rejectAll(): CkState;
|
|
@@ -427,6 +487,8 @@ declare module '@ecomconsult/consentkit' {
|
|
|
427
487
|
export { ConsentKit };
|
|
428
488
|
export function init(config?: CkConfig): CkState;
|
|
429
489
|
export function allowed(category: CkCategory | string): boolean;
|
|
490
|
+
/** v0.5.8 (SPEC V1.12 §3). */
|
|
491
|
+
export function allowedService(id: string): boolean;
|
|
430
492
|
export function getState(): CkState;
|
|
431
493
|
export function accept(choice?: CkAcceptArg): CkState;
|
|
432
494
|
export function rejectAll(): CkState;
|
|
@@ -442,6 +504,8 @@ declare module '@ecomconsult/consentkit/core' {
|
|
|
442
504
|
export { ConsentKit };
|
|
443
505
|
export function init(config?: CkConfig): CkState;
|
|
444
506
|
export function allowed(category: CkCategory | string): boolean;
|
|
507
|
+
/** v0.5.8 (SPEC V1.12 §3). */
|
|
508
|
+
export function allowedService(id: string): boolean;
|
|
445
509
|
export function getState(): CkState;
|
|
446
510
|
export function accept(choice?: CkAcceptArg): CkState;
|
|
447
511
|
export function rejectAll(): CkState;
|
|
@@ -456,6 +520,8 @@ export interface UseConsentResult {
|
|
|
456
520
|
/** Current state. On the server, an undecided snapshot. */
|
|
457
521
|
state: CkState;
|
|
458
522
|
allowed(category: CkCategory | string): boolean;
|
|
523
|
+
/** v0.5.8 (SPEC V1.12 §3). May this one declared service run? */
|
|
524
|
+
allowedService(id: string): boolean;
|
|
459
525
|
/** Defaults to `'all'` when called with no argument. */
|
|
460
526
|
accept(choice?: CkAcceptArg): CkState;
|
|
461
527
|
rejectAll(): CkState;
|
package/npm/index.mjs
CHANGED
|
@@ -46,6 +46,10 @@ export default ConsentKit;
|
|
|
46
46
|
export const {
|
|
47
47
|
init,
|
|
48
48
|
allowed,
|
|
49
|
+
// v0.5.8 (SPEC V1.12 §3): «may this ONE declared service run?» — the category
|
|
50
|
+
// check plus the visitor's per-service refusal, which getState() alone cannot
|
|
51
|
+
// reconstruct. Part of the public surface, so it is a named import too.
|
|
52
|
+
allowedService,
|
|
49
53
|
getState,
|
|
50
54
|
accept,
|
|
51
55
|
rejectAll,
|
package/npm/internal-stub.mjs
CHANGED
|
@@ -28,10 +28,15 @@ export function undecidedState() {
|
|
|
28
28
|
*/
|
|
29
29
|
export function createStub() {
|
|
30
30
|
const stub = {
|
|
31
|
-
version: '0.5.
|
|
31
|
+
version: '0.5.9',
|
|
32
32
|
config: {},
|
|
33
33
|
init: function () { return undecidedState(); },
|
|
34
34
|
allowed: function (cat) { return cat === 'necessary'; },
|
|
35
|
+
// v0.5.8 (SPEC V1.12 §3): may this one declared service run? `true` here
|
|
36
|
+
// for the same reason the real core answers `true` for an unknown id — a
|
|
37
|
+
// stub means the engine never attached and is withholding nothing, so
|
|
38
|
+
// claiming a refusal it does not enforce would be a lie consumer code acts on.
|
|
39
|
+
allowedService: function () { return true; },
|
|
35
40
|
getState: undecidedState,
|
|
36
41
|
accept: function () { return undecidedState(); },
|
|
37
42
|
rejectAll: function () { return undecidedState(); },
|
|
@@ -51,6 +56,11 @@ export function createStub() {
|
|
|
51
56
|
_infra: function () { return []; },
|
|
52
57
|
_isInfra: function () { return false; },
|
|
53
58
|
_blocked: function () { return []; },
|
|
59
|
+
// v0.5.8 (SPEC V1.12 §3): the service registry. Empty for the same reason
|
|
60
|
+
// _baseAllow and _infra are — nothing was normalised, nothing is blocked.
|
|
61
|
+
_serviceForUrl: function () { return null; },
|
|
62
|
+
_services: function () { return []; },
|
|
63
|
+
_deniedServices: function () { return []; },
|
|
54
64
|
_isStub: true
|
|
55
65
|
};
|
|
56
66
|
return stub;
|
package/npm/react.mjs
CHANGED
|
@@ -113,6 +113,7 @@ function sameState(a, b) {
|
|
|
113
113
|
* @returns {{
|
|
114
114
|
* state: object,
|
|
115
115
|
* allowed: (cat: string) => boolean,
|
|
116
|
+
* allowedService: (id: string) => boolean,
|
|
116
117
|
* accept: (choice?: any) => object,
|
|
117
118
|
* rejectAll: () => object,
|
|
118
119
|
* withdraw: () => object,
|
|
@@ -127,6 +128,14 @@ export function useConsent() {
|
|
|
127
128
|
try { return api().allowed(cat); } catch (e) { return false; }
|
|
128
129
|
}, []);
|
|
129
130
|
|
|
131
|
+
/* v0.5.8 (SPEC V1.12 §3). On the server there is no stored decision and no
|
|
132
|
+
service registry, so nothing is being withheld — `true`, matching what the
|
|
133
|
+
core answers for an id it does not know. */
|
|
134
|
+
const allowedService = useCallback(function (id) {
|
|
135
|
+
if (!hasDom()) return true;
|
|
136
|
+
try { return api().allowedService(id); } catch (e) { return true; }
|
|
137
|
+
}, []);
|
|
138
|
+
|
|
130
139
|
const accept = useCallback(function (choice) {
|
|
131
140
|
if (!hasDom()) return SERVER_SNAPSHOT;
|
|
132
141
|
return api().accept(choice === undefined ? 'all' : choice);
|
|
@@ -147,7 +156,7 @@ export function useConsent() {
|
|
|
147
156
|
api().show();
|
|
148
157
|
}, []);
|
|
149
158
|
|
|
150
|
-
return { state, allowed, accept, rejectAll, withdraw, show };
|
|
159
|
+
return { state, allowed, allowedService, accept, rejectAll, withdraw, show };
|
|
151
160
|
}
|
|
152
161
|
|
|
153
162
|
export default useConsent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecomconsult/consentkit",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"description": "GDPR cookie consent core with blocking engine, Shadow DOM UI and Google Consent Mode v2. Zero dependencies, no build step.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"author": "E-COM CONSULT PLUS",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"scripts": {
|
|
24
|
-
"test": "node --test test/*.test.mjs"
|
|
24
|
+
"test": "node --test test/*.test.mjs",
|
|
25
|
+
"build": "node tools/build-inline.mjs --langs=ru,ro,en --language=auto --layout=bar --position=bottom --accent=#2B50D8 --mode=auto --policy=1 --out=ready/ru-bar.txt && node tools/build-inline.mjs --langs=ru,ro,en --language=auto --layout=box --position=bottom-left --accent=#2B50D8 --mode=auto --policy=1 --out=ready/ru-box.txt && node tools/build-inline.mjs --langs=ru,ro,en --language=auto --layout=box --position=bottom-right --accent=#2B50D8 --mode=auto --policy=1 --out=ready/ru-box-right.txt && node tools/build-inline.mjs --langs=ru,ro,en --language=auto --layout=modal --position=bottom --accent=#2B50D8 --mode=auto --policy=1 --out=ready/ru-modal.txt && node tools/build-inline.mjs --langs=en --language=en --layout=bar --position=bottom --accent=#2B50D8 --mode=auto --policy=1 --out=ready/en-bar.txt && node tools/build-inline.mjs --langs=bg,ca,cs,da,de,el,en,es,et,fi,fr,ga,hr,hu,is,it,lt,lv,mk,mt,nb,nl,no,pl,pt,ro,ru,sk,sl,sq,sr,sv,tr,uk --language=auto --layout=bar --position=bottom --accent=#2B50D8 --mode=auto --policy=1 --out=ready/eu-bar.txt && node tools/export-hostdb.mjs && node tools/sync-site.mjs && node tools/build-site.mjs && cp -f src/ck-core.js src/ck-locales.js src/ck-ui-branding.js src/ck-ui.js src/ck-debug-loader.js plugins/wordpress/consentkit/assets/"
|
|
25
26
|
},
|
|
26
27
|
"type": "module",
|
|
27
28
|
"sideEffects": true,
|