@financial-times/cmp-client 2.0.4 → 2.0.5-beta.2

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.
Files changed (46) hide show
  1. package/dist/client.d.ts +3 -63
  2. package/dist/client.d.ts.map +1 -0
  3. package/dist/consent-ready/index.d.ts +5 -0
  4. package/dist/consent-ready/index.d.ts.map +1 -0
  5. package/dist/consent-ready/utils/__fixtures__/strings.d.ts +9 -0
  6. package/dist/consent-ready/utils/__fixtures__/strings.d.ts.map +1 -0
  7. package/dist/consent-ready/utils/__tests__/check-consent.test.d.ts +2 -0
  8. package/dist/consent-ready/utils/__tests__/check-consent.test.d.ts.map +1 -0
  9. package/dist/consent-ready/utils/__tests__/get-parsed-consent.test.d.ts +2 -0
  10. package/dist/consent-ready/utils/__tests__/get-parsed-consent.test.d.ts.map +1 -0
  11. package/dist/consent-ready/utils/__tests__/validators.test.d.ts +2 -0
  12. package/dist/consent-ready/utils/__tests__/validators.test.d.ts.map +1 -0
  13. package/dist/consent-ready/utils/get-consent-payload.d.ts +18 -0
  14. package/dist/consent-ready/utils/get-consent-payload.d.ts.map +1 -0
  15. package/dist/consent-ready/utils/get-parsed-consent.d.ts +14 -0
  16. package/dist/consent-ready/utils/get-parsed-consent.d.ts.map +1 -0
  17. package/dist/consent-ready/utils/has-consent-changed.d.ts +3 -0
  18. package/dist/consent-ready/utils/has-consent-changed.d.ts.map +1 -0
  19. package/dist/consent-ready/utils/validators.d.ts +16 -0
  20. package/dist/consent-ready/utils/validators.d.ts.map +1 -0
  21. package/dist/html/__tests__/cmp-footer-links.test.d.ts +2 -0
  22. package/dist/html/__tests__/cmp-footer-links.test.d.ts.map +1 -0
  23. package/dist/html/cmp-footer-link.d.ts +8 -0
  24. package/dist/html/cmp-footer-link.d.ts.map +1 -0
  25. package/dist/html/cmp-scripts.d.ts +16 -0
  26. package/dist/html/cmp-scripts.d.ts.map +1 -0
  27. package/dist/{client.cjs → index.cjs} +409 -158
  28. package/dist/index.d.ts +6 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/{client.js → index.js} +408 -157
  31. package/dist/lib/constants.d.ts +13 -0
  32. package/dist/lib/constants.d.ts.map +1 -0
  33. package/dist/{debug.d.ts → lib/debug.d.ts} +12 -13
  34. package/dist/lib/debug.d.ts.map +1 -0
  35. package/dist/{properties.d.ts → lib/properties.d.ts} +17 -19
  36. package/dist/lib/properties.d.ts.map +1 -0
  37. package/dist/utils/dom.d.ts +3 -0
  38. package/dist/utils/dom.d.ts.map +1 -0
  39. package/package.json +20 -30
  40. package/typings/globals.d.ts +20 -0
  41. package/typings/modules.d.ts +1 -0
  42. package/typings/types.d.ts +88 -0
  43. package/dist/debug.cjs +0 -32
  44. package/dist/debug.js +0 -32
  45. package/dist/properties.cjs +0 -21
  46. package/dist/properties.js +0 -21
