@ecomconsult/consentkit 0.5.4 → 0.5.6
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 +5 -0
- package/npm/internal-stub.mjs +1 -1
- package/package.json +1 -1
- package/src/ck-core.js +1 -1
- package/src/ck-locales.js +11 -11
- package/src/ck-ui-branding.js +45 -2
- package/src/ck-ui.js +29 -23
package/README.md
CHANGED
|
@@ -555,6 +555,11 @@ Removing it is a supported, first-class option — no obligation, no nag:
|
|
|
555
555
|
node tools/build-inline.mjs --langs=en,ru --no-branding # block without it
|
|
556
556
|
```
|
|
557
557
|
|
|
558
|
+
The line is `branding.poweredBy.text`; with `language: 'auto'` supply
|
|
559
|
+
`branding.poweredBy.texts` instead — `{ ru: '…', ro: '…', en: '…' }`, resolved
|
|
560
|
+
against the language the banner actually picked (`texts[lang]` → base code →
|
|
561
|
+
`texts.en` → `text`), so the attribution matches what the visitor is reading.
|
|
562
|
+
|
|
558
563
|
If you write the config by hand, simply omit the `branding` object; nothing
|
|
559
564
|
renders without it. Either way costs you ~200 bytes, not a licence: the client
|
|
560
565
|
is MIT and the line is yours to drop.
|
package/npm/internal-stub.mjs
CHANGED
|
@@ -28,7 +28,7 @@ export function undecidedState() {
|
|
|
28
28
|
*/
|
|
29
29
|
export function createStub() {
|
|
30
30
|
const stub = {
|
|
31
|
-
version: '0.5.
|
|
31
|
+
version: '0.5.6',
|
|
32
32
|
config: {},
|
|
33
33
|
init: function () { return undecidedState(); },
|
|
34
34
|
allowed: function (cat) { return cat === 'necessary'; },
|
package/package.json
CHANGED
package/src/ck-core.js
CHANGED
package/src/ck-locales.js
CHANGED
|
@@ -553,30 +553,30 @@
|
|
|
553
553
|
};
|
|
554
554
|
|
|
555
555
|
L.ro = {
|
|
556
|
-
bannerTitle: '
|
|
557
|
-
bannerText: 'Cookie-urile necesare mențin site-ul în funcțiune. Restul
|
|
556
|
+
bannerTitle: 'Cookie-uri pe acest site',
|
|
557
|
+
bannerText: 'Cookie-urile necesare mențin site-ul în funcțiune. Restul pornesc doar cu acordul dumneavoastră. Puteți schimba decizia oricând.',
|
|
558
558
|
more: 'Aflați mai multe',
|
|
559
559
|
acceptAll: 'Acceptă tot',
|
|
560
560
|
rejectAll: 'Respinge tot',
|
|
561
561
|
customize: 'Personalizează',
|
|
562
562
|
bannerLabel: 'Consimțământ pentru cookie-uri',
|
|
563
563
|
panelTitle: 'Setări cookie-uri',
|
|
564
|
-
panelIntro: 'Alegeți ce
|
|
564
|
+
panelIntro: 'Alegeți ce permiteți. Implicit este pornit doar strictul necesar.',
|
|
565
565
|
save: 'Salvează alegerea',
|
|
566
566
|
close: 'Închide',
|
|
567
567
|
alwaysOn: 'mereu active',
|
|
568
|
-
cookiesIn: '
|
|
568
|
+
cookiesIn: 'Ce cookie-uri',
|
|
569
569
|
noCookies: 'Nu au fost declarate cookie-uri pentru acest grup.',
|
|
570
|
-
colName: '
|
|
571
|
-
colVendor: '
|
|
572
|
-
colPurpose: '
|
|
570
|
+
colName: 'Denumire',
|
|
571
|
+
colVendor: 'Cine le pune',
|
|
572
|
+
colPurpose: 'Pentru ce',
|
|
573
573
|
colExpiry: 'Expiră',
|
|
574
574
|
floating: 'Setări cookie-uri',
|
|
575
575
|
cat: {
|
|
576
|
-
necessary: { title: 'Necesare', desc: 'Sunt necesare pentru funcționarea site-ului: autentificare, securitate, reținerea
|
|
577
|
-
functional: { title: 'Funcționale', desc: 'Rețin
|
|
578
|
-
analytics: { title: 'Analiză', desc: 'Ne
|
|
579
|
-
marketing: { title: 'Marketing', desc: '
|
|
576
|
+
necessary: { title: 'Necesare', desc: 'Sunt necesare pentru funcționarea site-ului: autentificare, securitate, reținerea alegerii dumneavoastră. Nu pot fi dezactivate.' },
|
|
577
|
+
functional: { title: 'Funcționale', desc: 'Rețin alegerile dumneavoastră: limba, coșul, chatul.' },
|
|
578
|
+
analytics: { title: 'Analiză', desc: 'Ne ajută să înțelegem ce merge bine pe site și ce nu.' },
|
|
579
|
+
marketing: { title: 'Marketing', desc: 'Potrivesc reclamele cu interesele dumneavoastră pe alte site-uri.' }
|
|
580
580
|
}
|
|
581
581
|
};
|
|
582
582
|
|
package/src/ck-ui-branding.js
CHANGED
|
@@ -348,6 +348,34 @@
|
|
|
348
348
|
return out.join('\n');
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
/* Pick the attribution line for the language the banner actually resolved to.
|
|
352
|
+
|
|
353
|
+
A SaaS server renders one config per site but cannot know the visitor's
|
|
354
|
+
language: with `language: 'auto'` the code that decides is ck-ui's
|
|
355
|
+
resolveLang(), in the browser, long after the config was serialised. So a
|
|
356
|
+
single `poweredBy.text` produced "Made by E-COM Consult" under a fully
|
|
357
|
+
Russian banner. `poweredBy.texts` lets the server send every line it has
|
|
358
|
+
and leaves the choice here, where the resolved language is known.
|
|
359
|
+
|
|
360
|
+
host.lang is the code ck-ui resolved ('ru', 'pt-br', ...). It is optional
|
|
361
|
+
on purpose: a page still running an older cached ck-ui.js passes no lang,
|
|
362
|
+
and that must degrade to the English/`text` line rather than throw. */
|
|
363
|
+
function pickPoweredByText(texts, lang, str) {
|
|
364
|
+
if (!texts || typeof texts !== 'object' || Array.isArray(texts)) return null;
|
|
365
|
+
var code = (typeof lang === 'string') ? lang.toLowerCase() : '';
|
|
366
|
+
// Own keys only. ck-ui's resolveLang() can only return a real locale key or
|
|
367
|
+
// 'en', so 'constructor' never arrives through the normal path — but `host`
|
|
368
|
+
// is caller-supplied on a published extension entry point, and reading an
|
|
369
|
+
// inherited key would hand str() a function instead of a missing line.
|
|
370
|
+
// Values go through str() as well, so anything non-string falls through.
|
|
371
|
+
function own(k) {
|
|
372
|
+
return (k && Object.prototype.hasOwnProperty.call(texts, k)) ? str(texts[k]) : null;
|
|
373
|
+
}
|
|
374
|
+
var hit = own(code);
|
|
375
|
+
if (!hit && code.length > 2) hit = own(code.slice(0, 2)); // ru-RU -> ru
|
|
376
|
+
return hit || own('en');
|
|
377
|
+
}
|
|
378
|
+
|
|
351
379
|
/* Powered-by line. true -> localised default; object -> caller's text/url.
|
|
352
380
|
Rendered after the actions in DOM order and styled quiet on purpose. */
|
|
353
381
|
function buildPoweredBy(cfg, host) {
|
|
@@ -361,7 +389,8 @@
|
|
|
361
389
|
if (pb === true) {
|
|
362
390
|
text = T.poweredBy; // en fallback guaranteed by STR_KEYS
|
|
363
391
|
} else if (typeof pb === 'object' && !Array.isArray(pb)) {
|
|
364
|
-
|
|
392
|
+
// texts[lang] -> texts[base] -> texts.en -> text -> T.poweredBy
|
|
393
|
+
text = pickPoweredByText(pb.texts, host.lang, str) || str(pb.text) || T.poweredBy;
|
|
365
394
|
url = safeLinkUrl(pb.url);
|
|
366
395
|
} else {
|
|
367
396
|
return null;
|
|
@@ -467,12 +496,26 @@
|
|
|
467
496
|
styling, so a config that gains a logo after the first ck:init has to
|
|
468
497
|
rebuild rather than restyle. Returns '-' when there is no branding config,
|
|
469
498
|
which is what keeps an unbranded page's signature stable. */
|
|
499
|
+
function textsSig(texts) {
|
|
500
|
+
if (!texts || typeof texts !== 'object' || Array.isArray(texts)) return '-';
|
|
501
|
+
var keys = [], k;
|
|
502
|
+
for (k in texts) {
|
|
503
|
+
if (Object.prototype.hasOwnProperty.call(texts, k) && str(texts[k])) keys.push(k);
|
|
504
|
+
}
|
|
505
|
+
keys.sort();
|
|
506
|
+
var out = [];
|
|
507
|
+
for (var i = 0; i < keys.length; i++) out.push(keys[i] + '=' + str(texts[keys[i]]));
|
|
508
|
+
return out.join(',');
|
|
509
|
+
}
|
|
510
|
+
|
|
470
511
|
function brandSignature(cfg) {
|
|
471
512
|
var b = brandingCfg(cfg);
|
|
472
513
|
if (!b) return '-';
|
|
473
514
|
var pb = b.poweredBy;
|
|
515
|
+
// texts is folded in with sorted keys so the signature is stable across key
|
|
516
|
+
// order — without it a server swapping only `texts` would not remount.
|
|
474
517
|
var pbSig = (pb && typeof pb === 'object')
|
|
475
|
-
? 'o:' + String(pb.text || '') + ':' + String(pb.url || '')
|
|
518
|
+
? 'o:' + String(pb.text || '') + ':' + String(pb.url || '') + ':' + textsSig(pb.texts)
|
|
476
519
|
: String(!!pb);
|
|
477
520
|
// Logos are hashed by length + head so a long data: URI does not bloat the key.
|
|
478
521
|
function tag(v) {
|
package/src/ck-ui.js
CHANGED
|
@@ -12,82 +12,82 @@
|
|
|
12
12
|
|
|
13
13
|
var DICT = {
|
|
14
14
|
en: {
|
|
15
|
-
bannerTitle: '
|
|
16
|
-
bannerText: 'Necessary cookies keep the site working.
|
|
15
|
+
bannerTitle: 'Cookies on this site',
|
|
16
|
+
bannerText: 'Necessary cookies keep the site working. The rest are used only if you allow them. You can change your choice at any time.',
|
|
17
17
|
more: 'Learn more',
|
|
18
18
|
acceptAll: 'Accept all',
|
|
19
19
|
rejectAll: 'Reject all',
|
|
20
20
|
customize: 'Customize',
|
|
21
21
|
bannerLabel: 'Cookie consent',
|
|
22
22
|
panelTitle: 'Cookie settings',
|
|
23
|
-
panelIntro: 'Choose
|
|
23
|
+
panelIntro: 'Choose what to allow. By default only the necessary ones are on.',
|
|
24
24
|
save: 'Save choices',
|
|
25
25
|
close: 'Close',
|
|
26
26
|
alwaysOn: 'always on',
|
|
27
|
-
cookiesIn: '
|
|
27
|
+
cookiesIn: 'Which cookies',
|
|
28
28
|
noCookies: 'No cookies declared for this group.',
|
|
29
29
|
colName: 'Name',
|
|
30
|
-
colVendor: '
|
|
31
|
-
colPurpose: '
|
|
30
|
+
colVendor: 'Who sets it',
|
|
31
|
+
colPurpose: 'What for',
|
|
32
32
|
colExpiry: 'Expires',
|
|
33
33
|
floating: 'Cookie settings',
|
|
34
34
|
poweredBy: 'Powered by ConsentKit',
|
|
35
35
|
cat: {
|
|
36
36
|
necessary: {
|
|
37
37
|
title: 'Necessary',
|
|
38
|
-
desc: 'Needed for the site to work
|
|
38
|
+
desc: 'Needed for the site to work: signing in, security, remembering your choice. They cannot be turned off.'
|
|
39
39
|
},
|
|
40
40
|
functional: {
|
|
41
41
|
title: 'Functional',
|
|
42
|
-
desc: 'Remember your
|
|
42
|
+
desc: 'Remember your choices: language, basket, chat.'
|
|
43
43
|
},
|
|
44
44
|
analytics: {
|
|
45
45
|
title: 'Analytics',
|
|
46
|
-
desc: 'Help us
|
|
46
|
+
desc: 'Help us understand what works well on the site and what does not.'
|
|
47
47
|
},
|
|
48
48
|
marketing: {
|
|
49
49
|
title: 'Marketing',
|
|
50
|
-
desc: '
|
|
50
|
+
desc: 'Match ads to your interests on other sites.'
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
ru: {
|
|
55
|
-
bannerTitle: '
|
|
56
|
-
bannerText: 'Необходимые cookie нужны, чтобы сайт работал.
|
|
55
|
+
bannerTitle: 'Cookie на этом сайте',
|
|
56
|
+
bannerText: 'Необходимые cookie нужны, чтобы сайт работал. Остальные включаются только с вашего согласия. Решение можно изменить в любой момент.',
|
|
57
57
|
more: 'Подробнее',
|
|
58
58
|
acceptAll: 'Принять всё',
|
|
59
59
|
rejectAll: 'Отклонить всё',
|
|
60
60
|
customize: 'Настроить',
|
|
61
61
|
bannerLabel: 'Согласие на cookie',
|
|
62
62
|
panelTitle: 'Настройки cookie',
|
|
63
|
-
panelIntro: 'Выберите,
|
|
63
|
+
panelIntro: 'Выберите, что разрешить. По умолчанию включено только необходимое.',
|
|
64
64
|
save: 'Сохранить выбор',
|
|
65
65
|
close: 'Закрыть',
|
|
66
66
|
alwaysOn: 'всегда активны',
|
|
67
|
-
cookiesIn: '
|
|
67
|
+
cookiesIn: 'Какие cookie',
|
|
68
68
|
noCookies: 'Для этой группы cookie не заявлены.',
|
|
69
|
-
colName: '
|
|
70
|
-
colVendor: '
|
|
71
|
-
colPurpose: '
|
|
69
|
+
colName: 'Название',
|
|
70
|
+
colVendor: 'Кто ставит',
|
|
71
|
+
colPurpose: 'Зачем',
|
|
72
72
|
colExpiry: 'Срок',
|
|
73
73
|
floating: 'Настройки cookie',
|
|
74
74
|
poweredBy: 'Работает на ConsentKit',
|
|
75
75
|
cat: {
|
|
76
76
|
necessary: {
|
|
77
77
|
title: 'Необходимые',
|
|
78
|
-
desc: '
|
|
78
|
+
desc: 'Нужны, чтобы сайт работал: вход, безопасность, память о вашем выборе. Отключить нельзя.'
|
|
79
79
|
},
|
|
80
80
|
functional: {
|
|
81
81
|
title: 'Функциональные',
|
|
82
|
-
desc: 'Запоминают
|
|
82
|
+
desc: 'Запоминают ваш выбор: язык, корзину, чат.'
|
|
83
83
|
},
|
|
84
84
|
analytics: {
|
|
85
85
|
title: 'Аналитика',
|
|
86
|
-
desc: '
|
|
86
|
+
desc: 'Помогают нам понять, что на сайте удобно, а что нет.'
|
|
87
87
|
},
|
|
88
88
|
marketing: {
|
|
89
89
|
title: 'Маркетинг',
|
|
90
|
-
desc: '
|
|
90
|
+
desc: 'Подбирают рекламу под ваши интересы на других сайтах.'
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -370,8 +370,12 @@
|
|
|
370
370
|
return (b && typeof b === 'object') ? b : null;
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
/* LANG travels with T: an extension that renders language-dependent text of
|
|
374
|
+
its own (branding.poweredBy.texts) needs the code the banner resolved to,
|
|
375
|
+
which only this file knows — the config may say 'auto' and the answer then
|
|
376
|
+
comes from the visitor's browser at mount time. */
|
|
373
377
|
function extHost() {
|
|
374
|
-
return { el: el, str: str, T: T };
|
|
378
|
+
return { el: el, str: str, T: T, lang: LANG };
|
|
375
379
|
}
|
|
376
380
|
|
|
377
381
|
function buildBrandLogo(cfg) {
|
|
@@ -427,6 +431,7 @@
|
|
|
427
431
|
var mountedSig = null;
|
|
428
432
|
var host = null, root = null;
|
|
429
433
|
var T = DICT.en;
|
|
434
|
+
var LANG = 'en'; // the code T was built from, reassigned per mount
|
|
430
435
|
var nodes = {}; // banner/panel/fab refs
|
|
431
436
|
var switches = {}; // category -> button
|
|
432
437
|
var panelOpen = false;
|
|
@@ -1649,7 +1654,8 @@
|
|
|
1649
1654
|
}
|
|
1650
1655
|
|
|
1651
1656
|
var table = localeTable(); // read at render time
|
|
1652
|
-
|
|
1657
|
+
LANG = resolveLang(cfg && cfg.language, table);
|
|
1658
|
+
T = buildStrings(LANG, table);
|
|
1653
1659
|
|
|
1654
1660
|
host = document.getElementById('ck-root');
|
|
1655
1661
|
if (!host) {
|