@getvitops/astro 8.2.0-alpha.0 → 8.3.0-alpha.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +584 -26
  2. package/dist/config-adapters-CbTywgEY.mjs +71 -0
  3. package/dist/config-adapters-CbTywgEY.mjs.map +1 -0
  4. package/dist/exports/tracking.d.mts +1 -1
  5. package/dist/exports/tracking.mjs +1 -1
  6. package/dist/index.d.mts +83 -43
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.mjs +351 -60
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/middleware.d.mts +0 -2
  11. package/dist/middleware.d.mts.map +1 -1
  12. package/dist/middleware.mjs +1 -2
  13. package/dist/routes/conversion.d.mts +71 -15
  14. package/dist/routes/conversion.d.mts.map +1 -1
  15. package/dist/routes/conversion.mjs +79 -68
  16. package/dist/routes/conversion.mjs.map +1 -1
  17. package/dist/{tracking-M2PqlMpw.mjs → tracking-Cb3A0BrC.mjs} +2 -3
  18. package/dist/tracking-Cb3A0BrC.mjs.map +1 -0
  19. package/dist/{tracking-BNKKBqOe.d.mts → tracking-D2xOzjFD.d.mts} +5 -25
  20. package/dist/tracking-D2xOzjFD.d.mts.map +1 -0
  21. package/package.json +18 -6
  22. package/src/ads.ts +15 -22
  23. package/src/components/CookieConsent.astro +2 -1
  24. package/src/components/Entries.astro +58 -0
  25. package/src/components/Head.astro +6 -37
  26. package/src/components/ReviewCardBody.astro +16 -2
  27. package/src/components/SiteFooter.astro +79 -0
  28. package/src/components/SiteNav.astro +163 -0
  29. package/src/components/SiteNavList.astro +73 -0
  30. package/src/components/sitenav.ts +260 -0
  31. package/src/inline-scripts.ts +53 -0
  32. package/src/json-ld.ts +19 -0
  33. package/src/schemas/Article.astro +2 -1
  34. package/src/schemas/BookActions.astro +2 -1
  35. package/src/schemas/Breadcrumb.astro +2 -1
  36. package/src/schemas/Carousel.astro +2 -1
  37. package/src/schemas/CourseList.astro +2 -1
  38. package/src/schemas/Dataset.astro +2 -1
  39. package/src/schemas/DiscussionForum.astro +2 -1
  40. package/src/schemas/EducationQA.astro +2 -1
  41. package/src/schemas/EmployerAggregateRating.astro +2 -1
  42. package/src/schemas/Event.astro +2 -1
  43. package/src/schemas/FAQ.astro +2 -1
  44. package/src/schemas/FactCheck.astro +2 -1
  45. package/src/schemas/ImageMetadata.astro +2 -1
  46. package/src/schemas/JobPosting.astro +2 -1
  47. package/src/schemas/LocalBusiness.astro +2 -1
  48. package/src/schemas/MathSolver.astro +2 -1
  49. package/src/schemas/MovieCarousel.astro +2 -1
  50. package/src/schemas/Organization.astro +2 -1
  51. package/src/schemas/Product.astro +2 -1
  52. package/src/schemas/ProfilePage.astro +2 -1
  53. package/src/schemas/QAPage.astro +2 -1
  54. package/src/schemas/Recipe.astro +2 -1
  55. package/src/schemas/Review.astro +2 -1
  56. package/src/schemas/SoftwareApp.astro +2 -1
  57. package/src/seo.ts +6 -5
  58. package/src/tracking.ts +5 -9
  59. package/virtual.d.ts +17 -0
  60. package/dist/tracking-BNKKBqOe.d.mts.map +0 -1
  61. package/dist/tracking-M2PqlMpw.mjs.map +0 -1