@@ -1,4 +1,10 @@
1
- import { FT_DOTCOM_PROD } from "./properties.js";
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
2
8
  const request = (url, { credentials = "omit" } = {}) => {
3
9
  return fetch(`https://session-next.ft.com${url}`, {
4
10
  credentials,
@@ -69,10 +75,68 @@ const getUuid = () => {
69
75
  }
70
76
  return requests.uuid;
71
77
  };
78
+ const SOURCEPOINT_CONSENT_SOURCE = "sourcepoint-cmp";
79
+ const SOURCEPOINT_FOW_SCOPE = "FTPINK";
80
+ const CONSENT_COOKIE_NAME = "FTConsent";
81
+ const SOURCEPOINT_FOW_ID = "sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk";
82
+ const FT_COOKIE_DOMAIN = ".ft.com";
83
+ const FT_CONSENT_PROXY_HOST = "https://consent.ft.com";
84
+ const legislation = {
85
+ CCPA: "ccpa",
86
+ GDPR: "gdpr"
87
+ };
88
+ const iabCustomCategories = {
89
+ permutiveAds: {
90
+ purposes: [2, 4, 8, 9],
91
+ iabVendors: [361],
92
+ customVendors: [],
93
+ specialFeatures: []
94
+ },
95
+ demographicAds: {
96
+ purposes: [3, 4, 7, 9, 10],
97
+ iabVendors: [],
98
+ customVendors: [],
99
+ specialFeatures: []
100
+ }
101
+ };
102
+ const defaults = {
103
+ joinHref: true,
104
+ gdpr: {},
105
+ ccpa: {}
106
+ };
107
+ const FT_DOTCOM_LOCAL = {
108
+ ...defaults,
109
+ accountId: 1906,
110
+ baseEndpoint: "https://cdn.privacy-mgmt.com",
111
+ propertyHref: "https://local.ft.com"
112
+ };
113
+ const FT_DOTCOM_PROD = {
114
+ ...defaults,
115
+ accountId: 1906,
116
+ baseEndpoint: "https://cdn.privacy-mgmt.com",
117
+ propertyId: 31642
118
+ };
119
+ const properties = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
120
+ __proto__: null,
121
+ FT_DOTCOM_LOCAL,
122
+ FT_DOTCOM_PROD
123
+ }, Symbol.toStringTag, { value: "Module" }));
124
+ function createContentScript(content) {
125
+ const s = document.createElement("script");
126
+ s.innerHTML = content;
127
+ return s;
128
+ }
129
+ function createSourceScript(src) {
130
+ const s = document.createElement("script");
131
+ s.src = src;
132
+ return s;
133
+ }
72
134
  function encodeConfig(obj) {
73
135
  let str = "";
136
+ if (!obj)
137
+ return str;
74
138
  for (const [key, val] of Object.entries(obj)) {
75
- switch (typeof obj[key]) {
139
+ switch (typeof val) {
76
140
  case "function":
77
141
  str += `${key}:${val.toString().replace(/"/g, "'").replace(/\s/g, "")},`;
78
142
  break;
@@ -100,13 +164,42 @@ const scriptContent = {
100
164
  tcfStub: `"use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){var t=function(){var t,e,o=[],n=window,r=n;for(;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=r.parent}t||(!function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"setGdprApplies"===n[0]?n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)&&null!==o?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=t:t()}();`,
101
165
  uspStub: `"use strict";(function () { var e = false; var c = window; var t = document; function r() { if (!c.frames["__uspapiLocator"]) { if (t.body) { var a = t.body; var e = t.createElement("iframe"); e.style.cssText = "display:none"; e.name = "__uspapiLocator"; a.appendChild(e) } else { setTimeout(r, 5) } } } r(); function p() { var a = arguments; __uspapi.a = __uspapi.a || []; if (!a.length) { return __uspapi.a } else if (a[0] === "ping") { a[2]({ gdprAppliesGlobally: e, cmpLoaded: false }, true) } else { __uspapi.a.push([].slice.apply(a)) } } function l(t) { var r = typeof t.data === "string"; try { var a = r ? JSON.parse(t.data) : t.data; if (a.__cmpCall) { var n = a.__cmpCall; c.__uspapi(n.command, n.parameter, function (a, e) { var c = { __cmpReturn: { returnValue: a, success: e, callId: n.callId } }; t.source.postMessage(r ? JSON.stringify(c) : c, "*") }) } } catch (a) { } } if (typeof __uspapi !== "function") { c.__uspapi = p; __uspapi.msgHandler = l; c.addEventListener("message", l, false) } })();`
102
166
  };
103
- var __defProp = Object.defineProperty;
104
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
105
- var __publicField = (obj, key, value) => {
106
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
107
- return value;
108
- };
109
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
167
+ function getCmpScripts(config) {
168
+ const fragment = document.createDocumentFragment();
169
+ fragment.appendChild(createContentScript(scriptContent.tcfStub));
170
+ fragment.appendChild(createContentScript(scriptContent.uspStub));
171
+ fragment.appendChild(createContentScript(scriptContent.getSPConfig(config)));
172
+ fragment.appendChild(createSourceScript(scriptSources.cmpFrames));
173
+ return fragment;
174
+ }
175
+ function getConsentPayload(parsedConsent, { shouldUpdateConsentStore, formOfWordsId, cookieDomain }) {
176
+ const categoryNames = Object.keys(parsedConsent);
177
+ const data = categoryNames.reduce(
178
+ (payload, categoryName) => {
179
+ payload[categoryName] = {
180
+ onsite: {
181
+ status: parsedConsent[categoryName],
182
+ lbi: false,
183
+ source: SOURCEPOINT_CONSENT_SOURCE,
184
+ fow: formOfWordsId
185
+ }
186
+ };
187
+ return payload;
188
+ },
189
+ {}
190
+ );
191
+ if (!shouldUpdateConsentStore) {
192
+ return { data };
193
+ } else {
194
+ return {
195
+ setConsentCookie: true,
196
+ formOfWordsId,
197
+ consentSource: SOURCEPOINT_CONSENT_SOURCE,
198
+ cookieDomain,
199
+ data
200
+ };
201
+ }
202
+ }
110
203
  class DecodingError extends Error {
111
204
  /**
112
205
  * constructor - constructs an DecodingError
@@ -195,6 +288,10 @@ class Base64Url {
195
288
  return result;
196
289
  }
197
290
  }
291
+ /**
292
+ * Base 64 URL character set. Different from standard Base64 char set
293
+ * in that '+' and '/' are replaced with '-' and '_'.
294
+ */
198
295
  __publicField(Base64Url, "DICT", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
199
296
  __publicField(Base64Url, "REVERSE_DICT", /* @__PURE__ */ new Map([
200
297
  ["A", 0],
@@ -262,26 +359,29 @@ __publicField(Base64Url, "REVERSE_DICT", /* @__PURE__ */ new Map([
262
359
  ["-", 62],
263
360
  ["_", 63]
264
361
  ]));
362
+ /**
363
+ * log2(64) = 6
364
+ */
265
365
  __publicField(Base64Url, "BASIS", 6);
266
366
  __publicField(Base64Url, "LCM", 24);
267
- const _ConsentLanguages = class _ConsentLanguages2 {
367
+ const _ConsentLanguages = class _ConsentLanguages {
268
368
  has(key) {
269
- return _ConsentLanguages2.langSet.has(key);
369
+ return _ConsentLanguages.langSet.has(key);
270
370
  }
271
371
  parseLanguage(lang) {
272
372
  lang = lang.toUpperCase();
273
373
  const primaryLanguage = lang.split("-")[0];
274
374
  if (lang.length >= 2 && primaryLanguage.length == 2) {
275
- if (_ConsentLanguages2.langSet.has(lang)) {
375
+ if (_ConsentLanguages.langSet.has(lang)) {
276
376
  return lang;
277
- } else if (_ConsentLanguages2.langSet.has(primaryLanguage)) {
377
+ } else if (_ConsentLanguages.langSet.has(primaryLanguage)) {
278
378
  return primaryLanguage;
279
379
  }
280
380
  const fullPrimaryLang = primaryLanguage + "-" + primaryLanguage;
281
- if (_ConsentLanguages2.langSet.has(fullPrimaryLang)) {
381
+ if (_ConsentLanguages.langSet.has(fullPrimaryLang)) {
282
382
  return fullPrimaryLang;
283
383
  }
284
- for (const supportedLang of _ConsentLanguages2.langSet) {
384
+ for (const supportedLang of _ConsentLanguages.langSet) {
285
385
  if (supportedLang.indexOf(lang) !== -1 || supportedLang.indexOf(primaryLanguage) !== -1) {
286
386
  return supportedLang;
287
387
  }
@@ -290,10 +390,10 @@ const _ConsentLanguages = class _ConsentLanguages2 {
290
390
  throw new Error(`unsupported language ${lang}`);
291
391
  }
292
392
  forEach(callback) {
293
- _ConsentLanguages2.langSet.forEach(callback);
393
+ _ConsentLanguages.langSet.forEach(callback);
294
394
  }
295
395
  get size() {
296
- return _ConsentLanguages2.langSet.size;
396
+ return _ConsentLanguages.langSet.size;
297
397
  }
298
398
  };
299
399
  __publicField(_ConsentLanguages, "langSet", /* @__PURE__ */ new Set([
@@ -424,7 +524,7 @@ var RestrictionType;
424
524
  RestrictionType2[RestrictionType2["REQUIRE_CONSENT"] = 1] = "REQUIRE_CONSENT";
425
525
  RestrictionType2[RestrictionType2["REQUIRE_LI"] = 2] = "REQUIRE_LI";
426
526
  })(RestrictionType || (RestrictionType = {}));
427
- const _PurposeRestriction = class _PurposeRestriction2 extends Cloneable {
527
+ const _PurposeRestriction = class _PurposeRestriction extends Cloneable {
428
528
  /**
429
529
  * constructor
430
530
  *
@@ -447,7 +547,7 @@ const _PurposeRestriction = class _PurposeRestriction2 extends Cloneable {
447
547
  }
448
548
  static unHash(hash) {
449
549
  const splitUp = hash.split(this.hashSeparator);
450
- const purpRestriction = new _PurposeRestriction2();
550
+ const purpRestriction = new _PurposeRestriction();
451
551
  if (splitUp.length !== 2) {
452
552
  throw new TCModelError("hash", hash);
453
553
  }
@@ -459,7 +559,7 @@ const _PurposeRestriction = class _PurposeRestriction2 extends Cloneable {
459
559
  if (!this.isValid()) {
460
560
  throw new Error("cannot hash invalid PurposeRestriction");
461
561
  }
462
- return `${this.purposeId}${_PurposeRestriction2.hashSeparator}${this.restrictionType}`;
562
+ return `${this.purposeId}${_PurposeRestriction.hashSeparator}${this.restrictionType}`;
463
563
  }
464
564
  /**
465
565
  * @return {number} The purpose Id associated with a publisher
@@ -489,7 +589,15 @@ let PurposeRestriction = _PurposeRestriction;
489
589
  class PurposeRestrictionVector extends Cloneable {
490
590
  constructor() {
491
591
  super(...arguments);
592
+ /**
593
+ * if this originatd from an encoded string we'll need a place to store the
594
+ * bit length; it can be set and got from here
595
+ */
492
596
  __publicField(this, "bitLength", 0);
597
+ /**
598
+ * a map indexed by a string which will be a 'hash' of the purpose and
599
+ * restriction type.
600
+ */
493
601
  __publicField(this, "map", /* @__PURE__ */ new Map());
494
602
  __publicField(this, "gvl_");
495
603
  }
@@ -726,6 +834,12 @@ var Segment;
726
834
  })(Segment || (Segment = {}));
727
835
  class SegmentIDs {
728
836
  }
837
+ /**
838
+ * 0 = default - reserved for core string (does not need to be present in the core string)
839
+ * 1 = OOB vendors disclosed
840
+ * 2 = OOB vendors allowed
841
+ * 3 = PublisherTC
842
+ */
729
843
  __publicField(SegmentIDs, "ID_TO_KEY", [
730
844
  Segment.CORE,
731
845
  Segment.VENDORS_DISCLOSED,
@@ -741,6 +855,10 @@ __publicField(SegmentIDs, "KEY_TO_ID", {
741
855
  class Vector extends Cloneable {
742
856
  constructor() {
743
857
  super(...arguments);
858
+ /**
859
+ * if this originatd from an encoded string we'll need a place to store the
860
+ * bit length; it can be set and got from here
861
+ */
744
862
  __publicField(this, "bitLength", 0);
745
863
  __publicField(this, "maxId_", 0);
746
864
  __publicField(this, "set_", /* @__PURE__ */ new Set());
@@ -1484,7 +1602,7 @@ class Json {
1484
1602
  return this.absCall(url, null, sendCookies, timeout);
1485
1603
  }
1486
1604
  }
1487
- const _GVL = class _GVL2 extends Cloneable {
1605
+ const _GVL = class _GVL extends Cloneable {
1488
1606
  /**
1489
1607
  * @param {VersionOrVendorList} [versionOrVendorList] - can be either a
1490
1608
  * [[VendorList]] object or a version number represented as a string or
@@ -1493,31 +1611,94 @@ const _GVL = class _GVL2 extends Cloneable {
1493
1611
  */
1494
1612
  constructor(versionOrVendorList) {
1495
1613
  super();
1614
+ /**
1615
+ * @param {Promise} resolved when this GVL object is populated with the data
1616
+ * or rejected if there is an error.
1617
+ */
1496
1618
  __publicField(this, "readyPromise");
1619
+ /**
1620
+ * @param {number} gvlSpecificationVersion - schema version for the GVL that is used
1621
+ */
1497
1622
  __publicField(this, "gvlSpecificationVersion");
1623
+ /**
1624
+ * @param {number} incremented with each published file change
1625
+ */
1498
1626
  __publicField(this, "vendorListVersion");
1627
+ /**
1628
+ * @param {number} tcfPolicyVersion - The TCF MO will increment this value
1629
+ * whenever a GVL change (such as adding a new Purpose or Feature or a change
1630
+ * in Purpose wording) legally invalidates existing TC Strings and requires
1631
+ * CMPs to re-establish transparency and consent from users. If the policy
1632
+ * version number in the latest GVL is different from the value in your TC
1633
+ * String, then you need to re-establish transparency and consent for that
1634
+ * user. A version 1 format TC String is considered to have a version value
1635
+ * of 1.
1636
+ */
1499
1637
  __publicField(this, "tcfPolicyVersion");
1638
+ /**
1639
+ * @param {string | Date} lastUpdated - the date in which the vendor list
1640
+ * json file was last updated.
1641
+ */
1500
1642
  __publicField(this, "lastUpdated");
1643
+ /**
1644
+ * @param {IntMap<Purpose>} a collection of [[Purpose]]s
1645
+ */
1501
1646
  __publicField(this, "purposes");
1647
+ /**
1648
+ * @param {IntMap<Purpose>} a collection of [[Purpose]]s
1649
+ */
1502
1650
  __publicField(this, "specialPurposes");
1651
+ /**
1652
+ * @param {IntMap<Feature>} a collection of [[Feature]]s
1653
+ */
1503
1654
  __publicField(this, "features");
1655
+ /**
1656
+ * @param {IntMap<Feature>} a collection of [[Feature]]s
1657
+ */
1504
1658
  __publicField(this, "specialFeatures");
1659
+ /**
1660
+ * @param {boolean} internal reference of when the GVL is ready to be used
1661
+ */
1505
1662
  __publicField(this, "isReady_", false);
1663
+ /**
1664
+ * @param {IntMap<Vendor>} a collection of [[Vendor]]s
1665
+ */
1506
1666
  __publicField(this, "vendors_");
1507
1667
  __publicField(this, "vendorIds");
1668
+ /**
1669
+ * @param {IntMap<Vendor>} a collection of [[Vendor]]. Used as a backup if a whitelist is sets
1670
+ */
1508
1671
  __publicField(this, "fullVendorList");
1672
+ /**
1673
+ * @param {ByPurposeVendorMap} vendors by purpose
1674
+ */
1509
1675
  __publicField(this, "byPurposeVendorMap");
1676
+ /**
1677
+ * @param {IDSetMap} vendors by special purpose
1678
+ */
1510
1679
  __publicField(this, "bySpecialPurposeVendorMap");
1680
+ /**
1681
+ * @param {IDSetMap} vendors by feature
1682
+ */
1511
1683
  __publicField(this, "byFeatureVendorMap");
1684
+ /**
1685
+ * @param {IDSetMap} vendors by special feature
1686
+ */
1512
1687
  __publicField(this, "bySpecialFeatureVendorMap");
1688
+ /**
1689
+ * @param {IntMap<Stack>} a collection of [[Stack]]s
1690
+ */
1513
1691
  __publicField(this, "stacks");
1692
+ /**
1693
+ * @param {IntMap<DataCategory>} a collection of [[DataCategory]]s
1694
+ */
1514
1695
  __publicField(this, "dataCategories");
1515
1696
  __publicField(this, "lang_");
1516
1697
  __publicField(this, "cacheLang_");
1517
1698
  __publicField(this, "isLatest", false);
1518
- let url = _GVL2.baseUrl;
1519
- this.lang_ = _GVL2.DEFAULT_LANGUAGE;
1520
- this.cacheLang_ = _GVL2.DEFAULT_LANGUAGE;
1699
+ let url = _GVL.baseUrl;
1700
+ this.lang_ = _GVL.DEFAULT_LANGUAGE;
1701
+ this.cacheLang_ = _GVL.DEFAULT_LANGUAGE;
1521
1702
  if (this.isVendorList(versionOrVendorList)) {
1522
1703
  this.populate(versionOrVendorList);
1523
1704
  this.readyPromise = Promise.resolve();
@@ -1527,20 +1708,20 @@ const _GVL = class _GVL2 extends Cloneable {
1527
1708
  }
1528
1709
  if (versionOrVendorList > 0) {
1529
1710
  const version = versionOrVendorList;
1530
- if (_GVL2.CACHE.has(version)) {
1531
- this.populate(_GVL2.CACHE.get(version));
1711
+ if (_GVL.CACHE.has(version)) {
1712
+ this.populate(_GVL.CACHE.get(version));
1532
1713
  this.readyPromise = Promise.resolve();
1533
1714
  } else {
1534
- url += _GVL2.versionedFilename.replace("[VERSION]", String(version));
1715
+ url += _GVL.versionedFilename.replace("[VERSION]", String(version));
1535
1716
  this.readyPromise = this.fetchJson(url);
1536
1717
  }
1537
1718
  } else {
1538
- if (_GVL2.CACHE.has(_GVL2.LATEST_CACHE_KEY)) {
1539
- this.populate(_GVL2.CACHE.get(_GVL2.LATEST_CACHE_KEY));
1719
+ if (_GVL.CACHE.has(_GVL.LATEST_CACHE_KEY)) {
1720
+ this.populate(_GVL.CACHE.get(_GVL.LATEST_CACHE_KEY));
1540
1721
  this.readyPromise = Promise.resolve();
1541
1722
  } else {
1542
1723
  this.isLatest = true;
1543
- this.readyPromise = this.fetchJson(url + _GVL2.latestFilename);
1724
+ this.readyPromise = this.fetchJson(url + _GVL.latestFilename);
1544
1725
  }
1545
1726
  }
1546
1727
  }
@@ -1597,11 +1778,11 @@ const _GVL = class _GVL2 extends Cloneable {
1597
1778
  */
1598
1779
  static emptyLanguageCache(lang) {
1599
1780
  let result = false;
1600
- if (lang == null && _GVL2.LANGUAGE_CACHE.size > 0) {
1601
- _GVL2.LANGUAGE_CACHE = /* @__PURE__ */ new Map();
1781
+ if (lang == null && _GVL.LANGUAGE_CACHE.size > 0) {
1782
+ _GVL.LANGUAGE_CACHE = /* @__PURE__ */ new Map();
1602
1783
  result = true;
1603
1784
  } else if (typeof lang === "string" && this.consentLanguages.has(lang.toUpperCase())) {
1604
- _GVL2.LANGUAGE_CACHE.delete(lang.toUpperCase());
1785
+ _GVL.LANGUAGE_CACHE.delete(lang.toUpperCase());
1605
1786
  result = true;
1606
1787
  }
1607
1788
  return result;
@@ -1616,17 +1797,17 @@ const _GVL = class _GVL2 extends Cloneable {
1616
1797
  static emptyCache(vendorListVersion) {
1617
1798
  let retr = false;
1618
1799
  if (Number.isInteger(vendorListVersion) && vendorListVersion >= 0) {
1619
- _GVL2.CACHE.delete(vendorListVersion);
1800
+ _GVL.CACHE.delete(vendorListVersion);
1620
1801
  retr = true;
1621
1802
  } else if (vendorListVersion === void 0) {
1622
- _GVL2.CACHE = /* @__PURE__ */ new Map();
1803
+ _GVL.CACHE = /* @__PURE__ */ new Map();
1623
1804
  retr = true;
1624
1805
  }
1625
1806
  return retr;
1626
1807
  }
1627
1808
  cacheLanguage() {
1628
- if (!_GVL2.LANGUAGE_CACHE.has(this.cacheLang_)) {
1629
- _GVL2.LANGUAGE_CACHE.set(this.cacheLang_, {
1809
+ if (!_GVL.LANGUAGE_CACHE.has(this.cacheLang_)) {
1810
+ _GVL.LANGUAGE_CACHE.set(this.cacheLang_, {
1630
1811
  purposes: this.purposes,
1631
1812
  specialPurposes: this.specialPurposes,
1632
1813
  features: this.features,
@@ -1676,25 +1857,25 @@ const _GVL = class _GVL2 extends Cloneable {
1676
1857
  async changeLanguage(lang) {
1677
1858
  let parsedLanguage = lang;
1678
1859
  try {
1679
- parsedLanguage = _GVL2.consentLanguages.parseLanguage(lang);
1860
+ parsedLanguage = _GVL.consentLanguages.parseLanguage(lang);
1680
1861
  } catch (e) {
1681
1862
  throw new GVLError("Error during parsing the language: " + e.message);
1682
1863
  }
1683
1864
  const cacheLang = lang.toUpperCase();
1684
- if (parsedLanguage.toLowerCase() === _GVL2.DEFAULT_LANGUAGE.toLowerCase() && !_GVL2.LANGUAGE_CACHE.has(cacheLang)) {
1865
+ if (parsedLanguage.toLowerCase() === _GVL.DEFAULT_LANGUAGE.toLowerCase() && !_GVL.LANGUAGE_CACHE.has(cacheLang)) {
1685
1866
  return;
1686
1867
  }
1687
1868
  if (parsedLanguage !== this.lang_) {
1688
1869
  this.lang_ = parsedLanguage;
1689
- if (_GVL2.LANGUAGE_CACHE.has(cacheLang)) {
1690
- const cached = _GVL2.LANGUAGE_CACHE.get(cacheLang);
1870
+ if (_GVL.LANGUAGE_CACHE.has(cacheLang)) {
1871
+ const cached = _GVL.LANGUAGE_CACHE.get(cacheLang);
1691
1872
  for (const prop in cached) {
1692
1873
  if (cached.hasOwnProperty(prop)) {
1693
1874
  this[prop] = cached[prop];
1694
1875
  }
1695
1876
  }
1696
1877
  } else {
1697
- const url = _GVL2.baseUrl + _GVL2.languageFilename.replace("[LANG]", this.lang_.toLowerCase());
1878
+ const url = _GVL.baseUrl + _GVL.languageFilename.replace("[LANG]", this.lang_.toLowerCase());
1698
1879
  try {
1699
1880
  await this.fetchJson(url);
1700
1881
  this.cacheLang_ = cacheLang;
@@ -1731,10 +1912,10 @@ const _GVL = class _GVL2 extends Cloneable {
1731
1912
  this.mapVendors();
1732
1913
  this.isReady_ = true;
1733
1914
  if (this.isLatest) {
1734
- _GVL2.CACHE.set(_GVL2.LATEST_CACHE_KEY, this.getJson());
1915
+ _GVL.CACHE.set(_GVL.LATEST_CACHE_KEY, this.getJson());
1735
1916
  }
1736
- if (!_GVL2.CACHE.has(this.vendorListVersion)) {
1737
- _GVL2.CACHE.set(this.vendorListVersion, this.getJson());
1917
+ if (!_GVL.CACHE.has(this.vendorListVersion)) {
1918
+ _GVL.CACHE.set(this.vendorListVersion, this.getJson());
1738
1919
  }
1739
1920
  }
1740
1921
  this.cacheLanguage();
@@ -1897,8 +2078,8 @@ const _GVL = class _GVL2 extends Cloneable {
1897
2078
  * @return {GVL}
1898
2079
  */
1899
2080
  clone() {
1900
- const result = new _GVL2(this.getJson());
1901
- if (this.lang_ !== _GVL2.DEFAULT_LANGUAGE) {
2081
+ const result = new _GVL(this.getJson());
2082
+ if (this.lang_ !== _GVL.DEFAULT_LANGUAGE) {
1902
2083
  result.changeLanguage(this.lang_);
1903
2084
  }
1904
2085
  return result;
@@ -1912,10 +2093,47 @@ __publicField(_GVL, "LANGUAGE_CACHE", /* @__PURE__ */ new Map());
1912
2093
  __publicField(_GVL, "CACHE", /* @__PURE__ */ new Map());
1913
2094
  __publicField(_GVL, "LATEST_CACHE_KEY", 0);
1914
2095
  __publicField(_GVL, "DEFAULT_LANGUAGE", "EN");
2096
+ /**
2097
+ * Set of available consent languages published by the IAB
2098
+ */
1915
2099
  __publicField(_GVL, "consentLanguages", new ConsentLanguages());
1916
2100
  __publicField(_GVL, "baseUrl_");
2101
+ /**
2102
+ * @static
2103
+ * @param {string} - the latest is assumed to be vendor-list.json because
2104
+ * that is what the iab uses, but it could be different... if you want
2105
+ */
1917
2106
  __publicField(_GVL, "latestFilename", "vendor-list.json");
2107
+ /**
2108
+ * @static
2109
+ * @param {string} - the versioned name is assumed to be
2110
+ * vendor-list-v[VERSION].json where [VERSION] will be replaced with the
2111
+ * specified version. But it could be different... if you want just make
2112
+ * sure to include the [VERSION] macro if you have a numbering scheme, it's a
2113
+ * simple string substitution.
2114
+ *
2115
+ * eg.
2116
+ * ```javascript
2117
+ * GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
2118
+ * GVL.versionedFilename = "vendorlist?getVersion=[VERSION]";
2119
+ * ```
2120
+ */
1918
2121
  __publicField(_GVL, "versionedFilename", "archives/vendor-list-v[VERSION].json");
2122
+ /**
2123
+ * @param {string} - Translations of the names and descriptions for Purposes,
2124
+ * Special Purposes, Features, and Special Features to non-English languages
2125
+ * are contained in a file where attributes containing English content
2126
+ * (except vendor declaration information) are translated. The iab publishes
2127
+ * one following the scheme below where the LANG is the iso639-1 language
2128
+ * code. For a list of available translations
2129
+ * [please go here](https://register.consensu.org/Translation).
2130
+ *
2131
+ * eg.
2132
+ * ```javascript
2133
+ * GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
2134
+ * GVL.languageFilename = "purposes?getPurposes=[LANG]";
2135
+ * ```
2136
+ */
1919
2137
  __publicField(_GVL, "languageFilename", "purposes-[LANG].json");
1920
2138
  let GVL = _GVL;
1921
2139
  class TCModel extends Cloneable {
@@ -1941,20 +2159,83 @@ class TCModel extends Cloneable {
1941
2159
  __publicField(this, "cmpVersion_", 0);
1942
2160
  __publicField(this, "vendorListVersion_", 0);
1943
2161
  __publicField(this, "numCustomPurposes_", 0);
2162
+ // Member Variable for GVL
1944
2163
  __publicField(this, "gvl_");
1945
2164
  __publicField(this, "created");
1946
2165
  __publicField(this, "lastUpdated");
2166
+ /**
2167
+ * The TCF designates certain Features as special, that is, a CMP must afford
2168
+ * the user a means to opt in to their use. These Special Features are
2169
+ * published and numbered in the GVL separately from normal Features.
2170
+ * Provides for up to 12 special features.
2171
+ */
1947
2172
  __publicField(this, "specialFeatureOptins", new Vector());
2173
+ /**
2174
+ * Renamed from `PurposesAllowed` in TCF v1.1
2175
+ * The user’s consent value for each Purpose established on the legal basis
2176
+ * of consent. Purposes are published in the Global Vendor List (see. [[GVL]]).
2177
+ */
1948
2178
  __publicField(this, "purposeConsents", new Vector());
2179
+ /**
2180
+ * The user’s permission for each Purpose established on the legal basis of
2181
+ * legitimate interest. If the user has exercised right-to-object for a
2182
+ * purpose.
2183
+ */
1949
2184
  __publicField(this, "purposeLegitimateInterests", new Vector());
2185
+ /**
2186
+ * The user’s consent value for each Purpose established on the legal basis
2187
+ * of consent, for the publisher. Purposes are published in the Global
2188
+ * Vendor List.
2189
+ */
1950
2190
  __publicField(this, "publisherConsents", new Vector());
2191
+ /**
2192
+ * The user’s permission for each Purpose established on the legal basis of
2193
+ * legitimate interest. If the user has exercised right-to-object for a
2194
+ * purpose.
2195
+ */
1951
2196
  __publicField(this, "publisherLegitimateInterests", new Vector());
2197
+ /**
2198
+ * The user’s consent value for each Purpose established on the legal basis
2199
+ * of consent, for the publisher. Purposes are published in the Global
2200
+ * Vendor List.
2201
+ */
1952
2202
  __publicField(this, "publisherCustomConsents", new Vector());
2203
+ /**
2204
+ * The user’s permission for each Purpose established on the legal basis of
2205
+ * legitimate interest. If the user has exercised right-to-object for a
2206
+ * purpose that is established in the publisher's custom purposes.
2207
+ */
1953
2208
  __publicField(this, "publisherCustomLegitimateInterests", new Vector());
2209
+ /**
2210
+ * set by a publisher if they wish to collect consent and LI Transparency for
2211
+ * purposes outside of the TCF
2212
+ */
1954
2213
  __publicField(this, "customPurposes");
2214
+ /**
2215
+ * Each [[Vendor]] is keyed by id. Their consent value is true if it is in
2216
+ * the Vector
2217
+ */
1955
2218
  __publicField(this, "vendorConsents", new Vector());
2219
+ /**
2220
+ * Each [[Vendor]] is keyed by id. Whether their Legitimate Interests
2221
+ * Disclosures have been established is stored as boolean.
2222
+ * see: [[Vector]]
2223
+ */
1956
2224
  __publicField(this, "vendorLegitimateInterests", new Vector());
2225
+ /**
2226
+ * The value included for disclosed vendors signals which vendors have been
2227
+ * disclosed to the user in the interface surfaced by the CMP. This section
2228
+ * content is required when writing a TC string to the global (consensu)
2229
+ * scope. When a CMP has read from and is updating a TC string from the
2230
+ * global consensu.org storage, the CMP MUST retain the existing disclosure
2231
+ * information and only add information for vendors that it has disclosed
2232
+ * that had not been disclosed by other CMPs in prior interactions with this
2233
+ * device/user agent.
2234
+ */
1957
2235
  __publicField(this, "vendorsDisclosed", new Vector());
2236
+ /**
2237
+ * Signals which vendors the publisher permits to use OOB legal bases.
2238
+ */
1958
2239
  __publicField(this, "vendorsAllowed", new Vector());
1959
2240
  __publicField(this, "publisherRestrictions", new PurposeRestrictionVector());
1960
2241
  if (gvl) {
@@ -2336,6 +2617,9 @@ class TCModel extends Cloneable {
2336
2617
  this.lastUpdated = utcDate;
2337
2618
  }
2338
2619
  }
2620
+ /**
2621
+ * Set of available consent languages published by the IAB
2622
+ */
2339
2623
  __publicField(TCModel, "consentLanguages", GVL.consentLanguages);
2340
2624
  class TCString {
2341
2625
  /**
@@ -2389,20 +2673,6 @@ class TCString {
2389
2673
  return tcModel;
2390
2674
  }
2391
2675
  }
2392
- const iabCustomCategories = {
2393
- permutiveAds: {
2394
- purposes: [2, 4, 8, 9],
2395
- iabVendors: [361],
2396
- customVendors: [],
2397
- specialFeatures: []
2398
- },
2399
- demographicAds: {
2400
- purposes: [3, 4, 7, 9, 10],
2401
- iabVendors: [],
2402
- customVendors: [],
2403
- specialFeatures: []
2404
- }
2405
- };
2406
2676
  function isValidGdprValue(val) {
2407
2677
  if (val === null) {
2408
2678
  return true;
@@ -2444,10 +2714,6 @@ function validateIabConsentCategory(categoryName) {
2444
2714
  throw new Error("Provided custom category identifier does not exist. Please check");
2445
2715
  }
2446
2716
  }
2447
- const legislation = {
2448
- CCPA: "ccpa",
2449
- GDPR: "gdpr"
2450
- };
2451
2717
  function checkConsentFor(categoryName, consentState) {
2452
2718
  validateIabConsentCategory(categoryName);
2453
2719
  validateRawConsentState(consentState);
@@ -2477,47 +2743,29 @@ function getParsedConsent(rawConsentState) {
2477
2743
  return parsedConsent;
2478
2744
  }, {});
2479
2745
  }
2480
- function updateFooterLinkCMP() {
2481
- const cookieLink = document.querySelector(
2482
- "[href='https://www.ft.com/preferences/manage-cookies']"
2746
+ function getConsentCookieValue() {
2747
+ const cookies = Object.fromEntries(
2748
+ document.cookie.split("; ").map((cookie) => cookie.split("="))
2749
+ );
2750
+ const encodedValue = cookies[CONSENT_COOKIE_NAME];
2751
+ if (!encodedValue)
2752
+ return {};
2753
+ const decodedValue = decodeURIComponent(encodedValue);
2754
+ return Object.fromEntries(
2755
+ decodedValue.split(",").map((consent) => {
2756
+ const [category, value] = consent.split(":");
2757
+ const booleanConsent = [category, value === "on" ? true : false];
2758
+ return booleanConsent;
2759
+ })
2483
2760
  );
2484
- if (cookieLink) {
2485
- cookieLink.href = "#";
2486
- cookieLink.setAttribute("onclick", "window._sp_.gdpr.loadPrivacyManagerModal(827767);");
2487
- cookieLink.dataset.cmpLink = "updated";
2488
- return true;
2489
- } else {
2490
- console.warn("CMP Footer Link was not found and not updated");
2491
- return false;
2492
- }
2493
2761
  }
2494
- const SOURCEPOINT_CONSENT_SOURCE = "sourcepoint-cmp";
2495
- const SOURCEPOINT_FOW_SCOPE = "FTPINK";
2496
- const CONSENT_COOKIE_NAME = "FTConsent";
2497
- function getPayload(parsedConsent, { shouldUpdateConsentStore, formOfWordsId, cookieDomain }) {
2498
- const categoryNames = Object.keys(parsedConsent);
2499
- const data = categoryNames.reduce((payload, categoryName) => {
2500
- payload[categoryName] = {
2501
- onsite: {
2502
- status: parsedConsent[categoryName],
2503
- lbi: false,
2504
- source: SOURCEPOINT_CONSENT_SOURCE,
2505
- fow: formOfWordsId
2506
- }
2507
- };
2508
- return payload;
2509
- }, {});
2510
- if (!shouldUpdateConsentStore) {
2511
- return { data };
2512
- } else {
2513
- return {
2514
- setConsentCookie: true,
2515
- formOfWordsId,
2516
- consentSource: SOURCEPOINT_CONSENT_SOURCE,
2517
- cookieDomain,
2518
- data
2519
- };
2520
- }
2762
+ function hasConsentChanged(parsedConsent) {
2763
+ const categories = Object.keys(parsedConsent);
2764
+ const previousConsent = getConsentCookieValue();
2765
+ return categories.some((category) => {
2766
+ const adaptedCategoryName = `${category.toLowerCase()}Onsite`;
2767
+ return parsedConsent[category] !== previousConsent[adaptedCategoryName];
2768
+ });
2521
2769
  }
2522
2770
  async function saveConsent(consentEndpoint, payload) {
2523
2771
  try {
@@ -2538,7 +2786,7 @@ async function saveConsent(consentEndpoint, payload) {
2538
2786
  }
2539
2787
  function consentReadyHandlerFn(props) {
2540
2788
  const { userId, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore } = props;
2541
- return async (legislation2, _, consentString, consentMeta) => {
2789
+ return async function consentReadyHandler(legislation2, _, consentString, consentMeta) {
2542
2790
  const activeLegislation = consentMeta.applies ? legislation2 : "gdpr";
2543
2791
  if (activeLegislation !== legislation2 || !consentString) {
2544
2792
  return;
@@ -2557,7 +2805,7 @@ function consentReadyHandlerFn(props) {
2557
2805
  if (shouldUpdateConsentStore) {
2558
2806
  consentEndpoint = `${consentProxyHost}/__consent/consent-record/${SOURCEPOINT_FOW_SCOPE}/${userId}`;
2559
2807
  }
2560
- const payload = getPayload(parsedConsent, {
2808
+ const payload = getConsentPayload(parsedConsent, {
2561
2809
  formOfWordsId,
2562
2810
  cookieDomain,
2563
2811
  shouldUpdateConsentStore
@@ -2566,51 +2814,6 @@ function consentReadyHandlerFn(props) {
2566
2814
  document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
2567
2815
  };
2568
2816
  }
2569
- function hasConsentChanged(parsedConsent) {
2570
- const categories = Object.keys(parsedConsent);
2571
- const previousConsent = getConsentCookieValue();
2572
- return categories.some((category) => {
2573
- const adaptedCategoryName = `${category.toLowerCase()}Onsite`;
2574
- return parsedConsent[category] !== previousConsent[adaptedCategoryName];
2575
- });
2576
- }
2577
- function getConsentCookieValue() {
2578
- const cookies = Object.fromEntries(
2579
- document.cookie.split("; ").map((cookie) => cookie.split("="))
2580
- );
2581
- const encodedValue = cookies[CONSENT_COOKIE_NAME];
2582
- if (!encodedValue)
2583
- return {};
2584
- const decodedValue = decodeURIComponent(encodedValue);
2585
- return Object.fromEntries(
2586
- decodedValue.split(",").map((consent) => {
2587
- const [category, value] = consent.split(":");
2588
- const booleanConsent = [category, value === "on" ? true : false];
2589
- return booleanConsent;
2590
- })
2591
- );
2592
- }
2593
- const SOURCEPOINT_FOW_ID = "sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk";
2594
- const FT_COOKIE_DOMAIN = ".ft.com";
2595
- const FT_CONSENT_PROXY_HOST = "https://consent.ft.com";
2596
- function createContentScript(content) {
2597
- const s = document.createElement("script");
2598
- s.innerHTML = content;
2599
- return s;
2600
- }
2601
- function createSourceScript(src) {
2602
- const s = document.createElement("script");
2603
- s.src = src;
2604
- return s;
2605
- }
2606
- function getCmpScripts(config) {
2607
- const fragment = document.createDocumentFragment();
2608
- fragment.appendChild(createContentScript(scriptContent.tcfStub));
2609
- fragment.appendChild(createContentScript(scriptContent.uspStub));
2610
- fragment.appendChild(createContentScript(scriptContent.getSPConfig(config)));
2611
- fragment.appendChild(createSourceScript(scriptSources.cmpFrames));
2612
- return fragment;
2613
- }
2614
2817
  async function initSourcepointCmp({
2615
2818
  propertyConfig = FT_DOTCOM_PROD,
2616
2819
  userId,
@@ -2620,11 +2823,10 @@ async function initSourcepointCmp({
2620
2823
  formOfWordsId = SOURCEPOINT_FOW_ID,
2621
2824
  useConsentStore = true
2622
2825
  }) {
2623
- let maybeUserId = userId;
2624
- if (!maybeUserId && useFTSession) {
2826
+ if (!userId && useFTSession) {
2625
2827
  try {
2626
2828
  const response = await getUuid();
2627
- maybeUserId = response == null ? void 0 : response.uuid;
2829
+ userId = response == null ? void 0 : response.uuid;
2628
2830
  } catch (error) {
2629
2831
  console.error(error);
2630
2832
  }
@@ -2632,8 +2834,8 @@ async function initSourcepointCmp({
2632
2834
  if (!(propertyConfig == null ? void 0 : propertyConfig.accountId)) {
2633
2835
  throw new Error("Please pass a valid property config");
2634
2836
  }
2635
- if (maybeUserId) {
2636
- propertyConfig.authId = maybeUserId;
2837
+ if (userId) {
2838
+ propertyConfig.authId = userId;
2637
2839
  }
2638
2840
  const scripts = getCmpScripts(propertyConfig);
2639
2841
  document.head.appendChild(scripts);
@@ -2641,7 +2843,7 @@ async function initSourcepointCmp({
2641
2843
  window._sp_.addEventListener(
2642
2844
  "onConsentReady",
2643
2845
  consentReadyHandlerFn({
2644
- userId: maybeUserId,
2846
+ userId,
2645
2847
  consentProxyHost,
2646
2848
  cookieDomain,
2647
2849
  formOfWordsId,
@@ -2650,8 +2852,57 @@ async function initSourcepointCmp({
2650
2852
  );
2651
2853
  });
2652
2854
  }
2855
+ const events = {
2856
+ onMessageChoiceSelect: (...args) => {
2857
+ console.log("[event] onMessageChoiceSelect", args);
2858
+ },
2859
+ onMessageReady: (...args) => {
2860
+ console.log("[event] onMessageReady", args);
2861
+ },
2862
+ onMessageChoiceError: (...args) => {
2863
+ console.log("[event] onMessageChoiceError", args);
2864
+ },
2865
+ onPrivacyManagerAction: (...args) => {
2866
+ console.log("[event] onPrivacyManagerAction", args);
2867
+ },
2868
+ onPMCancel: (...args) => {
2869
+ console.log("[event] onPMCancel", args);
2870
+ },
2871
+ onMessageReceiveData: (...args) => {
2872
+ console.log("[event] onMessageReceiveData", args);
2873
+ },
2874
+ onSPPMObjectReady: (...args) => {
2875
+ console.log("[event] onSPPMObjectReady", args);
2876
+ },
2877
+ onConsentReady: (...args) => {
2878
+ console.log("[event] onConsentReady", args);
2879
+ },
2880
+ onError: (...args) => {
2881
+ console.log("[event] onError", args);
2882
+ }
2883
+ };
2884
+ const debug = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2885
+ __proto__: null,
2886
+ events
2887
+ }, Symbol.toStringTag, { value: "Module" }));
2888
+ function updateFooterLinkCMP() {
2889
+ const cookieLink = document.querySelector(
2890
+ "[href='https://www.ft.com/preferences/manage-cookies']"
2891
+ );
2892
+ if (cookieLink) {
2893
+ cookieLink.href = "#";
2894
+ cookieLink.setAttribute("onclick", "window._sp_.gdpr.loadPrivacyManagerModal(827767);");
2895
+ cookieLink.dataset.cmpLink = "updated";
2896
+ return true;
2897
+ } else {
2898
+ console.warn("CMP Footer Link was not found and not updated");
2899
+ return false;
2900
+ }
2901
+ }
2653
2902
  export {
2903
+ debug,
2654
2904
  getCmpScripts,
2655
2905
  initSourcepointCmp,
2906
+ properties,
2656
2907
  updateFooterLinkCMP
2657
2908
  };