@getvitops/astro 4.1.0 → 6.0.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,292 @@
1
1
  # @getvitops/astro
2
2
 
3
+ ## 6.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Carousel rework: a scroll strip that is operable and discoverable with no JS in every engine, and
8
+ real controls where the scroll-marker pseudo-elements are missing.
9
+
10
+ `::scroll-button()`, `::scroll-marker` and `::scroll-marker-group` are still Chromium-only, and
11
+ there is no usable polyfill (the one prototype targets the superseded syntax and only re-parses
12
+ inline `<style>` elements). So the carousel no longer assumes them: `<wc-carousel>` builds real
13
+ prev/next `<button>`s and a real dot nav where they are absent, styled from the same declarations
14
+ as the native ones. Which branch is live is decided **by the stylesheet** — one `@supports` sets
15
+ `--carousel-native-nav: 1` and the element reads it back — so the condition is written once and
16
+ the two cannot disagree.
17
+
18
+ **Breaking — `.carousel` is now a shell and `.carousel__track` is the scroller** (all formats). The
19
+ hint and the controls need a home outside the scrollport, and absolute positioning against the
20
+ shell replaces `position: fixed` + `anchor-name`/`position-area`, which pinned controls to a
21
+ viewport corner in any engine without anchor positioning. The 5.x single-element form is still
22
+ styled via `:not(:has(> .carousel__track))` and is promoted by the element at runtime, but it is
23
+ deprecated: wrap your slides in `<ul class="carousel__track">`.
24
+
25
+ **Breaking — looping is opt-in.** `<wc-carousel loop>` clones the slides; the default no longer
26
+ does. Cloning triples the markup, duplicates every image element and makes the scrollbar report 3×
27
+ the real content. `autoplay` implies `loop`. Migration: add `loop`.
28
+
29
+ **Breaking — `[part='autoplay']` is now `.carousel__autoplay`** (aliased for one release; `part`
30
+ only crosses a shadow boundary and this element is light DOM, so it was never a part). The button
31
+ is also a child of the shell rather than the track, where it used to occupy a slide-width column.
32
+
33
+ **Breaking — the host role is `group`, not `region`.** `region` is a landmark, so every carousel
34
+ grew an entry in the landmark list. Pass `landmark` to `<Carousel />` where it really is one.
35
+
36
+ **Changed (visual)** — the scrollbar is visible by default (`scrollbar-width: thin`, was `none`)
37
+ and a "Scroll for more" hint renders above the strip; both dim once the visitor scrolls, via a
38
+ scroll-progress timeline where available and a `data-scrolled` attribute otherwise. Opt out with
39
+ `.carousel--no-scrollbar` and `hint={false}`. `@getvitops/core`'s `global.css` also gains a narrow
40
+ media reset (`max-inline-size: 100%` on replaced elements, `block-size: auto` on `img`/`video`) —
41
+ deliberately without `display: block`, which would change inline images in prose.
42
+
43
+ **Added** — `@getvitops/astro/components/Carousel.astro`, a tier-3 wrapper emitting semantic
44
+ `<ul>`/`<li>`/`<figure>` markup with the right per-slide image priorities: the first slide eager
45
+ and high (the LCP candidate), the rest `lazy`/`low`/`async`. `loading="lazy"` is honoured for
46
+ images clipped by a horizontal scroll container, so off-screen slides defer with no JavaScript at
47
+ all. Also new: `carousel--markers-below` and `carousel--no-scrollbar`, and
48
+ `--carousel-slide-aspect`, which keeps slide heights equal whatever each image's aspect ratio is.
49
+
50
+ **Fixed** — `::scroll-button()` glyphs sat off-centre in their circles (`global.css`'s `*` reset
51
+ does not reach a pseudo-element, so the button was `content-box` with the UA's `padding: 1px 6px`
52
+ and `inline-size` + `aspect-ratio` sized an ellipse); the hover state was a no-op (it set the same
53
+ token as the base rule); slide heights varied with each image's aspect ratio; navigation used
54
+ physical `left`/`right` and so put "previous" on the wrong side in RTL; cloned slides duplicated
55
+ their `id`s; and `scrollBy(clientWidth)` overshot whenever `--carousel-slide-size` was not `100%`.
56
+
57
+ ### Patch Changes
58
+
59
+ - Updated dependencies
60
+ - @getvitops/core@6.0.0
61
+ - @getvitops/generator@6.0.0
62
+ - @getvitops/vite@6.0.0
63
+ - @getvitops/utils@6.0.0
64
+
65
+ ## 5.0.0
66
+
67
+ ### Major Changes
68
+
69
+ - **Dangling token references are now a build failure.** `validate()` resolves every `var(--…)` a
70
+ config authors — in `patterns.defaults` / `radii` / `groups` / `items.*.{base,overrides,states}`,
71
+ `typography.roles` and `shadows` — against the tokens that config actually emits. A reference to a
72
+ token that does not exist used to validate, generate, minify and ship, then resolve to nothing in
73
+ the browser: one downstream config shipped a `.cta` whose `color` fell back to `inherit` on a brand
74
+ fill (unreadable text on every filled button), and two of its four dead references had been dead for
75
+ several releases with nothing ever reporting them.
76
+
77
+ The check is deliberately anchored to the namespaces the generator owns — `--color-*`, `--shadow-*`,
78
+ `--z-tier-*`, `--surface-glass`, `--overlay` — the same discipline `vitops lint` follows. A pattern
79
+ may legitimately reference a framework token from `@getvitops/core` or a hook of your own, and
80
+ enumerating "every valid token" would make those false positives. A reference carrying a fallback
81
+ (`var(--x, 0.25rem)`) is never flagged: that is you saying what happens when the token is absent.
82
+ Errors name the config path and suggest the nearest token that does exist.
83
+
84
+ Two related diagnostics ship with it:
85
+ - **Pre-1.0 colour-grammar references are reported as one rename table**, not as a dozen separate
86
+ "no such token" errors — the shape the 3.0 flat-config detector uses, applied to the 1.0 colour
87
+ change. It is built from your own role names, and it says to apply the renames _simultaneously_,
88
+ because several of them rotate (`--surface-bg` → `--color-bg-surface-muted`,
89
+ `--surface-bg-bold` → `--color-bg-surface`) and sequential replacement compounds them.
90
+ - **A surface-shaped role declared chromatic now warns.** A bare hue string is shorthand for
91
+ `kind: "chromatic"`, which emits no bare `--color-bg-<role>` and no `.bg-<role>` — so writing
92
+ `"surface": "ink"` silently removed `--color-bg-surface` and the 36 references the framework's own
93
+ CSS makes to it. Relatedly, `--surface-glass`, `--overlay` and `.glass` are no longer emitted when
94
+ `surface` is chromatic: they read `--color-bg-surface`, so emitting them pointed at nothing.
95
+
96
+ **`vitops lint --fix` is now the migration tool.** It reads `var(--…)` out of CSS and `<style>`
97
+ blocks (not just `class` attributes) and rewrites pre-1.0 token references in a **single pass**, so
98
+ the rotating renames cannot compound. Nothing else is rewritten — every other finding it reports is
99
+ a judgement call. Run it after a major bump.
100
+
101
+ **`--help` works on every subcommand.** `vitops lint --help` used to exit non-zero with
102
+ `Unknown option '--help'`; every leaf subcommand parsed its own argv strictly and none declared the
103
+ option. It is now answered before dispatch, so no command can forget it, and a drift guard fails the
104
+ build if a command has no documented options. (`validate`'s options were genuinely undocumented and
105
+ now are.)
106
+
107
+ **The Astro integration reads `site.tracking` and `site.legal.cookieConsent`.** These drive the
108
+ generated cookie notice, while `vitops({ consent, tracking })` drove the runtime — two hand-synced
109
+ declarations of the same fact with nothing comparing them, so a site could ship a notice naming
110
+ categories its banner never offered, or disclosing an `_ac` cookie no capture script ever wrote, and
111
+ the build was clean. The config blocks are now defaults (as `css` / `fonts` / `favicon` / `ads`
112
+ already were) and a genuine contradiction — `true` against `false` on the same fact — **fails the
113
+ build**, naming both sides. An absent option is not a contradiction; it just takes the config's
114
+ value.
115
+
116
+ Also fixed, each from a downstream report:
117
+ - **`@getvitops/astro/tracking`** re-exports `@getvitops/utils/tracking` (plus `TRACKING_ENDPOINT`),
118
+ so the documented conversion flow works with one install. Under strict pnpm app code cannot
119
+ resolve a transitive dependency, and the obvious workaround — importing the same symbols from the
120
+ package index — is the one that drags the integration's Node builtins toward a Worker bundle. This
121
+ entry and `./routes` are both clean.
122
+ - **`createConversionRoute`'s example was broken on every supported Astro.** It read the binding off
123
+ `locals.runtime.env`, removed in Astro v6, while the package peers on `>= 7` — and because the
124
+ throw precedes the response, Astro re-reads the request and reports a misleading "Body has already
125
+ been used". It also called a `toNotifyContext()` helper that does not exist. The example now uses
126
+ `import { env } from 'cloudflare:workers'` and a plain `NotifyContext`.
127
+ - **`/api/track` is exported as `TRACKING_ENDPOINT`**, and the integration warns at build when
128
+ tracking is on and no route answers it. It was a bare literal inside the inlined capture script:
129
+ name the route file anything else and every `tel:` beacon 404s, conversions vanish, and nothing
130
+ errors anywhere.
131
+ - **`describeEvent` no longer reports "from Unknown"** for forms that don't have a field literally
132
+ named `name`. It now falls back through `first_name`/`last_name`, `full_name`, and finally the
133
+ email address.
134
+ - **`sendEmail` takes `timeoutMs` (default 10s).** `binding.send()` had no deadline, so one hung
135
+ attempt hung the request that produced it — indefinitely, in the one module otherwise built on
136
+ always saying why. A timeout is retried, like any other transient failure.
137
+ - **`vitops search notify` warns when the sitemap's URLs aren't on the configured origin.** A 404
138
+ fails loudly; a well-formed sitemap belonging to someone else did not — a route collision served a
139
+ valid document listing another site's pages and the run reported a healthy submission. Surfaces at
140
+ `--dry`.
141
+ - **`require()` warns when the page has no `<wc-consent>`.** The demand can never be granted, so
142
+ whatever waited on it never runs — silently. Hit by rendering `<Tracking />` on pages where
143
+ `<CookieConsent />` wasn't.
144
+ - **`vitops agents` no longer writes a path it guessed.** It used to warn and then write "tokens
145
+ live in `design-system.json`" into a project whose tokens are in `company.json`, with the four
146
+ emitted `vitops generate` commands hard-coded to match — copy-paste-broken in exactly the projects
147
+ that most need the block to be right. It now finds the config by shape, interpolates the resolved
148
+ path into every emitted command, and fails rather than guessing when there is nothing to name.
149
+ - **`vitops search setup --dry` and `vitops ads setup --dry` run without credentials.** A dry run
150
+ that mutates nothing should not demand the token to mutate; with none set it plans from scratch
151
+ and says so. (`--check` still needs them — drift is a comparison against live state.) Both now
152
+ also mention that the Cloudflare token needs `Zone:Read` alongside `Zone:DNS:Edit` — the
153
+ zone-by-name lookup uses it, and its absence read as "the zone isn't in this account".
154
+ - **`vitops legal` names the files it wrote and flags new ones.** Enabling `cookieConsent` silently
155
+ produced a `cookie-notice` document that then needs a page, a route, a link and a `policyUrl`; the
156
+ command said only "3 files". The review reminder is also printed on the stdout path, where it was
157
+ missing entirely.
158
+ - **`vitops init` writes a versioned `$schema`** — `./node_modules/@getvitops/generator/schema.json`,
159
+ following wrangler — instead of an unpinned unpkg URL that resolved to whatever was newest, so an
160
+ editor validated a pinned project against a schema it wasn't built with.
161
+ - **`favicon.backgroundColor` and `favicon.name` are described accurately.** `backgroundColor` is
162
+ not manifest-only: it fills the opaque `apple-touch-icon.png` and `icon-mask.png`, which are
163
+ written whether or not a manifest is. `name` documents that it and `themeColor` **together** are
164
+ what make a site installable. The missing-background warning now also fires for a dark opaque mark,
165
+ not only a transparent source — `apple-touch-icon` insets the logo and fills the surround either
166
+ way.
167
+
168
+ - **The framework now says out loud which patterns are foundational, and reports it when you
169
+ reach past them.** From repeated downstream reports: sites were inventing a `.wrap` class and
170
+ using it everywhere instead of `.centered`, and `.subgrid` — the class for any set of cards —
171
+ was going essentially unused. Neither failure is visible in a build: every class involved is
172
+ real, nothing errors, and the page renders.
173
+
174
+ **`.subgrid` was missing from the generated class reference entirely.** So was `.cluster`, and
175
+ so was `.region`. `vitops docs classes` is the doc an agent is told to fetch for "which class
176
+ do I apply", and the framework's answer for a set of cards was not in it — which is most of why
177
+ it never got used. All three are now documented, along with `grid-auto`, and the reference opens
178
+ with a **Foundations** section that states the six substitutions as
179
+ _temptation → what to write instead_ rather than as a vocabulary list. The same table is now in
180
+ the shipped agent skill and in the `@getvitops/create` template's `AGENTS.md`, because a pointer
181
+ to a doc only helps someone who already suspects there is something to look up. (`css`/`bricks`
182
+ and `tailwind` alike — this is documentation and the `TIERS` manifest, not emitted CSS.)
183
+
184
+ **`vitops lint` gained three reuse rules and a markup pass.** The existing `.centered` rule only
185
+ fired when the hand-written CSS already referenced `--width-measure`, which is precisely the
186
+ author who was never going to hand-roll a container. It now also catches a page-scale
187
+ `max-width` (≥ 48rem, or a `ch` reading measure) with auto margins, and a
188
+ container-shaped class name — `wrap`, `wrapper`, `container`, `inner`, `shell`, … — carrying any
189
+ width cap at all. Reading the cap out of `min()` / `clamp()` too. New rules report a
190
+ hand-written `repeat()` grid as `.subgrid` (or `.grid-auto`), and a new **markup** pass reports a
191
+ repeated card set laid out without either — a loop that renders a card, or three or more cards
192
+ written out. That last one is the only check that can see this drift at all, since a card list
193
+ built from utility classes contains no bad class and no hand-written CSS.
194
+
195
+ All of these are `suggestion` severity, so they do not fail your build unless you pass
196
+ `--strict`. They found five real instances in this repo's own docs site.
197
+
198
+ **`vitops lint [files...]`** now takes explicit paths instead of scanning `--src`, so it can be
199
+ wired into a pre-commit hook — `vp`'s `staged` key appends the staged files to whatever it runs,
200
+ and a command that refused positionals could not be put in the one place the feedback lands at
201
+ the moment the code is written. Unreadable and non-source paths are skipped rather than fatal. The
202
+ `@getvitops/create` emdash template wires it up with `--strict` and adds a `lint:design` script.
203
+
204
+ **Two answers for "the whole card is a link", because one cannot exist.** Reported downstream:
205
+ agents dislike the `<li>` wrapper when a card is a link and write `<li><a class="card">` instead.
206
+ That shape is **wrong in a way that renders fine**, which is why it survives review — the `<li>`
207
+ is the grid item, so the anchor is an ordinary block inside it and the tranches within the anchor
208
+ never reach the parent's shared row lines. The alignment `.subgrid` exists for silently does not
209
+ happen, and the anchor does not fill the cell either. Putting the anchor in the grid's place
210
+ (`<ul><a></ul>`) is invalid HTML, so there was genuinely no correct shape to reach for.
211
+
212
+ There are now two, and they trade against each other because **no CSS-only technique can make a
213
+ whole card clickable and leave its text selectable** — a transparent overlay necessarily receives
214
+ the pointer-drag:
215
+
216
+ | Want | Use |
217
+ | ---------------------------------------- | ------------------------------------------- |
218
+ | zero JS, whole card clickable | `.stretched-link` — **text not selectable** |
219
+ | selectable text **and** a clickable card | `<Cards>` / `<wc-cards>` — needs JS |
220
+
221
+ `.stretched-link` goes on a link inside the card; its `::after` covers the card.
222
+ **`<wc-cards>` is a new tier-2 element** that adds no overlay and instead tells a click apart from
223
+ the end of a drag, so text selection survives. Its fallback is the card's own link, fully usable
224
+ with no JS, and the pointer cursor is applied by the element — so the affordance never appears
225
+ without the behaviour. `<Cards>` emits it for you. They are alternatives, never layered: with an
226
+ overlay present the JS has nothing to do, and `vitops lint` reports the combination. (All formats
227
+ — pattern partials, deliberately not `utilities.css`, which the tailwind format skips on the
228
+ invariant that everything left in it is a name Tailwind ships itself.)
229
+
230
+ ### Breaking
231
+ - **`<Subgrid />` renders its slot verbatim — author the `<li>` items yourself.**
232
+
233
+ ```diff
234
+ <Subgrid>
235
+ - <article class="card">…</article>
236
+ + <li class="card subgrid-card">…</li>
237
+ </Subgrid>
238
+ ```
239
+
240
+ It used to parse the slotted HTML and rebuild each child as an `<li>`, carrying over only
241
+ `class` and `style`. That existed solely because a `<ul>` may contain nothing else, and it cost
242
+ more than it bought: the child's tag was discarded, `id`/`data-*`/`aria-*` were silently
243
+ dropped, and `href` could not survive at all. Nothing is copied now, so nothing is lost. `as`
244
+ picks the container (`ul` by default, `ol`, `div`), and all other props are forwarded — they
245
+ were previously discarded, including `role`.
246
+
247
+ - **`<Subgrid />` and `<Tree />` now emit `role="list"`,** as does the Bricks `sitenav` element.
248
+ `list-style: none` stops Safari + VoiceOver announcing a `<ul>` as a list, so every marker-less
249
+ framework list was silently losing the semantics its `<ul>` was chosen for. If you hand-write
250
+ `.subgrid`, `.list`, `.facet-list`, `.nav-items`, `.collapse-menu` or `.tree` markup, add
251
+ `role="list"` yourself — the framework cannot add it to markup it does not render, and each
252
+ partial now says so at the `list-style` reset.
253
+ - **`<Cards />` no longer adds `class="card"` to slotted children,** because it no longer parses
254
+ them. Write the class on the item. It now emits `<wc-cards>` around a `<Subgrid>`, which is what
255
+ makes the whole card clickable — and like `<Tree />`, **it emits its own element, so do not wrap
256
+ it in `<wc-cards>` yourself.** It also previously passed a `role="list"` that `<Subgrid>` silently
257
+ discarded, so that never took effect.
258
+ - **`.subgrid-card` now sets `position: relative`**, so `stretched-link` inside it needs no extra
259
+ class. If you were absolutely positioning a descendant of a `.subgrid-card` against an ancestor
260
+ _outside_ that card, it will now resolve against the card. Move the positioning context
261
+ explicitly. (`css`/`bricks`/`tailwind` — the pattern partial is inlined into all three.) Not
262
+ reachable by `vitops lint --fix`: the fix depends on which ancestor you meant, which the
263
+ linter cannot know.
264
+
265
+ ### Fixed
266
+ - **`packages/generator/src/docs.ts` contained a literal NUL byte** (`CODE_SLOT`, written as the
267
+ raw character rather than an escape). libmagic classified the file as `data` rather than text, so
268
+ grep and ripgrep treated the largest doc emitter in the repo as **binary and silently skipped
269
+ it** — every search for a string in it returned nothing, with no error. It is now written as the `\u0000` escape.
270
+ Behaviour is identical; the file is searchable.
271
+ - **`.grid-auto` is documented.** It was a real framework class for auto-fit card grids with no
272
+ entry in the class reference, so the honest alternative to `subgrid` was as invisible as
273
+ `subgrid` itself.
274
+ - **`.raised` replaces the advice to use `.relative` above a `stretched-link` overlay**, which
275
+ could not work: a positioned element at `z-index: auto` does not rise above an explicit
276
+ `z-index` regardless of DOM order, so a second link or button in the card stayed underneath and
277
+ unclickable. `.raised` sets both, against the same `--z-tier-raised` token the overlay now uses
278
+ instead of a hard-coded `1`.
279
+
280
+ ### Patch Changes
281
+
282
+ - Updated dependencies
283
+ - Updated dependencies
284
+ - Updated dependencies
285
+ - @getvitops/generator@5.0.0
286
+ - @getvitops/utils@5.0.0
287
+ - @getvitops/core@5.0.0
288
+ - @getvitops/vite@5.0.0
289
+
3
290
  ## 4.1.0
