@getvitops/astro 0.9.0 → 2.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/dist/index.d.mts CHANGED
@@ -1,7 +1,328 @@
1
- import { Format } from "@getvitops/generator";
1
+ import { LegalOutput, SiteFont, StylesheetFormat } from "@getvitops/generator";
2
+ import { generateIconInclude } from "@getvitops/utils";
2
3
  import { AstroIntegration } from "astro";
3
4
  export * from "@getvitops/utils";
4
5
 
6
+ //#region src/analytics.d.ts
7
+ /**
8
+ * The `<Analytics />` resolution layer — provider config in, the exact tags to
9
+ * emit out.
10
+ *
11
+ * Kept separate from `Analytics.astro` for the same reason `seo.ts` is separate
12
+ * from `Seo.astro`: everything decidable is a pure function and asserted in
13
+ * `analytics.test.ts`, and the component only renders what this returns.
14
+ *
15
+ * Two properties here are the point of the whole file:
16
+ *
17
+ * - **Which consent category a provider needs is derived, never declared.** It
18
+ * follows from whether that provider sets cookies, which follows from its own
19
+ * configuration (Matomo with `disableCookies` is genuinely cookieless; Matomo
20
+ * with `cookies: true` is not). A consumer cannot mark Google Analytics
21
+ * `necessary` to skip a banner, because `setsCookies` isn't theirs to set.
22
+ * - **The same fact drives the legal documents.** `@getvitops/generator`'s
23
+ * `legal/providers.ts` maps the *site config's* `analytics` block onto named
24
+ * processors with cookie lists. If a provider is configured here but not
25
+ * there, the site runs a tag its own cookie notice doesn't disclose — so the
26
+ * integration warns, and `warnings` is returned as data so that check is a
27
+ * test rather than a log line someone might scroll past.
28
+ */
29
+ /**
30
+ * When a tag is allowed to load. Third-party analytics is never worth a
31
+ * millisecond of the critical path, so the default puts every tag after `load`.
32
+ */
33
+ type AnalyticsStrategy = 'idle' | 'async' | 'interaction';
34
+ /**
35
+ * The consent vocabulary, mirroring `@getvitops/core`'s `consent/store.ts`.
36
+ * Mirrored rather than imported because this value is `JSON.stringify`d into the
37
+ * virtual module and the component reads it at build time, while core's copy is a
38
+ * browser runtime — `consent.test.ts` and `analytics.test.ts` pin both ends.
39
+ */
40
+ type ConsentCategory = 'necessary' | 'analytics' | 'marketing' | 'preferences';
41
+ type OptionalConsentCategory = Exclude<ConsentCategory, 'necessary'>;
42
+ interface GoogleAnalyticsOptions {
43
+ /** Measurement ID, e.g. `G-XXXXXXXXXX`. */
44
+ id: string;
45
+ /**
46
+ * Which category gates it (default `analytics`). Set `marketing` when the
47
+ * property feeds Google Ads — the tag is the same, the permission isn't.
48
+ */
49
+ category?: OptionalConsentCategory;
50
+ /** Extra `gtag('config', id, …)` parameters, e.g. `{ send_page_view: false }`. */
51
+ config?: Record<string, string | number | boolean>;
52
+ }
53
+ interface ClarityOptions {
54
+ /** Clarity project ID. */
55
+ id: string;
56
+ category?: OptionalConsentCategory;
57
+ }
58
+ interface MatomoOptions {
59
+ /** Instance base URL — self-hosted, or `https://<you>.matomo.cloud`. */
60
+ url: string;
61
+ /** Site ID within that instance. */
62
+ siteId: string | number;
63
+ /**
64
+ * Let Matomo set its cookies (default **false**).
65
+ *
66
+ * The default is what makes Matomo the cookieless option: with
67
+ * `disableCookies` it stores no identifier on the device, needs no banner, and
68
+ * the generated cookie notice can state positively that it sets none. Turning
69
+ * this on gives you returning-visitor metrics and a consent obligation.
70
+ */
71
+ cookies?: boolean;
72
+ }
73
+ interface PlausibleOptions {
74
+ /** The domain as registered in Plausible, e.g. `example.com`. */
75
+ domain: string;
76
+ /** Script URL — override for a self-hosted instance or a custom-events build. */
77
+ src?: string;
78
+ }
79
+ interface GetvitopsAnalyticsOptions {
80
+ googleAnalytics?: string | GoogleAnalyticsOptions;
81
+ clarity?: string | ClarityOptions;
82
+ matomo?: MatomoOptions;
83
+ plausible?: string | PlausibleOptions;
84
+ /** When tags load (default `'idle'`). */
85
+ strategy?: AnalyticsStrategy;
86
+ }
87
+ /**
88
+ * The consent gate, configured on the integration rather than inside `analytics`.
89
+ *
90
+ * That placement is the design, not an accident: analytics is one consumer of
91
+ * consent, not its owner. A/B assignment, account personalisation and third-party
92
+ * embeds gate on the same choice via `data-consent`, and a site can enable the
93
+ * banner with no analytics configured at all.
94
+ */
95
+ interface GetvitopsConsentOptions {
96
+ /**
97
+ * Categories the banner offers. Defaults to the ones the configured providers
98
+ * actually need — offering a choice nothing is waiting on is noise.
99
+ */
100
+ categories?: OptionalConsentCategory[];
101
+ /** Link the banner to the cookie notice (`vitops legal` renders one). */
102
+ policyUrl?: string;
103
+ }
104
+ /** One tag, fully resolved. */
105
+ interface ResolvedTag {
106
+ key: 'googleAnalytics' | 'clarity' | 'matomo' | 'plausible';
107
+ /** The provider as a reader would recognise it — used in warnings. */
108
+ provider: string;
109
+ category: ConsentCategory;
110
+ setsCookies: boolean;
111
+ /** Names (or `prefix*` patterns) to clear when consent is withdrawn. */
112
+ cookies: string[];
113
+ strategy: AnalyticsStrategy;
114
+ /**
115
+ * Emitted inert (`type="text/plain"`) for the runtime to activate, rather than
116
+ * as a live `<script>`. False only for the one case that needs no runtime at
117
+ * all: a cookieless provider with `strategy: 'async'`.
118
+ */
119
+ gated: boolean;
120
+ /** Bootstrap JS. Runs before `src`, so a queue is populated before it drains. */
121
+ inline: string;
122
+ src: string | null;
123
+ attrs: Record<string, string>;
124
+ }
125
+ interface ResolvedAnalytics {
126
+ tags: ResolvedTag[];
127
+ /** Does anything here need `@getvitops/core/consent` loaded? */
128
+ needsRuntime: boolean;
129
+ /** Configuration problems, as prose. The integration logs these. */
130
+ warnings: string[];
131
+ }
132
+ interface ResolveAnalyticsContext {
133
+ /** Is the consent gate enabled on this site (`getvitops({ consent })`)? */
134
+ consent?: boolean;
135
+ }
136
+ /**
137
+ * Resolve the configured providers into the tags to emit.
138
+ *
139
+ * An invalid provider is dropped with a warning rather than throwing: one
140
+ * malformed ID should not take down a build, and a missing tag is visible in the
141
+ * output while a failed build is just a red wall.
142
+ */
143
+ declare function resolveAnalytics(opts: GetvitopsAnalyticsOptions | undefined, ctx?: ResolveAnalyticsContext): ResolvedAnalytics;
144
+ /** Which optional categories a set of tags actually needs a visitor to decide. */
145
+ declare function consentCategories(tags: ResolvedTag[]): OptionalConsentCategory[];
146
+ //#endregion
147
+ //#region src/seo.d.ts
148
+ /**
149
+ * The `<Seo />` resolution layer — site-level defaults merged with per-page props
150
+ * into the exact tags to emit.
151
+ *
152
+ * Kept separate from `Seo.astro` deliberately. The component this replaces
153
+ * (`SEO.astro`, deleted in c949cae) fused resolution with markup, which is why it
154
+ * was never unit-tested and why its title handling drifted: it computed a title
155
+ * for `og:title` but left `<title>` to the layout, so the two could disagree.
156
+ * Everything decidable lives here and is asserted in `seo.test.ts`; the component
157
+ * only renders what this returns.
158
+ */
159
+ /** Twitter card types, per <https://developer.x.com/en/docs/twitter-for-websites/cards>. */
160
+ type SeoTwitterCard = 'summary' | 'summary_large_image' | 'app' | 'player';
161
+ /** Open Graph object types this component knows how to describe. */
162
+ type SeoOgType = 'website' | 'article' | 'profile';
163
+ /**
164
+ * Site-level SEO defaults, passed to `getvitops({ seo })` and baked into the
165
+ * `virtual:getvitops/head` module. Per-page `<Seo />` props override these.
166
+ *
167
+ * The vocabulary mirrors the site-config schema's `seo` block
168
+ * (`@getvitops/generator`, `src/site.ts`) so a `SiteConfig` → these adapter would
169
+ * be a flat field map — but it is not imported from there. This is the
170
+ * integration's own option surface, and it must stay JSON-serialisable: it is
171
+ * `JSON.stringify`d into the virtual module, so no functions, no `URL`s, no dates.
172
+ */
173
+ interface GetvitopsSeoOptions {
174
+ /** `og:site_name`, and the `<title>` when a page passes none. */
175
+ siteName?: string;
176
+ /**
177
+ * Page-title pattern; `%s` is the page's own title. e.g. `'%s · Acme'`.
178
+ *
179
+ * Applies to `<title>` only. `og:title`/`twitter:title` get the untemplated
180
+ * title: a social card already shows `og:site_name` and the domain, so the
181
+ * suffix would sit directly above the brand it repeats. Override per page with
182
+ * `ogTitle`.
183
+ *
184
+ * Skipped when a page's title already equals `siteName` — a homepage titled
185
+ * "Acme" emits `Acme`, not `Acme · Acme` — and never applied to `defaultTitle`.
186
+ */
187
+ titleTemplate?: string;
188
+ /** `<title>` for pages that pass none. Used verbatim — the template is not applied. */
189
+ defaultTitle?: string;
190
+ /** `<meta name="description">` for pages that pass none. */
191
+ defaultDescription?: string;
192
+ /** Site-wide robots directive, e.g. `'index,follow,max-image-preview:large'`. */
193
+ robots?: string;
194
+ /** Google Search Console verification token. */
195
+ googleSiteVerification?: string;
196
+ /** Bing Webmaster Tools verification token. */
197
+ bingSiteVerification?: string;
198
+ openGraph?: {
199
+ /** Default `og:type` (default `'website'`). */type?: SeoOgType; /** `og:locale`. Written either way — `en-CA` and `en_CA` both emit `en_CA`. */
200
+ locale?: string; /** Additional locales the same content exists in → `og:locale:alternate`. */
201
+ localeAlternates?: string[]; /** Fallback share image. Relative URLs resolve against `site`. */
202
+ image?: {
203
+ url: string;
204
+ alt?: string;
205
+ width?: number;
206
+ height?: number;
207
+ type?: string;
208
+ };
209
+ };
210
+ twitter?: {
211
+ /** Card type when no image resolves (default `'summary'`). */card?: SeoTwitterCard; /** The site's own handle, `@acme`. */
212
+ site?: string; /** Default author handle, `@ada`. */
213
+ creator?: string;
214
+ };
215
+ }
216
+ /** Per-page `<Seo />` props. Everything is optional; defaults fill the gaps. */
217
+ interface SeoProps {
218
+ /** Page title, before `titleTemplate` is applied. */
219
+ title?: string;
220
+ /**
221
+ * `og:title`/`twitter:title`, when the social headline should differ from
222
+ * `title`. Defaults to `title` **without** `titleTemplate` — see the note on
223
+ * `titleTemplate` for why the suffix is dropped there.
224
+ */
225
+ ogTitle?: string;
226
+ description?: string;
227
+ /** Overrides the computed canonical. Relative values resolve against `site`. */
228
+ canonical?: string;
229
+ /** Overrides `og:site_name` and the title fallback. */
230
+ siteName?: string;
231
+ /** Share image for this page. Relative URLs resolve against `site`. */
232
+ image?: string;
233
+ imageAlt?: string;
234
+ imageWidth?: number;
235
+ imageHeight?: number;
236
+ /** MIME type of the share image, e.g. `'image/png'`. */
237
+ imageType?: string;
238
+ noindex?: boolean;
239
+ nofollow?: boolean;
240
+ noarchive?: boolean;
241
+ nocache?: boolean;
242
+ /** Extra robots directives, e.g. `'max-snippet:-1'`. Appended to the composed value. */
243
+ robotsExtras?: string;
244
+ /** Full robots override. Wins over the flags above and the site default. */
245
+ robots?: string;
246
+ /** `og:type` for this page (default: the site default, else `'website'`). */
247
+ type?: SeoOgType;
248
+ /** Emitted only when `type` is `'article'`. */
249
+ article?: {
250
+ publishedTime?: string;
251
+ modifiedTime?: string;
252
+ expirationTime?: string;
253
+ authors?: string[];
254
+ section?: string;
255
+ tags?: string[];
256
+ };
257
+ /** `og:locale` for this page. */
258
+ locale?: string;
259
+ /** Twitter author handle for this page, `@ada`. */
260
+ twitterCreator?: string;
261
+ /**
262
+ * Translations of *this* page, as `<link rel="alternate" hreflang>`.
263
+ *
264
+ * Explicit only, and it must include the current page. Nothing is inferred:
265
+ * the deleted component derived alternates from the site's locale list and
266
+ * pointed every one of them at that locale's homepage, so every page on the
267
+ * site claimed the homepage as its translation. Only the page knows its own
268
+ * translated URLs. Pass `hreflang: 'x-default'` for the fallback entry.
269
+ */
270
+ alternates?: {
271
+ hreflang: string;
272
+ href: string;
273
+ }[];
274
+ }
275
+ /** A `<meta property>` tag (Open Graph uses `property`, not `name`). */
276
+ interface SeoPropertyTag {
277
+ property: string;
278
+ content: string;
279
+ }
280
+ /** A `<meta name>` tag. */
281
+ interface SeoNameTag {
282
+ name: string;
283
+ content: string;
284
+ }
285
+ /** Everything `<Seo />` renders, already decided. `null` means "emit nothing". */
286
+ interface ResolvedSeo {
287
+ title: string | null;
288
+ /** `og:title`/`twitter:title` — the page title without `titleTemplate`. */
289
+ socialTitle: string | null;
290
+ description: string | null;
291
+ canonical: string | null;
292
+ robots: string | null;
293
+ openGraph: SeoPropertyTag[];
294
+ twitter: SeoNameTag[];
295
+ verification: SeoNameTag[];
296
+ alternates: {
297
+ hreflang: string;
298
+ href: string;
299
+ }[];
300
+ }
301
+ /** Render context supplied by the component from `Astro`. */
302
+ interface SeoContext {
303
+ /**
304
+ * The deployed origin — `Astro.site`, or `config.site` via the virtual module.
305
+ *
306
+ * `undefined` when neither is set, and then every absolute-URL tag is dropped
307
+ * rather than being derived from the request. `astro-seo` falls back to
308
+ * `Astro.url` here; on a static build that is `http://localhost:4321`, which
309
+ * would bake a localhost canonical into production HTML.
310
+ */
311
+ site?: URL | undefined;
312
+ /** `Astro.url.pathname` — already includes `base`. */
313
+ pathname: string;
314
+ /** `Astro.url.search`, if the canonical should keep the query string. */
315
+ search?: string;
316
+ }
317
+ /**
318
+ * Merges site defaults with page props into the final tag set.
319
+ *
320
+ * Pure — no `Astro`, no filesystem, no config lookup. Everything it needs comes
321
+ * through its three arguments, which is what makes it testable and what keeps the
322
+ * package free of the consumer-global coupling that sank the previous site model.
323
+ */
324
+ declare function resolveSeo(defaults: GetvitopsSeoOptions, props: SeoProps, ctx: SeoContext): ResolvedSeo;
325
+ //#endregion
5
326
  //#region src/integration.d.ts
