@ecomconsult/consentkit 0.5.2 → 0.5.4
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/npm/internal-stub.mjs +1 -1
- package/package.json +1 -1
- package/src/ck-core.js +77 -1
- package/src/ck-debug.js +12 -3
- package/src/ck-ui.js +167 -1
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.4',
|
|
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
|
@@ -81,6 +81,13 @@
|
|
|
81
81
|
// INFRA_DB: the rest of Cloudflare's edge is infrastructure, but this one
|
|
82
82
|
// beacon is a measurement product (§8 names it by hand for that reason).
|
|
83
83
|
'static.cloudflareinsights.com': 'analytics',
|
|
84
|
+
// Tilda's stats endpoint. The REST of tildaapi.one is platform plumbing and
|
|
85
|
+
// sits in INFRA_DB host by host; this one subdomain measures visitors, so it
|
|
86
|
+
// is classified here instead. There is deliberately NO bare `tildaapi.one`
|
|
87
|
+
// in either table: lookupHostMap returns the FIRST matching key, not the
|
|
88
|
+
// longest, so a bare entry could shadow this one depending on insertion
|
|
89
|
+
// order. Every Tilda API host is therefore named in full.
|
|
90
|
+
'stat.tildaapi.one': 'analytics',
|
|
84
91
|
|
|
85
92
|
// --- marketing -----------------------------------------------------
|
|
86
93
|
'connect.facebook.net': 'marketing',
|
|
@@ -137,6 +144,22 @@
|
|
|
137
144
|
// iuteCredit — a Moldovan consumer-credit calculator embedded on shop
|
|
138
145
|
// product pages. A third party the owner chose, offering a feature.
|
|
139
146
|
'iutecredit.md': 'functional',
|
|
147
|
+
// Google Maps — a map or a store locator the owner embedded. It is a
|
|
148
|
+
// FEATURE, not measurement: a visitor who declines functional loses the map
|
|
149
|
+
// and nothing else. The two API hosts are dedicated to Maps, so the whole
|
|
150
|
+
// host is the right scope; the www.google.com/maps halves cannot be, and
|
|
151
|
+
// are path-scoped in PATH_DB below.
|
|
152
|
+
//
|
|
153
|
+
// maps.gstatic.com is the deliberate exception to `gstatic.com` sitting in
|
|
154
|
+
// INFRA_DB: the parent serves fonts and ordinary images a page is broken
|
|
155
|
+
// without, but this subdomain serves the map tiles and marker sprites of an
|
|
156
|
+
// embed the owner chose. categoryForUrl runs BEFORE the strict allowlist, so
|
|
157
|
+
// naming it here classifies (and holds) it while fonts.gstatic.com stays
|
|
158
|
+
// waved through — which is the split the pair of tests in blocking.test.mjs
|
|
159
|
+
// pins down.
|
|
160
|
+
'maps.googleapis.com': 'functional',
|
|
161
|
+
'places.googleapis.com': 'functional',
|
|
162
|
+
'maps.gstatic.com': 'functional',
|
|
140
163
|
|
|
141
164
|
// --- necessary -----------------------------------------------------
|
|
142
165
|
// recaptcha.net is Google's alternate reCAPTCHA domain, served for regions
|
|
@@ -183,6 +206,34 @@
|
|
|
183
206
|
'/gtag/js': 'analytics', // googletagmanager.com/gtag/js?id=G-XXXX
|
|
184
207
|
'www.google.com/recaptcha/': 'necessary',
|
|
185
208
|
'www.gstatic.com/recaptcha/': 'necessary',
|
|
209
|
+
// Google Maps on www.google.<tld>. Like reCAPTCHA above, the host cannot be
|
|
210
|
+
// given a category as a whole, so the map is named by path. Functional: it
|
|
211
|
+
// is a map the owner put on the page, and allowed() holds it until the
|
|
212
|
+
// visitor accepts functional.
|
|
213
|
+
//
|
|
214
|
+
// The host half is kept IN the key rather than matching a bare '/maps/'.
|
|
215
|
+
// Every fragment here is tested against the WHOLE resolved URL, so a bare
|
|
216
|
+
// key would also classify a site's OWN page at /maps/… . For '/gtag/js'
|
|
217
|
+
// that is intended (a self-hosted gtag really is analytics); a first-party
|
|
218
|
+
// route called /maps/embed is just a route.
|
|
219
|
+
//
|
|
220
|
+
// Google serves the iframe embed from google.com/maps/embed regardless of
|
|
221
|
+
// the visitor's country, so google.com covers the embed case; the ccTLD
|
|
222
|
+
// hosts appear for /maps/ links, which the first key covers on www.google
|
|
223
|
+
// .com and which are ordinary navigation elsewhere.
|
|
224
|
+
'www.google.com/maps/': 'functional',
|
|
225
|
+
'google.com/maps/embed': 'functional', // also maps.google.com
|
|
226
|
+
// Google Ads pings that carry no cookie of their own but still report a
|
|
227
|
+
// visit to the ad platform — the remarketing/conversion beacons a gtag or
|
|
228
|
+
// Ads tag fires against www.google.<tld>. They reach doubleclick.net too,
|
|
229
|
+
// where HOST_DB already files them as marketing; these keys are what catches
|
|
230
|
+
// the www.google.com and www.google.lt (and every other ccTLD) form, which
|
|
231
|
+
// no host entry can cover without ruling on all of Google at once. Matching
|
|
232
|
+
// is a substring test against the WHOLE resolved URL, so a leading path
|
|
233
|
+
// fragment matches every host.
|
|
234
|
+
'/pagead/1p-user-list/': 'marketing',
|
|
235
|
+
'/pagead/1p-conversion/': 'marketing',
|
|
236
|
+
'/ads/ga-audiences': 'marketing',
|
|
186
237
|
'/trackers/ga.js': 'analytics',
|
|
187
238
|
'/trackers/pixel.js': 'marketing',
|
|
188
239
|
'/trackers/chat.js': 'functional'
|
|
@@ -304,7 +355,21 @@
|
|
|
304
355
|
// --- site builders and hosting platforms ---------------------------
|
|
305
356
|
'tildacdn.com',
|
|
306
357
|
'tildacdn.net',
|
|
358
|
+
'tildacdn.one',
|
|
359
|
+
'static.tildacdn.one', // redundant under the line above, named
|
|
360
|
+
// for symmetry with the tildacdn.com
|
|
361
|
+
// fixtures, which use the same subdomain
|
|
307
362
|
'tilda.ws',
|
|
363
|
+
// Tilda's own platform APIs: block feeds, geo lookup, the members area and
|
|
364
|
+
// form delivery. A Tilda page is broken without them and none of them is a
|
|
365
|
+
// decision the site owner made — they are the builder serving its own site.
|
|
366
|
+
// Enumerated one by one rather than as a bare `tildaapi.one`, because
|
|
367
|
+
// stat.tildaapi.one IS measurement and sits in HOST_DB as analytics; a bare
|
|
368
|
+
// suffix here would be a claim about that host too.
|
|
369
|
+
'feeds.tildaapi.one',
|
|
370
|
+
'geo.tildaapi.one',
|
|
371
|
+
'members.tildaapi.one',
|
|
372
|
+
'forms.tildaapi.one',
|
|
308
373
|
'static.wixstatic.com',
|
|
309
374
|
'parastorage.com', // Wix static assets
|
|
310
375
|
'cdn.shopify.com',
|
|
@@ -325,6 +390,8 @@
|
|
|
325
390
|
'b-cdn.net', // bunny.net
|
|
326
391
|
// --- fonts ----------------------------------------------------------
|
|
327
392
|
'fonts.googleapis.com',
|
|
393
|
+
'fonts.google.com', // the catalogue host; some embeds and
|
|
394
|
+
// builders link stylesheets through it
|
|
328
395
|
// gstatic.com whole: Google's static-asset domain. Its subdomains serve
|
|
329
396
|
// fonts (fonts.gstatic.com), the reCAPTCHA widget's own code
|
|
330
397
|
// (www.gstatic.com/recaptcha/) and ordinary images — assets a page is
|
|
@@ -880,6 +947,15 @@
|
|
|
880
947
|
// miss every page that sets it after the core loads.
|
|
881
948
|
function isInfraHost(host) {
|
|
882
949
|
if (!host) { return false; }
|
|
950
|
+
// A host the database gives a CATEGORY to is never infrastructure, even when
|
|
951
|
+
// it sits under an INFRA_DB suffix. Without this, maps.gstatic.com (named as
|
|
952
|
+
// `functional` in HOST_DB, under a bare `gstatic.com` here) would be held
|
|
953
|
+
// back by the engine until functional consent while the scanner — which
|
|
954
|
+
// reads _infra() to set thirdParty[].infra — filed it as infrastructure and
|
|
955
|
+
// kept it out of the report entirely. Blocking and reporting would then
|
|
956
|
+
// disagree about one host, which is exactly what §8 exists to prevent.
|
|
957
|
+
// Every other INFRA_DB entry is uncategorised, so this changes nothing else.
|
|
958
|
+
if (lookupHostMap(EXTRA_DB, host) || lookupHostMap(HOST_DB, host)) { return false; }
|
|
883
959
|
for (var i = 0; i < INFRA_DB.length; i++) {
|
|
884
960
|
if (hostMatches(host, INFRA_DB[i])) { return true; }
|
|
885
961
|
}
|
|
@@ -1461,7 +1537,7 @@
|
|
|
1461
1537
|
// Public API
|
|
1462
1538
|
// ---------------------------------------------------------------------------
|
|
1463
1539
|
var ConsentKit = {
|
|
1464
|
-
version: '0.5.
|
|
1540
|
+
version: '0.5.4',
|
|
1465
1541
|
config: config,
|
|
1466
1542
|
|
|
1467
1543
|
init: function (userConfig) {
|
package/src/ck-debug.js
CHANGED
|
@@ -207,6 +207,7 @@
|
|
|
207
207
|
themeFontInherit: 'наследуется',
|
|
208
208
|
themeFontSystem: 'системный',
|
|
209
209
|
themeFontPage: 'со страницы',
|
|
210
|
+
themeFontTry: 'попытка',
|
|
210
211
|
themeRadius: 'скругления',
|
|
211
212
|
themeCard: 'карточка',
|
|
212
213
|
themeBtn: 'кнопки',
|
|
@@ -267,6 +268,7 @@
|
|
|
267
268
|
themeFontInherit: 'inherited',
|
|
268
269
|
themeFontSystem: 'system',
|
|
269
270
|
themeFontPage: 'from the page',
|
|
271
|
+
themeFontTry: 'attempt',
|
|
270
272
|
themeRadius: 'radii',
|
|
271
273
|
themeCard: 'card',
|
|
272
274
|
themeBtn: 'buttons',
|
|
@@ -607,12 +609,19 @@
|
|
|
607
609
|
site whose body is unstyled is exactly the Times bug being diagnosed. */
|
|
608
610
|
function fontRow(built, T) {
|
|
609
611
|
if (built.font !== 'inherit') return built.font + ' (' + T.themeFontSystem + ')';
|
|
610
|
-
var page = null;
|
|
612
|
+
var page = null, n = 0;
|
|
611
613
|
try {
|
|
612
614
|
if (CK && typeof CK._resolvePageFont === 'function') page = CK._resolvePageFont();
|
|
613
615
|
} catch (e) { page = null; }
|
|
614
|
-
|
|
615
|
-
|
|
616
|
+
// The attempt number is the whole point of the 0.5.3 re-probe: a page whose
|
|
617
|
+
// stylesheets land late resolves on look 2 or 3, and «попытка 1» vs
|
|
618
|
+
// «попытка 3» is what tells those two pages apart in the panel.
|
|
619
|
+
try {
|
|
620
|
+
if (CK && typeof CK._pageFontAttempt === 'function') n = CK._pageFontAttempt();
|
|
621
|
+
} catch (e) { n = 0; }
|
|
622
|
+
var tries = (typeof n === 'number' && n > 1) ? ', ' + T.themeFontTry + ' ' + n : '';
|
|
623
|
+
return page ? page + ' (' + T.themeFontPage + tries + ')'
|
|
624
|
+
: 'inherit (' + T.themeFontInherit + tries + ')';
|
|
616
625
|
}
|
|
617
626
|
|
|
618
627
|
// Resolved lazily, not at parse time: this file runs before ConsentKit.init()
|
package/src/ck-ui.js
CHANGED
|
@@ -702,6 +702,40 @@
|
|
|
702
702
|
return null;
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
+
/* One probe at mount is not enough. On a page whose stylesheets are injected
|
|
706
|
+
by script (Tilda is the reported case) a CACHED reload mounts the banner
|
|
707
|
+
BEFORE those sheets apply, so every sample still computes to the UA default
|
|
708
|
+
and the probe returns null — the banner stays in Times and nothing looks
|
|
709
|
+
again. So the mount probe is only the first look: re-probes are scheduled
|
|
710
|
+
until the answer stops changing.
|
|
711
|
+
|
|
712
|
+
Both halves of that schedule are pure arithmetic, published on _contrast so
|
|
713
|
+
the behaviour is testable without timers or a DOM.
|
|
714
|
+
|
|
715
|
+
The timed ladder, in ms after mount. Deliberately front-loaded: a page that
|
|
716
|
+
styles itself quickly is corrected before a visitor can read the banner,
|
|
717
|
+
and the 4 s tail catches a slow webfont-driven sheet. `window.load` and
|
|
718
|
+
`document.fonts.ready` fire on their own and are NOT part of this ladder. */
|
|
719
|
+
var REPROBE_DELAYS = [500, 1500, 4000];
|
|
720
|
+
|
|
721
|
+
// Attempt is 1-based over the TIMED probes only; null means "no more timers".
|
|
722
|
+
function nextProbeDelay(attempt) {
|
|
723
|
+
if (typeof attempt !== 'number' || !isFinite(attempt) || attempt < 1) return null;
|
|
724
|
+
var i = Math.floor(attempt) - 1;
|
|
725
|
+
return i < REPROBE_DELAYS.length ? REPROBE_DELAYS[i] : null;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/* Should a freshly probed family replace what the banner is painting?
|
|
729
|
+
`current` is the applied value (null while the page still states nothing).
|
|
730
|
+
Only a non-null find is ever worth applying — a later null means the page
|
|
731
|
+
got LESS specific, which never happens for real and would otherwise throw
|
|
732
|
+
away a good answer. */
|
|
733
|
+
function shouldReprobe(current, found) {
|
|
734
|
+
if (typeof found !== 'string' || !found) return false;
|
|
735
|
+
if (typeof current !== 'string' || !current) return true; // null -> found
|
|
736
|
+
return normFamily(current) !== normFamily(found);
|
|
737
|
+
}
|
|
738
|
+
|
|
705
739
|
// Ordered so the first hit is the most representative body text on the page.
|
|
706
740
|
var FONT_PROBES = ['main p', 'article p', '[role=main] p', 'p', 'h1', 'h2', 'a', 'button', 'li'];
|
|
707
741
|
|
|
@@ -735,6 +769,12 @@
|
|
|
735
769
|
// after a remount) quotes the value the banner actually painted.
|
|
736
770
|
var pageFont = null;
|
|
737
771
|
|
|
772
|
+
/* How many times the SCHEDULER has looked, for the debug panel's «попытка N».
|
|
773
|
+
Counted here and not inside resolvePageFont() on purpose: _resolvePageFont()
|
|
774
|
+
re-runs the whole probe on every debug-panel render, and counting there would
|
|
775
|
+
report «попытка 14» after a few renders and exhaust the cap on nothing. */
|
|
776
|
+
var fontProbeCount = 1; // the mount probe is attempt 1
|
|
777
|
+
|
|
738
778
|
function resolvePageFont() {
|
|
739
779
|
if (typeof document === 'undefined') return pageFont;
|
|
740
780
|
try {
|
|
@@ -766,6 +806,97 @@
|
|
|
766
806
|
return pageFont;
|
|
767
807
|
}
|
|
768
808
|
|
|
809
|
+
/* ------------------------------------------------ page-font re-probing */
|
|
810
|
+
|
|
811
|
+
/* Live timers, so remount() can cancel a schedule that belongs to the DOM it
|
|
812
|
+
is about to throw away. Everything here is guarded and only ever RUNS after
|
|
813
|
+
mount(), so the parse-time SSR context below never reaches it. */
|
|
814
|
+
var fontTimers = [];
|
|
815
|
+
var fontStable = false; // a non-null value survived one extra probe
|
|
816
|
+
var fontScheduled = false;
|
|
817
|
+
|
|
818
|
+
// Cap on SCHEDULED probes (the mount probe is not one of them): the three
|
|
819
|
+
// timed rungs plus window.load plus fonts.ready.
|
|
820
|
+
var MAX_REPROBES = 5;
|
|
821
|
+
|
|
822
|
+
function clearFontTimers() {
|
|
823
|
+
for (var i = 0; i < fontTimers.length; i++) {
|
|
824
|
+
try { clearTimeout(fontTimers[i]); } catch (e) { /* noop */ }
|
|
825
|
+
}
|
|
826
|
+
fontTimers = [];
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/* One look. Re-applies the theme when the family changed, and reports whether
|
|
830
|
+
the answer has now held still for a whole extra probe — which is the only
|
|
831
|
+
thing that stops the ladder early. Applying and stopping are deliberately
|
|
832
|
+
separate: a first non-null find is painted IMMEDIATELY (the visitor must not
|
|
833
|
+
wait out the confirmation), the confirmation only decides about timers. */
|
|
834
|
+
function probeFontOnce() {
|
|
835
|
+
var before = pageFont;
|
|
836
|
+
var found = resolvePageFont(); // rewrites the pageFont cache
|
|
837
|
+
if (shouldReprobe(before, found)) {
|
|
838
|
+
// applyTheme() rewrites themeStyle.textContent wholesale, so the --ck-font
|
|
839
|
+
// rule is REPLACED rather than appended a second time.
|
|
840
|
+
try { applyTheme(safeConfig()); } catch (e) { /* noop */ }
|
|
841
|
+
fontStable = false;
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
// Unchanged. Stable only once we have an actual family in hand: a page that
|
|
845
|
+
// keeps answering null is exactly the case that has to keep looking.
|
|
846
|
+
if (found) { fontStable = true; return true; }
|
|
847
|
+
return false;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/* Run a scheduled probe. Every trigger — window.load, fonts.ready and each
|
|
851
|
+
rung of the timed ladder — funnels through here so the cap and the counter
|
|
852
|
+
are counted in one place. */
|
|
853
|
+
function runScheduledProbe() {
|
|
854
|
+
if (!mounted || fontStable) return;
|
|
855
|
+
if (fontProbeCount >= 1 + MAX_REPROBES) return;
|
|
856
|
+
fontProbeCount++;
|
|
857
|
+
if (probeFontOnce()) clearFontTimers(); // settled: drop the rest
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/* Called once from the end of mount(). Not from applyTheme(): that runs again
|
|
861
|
+
on every palette-only ck:init, which would restart the whole ladder. */
|
|
862
|
+
function scheduleFontProbes(cfg) {
|
|
863
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') return;
|
|
864
|
+
if (fontScheduled) return;
|
|
865
|
+
// theme.font:'system' is a fixed stack — there is nothing to sample.
|
|
866
|
+
try {
|
|
867
|
+
var t = (cfg && cfg.theme) || {};
|
|
868
|
+
if (resolveFont(t) !== 'inherit') return;
|
|
869
|
+
} catch (e) { return; }
|
|
870
|
+
|
|
871
|
+
fontScheduled = true;
|
|
872
|
+
try {
|
|
873
|
+
for (var a = 1; ; a++) {
|
|
874
|
+
var d = nextProbeDelay(a);
|
|
875
|
+
if (d === null) break;
|
|
876
|
+
fontTimers.push(setTimeout(runScheduledProbe, d));
|
|
877
|
+
}
|
|
878
|
+
} catch (e) { /* noop */ }
|
|
879
|
+
|
|
880
|
+
// A cached reload's mount can precede the page's own stylesheets; `load`
|
|
881
|
+
// is the first moment every <link> in the document has definitely applied.
|
|
882
|
+
try {
|
|
883
|
+
if (document.readyState === 'complete') {
|
|
884
|
+
// Already past it — the ladder covers this case on its own.
|
|
885
|
+
} else {
|
|
886
|
+
window.addEventListener('load', function () { runScheduledProbe(); }, { once: true });
|
|
887
|
+
}
|
|
888
|
+
} catch (e) { /* noop */ }
|
|
889
|
+
|
|
890
|
+
// A webfont swapping in can change the computed family outright.
|
|
891
|
+
try {
|
|
892
|
+
if (document.fonts && typeof document.fonts.ready === 'object' &&
|
|
893
|
+
document.fonts.ready && typeof document.fonts.ready.then === 'function') {
|
|
894
|
+
document.fonts.ready.then(function () { runScheduledProbe(); },
|
|
895
|
+
function () { /* noop */ });
|
|
896
|
+
}
|
|
897
|
+
} catch (e) { /* noop */ }
|
|
898
|
+
}
|
|
899
|
+
|
|
769
900
|
/* --------------------------------------------------- button resolution */
|
|
770
901
|
|
|
771
902
|
var BTN_ROLES = ['accept', 'reject', 'settings'];
|
|
@@ -1030,7 +1161,11 @@
|
|
|
1030
1161
|
var fontCss = '';
|
|
1031
1162
|
if (built.font === 'inherit') {
|
|
1032
1163
|
var page = resolvePageFont();
|
|
1033
|
-
|
|
1164
|
+
// Owner rule (2026-09-06): the page's font when it can be read, the
|
|
1165
|
+
// system stack when it cannot — never a bare `inherit`, which on Tilda
|
|
1166
|
+
// and friends resolves to <body>'s browser default (Times). A later
|
|
1167
|
+
// re-probe that finds the page font swaps the system stack out again.
|
|
1168
|
+
fontCss = '\n:host{--ck-font:' + (page || SYSTEM_FONT) + '}';
|
|
1034
1169
|
} else {
|
|
1035
1170
|
pageFont = null; // theme.font:'system' opts out
|
|
1036
1171
|
}
|
|
@@ -1407,6 +1542,21 @@
|
|
|
1407
1542
|
|
|
1408
1543
|
function openPanel(invoker) {
|
|
1409
1544
|
if (!mounted || !nodes.panel) return;
|
|
1545
|
+
/* A visitor who opens the settings long after load is the last chance to
|
|
1546
|
+
get the typeface right, and by then the page is certainly styled. Only
|
|
1547
|
+
when the banner is still on `inherit` — a resolved family is left alone
|
|
1548
|
+
so opening the panel can never restyle a correct banner. Hooked here
|
|
1549
|
+
rather than on the ck:ui:open-preferences listener because the banner's
|
|
1550
|
+
own «Настроить» button calls openPanel() directly.
|
|
1551
|
+
|
|
1552
|
+
Gated on fontScheduled, which is only ever set for a theme that actually
|
|
1553
|
+
samples the page: with theme.font:'system' applyTheme() nulls pageFont on
|
|
1554
|
+
every call, so without this the condition would be permanently true and
|
|
1555
|
+
every panel open would re-probe the DOM and rewrite the sheet to produce
|
|
1556
|
+
byte-identical CSS, forever. */
|
|
1557
|
+
if (fontScheduled && !pageFont && !fontStable) {
|
|
1558
|
+
try { probeFontOnce(); } catch (e) { /* noop */ }
|
|
1559
|
+
}
|
|
1410
1560
|
lastFocus = invoker || root.activeElement || document.activeElement;
|
|
1411
1561
|
syncSwitches(safeState());
|
|
1412
1562
|
nodes.panelScrim.classList.remove('ck-hidden');
|
|
@@ -1482,6 +1632,12 @@
|
|
|
1482
1632
|
mounted = false;
|
|
1483
1633
|
panelOpen = false;
|
|
1484
1634
|
lastFocus = null;
|
|
1635
|
+
// The pending schedule belongs to the shadow root about to be rebuilt; the
|
|
1636
|
+
// fresh mount() starts its own ladder from a clean count.
|
|
1637
|
+
clearFontTimers();
|
|
1638
|
+
fontScheduled = false;
|
|
1639
|
+
fontStable = false;
|
|
1640
|
+
fontProbeCount = 1;
|
|
1485
1641
|
mount(cfg);
|
|
1486
1642
|
}
|
|
1487
1643
|
|
|
@@ -1526,6 +1682,10 @@
|
|
|
1526
1682
|
mounted = true;
|
|
1527
1683
|
mountedSig = signature(cfg);
|
|
1528
1684
|
syncFromState();
|
|
1685
|
+
|
|
1686
|
+
// Only now: scheduleFontProbes() re-applies the theme from a timer, and
|
|
1687
|
+
// applyTheme() is a no-op until there is a host and a themeStyle to write.
|
|
1688
|
+
scheduleFontProbes(cfg);
|
|
1529
1689
|
}
|
|
1530
1690
|
|
|
1531
1691
|
/* ---------------------------------------------------------------- events */
|
|
@@ -1553,6 +1713,8 @@
|
|
|
1553
1713
|
resolveRadius: resolveRadius,
|
|
1554
1714
|
resolveFont: resolveFont,
|
|
1555
1715
|
pickPageFont: pickPageFont,
|
|
1716
|
+
nextProbeDelay: nextProbeDelay,
|
|
1717
|
+
shouldReprobe: shouldReprobe,
|
|
1556
1718
|
resolveDetails: resolveDetails,
|
|
1557
1719
|
buildThemeCss: buildThemeCss
|
|
1558
1720
|
};
|
|
@@ -1563,6 +1725,10 @@
|
|
|
1563
1725
|
ck._resolvePageFont = function () {
|
|
1564
1726
|
return (typeof document === 'undefined' || !root) ? pageFont : resolvePageFont();
|
|
1565
1727
|
};
|
|
1728
|
+
// How many times the SCHEDULER has looked (1 = the mount probe alone). The
|
|
1729
|
+
// debug panel prints it: on a Tilda-style page the interesting fact is that
|
|
1730
|
+
// the family arrived on the third look, not on the first.
|
|
1731
|
+
ck._pageFontAttempt = function () { return fontProbeCount; };
|
|
1566
1732
|
})();
|
|
1567
1733
|
|
|
1568
1734
|
// SSR-safe: with no DOM there is nothing to render or listen to, so importing
|