@@ -0,0 +1,71 @@
1
+ import { t } from "@getvitops/utils/content";
2
+
3
+ // src/routes/config-adapters.ts
4
+ /**
5
+ * Resolves the one display name for a site's organization — `organization.name`
6
+ * (localizable; `locale` picks which one, defaulting to `site.defaultLocale`,
7
+ * which is also the fallback if the pick has no entry), falling back to
8
+ * `legalName` when `name` isn't set at all, and to `undefined` (never `''`)
9
+ * when neither resolves to anything — `t()` returns `''` for a genuinely
10
+ * missing translation, and an empty name is worse than none.
11
+ *
12
+ * This is the one place that fallback chain is written. An EmDash site's own
13
+ * `getSiteSettings().title` is a separate, runtime-only fact (EmDash's
14
+ * settings aren't readable at Astro build/config time at all — see
15
+ * AGENTS.md's "EmDash plugin as the design-system editing surface") and stays
16
+ * authoritative for what it drives (the rendered page chrome); this helper is
17
+ * for the build-time-only consumers that can't reach EmDash at all — favicon
18
+ * generation, generated legal documents, notification emails — so a scaffold
19
+ * needing a name in `astro.config.mjs` has one real source instead of a third
20
+ * hardcoded string.
21
+ */
22
+ function resolveOrganizationName(config, locale) {
23
+ const org = config.organization;
24
+ const resolvedLocale = locale ?? config.site.defaultLocale;
25
+ return (org?.name != null ? t(org.name, resolvedLocale, config.site.defaultLocale) || void 0 : void 0) ?? org?.legalName;
26
+ }
27
+ /**
28
+ * Builds the `context` option `createConversionRoute()` expects, straight from a
29
+ * resolved `Config` — instead of every consumer hand-writing a `NotifyContext`
30
+ * literal.
31
+ *
32
+ * `locationEmails` is primary-first, then every other location with an `email`,
33
+ * in `organization.locations`' own key order — `planNotifications` picks the
34
+ * first that's set, so order here is the whole precedence.
35
+ */
36
+ function toNotifyContext(config, locale) {
37
+ const org = config.organization;
38
+ const primaryKey = org?.primaryLocation;
39
+ const locationEmails = Object.entries(org?.locations ?? {}).sort(([a], [b]) => a === primaryKey ? -1 : b === primaryKey ? 1 : 0).map(([, loc]) => loc.email).filter((email) => !!email);
40
+ return {
41
+ notifications: config.site.notifications,
42
+ canonical: config.site.domains?.canonical,
43
+ organizationName: resolveOrganizationName(config, locale),
44
+ locationEmails
45
+ };
46
+ }
47
+ /**
48
+ * `site.crm` IS `CrmConfig` — both are the schema's inferred type from `@getvitops/config` — so
49
+ * this returns its argument's field unchanged.
50
+ *
51
+ * @deprecated Pass `config.site.crm` directly. Kept so existing callers keep compiling; it
52
+ * stopped being an adapter when the type stopped being a copy.
53
+ */
54
+ function toCrmConfig(config) {
55
+ return config.site.crm;
56
+ }
57
+ /**
58
+ * `site.ads.google`'s three server-side-relevant fields, for
59
+ * `createConversionRoute`'s `googleAdsOffline.config`. Undefined when the site has no Google Ads
60
+ * property configured at all, which `createConversionRoute` reads the same way `crm` being
61
+ * omitted does: the upload never runs.
62
+ *
63
+ * @deprecated Pass `config.site.ads?.google` directly — it is already assignable. Kept so existing
64
+ * callers keep compiling.
65
+ */
66
+ function toGoogleAdsConfig(config) {
67
+ return config.site.ads?.google;
68
+ }
69
+
70
+ export { toNotifyContext as i, toCrmConfig as n, toGoogleAdsConfig as r, resolveOrganizationName as t };
71
+ //# sourceMappingURL=config-adapters-CbTywgEY.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-adapters-CbTywgEY.mjs","names":[],"sources":["../src/routes/config-adapters.ts"],"sourcesContent":["/**\n * Adapts a resolved `Config` (`@getvitops/generator`) into the structural shapes\n * `createConversionRoute()` expects — `context: NotifyContext` and `crm.config:\n * CrmConfig`. Neither of those types can import `Config` themselves (they live in\n * `@getvitops/utils`, which the generator already depends on — importing back\n * would be a cycle), which is why `conversion.ts`'s own docblock used to describe\n * `toNotifyContext(config)` as a helper that \"does not exist.\" This package\n * already depends on both the generator and utils, so it's the one place the\n * adapter can live.\n *\n * `import type` only — erased at build, so pulling in `Config`'s type costs\n * nothing at runtime and doesn't drag the generator's `node:fs`/lightningcss\n * entry point into a Worker bundle.\n */\nimport type { Config } from '@getvitops/generator';\n// The `/content` subpath, not the root barrel: the root re-exports `favicon` (sharp), and a\n// Worker route should not depend on tree-shaking to keep it out.\nimport { t, type Localizable } from '@getvitops/utils/content';\nimport type { AdPropertySetup } from '@getvitops/utils/ads';\nimport type { CrmConfig } from '@getvitops/utils/crm';\nimport type { NotifyContext } from '@getvitops/utils/notify';\n\n/**\n * The slice of a `Config` that `resolveOrganizationName` reads. Structural on\n * purpose: `import config from './site.json'` types its literals widened\n * (`colors.utilities` becomes `string[]`, not the schema's union), so it is not\n * assignable to the full `Config`, and every scaffolded site calls this with\n * exactly such an import. A resolved `Config` still satisfies it.\n */\nexport interface OrganizationNameSource {\n organization?: { name?: Localizable | undefined; legalName?: string | undefined } | undefined;\n site: { defaultLocale: string };\n}\n\n/**\n * Resolves the one display name for a site's organization — `organization.name`\n * (localizable; `locale` picks which one, defaulting to `site.defaultLocale`,\n * which is also the fallback if the pick has no entry), falling back to\n * `legalName` when `name` isn't set at all, and to `undefined` (never `''`)\n * when neither resolves to anything — `t()` returns `''` for a genuinely\n * missing translation, and an empty name is worse than none.\n *\n * This is the one place that fallback chain is written. An EmDash site's own\n * `getSiteSettings().title` is a separate, runtime-only fact (EmDash's\n * settings aren't readable at Astro build/config time at all — see\n * AGENTS.md's \"EmDash plugin as the design-system editing surface\") and stays\n * authoritative for what it drives (the rendered page chrome); this helper is\n * for the build-time-only consumers that can't reach EmDash at all — favicon\n * generation, generated legal documents, notification emails — so a scaffold\n * needing a name in `astro.config.mjs` has one real source instead of a third\n * hardcoded string.\n */\nexport function resolveOrganizationName(\n config: OrganizationNameSource,\n locale?: string,\n): string | undefined {\n const org = config.organization;\n const resolvedLocale = locale ?? config.site.defaultLocale;\n const name =\n org?.name != null\n ? t(org.name, resolvedLocale, config.site.defaultLocale) || undefined\n : undefined;\n return name ?? org?.legalName;\n}\n\n/**\n * Builds the `context` option `createConversionRoute()` expects, straight from a\n * resolved `Config` — instead of every consumer hand-writing a `NotifyContext`\n * literal.\n *\n * `locationEmails` is primary-first, then every other location with an `email`,\n * in `organization.locations`' own key order — `planNotifications` picks the\n * first that's set, so order here is the whole precedence.\n */\nexport function toNotifyContext(config: Config, locale?: string): NotifyContext {\n const org = config.organization;\n const primaryKey = org?.primaryLocation;\n const locationEmails = Object.entries(org?.locations ?? {})\n .sort(([a], [b]) => (a === primaryKey ? -1 : b === primaryKey ? 1 : 0))\n .map(([, loc]) => loc.email)\n .filter((email): email is string => !!email);\n\n return {\n notifications: config.site.notifications,\n canonical: config.site.domains?.canonical,\n organizationName: resolveOrganizationName(config, locale),\n locationEmails,\n };\n}\n\n/**\n * `site.crm` IS `CrmConfig` — both are the schema's inferred type from `@getvitops/config` — so\n * this returns its argument's field unchanged.\n *\n * @deprecated Pass `config.site.crm` directly. Kept so existing callers keep compiling; it\n * stopped being an adapter when the type stopped being a copy.\n */\nexport function toCrmConfig(config: Config): CrmConfig | undefined {\n return config.site.crm;\n}\n\n/**\n * `site.ads.google`'s three server-side-relevant fields, for\n * `createConversionRoute`'s `googleAdsOffline.config`. Undefined when the site has no Google Ads\n * property configured at all, which `createConversionRoute` reads the same way `crm` being\n * omitted does: the upload never runs.\n *\n * @deprecated Pass `config.site.ads?.google` directly — it is already assignable. Kept so existing\n * callers keep compiling.\n */\nexport function toGoogleAdsConfig(\n config: Config,\n): Pick<AdPropertySetup, 'accountId' | 'conversionActionId' | 'reporting'> | undefined {\n return config.site.ads?.google;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoDA,SAAgB,wBACd,QACA,QACoB;CACpB,MAAM,MAAM,OAAO;CACnB,MAAM,iBAAiB,UAAU,OAAO,KAAK;CAK7C,QAHE,KAAK,QAAQ,OACT,EAAE,IAAI,MAAM,gBAAgB,OAAO,KAAK,aAAa,KAAK,SAC1D,WACS,KAAK;AACtB;;;;;;;;;;AAWA,SAAgB,gBAAgB,QAAgB,QAAgC;CAC9E,MAAM,MAAM,OAAO;CACnB,MAAM,aAAa,KAAK;CACxB,MAAM,iBAAiB,OAAO,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,CACxD,MAAM,CAAC,IAAI,CAAC,OAAQ,MAAM,aAAa,KAAK,MAAM,aAAa,IAAI,CAAE,CAAC,CACtE,KAAK,GAAG,SAAS,IAAI,KAAK,CAAC,CAC3B,QAAQ,UAA2B,CAAC,CAAC,KAAK;CAE7C,OAAO;EACL,eAAe,OAAO,KAAK;EAC3B,WAAW,OAAO,KAAK,SAAS;EAChC,kBAAkB,wBAAwB,QAAQ,MAAM;EACxD;CACF;AACF;;;;;;;;AASA,SAAgB,YAAY,QAAuC;CACjE,OAAO,OAAO,KAAK;AACrB;;;;;;;;;;AAWA,SAAgB,kBACd,QACqF;CACrF,OAAO,OAAO,KAAK,KAAK;AAC1B"}
@@ -1,3 +1,3 @@
1
- import { a as TRACKING_ENDPOINT } from "../tracking-BNKKBqOe.mjs";
1
+ import { a as TRACKING_ENDPOINT } from "../tracking-D2xOzjFD.mjs";
2
2
  export * from "@getvitops/utils/tracking";
