@escape-game-over/atlas 0.1.53 → 0.1.54
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/docs/client-scripts.md +2 -1
- package/package.json +1 -1
- package/src/analytics/index.ts +14 -5
- package/src/astro/Document.astro +10 -0
- package/src/index.ts +1 -0
- package/src/site/create.ts +4 -0
- package/src/site/page.ts +2 -0
package/docs/client-scripts.md
CHANGED
|
@@ -43,7 +43,8 @@ finding them.
|
|
|
43
43
|
| `element` | registering a custom element, and ending what it started | what the element does while it is on the page |
|
|
44
44
|
|
|
45
45
|
`consent` is the one module that ships its own behaviour: `<ConsentBanner
|
|
46
|
-
analytics={…}>` (`@escape-game-over/atlas/astro/consent-banner`)
|
|
46
|
+
slot="consent" analytics={…}>` (`@escape-game-over/atlas/astro/consent-banner`),
|
|
47
|
+
passed to `Document`, which fails the build when a page needs one and has none. It renders the
|
|
47
48
|
site's markup as its children, skips itself — script included — when the
|
|
48
49
|
analytics need no permission, and remembers, expires and applies the answer. The
|
|
49
50
|
answer is two, one per category: `analytics` (Google's `analytics_storage`) and
|
package/package.json
CHANGED
package/src/analytics/index.ts
CHANGED
|
@@ -70,7 +70,7 @@ export function analyticsScripts(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* The vendors this deployment loads that a visitor has to be asked about.
|
|
74
74
|
*
|
|
75
75
|
* The one place that question is answered, and at build time: a project leaves
|
|
76
76
|
* the banner — script and all — out of the HTML, rather than shipping a script
|
|
@@ -88,10 +88,10 @@ export function analyticsScripts(
|
|
|
88
88
|
* permission — which is the failure worth having, since the alternative is a
|
|
89
89
|
* new vendor silently setting cookies behind a banner that never appears.
|
|
90
90
|
*/
|
|
91
|
-
export function
|
|
91
|
+
export function consentVendors(
|
|
92
92
|
analytics: AnalyticsSettings | undefined
|
|
93
|
-
):
|
|
94
|
-
if (analytics === undefined) return
|
|
93
|
+
): readonly (keyof AnalyticsSettings)[] {
|
|
94
|
+
if (analytics === undefined) return [];
|
|
95
95
|
|
|
96
96
|
const VENDORS: Readonly<Record<keyof AnalyticsSettings, boolean>> = {
|
|
97
97
|
// Cookieless by design — nothing to permit, nothing to withdraw.
|
|
@@ -100,7 +100,16 @@ export function consentRequired(
|
|
|
100
100
|
google: googleEmits(analytics.google),
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
return Object.
|
|
103
|
+
return (Object.keys(VENDORS) as (keyof AnalyticsSettings)[]).filter(
|
|
104
|
+
(vendor) => VENDORS[vendor]
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Whether any vendor this deployment loads needs permission. */
|
|
109
|
+
export function consentRequired(
|
|
110
|
+
analytics: AnalyticsSettings | undefined
|
|
111
|
+
): boolean {
|
|
112
|
+
return consentVendors(analytics).length > 0;
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
/**
|
package/src/astro/Document.astro
CHANGED
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
* It sends a reader arriving from elsewhere to the page in the language they
|
|
17
17
|
* last chose; see `RememberLocale.astro`. `rememberLocale={false}` turns it off.
|
|
18
18
|
*
|
|
19
|
+
* A deployment whose analytics need permission must pass its banner in the
|
|
20
|
+
* `consent` slot — `<ConsentBanner slot="consent" …>` — or the build fails.
|
|
21
|
+
*
|
|
19
22
|
* `fonts={site.fonts}` writes the `@font-face` rules and preloads for the
|
|
20
23
|
* faces `siteFonts(site)` registered in the Astro config.
|
|
21
24
|
*
|
|
@@ -58,6 +61,12 @@ const {
|
|
|
58
61
|
rememberCampaign = false,
|
|
59
62
|
rememberLocale = true,
|
|
60
63
|
} = Astro.props;
|
|
64
|
+
|
|
65
|
+
if (meta.consentVendors.length > 0 && !Astro.slots.has("consent")) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`${meta.consentVendors.join(", ")} ${meta.consentVendors.length === 1 ? "needs" : "need"} permission, but this page has no consent banner. Pass one to Document: <ConsentBanner slot="consent" …>.`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
61
70
|
---
|
|
62
71
|
|
|
63
72
|
<!doctype html>
|
|
@@ -81,6 +90,7 @@ const {
|
|
|
81
90
|
<body {...body}>
|
|
82
91
|
<MetaTags tags={meta.bodyTags} />
|
|
83
92
|
<slot />
|
|
93
|
+
<slot name="consent" />
|
|
84
94
|
{restoreScroll && <ScrollRestore />}
|
|
85
95
|
{rememberCampaign && <RememberCampaign />}
|
|
86
96
|
</body>
|
package/src/index.ts
CHANGED
package/src/site/create.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { consentVendors } from "../analytics/index.ts";
|
|
1
2
|
import {
|
|
2
3
|
type LocaleMeta,
|
|
3
4
|
type LocalesOf,
|
|
@@ -342,6 +343,8 @@ export function createSite<
|
|
|
342
343
|
// Nothing. The body channel exists for Tag Manager's `<noscript>`,
|
|
343
344
|
// and no Google tag reaches this page.
|
|
344
345
|
bodyTags: [],
|
|
346
|
+
// Umami only, which asks nobody.
|
|
347
|
+
consentVendors: [],
|
|
345
348
|
};
|
|
346
349
|
}
|
|
347
350
|
|
|
@@ -418,6 +421,7 @@ export function createSite<
|
|
|
418
421
|
dir: localeMeta[locale].dir,
|
|
419
422
|
tags: document.head,
|
|
420
423
|
bodyTags: document.body,
|
|
424
|
+
consentVendors: consentVendors(project.analytics),
|
|
421
425
|
};
|
|
422
426
|
}
|
|
423
427
|
|
package/src/site/page.ts
CHANGED
|
@@ -65,6 +65,8 @@ export interface PageMeta {
|
|
|
65
65
|
* both, and cannot put either in the other's place.
|
|
66
66
|
*/
|
|
67
67
|
readonly bodyTags: MetaTag[];
|
|
68
|
+
/** The vendors that need a consent banner on this page; `Document` fails without one. */
|
|
69
|
+
readonly consentVendors: readonly string[];
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
/**
|