4
291
 
5
292
  ### Minor Changes
package/README.md CHANGED
@@ -45,6 +45,28 @@ import Head from '@getvitops/astro/Head.astro';
45
45
  priority. It does **not** emit a stylesheet `<link>` — the integration imports the generated CSS into
46
46
  Astro's module graph and Astro emits that link itself.
47
47
 
48
+ ## Rendering mode
49
+
50
+ **Prefer `output: 'static'`** (Astro's default). Nothing this integration produces needs a server:
51
+ the CSS, favicons and web-component bundles are all build-time artifacts, and the components
52
+ progressively enhance markup that is already complete in the HTML. A static build also gives the
53
+ sitemap every route, since `@astrojs/sitemap` lists prerendered routes only.
54
+
55
+ Opt individual routes out with `export const prerender = false` where a page genuinely needs
56
+ per-request work — a form `POST` handler, an auth-gated page, per-visitor content. That needs an
57
+ adapter, but leaves the rest of the site static.
58
+
59
+ ```astro
60
+ ---
61
+ // src/pages/account.astro — server-rendered; every other page stays static
62
+ export const prerender = false;
63
+ ---
64
+ ```
65
+
66
+ **EmDash sites invert this**, because the CMS admin and API need a server: they run
67
+ `output: 'server'` and opt _into_ prerendering per route. See
68
+ [`@getvitops/emdash`](../emdash/README.md#rendering-mode).
69
+
48
70
  ## Options
49
71
 
50
72
  | option | default | does |
@@ -0,0 +1,3 @@
1
+ import { a as TRACKING_ENDPOINT } from "../tracking-DdEKExlE.mjs";
2
+ export * from "@getvitops/utils/tracking";
3
+ export { TRACKING_ENDPOINT };
@@ -0,0 +1,5 @@
1
+ import { n as TRACKING_ENDPOINT } from "../tracking-CmSfxWC3.mjs";
2
+
3
+ export * from "@getvitops/utils/tracking"
4
+
5
+ export { TRACKING_ENDPOINT };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import { i as TRACKING_COOKIE, n as ResolveTrackingContext, o as TrackingCategory, r as ResolvedTracking, s as resolveTracking, t as GetvitopsTrackingOptions } from "./tracking-DdEKExlE.mjs";
1
2
  import { LegalOutput, SiteFont, StylesheetFormat } from "@getvitops/generator";
2
3
  import { generateIconInclude } from "@getvitops/utils";
3
4
  import { AdProvider } from "@getvitops/utils/ads";
@@ -342,57 +343,6 @@ interface SeoContext {
342
343
  */
343
344
  declare function resolveSeo(defaults: GetvitopsSeoOptions, props: SeoProps, ctx: SeoContext): ResolvedSeo;
344
345
  //#endregion
345
- //#region src/tracking.d.ts
346
- /**
347
- * The `<Tracking />` resolution layer — tracking config in, what to emit out.
348
- *
349
- * Separate from `Tracking.astro` for the same reason `analytics.ts` is separate
350
- * from `Analytics.astro`: everything decidable is a pure function asserted in
351
- * `tracking.test.ts`, and the component only renders what this returns.
352
- *
353
- * The one decision here is **which consent category the `_ac` cookie waits on**,
354
- * and it is stated rather than inferred. `_ac` is a 90-day identifier tying a
355
- * visitor to the ad that brought them, so `marketing` is the default — but a site
356
- * using click IDs purely for its own campaign reporting may reasonably file it
357
- * under `analytics`, and that is the consumer's call to make, not ours to guess.
358
- */
359
- /** Which consent category the attribution cookie waits on. */
360
- type TrackingCategory = 'marketing' | 'analytics';
361
- interface GetvitopsTrackingOptions {
362
- /** Capture ad click IDs and UTMs into `_ac`. */
363
- enabled?: boolean;
364
- /** Default `marketing`. */
365
- category?: TrackingCategory;
366
- /** Informational; capture recognises every known click-ID parameter regardless. */
367
- platforms?: string[];
368
- }
369
- /** The cookie the capture script writes. Mirrors `TRACKING_COOKIE` in utils. */
370
- declare const TRACKING_COOKIE = "_ac";
371
- interface ResolvedTracking {
372
- enabled: boolean;
373
- category: TrackingCategory;
374
- /** Cookie names to clear on revoke — rides on `data-consent-cookies`. */
375
- cookies: string[];
376
- /** Configuration problems, as prose. The integration logs these. */
377
- warnings: string[];
378
- }
379
- interface ResolveTrackingContext {
380
- /** Is the consent gate enabled on this site (`vitops({ consent })`)? */
381
- consent?: boolean;
382
- /** Categories the banner offers, so we can catch a demand with no row. */
383
- consentCategories?: readonly string[];
384
- }
385
- /**
386
- * Resolve the tracking config into what the component emits.
387
- *
388
- * Two warnings, both about the same failure — a persistent identifier written
389
- * with no way for the visitor to decline, or a permission asked for with no way
390
- * to answer. Returned as data rather than logged here so the check is a test
391
- * rather than a line someone might scroll past, exactly as `resolveAnalytics`
392
- * does.
393
- */
394
- declare function resolveTracking(opts: GetvitopsTrackingOptions | undefined, ctx?: ResolveTrackingContext): ResolvedTracking;
395
- //#endregion
396
346
  //#region src/integration.d.ts
397
347
  interface GetvitopsFaviconOptions {
398
348
  /** Source SVG or PNG. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/analytics.ts","../src/seo.ts","../src/tracking.ts","../src/integration.ts","../src/ads.ts","../src/lastmod.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/analytics.ts","../src/seo.ts","../src/integration.ts","../src/ads.ts","../src/lastmod.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { n as TRACKING_ENDPOINT, r as resolveTracking, t as TRACKING_COOKIE } from "./tracking-CmSfxWC3.mjs";
1
2
  import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
3
  import { dirname, join, relative, resolve } from "node:path";
3
4
  import { fileURLToPath } from "node:url";
@@ -325,39 +326,6 @@ function resolveFonts(decls) {
325
326
  };
326
327
  }
327
328
 
328
- //#endregion
329
- //#region src/tracking.ts
330
- /** The cookie the capture script writes. Mirrors `TRACKING_COOKIE` in utils. */
331
- const TRACKING_COOKIE = "_ac";
332
- /**
333
- * Resolve the tracking config into what the component emits.
334
- *
335
- * Two warnings, both about the same failure — a persistent identifier written
336
- * with no way for the visitor to decline, or a permission asked for with no way
337
- * to answer. Returned as data rather than logged here so the check is a test
338
- * rather than a line someone might scroll past, exactly as `resolveAnalytics`
339
- * does.
340
- */
341
- function resolveTracking(opts, ctx = {}) {
342
- const warnings = [];
343
- const category = opts?.category ?? "marketing";
344
- const enabled = opts?.enabled === true;
345
- if (!enabled) return {
346
- enabled: false,
347
- category,
348
- cookies: [],
349
- warnings
350
- };
351
- if (!ctx.consent) warnings.push(`tracking is on, so this site writes the \`${"_ac"}\` cookie — a 90-day identifier tying a visitor to the ad that brought them — and \`consent\` is off, so it is written for every visitor with no way to decline. Set \`consent: true\`.`);
352
- else if (ctx.consentCategories && !ctx.consentCategories.includes(category)) warnings.push(`tracking demands the \`${category}\` consent category, but the banner offers ${ctx.consentCategories.join(", ") || "nothing"}. Add \`${category}\` to \`consent.categories\`, or the visitor is asked about something the banner never names.`);
353
- return {
354
- enabled,
355
- category,
356
- cookies: ["_ac"],
357
- warnings
358
- };
359
- }
360
-
361
329
  //#endregion
362
330
  //#region src/integration.ts
363
331
  /**
@@ -426,6 +394,73 @@ function readSiteAds(configPath, siteEnv) {
426
394
  return null;
427
395
  }
428
396
  }
397
+ /**
398
+ * The consent + tracking facts a site config already states.
399
+ *
400
+ * These were the one pair the integration did not read. `site.tracking` and
401
+ * `site.legal.cookieConsent` drive the **generated cookie notice**, while
402
+ * `vitops({ consent, tracking })` drove the **runtime** — two hand-synced
403
+ * declarations of the same fact with nothing checking them against each other.
404
+ * The failure that produces is precisely the one the rest of the toolchain is
405
+ * fastidious about avoiding: a site can ship a cookie notice naming categories
406
+ * its banner never offers, or promising attribution that no capture script
407
+ * implements, and the build is clean. That is a compliance defect, not a
408
+ * documentation gap.
409
+ *
410
+ * Read as DEFAULTS, the same as `css` / `fonts` / `favicon` / `ads` — the
411
+ * config is where a site's facts live, and an integration option is how you
412
+ * override one. A genuine contradiction is an error rather than a warning; see
413
+ * `consentTrackingConflicts`.
414
+ */
415
+ function readSiteConsentTracking(configPath, siteEnv) {
416
+ try {
417
+ const cfg = resolveConfig(JSON.parse(readFileSync(configPath, "utf8")), siteEnv);
418
+ const t = cfg.site.tracking;
419
+ const cc = cfg.site.legal?.cookieConsent;
420
+ if (!t && !cc) return null;
421
+ return {
422
+ ...t ? { tracking: t } : {},
423
+ ...cc ? { consentEnabled: cc.enabled } : {},
424
+ ...cc?.categories ? { categories: cc.categories } : {}
425
+ };
426
+ } catch {
427
+ return null;
428
+ }
429
+ }
430
+ /**
431
+ * Contradictions between the config and an explicit integration option.
432
+ *
433
+ * Absent-vs-present is a default and resolves silently. `true` vs `false` on the
434
+ * same fact is not resolvable — one of the two documents is wrong, and picking
435
+ * either quietly is how a notice and a banner get out of step. The message names
436
+ * both sides so the fix does not require guessing which one won.
437
+ */
438
+ function consentTrackingConflicts(site, opts, configPath) {
439
+ const out = [];
440
+ const optConsent = opts.consent === void 0 ? void 0 : !!opts.consent;
441
+ if (site.consentEnabled !== void 0 && optConsent !== void 0 && site.consentEnabled !== optConsent) out.push(`consent: ${configPath} sets site.legal.cookieConsent.enabled: ${site.consentEnabled}, but vitops({ consent: ${optConsent} }) says the opposite. The generated cookie notice follows the config and the banner follows the option, so one of them would describe a site that does not exist. Set them the same, or drop the option and let the config decide.`);
442
+ const optTracking = opts.tracking === void 0 ? void 0 : opts.tracking === true ? true : opts.tracking === false ? false : opts.tracking.enabled ?? true;
443
+ if (site.tracking?.enabled !== void 0 && optTracking !== void 0 && site.tracking.enabled !== optTracking) out.push(`tracking: ${configPath} sets site.tracking.enabled: ${site.tracking.enabled}, but vitops({ tracking: ${optTracking} }) says the opposite. The cookie notice discloses \`_ac\` from the config while the capture script ships from the option — so the site would either disclose a cookie it never sets, or set one it never discloses.`);
444
+ return out;
445
+ }
446
+ /**
447
+ * Does a route answer `TRACKING_ENDPOINT`?
448
+ *
449
+ * Checked by filename rather than through Astro's route manifest, because this
450
+ * runs in `astro:config:setup` — before routes are collected. The extension set
451
+ * covers the ways a consumer can author the same endpoint; a false negative
452
+ * costs a warning, a false positive costs the whole point of the check, so this
453
+ * errs toward looking in more places.
454
+ */
455
+ function hasConversionRoute(root) {
456
+ const base = resolve(root, "src/pages", TRACKING_ENDPOINT.replace(/^\//, ""));
457
+ return [
458
+ ".ts",
459
+ ".js",
460
+ ".mjs",
461
+ ".astro"
462
+ ].some((ext) => existsSync(`${base}${ext}`) || existsSync(join(base, `index${ext}`)));
463
+ }
429
464
  const VIRTUAL_ID = "virtual:getvitops/head";
430
465
  const RESOLVED_ID = `\0${VIRTUAL_ID}`;
431
466
  function virtualHeadPlugin(data) {
@@ -516,10 +551,15 @@ function vitops(opts = {}) {
516
551
  if (!config.site) logger.warn("seo: needs the `site` astro.config option (your deployed URL) — without it <Seo /> omits canonical, og:url and any relative og:image rather than guessing an origin.");
517
552
  if (config.integrations.some((i) => i.name === "emdash")) logger.warn("seo: emdash() is registered, and its <EmDashHead> emits the same title/description/canonical/og tags from the CMS. Use one or the other — rendering both duplicates every tag.");
518
553
  }
519
- const consentEnabled = !!opts.consent;
520
- const consentOpts = typeof opts.consent === "object" ? opts.consent : {};
554
+ const siteConsent = siteInput ? readSiteConsentTracking(resolve(root, siteInput), opts.site?.siteEnv ?? "production") : null;
555
+ if (siteConsent) {
556
+ const conflicts = consentTrackingConflicts(siteConsent, opts, siteInput);
557
+ if (conflicts.length) throw new Error(`vitops: the site config and the integration options disagree about consent.\n\n` + conflicts.map((c) => ` • ${c}`).join("\n\n"));
558
+ }
559
+ const consentEnabled = opts.consent !== void 0 ? !!opts.consent : !!siteConsent?.consentEnabled;
560
+ const consentOpts = typeof opts.consent === "object" ? opts.consent : siteConsent?.categories ? { categories: siteConsent.categories } : {};
521
561
  const analytics = resolveAnalytics(opts.analytics, { consent: consentEnabled });
522
- const trackingOpts = opts.tracking === true ? { enabled: true } : opts.tracking || void 0;
562
+ const trackingOpts = opts.tracking === true ? { enabled: true } : opts.tracking || (siteConsent?.tracking?.enabled ? siteConsent.tracking : void 0);
523
563
  const adsConfig = siteInput ? readSiteAds(resolve(root, siteInput), opts.site?.siteEnv ?? "production") : null;
524
564
  const detectedCategories = consentCategories([...analytics.tags, ...resolveAds(adsConfig?.properties, {
525
565
  consent: consentEnabled,
@@ -535,6 +575,7 @@ function vitops(opts = {}) {
535
575
  consentCategories: offeredCategories
536
576
  });
537
577
  for (const warning of tracking.warnings) logger.warn(warning);
578
+ if (tracking.enabled && !hasConversionRoute(root)) logger.warn(`tracking is on, so the capture script beacons \`tel:\` conversions to ${TRACKING_ENDPOINT}, but no route answers that path. Add \`src/pages/api/track.ts\` exporting \`createConversionRoute(...)\` from \`@getvitops/astro/routes\` — otherwise every call conversion is silently lost.`);
538
579
  const ads = resolveAds(adsConfig?.properties, {
539
580
  consent: consentEnabled,
540
581
  consentCategories: offeredCategories,