3
3
  export { TRACKING_ENDPOINT };
@@ -1,4 +1,4 @@
1
- import { n as TRACKING_ENDPOINT } from "../tracking-M2PqlMpw.mjs";
1
+ import { n as TRACKING_ENDPOINT } from "../tracking-Cb3A0BrC.mjs";
2
2
 
3
3
  export * from "@getvitops/utils/tracking"
4
4
 
package/dist/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- import { i as TRACKING_COOKIE, n as ResolveTrackingContext, o as TrackingCategory, r as ResolvedTracking, s as resolveTracking, t as GetvitopsTrackingOptions } from "./tracking-BNKKBqOe.mjs";
2
- import { LegalOutput, SiteFont, StylesheetFormat } from "@getvitops/generator";
1
+ import { i as TRACKING_COOKIE, n as ResolveTrackingContext, o as TrackingCategory, r as ResolvedTracking, s as resolveTracking, t as GetvitopsTrackingOptions } from "./tracking-D2xOzjFD.mjs";
2
+ import { Config, LegalOutput, SiteFont, StylesheetFormat } from "@getvitops/generator";
3
3
  import { generateIconInclude } from "@getvitops/utils";
4
- import { AdProvider, ConversionLabelMap } from "@getvitops/utils/ads";
4
+ import { AdProvider } from "@getvitops/utils/ads";
5
+ import { AdPropertyConfig } from "@getvitops/config";
5
6
  import { OutputKind } from "@getvitops/utils/media";