6
327
  interface GetvitopsFaviconOptions {
7
328
  /** Source SVG or PNG. */
@@ -14,10 +335,28 @@ interface GetvitopsFaviconOptions {
14
335
  backgroundColor?: string;
15
336
  }
16
337
  interface GetvitopsCssOptions {
17
- /** Path to design-system.json (default 'design-system.json'). */
338
+ /**
339
+ * Path to the config (default `'design-system.json'`).
340
+ *
341
+ * May be a `design-system.json` **or** the larger site config that embeds one
342
+ * (`company.json` / `site.json`) — they are told apart by shape. Pointing this
343
+ * at a site config makes the top-level `site` option redundant and lets
344
+ * `legal` and `fonts` default their own `input` to it, so the path is declared
345
+ * once.
346
+ */
18
347
  input?: string;
19
- /** Output format (default 'tailwind'). */
20
- format?: Format;
348
+ /**
349
+ * Which `designSystem.themes` entry to build, when `input` is a site config.
350
+ * Default: the config's `defaultTheme`, else `default`.
351
+ */
352
+ theme?: string;
353
+ /**
354
+ * Output format (default 'tailwind'). Narrower than the generator's `Format`
355
+ * on purpose: this option exists to produce a stylesheet to inject, and the
356
+ * `design` format emits only `DESIGN.md`. Run that one via the CLI
357
+ * (`vitops generate --format design --out .`).
358
+ */
359
+ format?: StylesheetFormat;
21
360
  /** Directory the generated CSS is written to (default 'src/styles'). */
22
361
  out?: string;
23
362
  /**
@@ -28,8 +367,120 @@ interface GetvitopsCssOptions {
28
367
  * only your own pages (and previews rendered through them) are styled.
29
368
  */
30
369
  inject?: boolean;
370
+ /**
371
+ * Also flip to dark when the visitor's OS asks and they have made no explicit
372
+ * choice — `@media (prefers-color-scheme: dark)`.
373
+ *
374
+ * Off by default: turning it on flips the site dark for dark-OS visitors, which
375
+ * is a visible change to an existing site. Turning it **on** is what makes
376
+ * `<color-scheme-toggle>`'s "System" position do anything (System removes the
377
+ * theme attribute, so without this block it falls through to light), and it is
378
+ * the only way a no-JS page gets the OS appearance at all.
379
+ *
380
+ * The site config's `designSystem.defaultColorScheme: "system"` says the same thing and is the
381
+ * better home for it when you have one — this option wins if both are set, and
382
+ * exists because requiring a whole `SiteConfig` to set one boolean would be out
383
+ * of proportion.
384
+ */
385
+ systemColorScheme?: boolean;
386
+ }
387
+ interface GetvitopsSiteOptions {
388
+ /** Path to the site config (JSON). */
389
+ input: string;
390
+ /** Environment whose A/B variant applies (default 'production'). */
391
+ siteEnv?: string;
392
+ }
393
+ interface GetvitopsLegalOptions {
394
+ /**
395
+ * Path to the site config (JSON) the documents are rendered from. Optional
396
+ * when the top-level `site` option is set — it defaults to that file, since
397
+ * they are almost always the same one.
398
+ */
399
+ input?: string;
400
+ /**
401
+ * Where to write them (default 'src/content/legal'). The default is a content
402
+ * collection: the documents are markdown, and a collection is what lets a page
403
+ * render one through your own layout rather than the integration injecting a
404
+ * route (which nothing in this package does).
405
+ */
406
+ out?: string;
407
+ /** Output format (default 'md'). */
408
+ format?: LegalOutput;
409
+ /** Environment whose A/B variant applies (default 'production'). */
410
+ siteEnv?: string;
411
+ }
412
+ /** `changefreq`, mirroring @astrojs/sitemap's `ChangeFreq`. */
413
+ type GetvitopsSitemapChangeFreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
414
+ /** One sitemap entry, mirroring @astrojs/sitemap's `SitemapItem`. */
415
+ interface GetvitopsSitemapEntry {
416
+ url: string;
417
+ lastmod?: string;
418
+ changefreq?: GetvitopsSitemapChangeFreq;
419
+ priority?: number;
420
+ /** Alternate-language variants. `lang` is required, as upstream requires it. */
421
+ links?: {
422
+ lang: string;
423
+ hreflang?: string;
424
+ url: string;
425
+ }[];
426
+ }
427
+ /**
428
+ * Forwarded verbatim to `@astrojs/sitemap`. Deliberately a hand-written subset of
429
+ * its `SitemapOptions` rather than a re-export: aliasing would put an
430
+ * `import … from '@astrojs/sitemap'` — and, transitively via `SitemapItem`, from
431
+ * `sitemap` — into this package's published .d.mts, which cannot resolve for the
432
+ * consumers who don't install the optional peer. Worse, `skipLibCheck` (on by
433
+ * default via astro's base tsconfig) *suppresses* that error, silently degrading
434
+ * the option to `any` instead of failing loudly.
435
+ *
436
+ * Need something not listed here (e.g. `chunks`)? Add `sitemap()` to your own
437
+ * `integrations` array — getvitops detects it and leaves yours in charge.
438
+ */
439
+ interface GetvitopsSitemapOptions {
440
+ /** Keep a page out of the sitemap. Receives the page's full absolute URL. */
441
+ filter?: (page: string) => boolean;
442
+ /** Absolute URLs of pages Astro doesn't build but the site serves. */
443
+ customPages?: string[];
444
+ /** Absolute URLs of externally-generated sitemaps to list in the index. */
445
+ customSitemaps?: string[];
446
+ /** Max entries per file before it splits (default 45000). */
447
+ entryLimit?: number;
448
+ /** Filename prefix (default 'sitemap' → `sitemap-index.xml`). */
449
+ filenameBase?: string;
450
+ changefreq?: GetvitopsSitemapChangeFreq;
451
+ lastmod?: Date;
452
+ priority?: number;
453
+ /** Per-entry rewrite; return `undefined` to drop the entry. */
454
+ serialize?: (item: GetvitopsSitemapEntry) => GetvitopsSitemapEntry | Promise<GetvitopsSitemapEntry | undefined> | undefined;
455
+ /** Emit `<xhtml:link rel="alternate">` for localised routes. */
456
+ i18n?: {
457
+ defaultLocale: string;
458
+ locales: Record<string, string>;
459
+ };
460
+ /** XSL stylesheet to prettify the XML (path relative to `site`, or absolute URL). */
461
+ xslURL?: string;
462
+ /** XML namespaces to exclude (all included by default). */
463
+ namespaces?: {
464
+ news?: boolean;
465
+ xhtml?: boolean;
466
+ image?: boolean;
467
+ video?: boolean;
468
+ };
31
469
  }
32
470
  interface GetvitopsOptions {
471
+ /**
472
+ * Your site config — the one place to name it.
473
+ *
474
+ * A `SiteConfig` records site-level facts, several of which other options here
475
+ * need: `designSystem.defaultColorScheme` decides whether the generated colour layer
476
+ * carries a `prefers-color-scheme` block, `fonts` can supply the webfont
477
+ * declarations, and `legal` renders from it. Set this and each of those reads
478
+ * it, rather than repeating the path per feature. Every one can still be given
479
+ * explicitly, which wins.
480
+ *
481
+ * Needs `css`, since the generation runs in the Vite plugin `css` registers.
482
+ */
483
+ site?: GetvitopsSiteOptions;
33
484
  favicon?: GetvitopsFaviconOptions;
34
485
  /** Copy + link the web-component bundles (default true). */
35
486
  webComponents?: boolean;
@@ -47,8 +498,174 @@ interface GetvitopsOptions {
47
498
  * dev server, so on a static build that button simply isn't rendered.
48
499
  */
49
500
  editor?: boolean;
501
+ /**
502
+ * Render the site's legal documents (privacy policy, terms, cookie notice)
503
+ * from a site config, and re-render when it changes. Off unless provided.
504
+ *
505
+ * Requires `css`, which is what registers the Vite plugin that runs the
506
+ * generation — without it the documents would be written once and never
507
+ * refresh. Not using `css`? Run `vitops legal` from the CLI instead; it is the
508
+ * same renderer and works in any stack.
509
+ */
510
+ legal?: GetvitopsLegalOptions;
511
+ /**
512
+ * Load webfonts through Astro's Fonts API and emit `<Font />` for each from
513
+ * `<Head />`. Off unless provided.
514
+ *
515
+ * This is the seam the design system deliberately lacks. `design-system.json`'s
516
+ * `fonts` block holds **stacks only** — `--font-<name>` tokens and nothing else: no
517
+ * `@font-face`, no preload, no metrics-matched fallback. Declaring the family here
518
+ * makes the token resolvable *and* loaded, so the token keeps pointing at a
519
+ * `cssVariable` rather than at a literal stack the browser has no file for:
520
+ *
521
+ * ```js
522
+ * getvitops({ fonts: [{ name: 'League Spartan', provider: 'fontsource',
523
+ * cssVariable: '--font-league-spartan',
524
+ * weights: ['100 900'], subsets: ['latin'], preload: true }] })
525
+ * ```
526
+ * ```jsonc
527
+ * // design-system.json
528
+ * "fonts": { "display": "var(--font-league-spartan), sans-serif" }
529
+ * ```
530
+ *
531
+ * Pass a **string** instead to read the array from a site config's `fonts` block —
532
+ * the same declarations, kept next to the rest of the site's facts. (`siteEnv`
533
+ * picks the A/B variant, as in `legal`.) With the top-level `site` option set,
534
+ * plain `true` does the same thing without repeating the path.
535
+ *
536
+ * Independent of `css`: the loading runs in `astro:config:setup`, not in the Vite
537
+ * plugin. Both `<Head />` and the config entry are required — Astro's `fonts:`
538
+ * config resolves the files, and `<Font />` is what puts the `@font-face` on the
539
+ * page — so a declaration without `<Head />` in your layout loads nothing.
540
+ */
541
+ fonts?: boolean | string | SiteFont[] | GetvitopsFontsOptions;
542
+ /**
543
+ * Emit `sitemap-index.xml` + `sitemap-0.xml` via `@astrojs/sitemap`, and link it
544
+ * from `<Head />`. Off unless provided; `true` uses its defaults.
545
+ *
546
+ * Needs `@astrojs/sitemap` (an optional peer — install it yourself) and the
547
+ * `site` astro.config option, since a sitemap lists absolute URLs.
548
+ *
549
+ * Skipped with a warning when `emdash()` is registered — EmDash serves its own
550
+ * database-driven `/sitemap.xml` — and deferred to when you already list
551
+ * `@astrojs/sitemap` yourself. Note it enumerates **prerendered** routes only,
552
+ * so on-demand pages of an `output: 'server'` site are not listed.
553
+ */
554
+ sitemap?: boolean | GetvitopsSitemapOptions;
555
+ /**
556
+ * Site-level defaults for `<Seo />` (`@getvitops/astro/Seo.astro`) — site name,
557
+ * title template, Open Graph + Twitter defaults, verification tokens. Off unless
558
+ * provided; per-page props override every field.
559
+ *
560
+ * Needs the `site` astro.config option for canonical and `og:url`; without it
561
+ * `<Seo />` omits every absolute-URL tag rather than deriving one from the
562
+ * request, and this warns at build time.
563
+ *
564
+ * On an EmDash site prefer `<EmDashHead>`, which covers the same tags from the
565
+ * CMS — using both double-emits them.
566
+ */
567
+ seo?: GetvitopsSeoOptions;
568
+ /**
569
+ * Resolve semantic icon names centrally and, on a server build, derive which
570
+ * icons to bundle by scanning your source. Off unless provided; `true` uses
571
+ * the defaults below.
572
+ *
573
+ * Two separate jobs, and it is worth knowing which one you are buying:
574
+ *
575
+ * 1. **Naming.** `<Icon name="menu" />` resolves through the semantic map, so
576
+ * the icon set is a config value rather than something spelled out at every
577
+ * call site. A name containing `:` passes through untouched — that is the
578
+ * escape hatch for a set-specific glyph.
579
+ * 2. **Bundle size.** astro-icon is zero-config on a static build, but under
580
+ * `output: 'server'` it bundles EVERY icon in a set unless given an
581
+ * `include` map. That is the list consumers end up hand-maintaining. Here it
582
+ * is derived by scanning `scan` for icon references, merged with anything
583
+ * you declare. On a static build no `include` is passed at all, because
584
+ * there is nothing to trim.
585
+ *
586
+ * Names the scanner cannot read statically (`<Icon name={expr} />`) are
587
+ * reported with file and line, not guessed at — declare them in `include`.
588
+ */
589
+ icons?: boolean | GetvitopsIconsOptions;
590
+ /**
591
+ * Analytics tags for `<Analytics />` — Google Analytics, Microsoft Clarity,
592
+ * Matomo, Plausible. Off unless provided.
593
+ *
594
+ * Every tag loads off the critical path (`strategy`, default `'idle'`: after
595
+ * `load`, on an idle callback) and, when it sets cookies, only after consent.
596
+ *
597
+ * Which consent category a provider needs is derived from whether it sets
598
+ * cookies, not declared — so configuring a cookie-setting provider without
599
+ * `consent` warns rather than silently tracking everyone.
600
+ */
601
+ analytics?: GetvitopsAnalyticsOptions;
602
+ /**
603
+ * The consent gate: `@getvitops/core/consent` + `<CookieConsent />`. Off unless
604
+ * provided; `true` uses its defaults.
605
+ *
606
+ * A sibling of `analytics`, not part of it. The gate is general — anything
607
+ * marked `data-consent="<category>"` waits on the same choice, so A/B
608
+ * assignment, personalisation and third-party embeds use it too, and a site can
609
+ * enable it with no analytics configured at all.
610
+ *
611
+ * Pair it with `legal` so the cookie notice describes the categories this
612
+ * actually offers.
613
+ */
614
+ consent?: boolean | GetvitopsConsentOptions;
615
+ }
616
+ interface GetvitopsFontsOptions {
617
+ /** Path to a site config (JSON) whose `fonts` array holds the declarations. */
618
+ input?: string;
619
+ /** Declarations written inline; merged after anything `input` supplies. */
620
+ families?: SiteFont[];
621
+ /** Environment whose A/B variant applies to `input` (default 'production'). */
622
+ siteEnv?: string;
623
+ }
624
+ interface GetvitopsIconsOptions {
625
+ /** Icon set for UI chrome. Default `'fa7-solid'`. */
626
+ ui?: string;
627
+ /** Icon set for brand marks. Default `'simple-icons'`. */
628
+ brand?: string;
629
+ /**
630
+ * Weight for suffix-weighted sets like Phosphor (`'bold'`, `'fill'`, …).
631
+ * Ignored by sets that split weights across collections, e.g. Font Awesome.
632
+ */
633
+ weight?: string;
634
+ /**
635
+ * Icons to bundle, in `generateIconInclude`'s shape:
636
+ * `{ semantic: ['menu'], 'simple-icons': ['zoho'] }`.
637
+ *
638
+ * Merged with what the scan finds. Declared names that don't resolve **throw**
639
+ * (a config error); scanned names that don't resolve only **warn** (a source
640
+ * typo shouldn't kill the dev server).
641
+ */
642
+ include?: Parameters<typeof generateIconInclude>[0];
643
+ /**
644
+ * How `<Icon />` draws the glyph.
645
+ *
646
+ * `'inline'` (default) reads it from the `@iconify-json/*` collection and
647
+ * inlines the `<svg>` — no runtime request, no icon-integration peer.
648
+ * `'sprite'` emits `<use href="…/icons.svg#id">` instead, for pages served
649
+ * where the sprite is already on the origin.
650
+ *
651
+ * Note this is separate from `register`: whether astro-icon is registered for
652
+ * YOUR OWN `<Icon>` usage is a different question from how ours renders.
653
+ */
654
+ engine?: 'inline' | 'sprite';
655
+ /**
656
+ * Register the icon integration for you (default true). Set false when you
657
+ * already list `icon()` in `integrations` yourself — the scan, the sprite and
658
+ * the resolver still run either way.
659
+ */
660
+ register?: boolean;
661
+ /** Directories to scan, relative to the project root. Default `['src']`; `false` disables. */
662
+ scan?: string[] | false;
663
+ /** Public href of the sprite, for the `'sprite'` engine. Default `'/vitops/icons.svg'`. */
664
+ sprite?: string;
665
+ /** Aliases applied before the semantic map — legacy names, or values stored in CMS content. */
666
+ overrides?: Record<string, string>;
50
667
  }
51
668
  declare function getvitops(opts?: GetvitopsOptions): AstroIntegration;
52
669
  //#endregion
53
- export { type GetvitopsCssOptions, type GetvitopsFaviconOptions, type GetvitopsOptions, getvitops as default };
670
+ export { type AnalyticsStrategy, type ClarityOptions, type ConsentCategory, type GetvitopsAnalyticsOptions, type GetvitopsConsentOptions, type GetvitopsCssOptions, type GetvitopsFaviconOptions, type GetvitopsOptions, type GetvitopsSeoOptions, type GetvitopsSitemapChangeFreq, type GetvitopsSitemapEntry, type GetvitopsSitemapOptions, type GoogleAnalyticsOptions, type MatomoOptions, type OptionalConsentCategory, type PlausibleOptions, type ResolveAnalyticsContext, type ResolvedAnalytics, type ResolvedSeo, type ResolvedTag, type SeoContext, type SeoNameTag, type SeoOgType, type SeoPropertyTag, type SeoProps, type SeoTwitterCard, consentCategories, getvitops as default, resolveAnalytics, resolveSeo };
54
671
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/integration.ts"],"mappings":";;;;;UAsBiB,uBAAA;;EAEf,MAAA;EACA,YAAA;EAHe;EAKf,IAAA;;EAEA,UAAA;EACA,eAAA;AAAA;AAAA,UAGe,mBAAA;EAJf;EAMA,KAAA;EALe;EAOf,MAAA,GAAS,MAAM;EAJA;EAMf,GAAA;;;;;;;;EAQA,MAAA;AAAA;AAAA,UAGe,gBAAA;EACf,OAAA,GAAU,uBAAA;;EAEV,aAAA;EAFA;EAIA,GAAA,GAAM,mBAAmB;EAFzB;;;;;AAcM;AACP;;;;;EADC,MAAA;AAAA;AAAA,iBA2BsB,SAAA,CAAU,IAAA,GAAM,gBAAA,GAAwB,gBAAgB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/analytics.ts","../src/seo.ts","../src/integration.ts"],"mappings":"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"}