astro-consent 1.0.5 → 1.0.7
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/dist/cli.cjs +17 -171
- package/dist/config/defaults.js +12 -4
- package/dist/config/loadConfig.js +10 -19
- package/dist/index.js +22 -188
- package/dist/templates/cssTemplate.js +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -69,8 +69,9 @@ let source = fs.readFileSync(configPath, "utf8");
|
|
|
69
69
|
REMOVE MODE
|
|
70
70
|
───────────────────────────────────── */
|
|
71
71
|
if (command === "remove") {
|
|
72
|
-
source = source
|
|
73
|
-
|
|
72
|
+
source = source
|
|
73
|
+
.replace(/\s*astroConsent\s*\([\s\S]*?\),?/gm, "")
|
|
74
|
+
.replace(/import\s+astroConsent\s+from\s+["']astro-consent["'];?\n?/, "");
|
|
74
75
|
fs.writeFileSync(configPath, source.trim() + "\n", "utf8");
|
|
75
76
|
const cssFile = path.join(CWD, "src", "cookiebanner.css");
|
|
76
77
|
if (fs.existsSync(cssFile))
|
|
@@ -87,29 +88,26 @@ if (!fs.existsSync(cssDir)) {
|
|
|
87
88
|
fs.mkdirSync(cssDir, { recursive: true });
|
|
88
89
|
}
|
|
89
90
|
/* ─────────────────────────────────────
|
|
90
|
-
Create
|
|
91
|
+
Create CSS override file (ONCE)
|
|
91
92
|
───────────────────────────────────── */
|
|
92
93
|
if (!fs.existsSync(cssFile)) {
|
|
93
94
|
fs.writeFileSync(cssFile, `/* =========================================================
|
|
94
95
|
astro-consent — FULL THEME VARIABLES
|
|
95
|
-
|
|
96
|
-
This file is NEVER overwritten.
|
|
96
|
+
This file is NEVER overwritten
|
|
97
97
|
========================================================= */
|
|
98
98
|
|
|
99
99
|
:root {
|
|
100
|
-
/* ───── Core ───── */
|
|
101
100
|
--cb-font: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
--cb-bg: rgba(12,18,32,0.88);
|
|
102
|
+
--cb-bg: #0c1220;
|
|
105
103
|
--cb-border: rgba(255,255,255,0.08);
|
|
106
|
-
--cb-text: #
|
|
104
|
+
--cb-text: #ffffff;
|
|
107
105
|
--cb-muted: #9ca3af;
|
|
108
106
|
--cb-link: #60a5fa;
|
|
107
|
+
|
|
109
108
|
--cb-radius: 16px;
|
|
110
109
|
--cb-shadow: 0 20px 40px rgba(0,0,0,0.35);
|
|
111
110
|
|
|
112
|
-
/* ───── Buttons ───── */
|
|
113
111
|
--cb-btn-radius: 999px;
|
|
114
112
|
--cb-btn-padding: 10px 18px;
|
|
115
113
|
|
|
@@ -117,195 +115,43 @@ if (!fs.existsSync(cssFile)) {
|
|
|
117
115
|
--cb-accept-text: #052e16;
|
|
118
116
|
|
|
119
117
|
--cb-reject-bg: #374151;
|
|
120
|
-
--cb-reject-text: #
|
|
118
|
+
--cb-reject-text: #ffffff;
|
|
121
119
|
|
|
122
120
|
--cb-manage-bg: transparent;
|
|
123
|
-
--cb-manage-text: #
|
|
121
|
+
--cb-manage-text: #ffffff;
|
|
124
122
|
--cb-manage-border: rgba(255,255,255,0.15);
|
|
125
123
|
|
|
126
|
-
/* ───── Modal ───── */
|
|
127
|
-
--cb-modal-backdrop: rgba(0,0,0,0.55);
|
|
128
124
|
--cb-modal-bg: #0c1220;
|
|
125
|
+
--cb-modal-backdrop: rgba(0,0,0,0.55);
|
|
129
126
|
--cb-modal-radius: 18px;
|
|
130
127
|
--cb-modal-width: 480px;
|
|
131
128
|
|
|
132
|
-
/* ───── Toggles ───── */
|
|
133
129
|
--cb-toggle-off-bg: #374151;
|
|
134
130
|
--cb-toggle-on-bg: #22c55e;
|
|
135
131
|
--cb-toggle-knob: #ffffff;
|
|
136
132
|
}
|
|
137
|
-
|
|
138
|
-
/* =========================================================
|
|
139
|
-
Banner
|
|
140
|
-
========================================================= */
|
|
141
|
-
|
|
142
|
-
#astro-cookie-banner {
|
|
143
|
-
position: fixed;
|
|
144
|
-
left: 16px;
|
|
145
|
-
right: 16px;
|
|
146
|
-
bottom: 16px;
|
|
147
|
-
z-index: 9999;
|
|
148
|
-
font-family: var(--cb-font);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.cb-container {
|
|
152
|
-
max-width: 1200px;
|
|
153
|
-
margin: 0 auto;
|
|
154
|
-
padding: 20px 24px;
|
|
155
|
-
display: flex;
|
|
156
|
-
gap: 24px;
|
|
157
|
-
justify-content: space-between;
|
|
158
|
-
align-items: center;
|
|
159
|
-
|
|
160
|
-
background: var(--cb-bg);
|
|
161
|
-
backdrop-filter: blur(14px);
|
|
162
|
-
border-radius: var(--cb-radius);
|
|
163
|
-
border: 1px solid var(--cb-border);
|
|
164
|
-
box-shadow: var(--cb-shadow);
|
|
165
|
-
color: var(--cb-text);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.cb-title {
|
|
169
|
-
font-size: 16px;
|
|
170
|
-
font-weight: 600;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.cb-desc {
|
|
174
|
-
font-size: 14px;
|
|
175
|
-
color: var(--cb-muted);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
.cb-desc a {
|
|
179
|
-
color: var(--cb-link);
|
|
180
|
-
text-decoration: none;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.cb-actions {
|
|
184
|
-
display: flex;
|
|
185
|
-
gap: 10px;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/* =========================================================
|
|
189
|
-
Buttons
|
|
190
|
-
========================================================= */
|
|
191
|
-
|
|
192
|
-
.cb-actions button {
|
|
193
|
-
padding: var(--cb-btn-padding);
|
|
194
|
-
border-radius: var(--cb-btn-radius);
|
|
195
|
-
border: 0;
|
|
196
|
-
font-size: 14px;
|
|
197
|
-
font-weight: 600;
|
|
198
|
-
cursor: pointer;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.cb-accept {
|
|
202
|
-
background: var(--cb-accept-bg);
|
|
203
|
-
color: var(--cb-accept-text);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.cb-reject {
|
|
207
|
-
background: var(--cb-reject-bg);
|
|
208
|
-
color: var(--cb-reject-text);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.cb-manage {
|
|
212
|
-
background: var(--cb-manage-bg);
|
|
213
|
-
color: var(--cb-manage-text);
|
|
214
|
-
border: 1px solid var(--cb-manage-border);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/* =========================================================
|
|
218
|
-
Modal
|
|
219
|
-
========================================================= */
|
|
220
|
-
|
|
221
|
-
#astro-cookie-modal {
|
|
222
|
-
position: fixed;
|
|
223
|
-
inset: 0;
|
|
224
|
-
background: var(--cb-modal-backdrop);
|
|
225
|
-
display: flex;
|
|
226
|
-
align-items: center;
|
|
227
|
-
justify-content: center;
|
|
228
|
-
z-index: 10000;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
.cb-modal {
|
|
232
|
-
width: 100%;
|
|
233
|
-
max-width: var(--cb-modal-width);
|
|
234
|
-
background: var(--cb-modal-bg);
|
|
235
|
-
border-radius: var(--cb-modal-radius);
|
|
236
|
-
padding: 24px;
|
|
237
|
-
color: var(--cb-text);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/* =========================================================
|
|
241
|
-
Toggles
|
|
242
|
-
========================================================= */
|
|
243
|
-
|
|
244
|
-
.cb-toggle {
|
|
245
|
-
width: 44px;
|
|
246
|
-
height: 24px;
|
|
247
|
-
background: var(--cb-toggle-off-bg);
|
|
248
|
-
border-radius: 999px;
|
|
249
|
-
position: relative;
|
|
250
|
-
cursor: pointer;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
.cb-toggle span {
|
|
254
|
-
position: absolute;
|
|
255
|
-
width: 18px;
|
|
256
|
-
height: 18px;
|
|
257
|
-
background: var(--cb-toggle-knob);
|
|
258
|
-
border-radius: 50%;
|
|
259
|
-
top: 3px;
|
|
260
|
-
left: 3px;
|
|
261
|
-
transition: transform 0.2s ease;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
.cb-toggle.active {
|
|
265
|
-
background: var(--cb-toggle-on-bg);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
.cb-toggle.active span {
|
|
269
|
-
transform: translateX(20px);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/* =========================================================
|
|
273
|
-
Mobile
|
|
274
|
-
========================================================= */
|
|
275
|
-
|
|
276
|
-
@media (max-width: 640px) {
|
|
277
|
-
.cb-container {
|
|
278
|
-
flex-direction: column;
|
|
279
|
-
align-items: stretch;
|
|
280
|
-
gap: 16px;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
133
|
`, "utf8");
|
|
284
|
-
console.log("🎨 Created src/cookiebanner.css
|
|
134
|
+
console.log("🎨 Created src/cookiebanner.css");
|
|
285
135
|
}
|
|
286
136
|
/* ─────────────────────────────────────
|
|
287
|
-
Inject Astro integration
|
|
137
|
+
Inject Astro integration ONLY
|
|
288
138
|
───────────────────────────────────── */
|
|
289
139
|
if (!source.includes(`from "astro-consent"`)) {
|
|
290
140
|
source = `import astroConsent from "astro-consent";\n${source}`;
|
|
291
141
|
}
|
|
292
142
|
if (!source.includes("astroConsent(")) {
|
|
293
|
-
|
|
143
|
+
source = source.replace(/integrations\s*:\s*\[/, match => `${match}
|
|
144
|
+
astroConsent({
|
|
294
145
|
siteName: "My Website",
|
|
295
146
|
policyUrl: "/privacy",
|
|
296
147
|
consent: {
|
|
297
148
|
days: 30,
|
|
298
149
|
storageKey: "astro-consent"
|
|
299
|
-
},
|
|
300
|
-
categories: {
|
|
301
|
-
analytics: false,
|
|
302
|
-
marketing: false
|
|
303
150
|
}
|
|
304
151
|
}),
|
|
305
|
-
|
|
306
|
-
source = source.replace(/integrations\s*:\s*\[/, match => `${match}\n${injection}`);
|
|
152
|
+
`);
|
|
307
153
|
}
|
|
308
154
|
fs.writeFileSync(configPath, source, "utf8");
|
|
309
155
|
console.log("\n🎉 astro-consent installed successfully");
|
|
310
|
-
console.log("👉
|
|
156
|
+
console.log("👉 Style everything via src/cookiebanner.css");
|
|
311
157
|
console.log("👉 Run `astro-consent remove` to uninstall\n");
|
package/dist/config/defaults.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* DEFAULT_CONFIG
|
|
3
|
+
* ---------------------------------------------------------
|
|
4
|
+
* Fallback values ONLY.
|
|
5
|
+
*
|
|
6
|
+
* These are used:
|
|
7
|
+
* - when the user omits a value
|
|
8
|
+
* - during internal normalisation
|
|
9
|
+
*
|
|
10
|
+
* User-provided config ALWAYS takes priority.
|
|
5
11
|
*/
|
|
6
12
|
export const DEFAULT_CONFIG = {
|
|
7
13
|
siteName: "This website",
|
|
8
14
|
policyUrl: "/privacy",
|
|
9
15
|
consent: {
|
|
10
16
|
enabled: true,
|
|
17
|
+
// Number of days consent remains valid
|
|
11
18
|
days: 30,
|
|
12
|
-
|
|
19
|
+
// Must match runtime + frontend API
|
|
20
|
+
storageKey: "astro-consent"
|
|
13
21
|
},
|
|
14
22
|
categories: {
|
|
15
23
|
essential: {
|
|
@@ -8,11 +8,9 @@ import { DEFAULT_CONFIG } from "./defaults.js";
|
|
|
8
8
|
* Cache-busted to ensure updates are picked up during dev.
|
|
9
9
|
*/
|
|
10
10
|
export async function loadUserConfig(projectRoot) {
|
|
11
|
-
const configPath = path.join(projectRoot, "src", "
|
|
11
|
+
const configPath = path.join(projectRoot, "src", "astro-consent", "config.ts");
|
|
12
12
|
let userConfig = {};
|
|
13
13
|
try {
|
|
14
|
-
// 🔑 IMPORTANT:
|
|
15
|
-
// Bust Node ESM import cache using file modified time
|
|
16
14
|
const stat = fs.statSync(configPath);
|
|
17
15
|
const cacheBuster = `?v=${stat.mtimeMs}`;
|
|
18
16
|
const imported = await import(
|
|
@@ -21,20 +19,11 @@ export async function loadUserConfig(projectRoot) {
|
|
|
21
19
|
userConfig = imported?.default ?? {};
|
|
22
20
|
}
|
|
23
21
|
catch (err) {
|
|
24
|
-
console.warn("[
|
|
22
|
+
console.warn("[astro-consent] Failed to load user config, falling back to defaults");
|
|
25
23
|
}
|
|
26
24
|
return {
|
|
27
|
-
/* ─────────────────────────────
|
|
28
|
-
Site name
|
|
29
|
-
───────────────────────────── */
|
|
30
25
|
siteName: userConfig.siteName ?? DEFAULT_CONFIG.siteName,
|
|
31
|
-
/* ─────────────────────────────
|
|
32
|
-
Policy URL
|
|
33
|
-
───────────────────────────── */
|
|
34
26
|
policyUrl: userConfig.policyUrl ?? DEFAULT_CONFIG.policyUrl,
|
|
35
|
-
/* ─────────────────────────────
|
|
36
|
-
Consent settings
|
|
37
|
-
───────────────────────────── */
|
|
38
27
|
consent: {
|
|
39
28
|
enabled: userConfig.consent?.enabled ??
|
|
40
29
|
DEFAULT_CONFIG.consent.enabled,
|
|
@@ -43,15 +32,14 @@ export async function loadUserConfig(projectRoot) {
|
|
|
43
32
|
storageKey: userConfig.consent?.storageKey ??
|
|
44
33
|
DEFAULT_CONFIG.consent.storageKey
|
|
45
34
|
},
|
|
46
|
-
/* ─────────────────────────────
|
|
47
|
-
Categories
|
|
48
|
-
───────────────────────────── */
|
|
49
35
|
categories: mergeCategories(userConfig.categories, DEFAULT_CONFIG.categories)
|
|
50
36
|
};
|
|
51
37
|
}
|
|
52
38
|
/**
|
|
53
39
|
* Merge category config safely.
|
|
54
|
-
* Defaults are preserved
|
|
40
|
+
* - Defaults are preserved
|
|
41
|
+
* - User overrides win
|
|
42
|
+
* - Custom categories are supported
|
|
55
43
|
*/
|
|
56
44
|
function mergeCategories(userCategories, defaultCategories) {
|
|
57
45
|
const merged = {};
|
|
@@ -62,11 +50,14 @@ function mergeCategories(userCategories, defaultCategories) {
|
|
|
62
50
|
...(userCategories?.[key] ?? {})
|
|
63
51
|
};
|
|
64
52
|
}
|
|
65
|
-
//
|
|
53
|
+
// Add user-defined custom categories safely
|
|
66
54
|
if (userCategories) {
|
|
67
55
|
for (const key of Object.keys(userCategories)) {
|
|
68
56
|
if (!merged[key]) {
|
|
69
|
-
merged[key] =
|
|
57
|
+
merged[key] = {
|
|
58
|
+
...userCategories[key],
|
|
59
|
+
enabled: userCategories[key].enabled ?? false
|
|
60
|
+
};
|
|
70
61
|
}
|
|
71
62
|
}
|
|
72
63
|
}
|
package/dist/index.js
CHANGED
|
@@ -15,201 +15,35 @@ export default function astroConsent(options = {}) {
|
|
|
15
15
|
hooks: {
|
|
16
16
|
"astro:config:setup": ({ injectScript }) => {
|
|
17
17
|
/* ─────────────────────────────────────
|
|
18
|
-
|
|
18
|
+
LOAD USER CSS (required)
|
|
19
19
|
───────────────────────────────────── */
|
|
20
|
-
injectScript("head-inline",
|
|
21
|
-
const style = document.createElement("style");
|
|
22
|
-
style.innerHTML = \`
|
|
23
|
-
:root {
|
|
24
|
-
--cb-bg: rgba(12,18,32,.88);
|
|
25
|
-
--cb-border: rgba(255,255,255,.08);
|
|
26
|
-
--cb-text: #e5e7eb;
|
|
27
|
-
--cb-muted: #9ca3af;
|
|
28
|
-
--cb-link: #60a5fa;
|
|
29
|
-
--cb-accept: #22c55e;
|
|
30
|
-
--cb-reject: #374151;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/* ───── Banner ───── */
|
|
34
|
-
|
|
35
|
-
#astro-consent-banner {
|
|
36
|
-
position: fixed;
|
|
37
|
-
left: 16px;
|
|
38
|
-
right: 16px;
|
|
39
|
-
bottom: 16px;
|
|
40
|
-
z-index: 9999;
|
|
41
|
-
font-family: system-ui,-apple-system,BlinkMacSystemFont,sans-serif;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.cb-container {
|
|
45
|
-
max-width: 1200px;
|
|
46
|
-
margin: 0 auto;
|
|
47
|
-
padding: 20px 24px;
|
|
48
|
-
display: flex;
|
|
49
|
-
gap: 24px;
|
|
50
|
-
justify-content: space-between;
|
|
51
|
-
align-items: center;
|
|
52
|
-
|
|
53
|
-
background: var(--cb-bg);
|
|
54
|
-
backdrop-filter: blur(14px);
|
|
55
|
-
border-radius: 16px;
|
|
56
|
-
border: 1px solid var(--cb-border);
|
|
57
|
-
box-shadow: 0 20px 40px rgba(0,0,0,.35);
|
|
58
|
-
|
|
59
|
-
color: var(--cb-text);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.cb-text {
|
|
63
|
-
max-width: 760px;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.cb-title {
|
|
67
|
-
font-size: 16px;
|
|
68
|
-
font-weight: 600;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.cb-desc {
|
|
72
|
-
font-size: 14px;
|
|
73
|
-
color: var(--cb-muted);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.cb-desc a {
|
|
77
|
-
color: var(--cb-link);
|
|
78
|
-
text-decoration: none;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.cb-desc a:hover {
|
|
82
|
-
text-decoration: underline;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.cb-actions {
|
|
86
|
-
display: flex;
|
|
87
|
-
gap: 10px;
|
|
88
|
-
flex-shrink: 0;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.cb-actions button {
|
|
92
|
-
padding: 10px 18px;
|
|
93
|
-
border-radius: 999px;
|
|
94
|
-
border: 0;
|
|
95
|
-
font-size: 14px;
|
|
96
|
-
font-weight: 600;
|
|
97
|
-
cursor: pointer;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.cb-accept {
|
|
101
|
-
background: var(--cb-accept);
|
|
102
|
-
color: #052e16;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.cb-reject {
|
|
106
|
-
background: var(--cb-reject);
|
|
107
|
-
color: #e5e7eb;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.cb-manage {
|
|
111
|
-
background: transparent;
|
|
112
|
-
color: var(--cb-text);
|
|
113
|
-
border: 1px solid var(--cb-border);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/* ───── Modal ───── */
|
|
117
|
-
|
|
118
|
-
#astro-consent-modal {
|
|
119
|
-
position: fixed;
|
|
120
|
-
inset: 0;
|
|
121
|
-
background: rgba(0,0,0,.55);
|
|
122
|
-
display: flex;
|
|
123
|
-
align-items: center;
|
|
124
|
-
justify-content: center;
|
|
125
|
-
z-index: 10000;
|
|
126
|
-
font-family: system-ui,-apple-system,BlinkMacSystemFont,sans-serif;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.cb-modal {
|
|
130
|
-
width: 100%;
|
|
131
|
-
max-width: 480px;
|
|
132
|
-
background: #0c1220;
|
|
133
|
-
border-radius: 18px;
|
|
134
|
-
padding: 24px;
|
|
135
|
-
border: 1px solid var(--cb-border);
|
|
136
|
-
color: var(--cb-text);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.cb-row {
|
|
140
|
-
display: flex;
|
|
141
|
-
justify-content: space-between;
|
|
142
|
-
align-items: center;
|
|
143
|
-
padding: 12px 0;
|
|
144
|
-
border-bottom: 1px solid var(--cb-border);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.cb-row:last-child {
|
|
148
|
-
border-bottom: 0;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.cb-toggle {
|
|
152
|
-
width: 44px;
|
|
153
|
-
height: 24px;
|
|
154
|
-
background: #374151;
|
|
155
|
-
border-radius: 999px;
|
|
156
|
-
position: relative;
|
|
157
|
-
cursor: pointer;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.cb-toggle span {
|
|
161
|
-
position: absolute;
|
|
162
|
-
width: 18px;
|
|
163
|
-
height: 18px;
|
|
164
|
-
background: #fff;
|
|
165
|
-
border-radius: 50%;
|
|
166
|
-
top: 3px;
|
|
167
|
-
left: 3px;
|
|
168
|
-
transition: transform .2s;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
.cb-toggle.active {
|
|
172
|
-
background: var(--cb-accept);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.cb-toggle.active span {
|
|
176
|
-
transform: translateX(20px);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
@media (max-width: 640px) {
|
|
180
|
-
.cb-container {
|
|
181
|
-
flex-direction: column;
|
|
182
|
-
align-items: stretch;
|
|
183
|
-
gap: 16px;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
\`;
|
|
187
|
-
document.head.appendChild(style);
|
|
188
|
-
`);
|
|
20
|
+
injectScript("head-inline", `@import "/src/cookiebanner.css";`);
|
|
189
21
|
/* ─────────────────────────────────────
|
|
190
|
-
Consent runtime
|
|
22
|
+
Consent runtime (NO CSS)
|
|
191
23
|
───────────────────────────────────── */
|
|
192
24
|
injectScript("page", `
|
|
193
25
|
(() => {
|
|
194
26
|
const KEY = "${storageKey}";
|
|
195
27
|
const TTL = ${ttl};
|
|
196
28
|
|
|
197
|
-
function now(){ return Date.now(); }
|
|
29
|
+
function now() { return Date.now(); }
|
|
198
30
|
|
|
199
|
-
function read(){
|
|
200
|
-
try{
|
|
31
|
+
function read() {
|
|
32
|
+
try {
|
|
201
33
|
const raw = localStorage.getItem(KEY);
|
|
202
|
-
if(!raw) return null;
|
|
34
|
+
if (!raw) return null;
|
|
203
35
|
const data = JSON.parse(raw);
|
|
204
|
-
if(data.expiresAt < now()){
|
|
36
|
+
if (data.expiresAt < now()) {
|
|
205
37
|
localStorage.removeItem(KEY);
|
|
206
38
|
return null;
|
|
207
39
|
}
|
|
208
40
|
return data;
|
|
209
|
-
}catch{
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
210
44
|
}
|
|
211
45
|
|
|
212
|
-
function write(categories){
|
|
46
|
+
function write(categories) {
|
|
213
47
|
localStorage.setItem(KEY, JSON.stringify({
|
|
214
48
|
updatedAt: now(),
|
|
215
49
|
expiresAt: now() + TTL,
|
|
@@ -220,7 +54,7 @@ document.head.appendChild(style);
|
|
|
220
54
|
window.astroConsent = {
|
|
221
55
|
get: read,
|
|
222
56
|
set: write,
|
|
223
|
-
reset(){
|
|
57
|
+
reset() {
|
|
224
58
|
localStorage.removeItem(KEY);
|
|
225
59
|
location.reload();
|
|
226
60
|
}
|
|
@@ -228,7 +62,7 @@ document.head.appendChild(style);
|
|
|
228
62
|
})();
|
|
229
63
|
`);
|
|
230
64
|
/* ─────────────────────────────────────
|
|
231
|
-
Banner + modal UI
|
|
65
|
+
Banner + modal UI (NO CSS)
|
|
232
66
|
───────────────────────────────────── */
|
|
233
67
|
injectScript("page", `
|
|
234
68
|
(() => {
|
|
@@ -241,7 +75,7 @@ document.head.appendChild(style);
|
|
|
241
75
|
|
|
242
76
|
banner.innerHTML = \`
|
|
243
77
|
<div class="cb-container">
|
|
244
|
-
<div
|
|
78
|
+
<div>
|
|
245
79
|
<div class="cb-title">${siteName} uses cookies</div>
|
|
246
80
|
<div class="cb-desc">
|
|
247
81
|
Choose how your data is used.
|
|
@@ -259,18 +93,18 @@ document.head.appendChild(style);
|
|
|
259
93
|
document.body.appendChild(banner);
|
|
260
94
|
|
|
261
95
|
banner.querySelector(".cb-accept").onclick = () => {
|
|
262
|
-
window.astroConsent.set({ essential:true, analytics:true, marketing:true });
|
|
96
|
+
window.astroConsent.set({ essential: true, analytics: true, marketing: true });
|
|
263
97
|
banner.remove();
|
|
264
98
|
};
|
|
265
99
|
|
|
266
100
|
banner.querySelector(".cb-reject").onclick = () => {
|
|
267
|
-
window.astroConsent.set({ essential:true });
|
|
101
|
+
window.astroConsent.set({ essential: true });
|
|
268
102
|
banner.remove();
|
|
269
103
|
};
|
|
270
104
|
|
|
271
105
|
banner.querySelector(".cb-manage").onclick = openModal;
|
|
272
106
|
|
|
273
|
-
function openModal(){
|
|
107
|
+
function openModal() {
|
|
274
108
|
const modal = document.createElement("div");
|
|
275
109
|
modal.id = "astro-consent-modal";
|
|
276
110
|
|
|
@@ -293,7 +127,7 @@ document.head.appendChild(style);
|
|
|
293
127
|
<div class="cb-toggle" data-key="marketing"><span></span></div>
|
|
294
128
|
</div>
|
|
295
129
|
|
|
296
|
-
<div class="cb-actions"
|
|
130
|
+
<div class="cb-actions">
|
|
297
131
|
<button class="cb-accept">Save preferences</button>
|
|
298
132
|
</div>
|
|
299
133
|
</div>
|
|
@@ -303,7 +137,7 @@ document.head.appendChild(style);
|
|
|
303
137
|
|
|
304
138
|
modal.querySelectorAll(".cb-toggle").forEach(toggle => {
|
|
305
139
|
const key = toggle.getAttribute("data-key");
|
|
306
|
-
if(state[key]) toggle.classList.add("active");
|
|
140
|
+
if (state[key]) toggle.classList.add("active");
|
|
307
141
|
|
|
308
142
|
toggle.onclick = () => {
|
|
309
143
|
state[key] = !state[key];
|
|
@@ -312,13 +146,13 @@ document.head.appendChild(style);
|
|
|
312
146
|
});
|
|
313
147
|
|
|
314
148
|
modal.querySelector(".cb-accept").onclick = () => {
|
|
315
|
-
window.astroConsent.set({ essential:true, ...state });
|
|
149
|
+
window.astroConsent.set({ essential: true, ...state });
|
|
316
150
|
modal.remove();
|
|
317
151
|
banner.remove();
|
|
318
152
|
};
|
|
319
153
|
|
|
320
154
|
modal.onclick = e => {
|
|
321
|
-
if(e.target === modal) modal.remove();
|
|
155
|
+
if (e.target === modal) modal.remove();
|
|
322
156
|
};
|
|
323
157
|
}
|
|
324
158
|
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-consent",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "A privacy-first, GDPR-compliant cookie consent banner for Astro with a built-in preferences modal, zero dependencies, and full theme control.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": {
|