6
7
  import { AstroIntegration } from "astro";
7
8
  export * from "@getvitops/utils";
8
- //#region src/analytics.d.ts
9
9
  /**
10
10
  * The `<Analytics />` resolution layer — provider config in, the exact tags to
11
11
  * emit out.
@@ -175,8 +175,6 @@ interface ResolveAnalyticsContext {
175
175
  export declare function resolveAnalytics(opts: GetvitopsAnalyticsOptions | undefined, ctx?: ResolveAnalyticsContext): ResolvedAnalytics;
176
176
  /** Which optional categories a set of tags actually needs a visitor to decide. */
177
177
  export declare function consentCategories(tags: GatedTag[]): OptionalConsentCategory[];
178
- //#endregion
179
- //#region src/seo.d.ts
180
178
  /**
181
179
  * The `<Seo />` resolution layer — site-level defaults merged with per-page props
182
180
  * into the exact tags to emit.
@@ -196,11 +194,12 @@ type SeoOgType = 'website' | 'article' | 'profile';
196
194
  * Site-level SEO defaults, passed to `vitops({ seo })` and baked into the
197
195
  * `virtual:getvitops/head` module. Per-page `<Seo />` props override these.
198
196
  *
199
- * The vocabulary mirrors the site-config schema's `seo` block
200
- * (`@getvitops/generator`, `src/config.ts`) so a `Config` → these adapter would
201
- * be a flat field map — but it is not imported from there. This is the
202
- * integration's own option surface, and it must stay JSON-serialisable: it is
203
- * `JSON.stringify`d into the virtual module, so no functions, no `URL`s, no dates.
197
+ * `site.seo` in the site config is the source (`@getvitops/config`'s `SeoSchema`);
198
+ * `resolveSeoDefaults()` turns it into this shape for a build locale, and `vitops({ seo })` is merged
199
+ * over the result as an override. This interface is therefore the *resolved* shape — plain strings,
200
+ * `Localizable` already picked — and must stay JSON-serialisable: it is `JSON.stringify`d into the
201
+ * virtual module, so no functions, no `URL`s, no dates. `seo-defaults.test.ts` fails when a
202
+ * `site.seo` field is added to the schema and not read here (ADR-0002).
204
203
  */
205
204
  interface GetvitopsSeoOptions {
206
205
  /** `og:site_name`, and the `<title>` when a page passes none. */
@@ -361,8 +360,6 @@ interface SeoContext {
361
360
  * package free of the consumer-global coupling that sank the previous site model.
362
361
  */
363
362
  export declare function resolveSeo(defaults: GetvitopsSeoOptions, props: SeoProps, ctx: SeoContext): ResolvedSeo;
364
- //#endregion
365
- //#region src/integration.d.ts
366
363
  interface GetvitopsFaviconOptions {
367
364
  /** Source SVG or PNG. */
368
365
  source: string;
@@ -587,6 +584,17 @@ interface GetvitopsOptions {
587
584
  * dev server, so on a static build that button simply isn't rendered.
588
585
  */
589
586
  editor?: boolean;
587
+ /**
588
+ * Ship what a host needs to embed `<wc-theme-editor>`, WITHOUT loading it from `<Head />`
589
+ * (default false). Writes into `public/vitops/`: `design-manifest.json`, `editor.js`, a
590
+ * standalone `editor.css`, and `design-system-editor.html`, a page that mounts the editor.
591
+ *
592
+ * For hosts outside the site's own pages, such as the EmDash admin
593
+ * (`@getvitops/emdash`'s `designSystemEditor`, which iframes that page so the design
594
+ * system never leaks into the admin's styles). Public pages don't pay for the bundle.
595
+ * Requires `css`.
596
+ */
597
+ editorManifest?: boolean;
590
598
  /**
591
599
  * Render the site's legal documents (privacy policy, terms, cookie notice)
592
600
  * from a site config, and re-render when it changes. Off unless provided.
@@ -643,8 +651,11 @@ interface GetvitopsOptions {
643
651
  sitemap?: boolean | GetvitopsSitemapOptions;
644
652
  /**
645
653
  * Site-level defaults for `<Seo />` (`@getvitops/astro/Seo.astro`) — site name,
646
- * title template, Open Graph + Twitter defaults, verification tokens. Off unless
647
- * provided; per-page props override every field.
654
+ * title template, Open Graph + Twitter defaults, verification tokens.
655
+ *
656
+ * These come from `site.seo` in the site config (with `organization.name` as the site
657
+ * name); this option is an **override** merged over that, field by field, for a value
658
+ * an app wants to set in code. Per-page props override both.
648
659
  *
649
660
  * Needs the `site` astro.config option for canonical and `og:url`; without it
650
661
  * `<Seo />` omits every absolute-URL tag rather than deriving one from the
@@ -770,32 +781,13 @@ interface GetvitopsIconsOptions {
770
781
  overrides?: Record<string, string>;
771
782
  }
772
783
  export default function vitops(opts?: GetvitopsOptions): AstroIntegration;
773
- //#endregion
774
- //#region src/ads.d.ts
775
784
  /**
776
- * One ad property, mirroring a `site.ads` entry field for field.
777
- *
778
- * Structural rather than `SiteAdProperty` imported from the generator, matching
779
- * how `GetvitopsSeoOptions` and `GetvitopsTrackingOptions` already work: the
780
- * component surface must stay usable by a consumer who passes a plain object.
785
+ * One ad property, as `<Ads />` reads it: the fields of a `site.ads` entry that decide what is
786
+ * emitted. A subset of `AdPropertyConfig` from `@getvitops/config` — the schema's own inferred
787
+ * type, not a copy — so a plain object is still enough for a consumer to pass, and a field the
788
+ * schema renames fails here instead of silently reading `undefined`.
781
789
  */
782
- interface GetvitopsAdProperty {
783
- accountId?: string;
784
- pixelId?: string;
785
- /**
786
- * Google Ads only: the conversion action label(s) paired with `pixelId` (the
787
- * `AW-…` conversion id) — a bare string (back-compat, treated as `call`) or a
788
- * map of action → label. `<Tracking />`'s tel:/mailto: click handler and
789
- * `vitopsFormConversion()` each fire `gtag('event', 'conversion', …)` for
790
- * their own action at the moment of the interaction — see `gtagBootstrap` in
791
- * `@getvitops/utils/ads`.
792
- */
793
- conversionLabel?: string | ConversionLabelMap;
794
- /** Default `marketing`. `analytics` for a property used purely for measurement. */
795
- category?: 'marketing' | 'analytics';
796
- /** False keeps the property on record without emitting its tag. */
797
- enabled?: boolean;
798
- }
790
+ type GetvitopsAdProperty = Pick<AdPropertyConfig, 'accountId' | 'pixelId' | 'conversionLabel' | 'conversionActionId' | 'reporting' | 'category' | 'enabled'>;
799
791
  type GetvitopsAdsOptions = Partial<Record<AdProvider, GetvitopsAdProperty>>;
800
792
  /** One ad tag. `key` is the platform, so a caller can find one without matching prose. */
801
793
  interface ResolvedAdTag extends GatedTag {
@@ -820,8 +812,45 @@ interface ResolveAdsContext {
820
812
  }
821
813
  /** Resolve the configured ad properties into the tags `<Ads />` emits. */
822
814
  export declare function resolveAds(ads: GetvitopsAdsOptions | undefined, ctx?: ResolveAdsContext): ResolvedAds;
823
- //#endregion
824
- //#region src/lastmod.d.ts
815
+ /** The CSP source expression for one inline script: `'sha256-<base64>'`. */
816
+ export declare function cspScriptHash(script: string): string;
817
+ interface InlineScriptOptions {
818
+ /** `<Head />` emits the colour-scheme bootstrap (its `webComponents` prop). Default true. */
819
+ webComponents?: boolean;
820
+ /** `<Head />` emits the consent-gate stub (a site with the gate on). Default true. */
821
+ consent?: boolean;
822
+ }
823
+ /**
824
+ * CSP hash sources for every inline script `<Head />` can emit.
825
+ *
826
+ * Defaults to ALL of them: listing a hash for a script the page doesn't emit is
827
+ * harmless, while omitting one a page does emit is a violation.
828
+ */
829
+ export declare function inlineScriptHashes(opts?: InlineScriptOptions): string[];
830
+ interface ContentSecurityPolicyOptions {
831
+ /** Extra `script-src` sources, e.g. a hash for your own inline script or an origin. */
832
+ scriptSrc?: string[];
833
+ /** Origins for `connect-src` beyond `'self'` (analytics endpoints, a form API). */
834
+ connectSrc?: string[];
835
+ /** Origins for `img-src` beyond `'self'`, `data:` and `https:`. */
836
+ imgSrc?: string[];
837
+ /** Origins for `frame-src` (embeds). Default none. */
838
+ frameSrc?: string[];
839
+ /** A `report-uri` endpoint. Omit to rely on the browser console. */
840
+ reportUri?: string;
841
+ /** Which `<Head />` inline scripts to allow. Default all. */
842
+ inline?: InlineScriptOptions;
843
+ }
844
+ /**
845
+ * A strict starting policy for a prerendered site.
846
+ *
847
+ * `script-src` is `'self'` plus the `<Head />` hashes — no `'unsafe-inline'`.
848
+ * `style-src` keeps `'unsafe-inline'` because Astro inlines scoped `<style>` and
849
+ * components set `style=""` attributes; a style injection is far less dangerous
850
+ * than a script one, and hashing every stylesheet would break on any edit.
851
+ * `img-src` allows `https:` because editors paste images from anywhere.
852
+ */
853
+ export declare function contentSecurityPolicy(opts?: ContentSecurityPolicyOptions): string;
825
854
  interface GitLastmodOptions {
826
855
  /** Directories to read history from (default `src/pages`, `src/content`, `src/data`). */
827
856
  dirs?: string[];
@@ -849,6 +878,17 @@ export declare function slugFromContent(file: string): string | undefined;
849
878
  * flip presented as a fact.
850
879
  */
851
880
  export declare function gitLastmod(options?: GitLastmodOptions): Promise<(item: GetvitopsSitemapEntry) => GetvitopsSitemapEntry>;
852
- //#endregion
853
- export { type AnalyticsStrategy, type ClarityOptions, type ConsentCategory, type GatedTag, type GetvitopsAdProperty, type GetvitopsAdsOptions, type GetvitopsAnalyticsOptions, type GetvitopsConsentOptions, type GetvitopsCssOptions, type GetvitopsFaviconOptions, type GetvitopsMediaOptions, type GetvitopsOptions, type GetvitopsSeoOptions, type GetvitopsSitemapChangeFreq, type GetvitopsSitemapEntry, type GetvitopsSitemapOptions, type GetvitopsTrackingOptions, type GitLastmodOptions, type GoogleAnalyticsOptions, type MatomoOptions, type OptionalConsentCategory, type PlausibleOptions, type ResolveAdsContext, type ResolveAnalyticsContext, type ResolveTrackingContext, type ResolvedAdTag, type ResolvedAds, type ResolvedAnalytics, type ResolvedSeo, type ResolvedTag, type ResolvedTracking, type SeoContext, type SeoNameTag, type SeoOgType, type SeoPropertyTag, type SeoProps, type SeoTwitterCard, TRACKING_COOKIE, type TrackingCategory, resolveTracking };
881
+ interface ResolveSeoDefaultsOptions {
882
+ /** Build locale. Default `site.defaultLocale`; a value with no entry falls back to the default. */
883
+ locale?: string;
884
+ /** Which `site.environments` entry to read `robots` from. Default `'production'`. */
885
+ env?: string;
886
+ }
887
+ export declare function resolveSeoDefaults(config: Config, options?: ResolveSeoDefaultsOptions): GetvitopsSeoOptions;
888
+ /**
889
+ * Merge `vitops({ seo })` over config-derived defaults. The two nested objects merge key by key, so
890
+ * setting `openGraph.locale` in code doesn't discard the config's fallback image.
891
+ */
892
+ export declare function mergeSeoDefaults(fromConfig: GetvitopsSeoOptions, override: GetvitopsSeoOptions | undefined): GetvitopsSeoOptions;
893
+ export { type AnalyticsStrategy, type ClarityOptions, type ConsentCategory, type ContentSecurityPolicyOptions, type GatedTag, type GetvitopsAdProperty, type GetvitopsAdsOptions, type GetvitopsAnalyticsOptions, type GetvitopsConsentOptions, type GetvitopsCssOptions, type GetvitopsFaviconOptions, type GetvitopsMediaOptions, type GetvitopsOptions, type GetvitopsSeoOptions, type GetvitopsSitemapChangeFreq, type GetvitopsSitemapEntry, type GetvitopsSitemapOptions, type GetvitopsTrackingOptions, type GitLastmodOptions, type GoogleAnalyticsOptions, type InlineScriptOptions, type MatomoOptions, type OptionalConsentCategory, type PlausibleOptions, type ResolveAdsContext, type ResolveAnalyticsContext, type ResolveSeoDefaultsOptions, type ResolveTrackingContext, type ResolvedAdTag, type ResolvedAds, type ResolvedAnalytics, type ResolvedSeo, type ResolvedTag, type ResolvedTracking, type SeoContext, type SeoNameTag, type SeoOgType, type SeoPropertyTag, type SeoProps, type SeoTwitterCard, TRACKING_COOKIE, type TrackingCategory, resolveTracking };
854
894
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":["MediaOutputKind"],"sources":["../src/analytics.ts","../src/seo.ts","../src/integration.ts","../src/ads.ts","../src/lastmod.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":["MediaOutputKind"],"sources":["../src/analytics.ts","../src/seo.ts","../src/integration.ts","../src/ads.ts","../src/csp.ts","../src/lastmod.ts","../src/seo-defaults.ts"],"mappings":"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"}