nimbus-docs 0.1.7 → 0.1.8

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/schemas.d.ts CHANGED
@@ -18,7 +18,7 @@ interface DocSchemaConfig<TFields extends Record<string, z.ZodTypeAny> = Record<
18
18
  * For typed Astro `image()` fields or per-collection field narrowing, use
19
19
  * the richer `defineSchema(ctx => ...)` factory instead.
20
20
  */
21
- declare function defineDocSchema<TFields extends Record<string, z.ZodTypeAny> = Record<string, never>>(config?: DocSchemaConfig<TFields>): z.ZodObject<(("prev" | "next" | "title" | "description" | "mode" | "sidebar" | "head" | "banner" | "draft" | "noindex" | "searchable" | "tableOfContents" | "lastUpdated" | "socialImage" | "previousSlug") & keyof TFields extends never ? {
21
+ declare function defineDocSchema<TFields extends Record<string, z.ZodTypeAny> = Record<string, never>>(config?: DocSchemaConfig<TFields>): z.ZodObject<(("prev" | "next" | "title" | "description" | "mode" | "sidebar" | "head" | "banner" | "draft" | "noindex" | "searchable" | "tableOfContents" | "lastUpdated" | "socialImage" | "previousSlug" | "external_link") & keyof TFields extends never ? {
22
22
  title: z.ZodString;
23
23
  description: z.ZodOptional<z.ZodString>;
24
24
  mode: z.ZodDefault<z.ZodEnum<{
@@ -43,13 +43,33 @@ declare function defineDocSchema<TFields extends Record<string, z.ZodTypeAny> =
43
43
  }, z.core.$strip>]>>;
44
44
  hidden: z.ZodOptional<z.ZodBoolean>;
45
45
  hideChildren: z.ZodOptional<z.ZodBoolean>;
46
+ group: z.ZodOptional<z.ZodObject<{
47
+ label: z.ZodOptional<z.ZodString>;
48
+ badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
49
+ text: z.ZodString;
50
+ variant: z.ZodDefault<z.ZodEnum<{
51
+ success: "success";
52
+ default: "default";
53
+ info: "info";
54
+ note: "note";
55
+ tip: "tip";
56
+ warning: "warning";
57
+ caution: "caution";
58
+ danger: "danger";
59
+ }>>;
60
+ }, z.core.$strip>]>>;
61
+ hideIndex: z.ZodOptional<z.ZodBoolean>;
62
+ }, z.core.$strip>>;
46
63
  }, z.core.$strip>]>>;
47
64
  head: z.ZodDefault<z.ZodArray<z.ZodObject<{
48
65
  tag: z.ZodEnum<{
66
+ title: "title";
49
67
  meta: "meta";
50
68
  link: "link";
51
69
  script: "script";
52
70
  style: "style";
71
+ noscript: "noscript";
72
+ base: "base";
53
73
  }>;
54
74
  attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
55
75
  content: z.ZodOptional<z.ZodString>;
@@ -85,6 +105,7 @@ declare function defineDocSchema<TFields extends Record<string, z.ZodTypeAny> =
85
105
  label: z.ZodOptional<z.ZodString>;
86
106
  }, z.core.$strip>, z.ZodLiteral<false>]>>;
87
107
  previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
108
+ external_link: z.ZodOptional<z.ZodString>;
88
109
  } & { -readonly [P in keyof TFields]: TFields[P] } : ({
89
110
  title: z.ZodString;
90
111
  description: z.ZodOptional<z.ZodString>;
@@ -110,13 +131,33 @@ declare function defineDocSchema<TFields extends Record<string, z.ZodTypeAny> =
110
131
  }, z.core.$strip>]>>;
111
132
  hidden: z.ZodOptional<z.ZodBoolean>;
112
133
  hideChildren: z.ZodOptional<z.ZodBoolean>;
134
+ group: z.ZodOptional<z.ZodObject<{
135
+ label: z.ZodOptional<z.ZodString>;
136
+ badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
137
+ text: z.ZodString;
138
+ variant: z.ZodDefault<z.ZodEnum<{
139
+ success: "success";
140
+ default: "default";
141
+ info: "info";
142
+ note: "note";
143
+ tip: "tip";
144
+ warning: "warning";
145
+ caution: "caution";
146
+ danger: "danger";
147
+ }>>;
148
+ }, z.core.$strip>]>>;
149
+ hideIndex: z.ZodOptional<z.ZodBoolean>;
150
+ }, z.core.$strip>>;
113
151
  }, z.core.$strip>]>>;
114
152
  head: z.ZodDefault<z.ZodArray<z.ZodObject<{
115
153
  tag: z.ZodEnum<{
154
+ title: "title";
116
155
  meta: "meta";
117
156
  link: "link";
118
157
  script: "script";
119
158
  style: "style";
159
+ noscript: "noscript";
160
+ base: "base";
120
161
  }>;
121
162
  attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
122
163
  content: z.ZodOptional<z.ZodString>;
@@ -152,6 +193,7 @@ declare function defineDocSchema<TFields extends Record<string, z.ZodTypeAny> =
152
193
  label: z.ZodOptional<z.ZodString>;
153
194
  }, z.core.$strip>, z.ZodLiteral<false>]>>;
154
195
  previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
196
+ external_link: z.ZodOptional<z.ZodString>;
155
197
  } extends infer T_1 extends z.core.util.SomeObject ? { [K in keyof T_1 as K extends keyof TFields ? never : K]: T_1[K] } : never) & { [K_1 in keyof { -readonly [P in keyof TFields]: TFields[P] }]: { -readonly [P in keyof TFields]: TFields[P] }[K_1] }) extends infer T ? { [k in keyof T]: T[k] } : never, z.core.$strip>;
156
198
  /**
157
199
  * Factory options for `defineSchema`.
@@ -203,6 +245,26 @@ declare const docsSchema: z.ZodObject<{
203
245
  declare const partialsSchema: z.ZodDefault<z.ZodObject<{
204
246
  params: z.ZodOptional<z.ZodArray<z.ZodString>>;
205
247
  }, z.core.$strip>>;
248
+ /**
249
+ * Build a customizable partials schema. Mirrors `defineDocSchema` — use
250
+ * when porting upstream partials that ship product-specific frontmatter
251
+ * keys (e.g. CF's `inputParameters`) and you want them to validate without
252
+ * editing the source files.
253
+ *
254
+ * import { z } from "astro/zod";
255
+ * import { partialsCollection } from "nimbus-docs/content";
256
+ *
257
+ * defineCollection(partialsCollection({
258
+ * schemaFields: { inputParameters: z.string().optional() },
259
+ * }));
260
+ */
261
+ declare function definePartialsSchema<TFields extends Record<string, z.ZodTypeAny> = Record<string, never>>(config?: {
262
+ fields?: TFields;
263
+ }): z.ZodObject<("params" & keyof TFields extends never ? {
264
+ params: z.ZodOptional<z.ZodArray<z.ZodString>>;
265
+ } & { -readonly [P in keyof TFields]: TFields[P] } : ({
266
+ params: z.ZodOptional<z.ZodArray<z.ZodString>>;
267
+ } extends infer T_1 extends z.core.util.SomeObject ? { [K in keyof T_1 as K extends keyof TFields ? never : K]: T_1[K] } : never) & { [K_1 in keyof { -readonly [P in keyof TFields]: TFields[P] }]: { -readonly [P in keyof TFields]: TFields[P] }[K_1] }) extends infer T ? { [k in keyof T]: T[k] } : never, z.core.$strip>;
206
268
  /** Docs frontmatter, framework fields type-checked, extra keys allowed. */
207
269
  declare const lenientDocsSchema: z.ZodObject<{
208
270
  title: z.ZodString;
@@ -229,13 +291,33 @@ declare const lenientDocsSchema: z.ZodObject<{
229
291
  }, z.core.$strip>]>>;
230
292
  hidden: z.ZodOptional<z.ZodBoolean>;
231
293
  hideChildren: z.ZodOptional<z.ZodBoolean>;
294
+ group: z.ZodOptional<z.ZodObject<{
295
+ label: z.ZodOptional<z.ZodString>;
296
+ badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
297
+ text: z.ZodString;
298
+ variant: z.ZodDefault<z.ZodEnum<{
299
+ success: "success";
300
+ default: "default";
301
+ info: "info";
302
+ note: "note";
303
+ tip: "tip";
304
+ warning: "warning";
305
+ caution: "caution";
306
+ danger: "danger";
307
+ }>>;
308
+ }, z.core.$strip>]>>;
309
+ hideIndex: z.ZodOptional<z.ZodBoolean>;
310
+ }, z.core.$strip>>;
232
311
  }, z.core.$strip>]>>;
233
312
  head: z.ZodDefault<z.ZodArray<z.ZodObject<{
234
313
  tag: z.ZodEnum<{
314
+ title: "title";
235
315
  meta: "meta";
236
316
  link: "link";
237
317
  script: "script";
238
318
  style: "style";
319
+ noscript: "noscript";
320
+ base: "base";
239
321
  }>;
240
322
  attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
241
323
  content: z.ZodOptional<z.ZodString>;
@@ -271,6 +353,7 @@ declare const lenientDocsSchema: z.ZodObject<{
271
353
  label: z.ZodOptional<z.ZodString>;
272
354
  }, z.core.$strip>, z.ZodLiteral<false>]>>;
273
355
  previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
356
+ external_link: z.ZodOptional<z.ZodString>;
274
357
  }, z.core.$loose>;
275
358
  /** Partials frontmatter, framework fields type-checked, extra keys allowed. */
276
359
  declare const lenientPartialsSchema: z.ZodObject<{
@@ -298,5 +381,5 @@ declare const componentsSchema: z.ZodObject<{
298
381
  }, z.core.$strip>>>;
299
382
  }, z.core.$strip>;
300
383
  //#endregion
301
- export { ComponentProp, DefineSchemaOptions, DocSchemaConfig, componentsSchema, defineDocSchema, defineSchema, docsSchema, lenientDocsSchema, lenientPartialsSchema, partialsSchema };
384
+ export { ComponentProp, DefineSchemaOptions, DocSchemaConfig, componentsSchema, defineDocSchema, definePartialsSchema, defineSchema, docsSchema, lenientDocsSchema, lenientPartialsSchema, partialsSchema };
302
385
  //# sourceMappingURL=schemas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","names":[],"sources":["../src/schemas.ts"],"mappings":";;;;UAiBiB,eAAA,iBACC,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA;EAAhB;;;;;EAO/B,MAAA,GAAS,OAAA;AAAA;AA2OX;;;;;;;;AAAA,iBAAgB,eAAA,iBACE,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA,gBAAA,CAC/C,MAAA,GAAQ,eAAA,CAAgB,OAAA,IAAa,CAAA,CAAA,SAAA,yMAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAyBtB,mBAAA;EACf,MAAA,GAAS,CAAA,CAAE,UAAA;EACX,MAAA,GAAS,MAAA,SAAe,CAAA,CAAE,UAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BZ,YAAA,CACd,OAAA,GAAU,GAAA,EADgB,cAAA,CACa,aAAA,KAAkB,mBAAA,IAEjD,GAAA,EAFoE,cAAA,CAEvC,aAAA,KAAa,CAAA,CAAA,eAAA,CAAA,CAAA,CAAA,SAAA,MAAA,CAAA,CAAA,IAAA,CAAA,MAAA,GAAA,CAAA,CAAA,OAAA,mBAAA,CAAA,CAAA,IAAA,CAAA,iBAAA,uBAAA,CAAA,CAAA,SAAA,CAAA,QAAA;EAAA;;;cA8BvC,UAAA,EAAU,CAAA,CAAA,SAAA;EAAA;GAAoB,CAAA,CAAA,IAAA,CAAA,MAAA;;cAW9B,cAAA,EAAc,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;;;;cAad,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAGjB,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;cAU5B,mBAAA,EAAmB,CAAA,CAAA,SAAA;;;;;;;KAQb,aAAA,GAAgB,CAAA,CAAE,KAAA,QAAa,mBAAA;;cAG9B,gBAAA,EAAgB,CAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"schemas.d.ts","names":[],"sources":["../src/schemas.ts"],"mappings":";;;;UAkBiB,eAAA,iBACC,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA;EAAhB;;;;;EAO/B,MAAA,GAAS,OAAA;AAAA;AA6SX;;;;;;;;AAAA,iBAAgB,eAAA,iBACE,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA,gBAAA,CAC/C,MAAA,GAAQ,eAAA,CAAgB,OAAA,IAAa,CAAA,CAAA,SAAA,2NAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAyBtB,mBAAA;EACf,MAAA,GAAS,CAAA,CAAE,UAAA;EACX,MAAA,GAAS,MAAA,SAAe,CAAA,CAAE,UAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BZ,YAAA,CACd,OAAA,GAAU,GAAA,EADgB,cAAA,CACa,aAAA,KAAkB,mBAAA,IAEjD,GAAA,EAFoE,cAAA,CAEvC,aAAA,KAAa,CAAA,CAAA,eAAA,CAAA,CAAA,CAAA,SAAA,MAAA,CAAA,CAAA,IAAA,CAAA,MAAA,GAAA,CAAA,CAAA,OAAA,mBAAA,CAAA,CAAA,IAAA,CAAA,iBAAA,uBAAA,CAAA,CAAA,SAAA,CAAA,QAAA;EAAA;;;cA8BvC,UAAA,EAAU,CAAA,CAAA,SAAA;EAAA;GAAoB,CAAA,CAAA,IAAA,CAAA,MAAA;;cAW9B,cAAA,EAAc,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;iBAeX,oBAAA,iBACE,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA,gBAAA,CAC/C,MAAA;EAAU,MAAA,GAAS,OAAA;AAAA,IAAc,CAAA,CAAA,SAAA,mBAAA,OAAA;;;;;;cAmBtB,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAGjB,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;cAU5B,mBAAA,EAAmB,CAAA,CAAA,SAAA;;;;;;;KAQb,aAAA,GAAgB,CAAA,CAAE,KAAA,QAAa,mBAAA;;cAG9B,gBAAA,EAAgB,CAAA,CAAA,SAAA"}
package/dist/schemas.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as withStrictKeys } from "./strict-keys-BiXiT3pq.js";
1
+ import { n as isAbsoluteUrl, t as withStrictKeys } from "./strict-keys-fbKKxxKL.js";
2
2
  import { z } from "astro/zod";
3
3
 
4
4
  //#region src/schemas.ts
@@ -28,12 +28,18 @@ const sidebarBadgeSchema = z.union([z.string(), z.object({
28
28
  "danger"
29
29
  ], { error: "\"variant\" must be one of: default, info, note, success, tip, warning, caution, danger" }).default("default")
30
30
  })]);
31
+ const sidebarGroupSchema = z.object({
32
+ label: z.string({ error: "\"sidebar.group.label\" must be a string" }).optional(),
33
+ badge: sidebarBadgeSchema.optional(),
34
+ hideIndex: z.boolean({ error: "\"sidebar.group.hideIndex\" must be true or false" }).optional()
35
+ });
31
36
  const sidebarSchema = z.object({
32
37
  order: z.number({ error: "\"sidebar.order\" must be a number" }).optional(),
33
38
  label: z.string({ error: "\"sidebar.label\" must be a string" }).optional(),
34
39
  badge: sidebarBadgeSchema.optional(),
35
40
  hidden: z.boolean({ error: "\"sidebar.hidden\" must be true or false" }).optional(),
36
- hideChildren: z.boolean({ error: "\"sidebar.hideChildren\" must be true or false" }).optional()
41
+ hideChildren: z.boolean({ error: "\"sidebar.hideChildren\" must be true or false" }).optional(),
42
+ group: sidebarGroupSchema.optional()
37
43
  });
38
44
  const prevNextSchema = z.union([
39
45
  z.string(),
@@ -48,8 +54,11 @@ const headElementSchema = z.object({
48
54
  "meta",
49
55
  "link",
50
56
  "script",
51
- "style"
52
- ], { error: "head element \"tag\" must be \"meta\", \"link\", \"script\", or \"style\"" }),
57
+ "style",
58
+ "title",
59
+ "noscript",
60
+ "base"
61
+ ], { error: "head element \"tag\" must be one of: meta, link, script, style, title, noscript, base" }),
53
62
  attrs: z.record(z.string(), z.string()).default({}),
54
63
  content: z.string().optional()
55
64
  });
@@ -128,7 +137,8 @@ function baseDocSchema() {
128
137
  socialImage: z.string({ error: "\"socialImage\" must be a string (path or URL)" }).optional(),
129
138
  prev: prevNextSchema,
130
139
  next: prevNextSchema,
131
- previousSlug: z.union([z.string(), z.array(z.string())], { error: "\"previousSlug\" must be a string or array of strings" }).optional()
140
+ previousSlug: z.union([z.string(), z.array(z.string())], { error: "\"previousSlug\" must be a string or array of strings" }).optional(),
141
+ external_link: z.string({ error: "\"external_link\" must be a URL or absolute path" }).refine((v) => v.length > 0 && (isAbsoluteUrl(v) || v.startsWith("/")), { message: "\"external_link\" must be a non-empty absolute URL (e.g. \"https://example.com/foo\") or a site-absolute path (e.g. \"/replacement-page\"). Relative paths are rejected because they'd resolve against the entry's own URL rather than where the author intended." }).optional()
132
142
  });
133
143
  }
134
144
  /**
@@ -183,6 +193,22 @@ const docsSchema = defineDocSchema();
183
193
  const partialsObjectSchema = z.object({ params: z.array(z.string()).optional() });
184
194
  /** Schema for partials (`<Render file="..." />` snippets). */
185
195
  const partialsSchema = partialsObjectSchema.default({});
196
+ /**
197
+ * Build a customizable partials schema. Mirrors `defineDocSchema` — use
198
+ * when porting upstream partials that ship product-specific frontmatter
199
+ * keys (e.g. CF's `inputParameters`) and you want them to validate without
200
+ * editing the source files.
201
+ *
202
+ * import { z } from "astro/zod";
203
+ * import { partialsCollection } from "nimbus-docs/content";
204
+ *
205
+ * defineCollection(partialsCollection({
206
+ * schemaFields: { inputParameters: z.string().optional() },
207
+ * }));
208
+ */
209
+ function definePartialsSchema(config = {}) {
210
+ return partialsObjectSchema.extend(config.fields ?? {});
211
+ }
186
212
  /** Docs frontmatter, framework fields type-checked, extra keys allowed. */
187
213
  const lenientDocsSchema = baseDocSchema().passthrough();
188
214
  /** Partials frontmatter, framework fields type-checked, extra keys allowed. */
@@ -203,5 +229,5 @@ const componentsSchema = z.object({
203
229
  });
204
230
 
205
231
  //#endregion
206
- export { componentsSchema, defineDocSchema, defineSchema, docsSchema, lenientDocsSchema, lenientPartialsSchema, partialsSchema };
232
+ export { componentsSchema, defineDocSchema, definePartialsSchema, defineSchema, docsSchema, lenientDocsSchema, lenientPartialsSchema, partialsSchema };
207
233
  //# sourceMappingURL=schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["/**\n * Content schemas for Nimbus.\n *\n * `docsSchema` is the default frontmatter contract for the `docs` collection.\n * `partialsSchema` is the contract for `<Render file=\"...\" />` partials.\n * `defineDocSchema(config)` returns a customizable schema for advanced users\n * composing schemas outside the `docsCollection()` factory.\n *\n * Error messages target content authors, not framework developers.\n * Astro 6 ships Zod v4 via `astro/zod`. The v4 API uses a single `error`\n * field on every schema constructor — NOT v3's `required_error` /\n * `invalid_type_error` / `errorMap`.\n */\n\nimport { z } from \"astro/zod\";\nimport { withStrictKeys } from \"./_internal/strict-keys.js\";\n\nexport interface DocSchemaConfig<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n> {\n /**\n * Additional frontmatter fields merged into the default schema.\n * Generic-typed so the call-site shape is preserved through to\n * `entry.data.<field>` access in consumer code.\n */\n fields?: TFields;\n}\n\n// ---------------------------------------------------------------------------\n// Building blocks\n// ---------------------------------------------------------------------------\n\nconst sidebarBadgeSchema = z.union([\n z.string(),\n z.object({\n text: z.string({ error: 'sidebar badge needs a \"text\" field' }),\n variant: z\n .enum(\n [\"default\", \"info\", \"note\", \"success\", \"tip\", \"warning\", \"caution\", \"danger\"],\n {\n error:\n '\"variant\" must be one of: default, info, note, success, tip, warning, caution, danger',\n },\n )\n .default(\"default\"),\n }),\n]);\n\nconst sidebarSchema = z.object({\n order: z.number({ error: '\"sidebar.order\" must be a number' }).optional(),\n label: z.string({ error: '\"sidebar.label\" must be a string' }).optional(),\n badge: sidebarBadgeSchema.optional(),\n hidden: z.boolean({ error: '\"sidebar.hidden\" must be true or false' }).optional(),\n hideChildren: z\n .boolean({ error: '\"sidebar.hideChildren\" must be true or false' })\n .optional(),\n});\n\nconst prevNextSchema = z\n .union([\n z.string(),\n z.object({ link: z.string().optional(), label: z.string().optional() }),\n z.literal(false),\n ])\n .optional();\n\nconst headElementSchema = z.object({\n tag: z.enum([\"meta\", \"link\", \"script\", \"style\"], {\n error: 'head element \"tag\" must be \"meta\", \"link\", \"script\", or \"style\"',\n }),\n attrs: z.record(z.string(), z.string()).default({}),\n content: z.string().optional(),\n});\n\n// Mirrors `BannerProps` in types.ts. Layouts consume this directly off\n// `entry.data.banner` and render the `<Banner>` component with it, so the\n// schema is framework-owned (not user-extensible territory).\nconst bannerSchema = z.object({\n content: z.string({ error: 'banner \"content\" must be a string' }),\n type: z\n .enum([\"note\", \"tip\", \"caution\", \"danger\"], {\n error: 'banner \"type\" must be one of: note, tip, caution, danger',\n })\n .optional(),\n dismissible: z\n .object({\n id: z.string({\n error: 'banner \"dismissible.id\" must be a string — a stable identifier you bump when banner content meaningfully changes',\n }),\n days: z.number({ error: 'banner \"dismissible.days\" must be a number' }).optional(),\n })\n .optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Removed/renamed frontmatter keys — surface migration errors loudly\n// ---------------------------------------------------------------------------\n\n/**\n * Frontmatter keys that used to exist but no longer do. When user content\n * still carries one of these, Zod's default `.strip()` behavior would\n * silently drop it — the page would build, but with subtly different\n * behavior (the old toggle just disappears). That's a confusing failure\n * mode for an authoring contract.\n *\n * `withUnknownKeyCheck` (below) consults this map. Hits get the friendly\n * migration message verbatim; everything else falls through to a generic\n * \"Unknown frontmatter key\" error so typos don't sneak past either.\n *\n * Entries removed in the v0 → v1 cleanup:\n *\n * - `template` → `mode`: same shape, but `\"splash\"` is now `\"custom\"`.\n * - `pagefind` → `searchable`: same boolean; default now derives from\n * `noindex` (a non-crawlable page is non-searchable by default).\n * - `llms`: removed. All published pages are listed in `/llms.txt`; the\n * escape hatch is `noindex: true`.\n * - `aiDeprioritize`: removed. The framework no longer emits an\n * agent-downrank signal.\n * - `hero`: removed. Compose the hero in MDX body with user-owned\n * components instead of a frontmatter contract.\n */\nconst REMOVED_FRONTMATTER_KEYS: Record<string, string> = {\n template:\n 'was renamed to \"mode\". Replace `template: \"doc\"` with `mode: \"doc\"`, and `template: \"splash\"` with `mode: \"custom\"`.',\n pagefind:\n 'was renamed to \"searchable\". Same boolean shape; the default now derives from `noindex` (a non-crawlable page is non-searchable unless you set `searchable: true` explicitly).',\n llms:\n \"was removed. Every published page is now listed in /llms.txt; use `noindex: true` to keep a page out of both search engines and the LLM index.\",\n aiDeprioritize:\n \"was removed. The framework no longer emits an agent-downrank signal. If you want a page hidden from agents, use `noindex: true`.\",\n hero:\n \"was removed. Compose your hero in the MDX body using user-owned components; there is no longer a `hero` frontmatter contract.\",\n};\n\n/**\n * Apply this AFTER any `.extend()` so user-added fields are recognized\n * as valid. Wraps the schema in `.passthrough().superRefine()` so removed\n * keys raise a guided migration error; other unknown keys raise a\n * generic error pointing at `defineSchema({ extend: ... })`.\n */\nfunction withFrontmatterKeyCheck<T extends z.ZodObject<z.ZodRawShape>>(schema: T) {\n return withStrictKeys(schema, {\n removedKeys: REMOVED_FRONTMATTER_KEYS,\n contextLabel: \"Frontmatter key\",\n unknownHint: (key) =>\n `If you meant to add a custom field, declare it in your collection's schema via \\`defineSchema({ extend: z.object({ ${key}: ... }) })\\`.`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Base docs schema\n// ---------------------------------------------------------------------------\n\nfunction baseDocSchema() {\n return z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing required \"title\" in frontmatter. Every doc needs:\\n\\n ---\\n title: \"Your Page Title\"\\n ---'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n description: z.string({ error: '\"description\" must be a string' }).optional(),\n mode: z\n .enum([\"doc\", \"custom\"], {\n error: '\"mode\" must be \"doc\" or \"custom\"',\n })\n .default(\"doc\"),\n sidebar: z.union([z.literal(false), sidebarSchema]).optional(),\n head: z.array(headElementSchema).default([]),\n banner: bannerSchema.optional(),\n draft: z.boolean({ error: '\"draft\" must be true or false' }).default(false),\n noindex: z.boolean({ error: '\"noindex\" must be true or false' }).default(false),\n /**\n * Whether this page is included in the site search index. When omitted,\n * derives from `noindex` (a page that's not crawlable is by default not\n * searchable). Set explicitly to override — e.g. `{ noindex: true,\n * searchable: true }` keeps the page out of search engines but findable\n * in the site's own search.\n */\n searchable: z\n .boolean({ error: '\"searchable\" must be true or false' })\n .optional(),\n tableOfContents: z\n .union([\n z.literal(false),\n z\n .object({\n minHeadingLevel: z\n .number({ error: '\"minHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(2),\n maxHeadingLevel: z\n .number({ error: '\"maxHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(3),\n })\n .refine((v) => v.minHeadingLevel <= v.maxHeadingLevel, {\n message: \"minHeadingLevel must be <= maxHeadingLevel\",\n }),\n ])\n .optional(),\n lastUpdated: z.coerce\n .date({ error: '\"lastUpdated\" must be a valid date (e.g. 2024-01-15)' })\n .optional(),\n /**\n * Explicit per-page social/OG image override (path or absolute URL).\n * When omitted, the page route is expected to fall back to a\n * programmatically-generated card or the site-wide `config.socialImage`.\n */\n socialImage: z\n .string({ error: '\"socialImage\" must be a string (path or URL)' })\n .optional(),\n prev: prevNextSchema,\n next: prevNextSchema,\n /**\n * Versioning rename escape hatch.\n *\n * When a page is renamed between versions (the URL slug changes), the\n * newer version's frontmatter declares the slug it had in an older\n * version. The framework uses this to link the pages as cross-version\n * alternates and to emit a `<link rel=\"canonical\">` to the current\n * version's URL.\n *\n * Example: `docs-v1/old-name.mdx` was renamed in v2 to `new-name.mdx`.\n * On the new page (`docs/new-name.mdx`, current version), set:\n *\n * previousSlug: old-name\n *\n * Now `/new-name` and `/v1/old-name` are linked as the same logical\n * page in `<head>` alternates, and the v1 page's canonical points to\n * `/new-name`.\n *\n * Accepts a single slug string (the page's id in the older version)\n * or an array of strings when the page has been renamed across more\n * than one version.\n */\n previousSlug: z\n .union([z.string(), z.array(z.string())], {\n error: '\"previousSlug\" must be a string or array of strings',\n })\n .optional(),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Build a customizable docs schema. Use this when composing schemas outside\n * the `docsCollection()` factory (e.g. multiple docs collections with\n * different shapes).\n *\n * For typed Astro `image()` fields or per-collection field narrowing, use\n * the richer `defineSchema(ctx => ...)` factory instead.\n */\nexport function defineDocSchema<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n>(config: DocSchemaConfig<TFields> = {}) {\n const base = baseDocSchema();\n // Always extend (with `{}` when no fields) so the result type is\n // `ZodObject<baseShape & TFields>` rather than a union of branches.\n // A union widens the consumer view of `entry.data.X` to the intersection\n // of branch fields, which is \"no fields\" for the false branch and\n // re-erases everything we just preserved.\n const merged = base.extend((config.fields ?? {}) as TFields);\n // Cast back to the underlying ZodObject. Runtime wrap (`.passthrough()\n // .superRefine()`) stays — the unknown-key check still fires. But tsdown\n // collapses ZodEffects emissions to `ZodObject<Record<string, ZodType<unknown>>>`,\n // erasing every framework field type at every consumer's `entry.data.X`\n // access. The cast preserves the field shapes through .d.ts emission.\n return withFrontmatterKeyCheck(merged) as unknown as typeof merged;\n}\n\n/**\n * Factory options for `defineSchema`.\n *\n * - `extend`: additional fields merged into the framework schema. Use\n * this for user-defined frontmatter (`author`, `tags`, `cover`).\n * - `narrow`: replaces framework fields with tighter types within this\n * collection. Use when a collection has stricter rules — e.g.\n * `{ mode: z.literal(\"doc\") }` says no landing pages in this collection.\n */\nexport interface DefineSchemaOptions {\n extend?: z.ZodTypeAny;\n narrow?: Record<string, z.ZodTypeAny>;\n}\n\n/**\n * Build a typed docs schema with access to the Astro `SchemaContext`.\n * Use this when you want typed image fields (`ctx.image()`), per-\n * collection narrowing of framework fields, or both. The simpler\n * `defineDocSchema({ fields })` factory is still available for the\n * common case of just adding fields.\n *\n * import { defineCollection } from \"astro:content\";\n * import { z } from \"astro/zod\";\n * import { defineSchema } from \"nimbus-docs/schemas\";\n *\n * export const collections = {\n * docs: defineCollection({\n * loader: ...,\n * schema: defineSchema((ctx) => ({\n * extend: z.object({\n * cover: ctx.image().optional(),\n * author: z.string().optional(),\n * }),\n * narrow: {\n * mode: z.literal(\"doc\"), // no landing pages here\n * },\n * })),\n * }),\n * };\n */\nexport function defineSchema(\n factory: (ctx: import(\"astro:content\").SchemaContext) => DefineSchemaOptions,\n) {\n return (ctx: import(\"astro:content\").SchemaContext) => {\n const { extend, narrow } = factory(ctx);\n let schema = baseDocSchema() as z.ZodObject<any>;\n\n // narrowing first (overrides framework fields)\n if (narrow) {\n schema = schema.extend(narrow);\n }\n\n // additive extension (new user fields). Prefer .merge for ZodObject\n // (preserves object-ness for downstream .extend); fall back to .and\n // for any other Zod type (intersection, union, etc.).\n if (extend) {\n if (extend instanceof z.ZodObject) {\n schema = schema.merge(extend);\n } else {\n // Intersection path — `.and()` returns ZodIntersection, on which\n // we can't run `withUnknownKeyCheck` (it operates on ZodObject's\n // `.shape`). Users on this path lose the removed-key migration\n // diagnostic; they own that trade-off by reaching for the\n // non-object extend.\n return schema.and(extend);\n }\n }\n\n return withFrontmatterKeyCheck(schema);\n };\n}\n\n/** Default docs schema. Equivalent to `defineDocSchema()`. */\nexport const docsSchema = defineDocSchema();\n\nconst partialsObjectSchema = z.object({\n /**\n * Declared parameters this partial accepts.\n * Suffix with `?` for optional params: `[\"name\", \"deprecated?\"]`\n */\n params: z.array(z.string()).optional(),\n});\n\n/** Schema for partials (`<Render file=\"...\" />` snippets). */\nexport const partialsSchema = partialsObjectSchema.default({});\n\n// ---------------------------------------------------------------------------\n// Lenient variants — used by `nimbus-docs lint` (`nimbus/frontmatter-shape`).\n//\n// The standalone lint CLI can't yet see a site's extended\n// `content.config.ts` schema, so it validates the *types* of the fields\n// the framework owns while tolerating user-added fields (passthrough).\n// Unknown-key detection is deferred to when the engine can load the real\n// per-collection schema.\n// ---------------------------------------------------------------------------\n\n/** Docs frontmatter, framework fields type-checked, extra keys allowed. */\nexport const lenientDocsSchema = baseDocSchema().passthrough();\n\n/** Partials frontmatter, framework fields type-checked, extra keys allowed. */\nexport const lenientPartialsSchema = partialsObjectSchema.passthrough();\n\n// ---------------------------------------------------------------------------\n// Components collection — used by sites documenting their own UI components.\n// Pair with `componentsCollection()` from `nimbus-docs/content`. Authoring\n// pattern: hero `<Showcase>` block + `<Example>` blocks in the MDX body, with\n// `props` declared in frontmatter for a generated prop table.\n// ---------------------------------------------------------------------------\n\n/** One row in a component's `props` frontmatter array. */\nconst componentPropSchema = z.object({\n name: z.string({ error: 'prop needs a \"name\"' }),\n type: z.string({ error: 'prop needs a \"type\"' }),\n defaultValue: z.string().optional(),\n required: z.boolean().default(false),\n description: z.string({ error: 'prop needs a \"description\"' }),\n});\n\nexport type ComponentProp = z.infer<typeof componentPropSchema>;\n\n/** Default schema for the components collection. */\nexport const componentsSchema = z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"title\" in frontmatter — display name used in the sidebar and page header.'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n tagline: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"tagline\" in frontmatter — one-sentence summary shown under the title.'\n : `\"tagline\" must be a string, received ${typeof iss.input}`,\n }),\n props: z.array(componentPropSchema).default([]),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,MAAM,qBAAqB,EAAE,MAAM,CACjC,EAAE,QAAQ,EACV,EAAE,OAAO;CACP,MAAM,EAAE,OAAO,EAAE,OAAO,wCAAsC,CAAC;CAC/D,SAAS,EACN,KACC;EAAC;EAAW;EAAQ;EAAQ;EAAW;EAAO;EAAW;EAAW;EAAS,EAC7E,EACE,OACE,2FACH,CACF,CACA,QAAQ,UAAU;CACtB,CAAC,CACH,CAAC;AAEF,MAAM,gBAAgB,EAAE,OAAO;CAC7B,OAAO,EAAE,OAAO,EAAE,OAAO,sCAAoC,CAAC,CAAC,UAAU;CACzE,OAAO,EAAE,OAAO,EAAE,OAAO,sCAAoC,CAAC,CAAC,UAAU;CACzE,OAAO,mBAAmB,UAAU;CACpC,QAAQ,EAAE,QAAQ,EAAE,OAAO,4CAA0C,CAAC,CAAC,UAAU;CACjF,cAAc,EACX,QAAQ,EAAE,OAAO,kDAAgD,CAAC,CAClE,UAAU;CACd,CAAC;AAEF,MAAM,iBAAiB,EACpB,MAAM;CACL,EAAE,QAAQ;CACV,EAAE,OAAO;EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU;EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU;EAAE,CAAC;CACvE,EAAE,QAAQ,MAAM;CACjB,CAAC,CACD,UAAU;AAEb,MAAM,oBAAoB,EAAE,OAAO;CACjC,KAAK,EAAE,KAAK;EAAC;EAAQ;EAAQ;EAAU;EAAQ,EAAE,EAC/C,OAAO,6EACR,CAAC;CACF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;CACnD,SAAS,EAAE,QAAQ,CAAC,UAAU;CAC/B,CAAC;AAKF,MAAM,eAAe,EAAE,OAAO;CAC5B,SAAS,EAAE,OAAO,EAAE,OAAO,uCAAqC,CAAC;CACjE,MAAM,EACH,KAAK;EAAC;EAAQ;EAAO;EAAW;EAAS,EAAE,EAC1C,OAAO,8DACR,CAAC,CACD,UAAU;CACb,aAAa,EACV,OAAO;EACN,IAAI,EAAE,OAAO,EACX,OAAO,sHACR,CAAC;EACF,MAAM,EAAE,OAAO,EAAE,OAAO,gDAA8C,CAAC,CAAC,UAAU;EACnF,CAAC,CACD,UAAU;CACd,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AA6BF,MAAM,2BAAmD;CACvD,UACE;CACF,UACE;CACF,MACE;CACF,gBACE;CACF,MACE;CACH;;;;;;;AAQD,SAAS,wBAA8D,QAAW;AAChF,QAAO,eAAe,QAAQ;EAC5B,aAAa;EACb,cAAc;EACd,cAAc,QACZ,sHAAsH,IAAI;EAC7H,CAAC;;AAOJ,SAAS,gBAAgB;AACvB,QAAO,EAAE,OAAO;EACd,OAAO,EAAE,OAAO,EACd,QAAQ,QACN,IAAI,UAAU,SACV,8GACA,sCAAsC,OAAO,IAAI,SACxD,CAAC;EACF,aAAa,EAAE,OAAO,EAAE,OAAO,oCAAkC,CAAC,CAAC,UAAU;EAC7E,MAAM,EACH,KAAK,CAAC,OAAO,SAAS,EAAE,EACvB,OAAO,0CACR,CAAC,CACD,QAAQ,MAAM;EACjB,SAAS,EAAE,MAAM,CAAC,EAAE,QAAQ,MAAM,EAAE,cAAc,CAAC,CAAC,UAAU;EAC9D,MAAM,EAAE,MAAM,kBAAkB,CAAC,QAAQ,EAAE,CAAC;EAC5C,QAAQ,aAAa,UAAU;EAC/B,OAAO,EAAE,QAAQ,EAAE,OAAO,mCAAiC,CAAC,CAAC,QAAQ,MAAM;EAC3E,SAAS,EAAE,QAAQ,EAAE,OAAO,qCAAmC,CAAC,CAAC,QAAQ,MAAM;EAQ/E,YAAY,EACT,QAAQ,EAAE,OAAO,wCAAsC,CAAC,CACxD,UAAU;EACb,iBAAiB,EACd,MAAM,CACL,EAAE,QAAQ,MAAM,EAChB,EACG,OAAO;GACN,iBAAiB,EACd,OAAO,EAAE,OAAO,8CAA4C,CAAC,CAC7D,KAAK,CACL,IAAI,EAAE,CACN,IAAI,EAAE,CACN,QAAQ,EAAE;GACb,iBAAiB,EACd,OAAO,EAAE,OAAO,8CAA4C,CAAC,CAC7D,KAAK,CACL,IAAI,EAAE,CACN,IAAI,EAAE,CACN,QAAQ,EAAE;GACd,CAAC,CACD,QAAQ,MAAM,EAAE,mBAAmB,EAAE,iBAAiB,EACrD,SAAS,8CACV,CAAC,CACL,CAAC,CACD,UAAU;EACb,aAAa,EAAE,OACZ,KAAK,EAAE,OAAO,0DAAwD,CAAC,CACvE,UAAU;EAMb,aAAa,EACV,OAAO,EAAE,OAAO,kDAAgD,CAAC,CACjE,UAAU;EACb,MAAM;EACN,MAAM;EAuBN,cAAc,EACX,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,EACxC,OAAO,yDACR,CAAC,CACD,UAAU;EACd,CAAC;;;;;;;;;;AAeJ,SAAgB,gBAEd,SAAmC,EAAE,EAAE;AAavC,QAAO,wBAZM,eAAe,CAMR,OAAQ,OAAO,UAAU,EAAE,CAAa,CAMtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CxC,SAAgB,aACd,SACA;AACA,SAAQ,QAA+C;EACrD,MAAM,EAAE,QAAQ,WAAW,QAAQ,IAAI;EACvC,IAAI,SAAS,eAAe;AAG5B,MAAI,OACF,UAAS,OAAO,OAAO,OAAO;AAMhC,MAAI,OACF,KAAI,kBAAkB,EAAE,UACtB,UAAS,OAAO,MAAM,OAAO;MAO7B,QAAO,OAAO,IAAI,OAAO;AAI7B,SAAO,wBAAwB,OAAO;;;;AAK1C,MAAa,aAAa,iBAAiB;AAE3C,MAAM,uBAAuB,EAAE,OAAO,EAKpC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU,EACvC,CAAC;;AAGF,MAAa,iBAAiB,qBAAqB,QAAQ,EAAE,CAAC;;AAa9D,MAAa,oBAAoB,eAAe,CAAC,aAAa;;AAG9D,MAAa,wBAAwB,qBAAqB,aAAa;;AAUvE,MAAM,sBAAsB,EAAE,OAAO;CACnC,MAAM,EAAE,OAAO,EAAE,OAAO,yBAAuB,CAAC;CAChD,MAAM,EAAE,OAAO,EAAE,OAAO,yBAAuB,CAAC;CAChD,cAAc,EAAE,QAAQ,CAAC,UAAU;CACnC,UAAU,EAAE,SAAS,CAAC,QAAQ,MAAM;CACpC,aAAa,EAAE,OAAO,EAAE,OAAO,gCAA8B,CAAC;CAC/D,CAAC;;AAKF,MAAa,mBAAmB,EAAE,OAAO;CACvC,OAAO,EAAE,OAAO,EACd,QAAQ,QACN,IAAI,UAAU,SACV,yFACA,sCAAsC,OAAO,IAAI,SACxD,CAAC;CACF,SAAS,EAAE,OAAO,EAChB,QAAQ,QACN,IAAI,UAAU,SACV,qFACA,wCAAwC,OAAO,IAAI,SAC1D,CAAC;CACF,OAAO,EAAE,MAAM,oBAAoB,CAAC,QAAQ,EAAE,CAAC;CAChD,CAAC"}
1
+ {"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["/**\n * Content schemas for Nimbus.\n *\n * `docsSchema` is the default frontmatter contract for the `docs` collection.\n * `partialsSchema` is the contract for `<Render file=\"...\" />` partials.\n * `defineDocSchema(config)` returns a customizable schema for advanced users\n * composing schemas outside the `docsCollection()` factory.\n *\n * Error messages target content authors, not framework developers.\n * Astro 6 ships Zod v4 via `astro/zod`. The v4 API uses a single `error`\n * field on every schema constructor — NOT v3's `required_error` /\n * `invalid_type_error` / `errorMap`.\n */\n\nimport { z } from \"astro/zod\";\nimport { withStrictKeys } from \"./_internal/strict-keys.js\";\nimport { isAbsoluteUrl } from \"./_internal/url.js\";\n\nexport interface DocSchemaConfig<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n> {\n /**\n * Additional frontmatter fields merged into the default schema.\n * Generic-typed so the call-site shape is preserved through to\n * `entry.data.<field>` access in consumer code.\n */\n fields?: TFields;\n}\n\n// ---------------------------------------------------------------------------\n// Building blocks\n// ---------------------------------------------------------------------------\n\nconst sidebarBadgeSchema = z.union([\n z.string(),\n z.object({\n text: z.string({ error: 'sidebar badge needs a \"text\" field' }),\n variant: z\n .enum(\n [\"default\", \"info\", \"note\", \"success\", \"tip\", \"warning\", \"caution\", \"danger\"],\n {\n error:\n '\"variant\" must be one of: default, info, note, success, tip, warning, caution, danger',\n },\n )\n .default(\"default\"),\n }),\n]);\n\n// Group-level overrides for sidebar entries that act as a group label\n// (i.e. an `index.mdx` whose siblings become the group's children).\n// Starlight parity — sites migrating from Starlight write these as\n// `sidebar: { group: { … } }`. Apply only when the entry is the index\n// of a directory containing other entries.\nconst sidebarGroupSchema = z.object({\n /** Override the group label (defaults to the directory name). */\n label: z.string({ error: '\"sidebar.group.label\" must be a string' }).optional(),\n /** Override the group badge (defaults to none). */\n badge: sidebarBadgeSchema.optional(),\n /**\n * @deprecated No longer meaningful under structural separation. The\n * group label is now always the link to the index page (when one\n * exists), and the index is never duplicated as a child. Accepted but\n * ignored. Future major can drop the field.\n *\n * Pre-2026 Nimbus rendered the index as the first child link of its\n * group; this flag controlled that behavior. The \"Configuration >\n * Configuration\" duplicate it was meant to suppress can no longer\n * occur — the data model itself disallows it.\n */\n hideIndex: z\n .boolean({ error: '\"sidebar.group.hideIndex\" must be true or false' })\n .optional(),\n});\n\nconst sidebarSchema = z.object({\n order: z.number({ error: '\"sidebar.order\" must be a number' }).optional(),\n label: z.string({ error: '\"sidebar.label\" must be a string' }).optional(),\n badge: sidebarBadgeSchema.optional(),\n hidden: z.boolean({ error: '\"sidebar.hidden\" must be true or false' }).optional(),\n hideChildren: z\n .boolean({ error: '\"sidebar.hideChildren\" must be true or false' })\n .optional(),\n /** Group-level overrides; see `sidebarGroupSchema`. */\n group: sidebarGroupSchema.optional(),\n});\n\nconst prevNextSchema = z\n .union([\n z.string(),\n z.object({ link: z.string().optional(), label: z.string().optional() }),\n z.literal(false),\n ])\n .optional();\n\n// Head elements: every HTML tag that's valid as a direct child of <head>.\n// The earlier enum was meta/link/script/style only, which rejected the\n// equally-valid `title`, `noscript`, and `base` — the CF docs pilot hit\n// this on a page that overrides the browser tab title via\n// `head: [{ tag: title, content: \"Overview\" }]`. Keeping it an enum (vs.\n// a free `z.string()`) so typos still fail loudly, just over the full\n// real set rather than a curated subset.\nconst headElementSchema = z.object({\n tag: z.enum([\"meta\", \"link\", \"script\", \"style\", \"title\", \"noscript\", \"base\"], {\n error:\n 'head element \"tag\" must be one of: meta, link, script, style, title, noscript, base',\n }),\n attrs: z.record(z.string(), z.string()).default({}),\n content: z.string().optional(),\n});\n\n// Mirrors `BannerProps` in types.ts. Layouts consume this directly off\n// `entry.data.banner` and render the `<Banner>` component with it, so the\n// schema is framework-owned (not user-extensible territory).\nconst bannerSchema = z.object({\n content: z.string({ error: 'banner \"content\" must be a string' }),\n type: z\n .enum([\"note\", \"tip\", \"caution\", \"danger\"], {\n error: 'banner \"type\" must be one of: note, tip, caution, danger',\n })\n .optional(),\n dismissible: z\n .object({\n id: z.string({\n error: 'banner \"dismissible.id\" must be a string — a stable identifier you bump when banner content meaningfully changes',\n }),\n days: z.number({ error: 'banner \"dismissible.days\" must be a number' }).optional(),\n })\n .optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Removed/renamed frontmatter keys — surface migration errors loudly\n// ---------------------------------------------------------------------------\n\n/**\n * Frontmatter keys that used to exist but no longer do. When user content\n * still carries one of these, Zod's default `.strip()` behavior would\n * silently drop it — the page would build, but with subtly different\n * behavior (the old toggle just disappears). That's a confusing failure\n * mode for an authoring contract.\n *\n * `withUnknownKeyCheck` (below) consults this map. Hits get the friendly\n * migration message verbatim; everything else falls through to a generic\n * \"Unknown frontmatter key\" error so typos don't sneak past either.\n *\n * Entries removed in the v0 → v1 cleanup:\n *\n * - `template` → `mode`: same shape, but `\"splash\"` is now `\"custom\"`.\n * - `pagefind` → `searchable`: same boolean; default now derives from\n * `noindex` (a non-crawlable page is non-searchable by default).\n * - `llms`: removed. All published pages are listed in `/llms.txt`; the\n * escape hatch is `noindex: true`.\n * - `aiDeprioritize`: removed. The framework no longer emits an\n * agent-downrank signal.\n * - `hero`: removed. Compose the hero in MDX body with user-owned\n * components instead of a frontmatter contract.\n */\nconst REMOVED_FRONTMATTER_KEYS: Record<string, string> = {\n template:\n 'was renamed to \"mode\". Replace `template: \"doc\"` with `mode: \"doc\"`, and `template: \"splash\"` with `mode: \"custom\"`.',\n pagefind:\n 'was renamed to \"searchable\". Same boolean shape; the default now derives from `noindex` (a non-crawlable page is non-searchable unless you set `searchable: true` explicitly).',\n llms:\n \"was removed. Every published page is now listed in /llms.txt; use `noindex: true` to keep a page out of both search engines and the LLM index.\",\n aiDeprioritize:\n \"was removed. The framework no longer emits an agent-downrank signal. If you want a page hidden from agents, use `noindex: true`.\",\n hero:\n \"was removed. Compose your hero in the MDX body using user-owned components; there is no longer a `hero` frontmatter contract.\",\n};\n\n/**\n * Apply this AFTER any `.extend()` so user-added fields are recognized\n * as valid. Wraps the schema in `.passthrough().superRefine()` so removed\n * keys raise a guided migration error; other unknown keys raise a\n * generic error pointing at `defineSchema({ extend: ... })`.\n */\nfunction withFrontmatterKeyCheck<T extends z.ZodObject<z.ZodRawShape>>(schema: T) {\n return withStrictKeys(schema, {\n removedKeys: REMOVED_FRONTMATTER_KEYS,\n contextLabel: \"Frontmatter key\",\n unknownHint: (key) =>\n `If you meant to add a custom field, declare it in your collection's schema via \\`defineSchema({ extend: z.object({ ${key}: ... }) })\\`.`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Base docs schema\n// ---------------------------------------------------------------------------\n\nfunction baseDocSchema() {\n return z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing required \"title\" in frontmatter. Every doc needs:\\n\\n ---\\n title: \"Your Page Title\"\\n ---'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n description: z.string({ error: '\"description\" must be a string' }).optional(),\n mode: z\n .enum([\"doc\", \"custom\"], {\n error: '\"mode\" must be \"doc\" or \"custom\"',\n })\n .default(\"doc\"),\n sidebar: z.union([z.literal(false), sidebarSchema]).optional(),\n head: z.array(headElementSchema).default([]),\n banner: bannerSchema.optional(),\n draft: z.boolean({ error: '\"draft\" must be true or false' }).default(false),\n noindex: z.boolean({ error: '\"noindex\" must be true or false' }).default(false),\n /**\n * Whether this page is included in the site search index. When omitted,\n * derives from `noindex` (a page that's not crawlable is by default not\n * searchable). Set explicitly to override — e.g. `{ noindex: true,\n * searchable: true }` keeps the page out of search engines but findable\n * in the site's own search.\n */\n searchable: z\n .boolean({ error: '\"searchable\" must be true or false' })\n .optional(),\n tableOfContents: z\n .union([\n z.literal(false),\n z\n .object({\n minHeadingLevel: z\n .number({ error: '\"minHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(2),\n maxHeadingLevel: z\n .number({ error: '\"maxHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(3),\n })\n .refine((v) => v.minHeadingLevel <= v.maxHeadingLevel, {\n message: \"minHeadingLevel must be <= maxHeadingLevel\",\n }),\n ])\n .optional(),\n lastUpdated: z.coerce\n .date({ error: '\"lastUpdated\" must be a valid date (e.g. 2024-01-15)' })\n .optional(),\n /**\n * Explicit per-page social/OG image override (path or absolute URL).\n * When omitted, the page route is expected to fall back to a\n * programmatically-generated card or the site-wide `config.socialImage`.\n */\n socialImage: z\n .string({ error: '\"socialImage\" must be a string (path or URL)' })\n .optional(),\n prev: prevNextSchema,\n next: prevNextSchema,\n /**\n * Versioning rename escape hatch.\n *\n * When a page is renamed between versions (the URL slug changes), the\n * newer version's frontmatter declares the slug it had in an older\n * version. The framework uses this to link the pages as cross-version\n * alternates and to emit a `<link rel=\"canonical\">` to the current\n * version's URL.\n *\n * Example: `docs-v1/old-name.mdx` was renamed in v2 to `new-name.mdx`.\n * On the new page (`docs/new-name.mdx`, current version), set:\n *\n * previousSlug: old-name\n *\n * Now `/new-name` and `/v1/old-name` are linked as the same logical\n * page in `<head>` alternates, and the v1 page's canonical points to\n * `/new-name`.\n *\n * Accepts a single slug string (the page's id in the older version)\n * or an array of strings when the page has been renamed across more\n * than one version.\n */\n previousSlug: z\n .union([z.string(), z.array(z.string())], {\n error: '\"previousSlug\" must be a string or array of strings',\n })\n .optional(),\n /**\n * Rewrite this page's sidebar link to point at an external (or\n * cross-section) URL. The page still builds at its filesystem path —\n * `external_link` only changes how the sidebar links to it. The link\n * renders with `target=\"_blank\" rel=\"noopener\"` and is treated as\n * external by header/footer chrome.\n *\n * Must be either an absolute URL (`https://…`, `mailto:…`,\n * protocol-relative `//cdn.…`) or a site-absolute path (`/foo/bar`).\n * Relative strings (`\"foo\"`, `\"./bar\"`) and empty strings are\n * rejected — the sidebar builder consumes this directly as an\n * `<a href>`, and a relative href against the entry's own URL\n * would route somewhere unintended (typically into the entry's\n * own subtree). An empty string would produce an indexHref of\n * `\"\"` on group landings, breaking the link entirely.\n *\n * Starlight convention; CF docs uses this to redirect deprecated\n * pages to their replacements without 301s.\n */\n external_link: z\n .string({\n error: '\"external_link\" must be a URL or absolute path',\n })\n .refine((v) => v.length > 0 && (isAbsoluteUrl(v) || v.startsWith(\"/\")), {\n message:\n '\"external_link\" must be a non-empty absolute URL (e.g. \"https://example.com/foo\") ' +\n 'or a site-absolute path (e.g. \"/replacement-page\"). ' +\n \"Relative paths are rejected because they'd resolve against the entry's own URL rather than where the author intended.\",\n })\n .optional(),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Build a customizable docs schema. Use this when composing schemas outside\n * the `docsCollection()` factory (e.g. multiple docs collections with\n * different shapes).\n *\n * For typed Astro `image()` fields or per-collection field narrowing, use\n * the richer `defineSchema(ctx => ...)` factory instead.\n */\nexport function defineDocSchema<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n>(config: DocSchemaConfig<TFields> = {}) {\n const base = baseDocSchema();\n // Always extend (with `{}` when no fields) so the result type is\n // `ZodObject<baseShape & TFields>` rather than a union of branches.\n // A union widens the consumer view of `entry.data.X` to the intersection\n // of branch fields, which is \"no fields\" for the false branch and\n // re-erases everything we just preserved.\n const merged = base.extend((config.fields ?? {}) as TFields);\n // Cast back to the underlying ZodObject. Runtime wrap (`.passthrough()\n // .superRefine()`) stays — the unknown-key check still fires. But tsdown\n // collapses ZodEffects emissions to `ZodObject<Record<string, ZodType<unknown>>>`,\n // erasing every framework field type at every consumer's `entry.data.X`\n // access. The cast preserves the field shapes through .d.ts emission.\n return withFrontmatterKeyCheck(merged) as unknown as typeof merged;\n}\n\n/**\n * Factory options for `defineSchema`.\n *\n * - `extend`: additional fields merged into the framework schema. Use\n * this for user-defined frontmatter (`author`, `tags`, `cover`).\n * - `narrow`: replaces framework fields with tighter types within this\n * collection. Use when a collection has stricter rules — e.g.\n * `{ mode: z.literal(\"doc\") }` says no landing pages in this collection.\n */\nexport interface DefineSchemaOptions {\n extend?: z.ZodTypeAny;\n narrow?: Record<string, z.ZodTypeAny>;\n}\n\n/**\n * Build a typed docs schema with access to the Astro `SchemaContext`.\n * Use this when you want typed image fields (`ctx.image()`), per-\n * collection narrowing of framework fields, or both. The simpler\n * `defineDocSchema({ fields })` factory is still available for the\n * common case of just adding fields.\n *\n * import { defineCollection } from \"astro:content\";\n * import { z } from \"astro/zod\";\n * import { defineSchema } from \"nimbus-docs/schemas\";\n *\n * export const collections = {\n * docs: defineCollection({\n * loader: ...,\n * schema: defineSchema((ctx) => ({\n * extend: z.object({\n * cover: ctx.image().optional(),\n * author: z.string().optional(),\n * }),\n * narrow: {\n * mode: z.literal(\"doc\"), // no landing pages here\n * },\n * })),\n * }),\n * };\n */\nexport function defineSchema(\n factory: (ctx: import(\"astro:content\").SchemaContext) => DefineSchemaOptions,\n) {\n return (ctx: import(\"astro:content\").SchemaContext) => {\n const { extend, narrow } = factory(ctx);\n let schema = baseDocSchema() as z.ZodObject<any>;\n\n // narrowing first (overrides framework fields)\n if (narrow) {\n schema = schema.extend(narrow);\n }\n\n // additive extension (new user fields). Prefer .merge for ZodObject\n // (preserves object-ness for downstream .extend); fall back to .and\n // for any other Zod type (intersection, union, etc.).\n if (extend) {\n if (extend instanceof z.ZodObject) {\n schema = schema.merge(extend);\n } else {\n // Intersection path — `.and()` returns ZodIntersection, on which\n // we can't run `withUnknownKeyCheck` (it operates on ZodObject's\n // `.shape`). Users on this path lose the removed-key migration\n // diagnostic; they own that trade-off by reaching for the\n // non-object extend.\n return schema.and(extend);\n }\n }\n\n return withFrontmatterKeyCheck(schema);\n };\n}\n\n/** Default docs schema. Equivalent to `defineDocSchema()`. */\nexport const docsSchema = defineDocSchema();\n\nconst partialsObjectSchema = z.object({\n /**\n * Declared parameters this partial accepts.\n * Suffix with `?` for optional params: `[\"name\", \"deprecated?\"]`\n */\n params: z.array(z.string()).optional(),\n});\n\n/** Schema for partials (`<Render file=\"...\" />` snippets). */\nexport const partialsSchema = partialsObjectSchema.default({});\n\n/**\n * Build a customizable partials schema. Mirrors `defineDocSchema` — use\n * when porting upstream partials that ship product-specific frontmatter\n * keys (e.g. CF's `inputParameters`) and you want them to validate without\n * editing the source files.\n *\n * import { z } from \"astro/zod\";\n * import { partialsCollection } from \"nimbus-docs/content\";\n *\n * defineCollection(partialsCollection({\n * schemaFields: { inputParameters: z.string().optional() },\n * }));\n */\nexport function definePartialsSchema<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n>(config: { fields?: TFields } = {}) {\n // Same generic preservation trick as `defineDocSchema` — always extend\n // (even with `{}`) so the result type stays `ZodObject<base & TFields>`\n // rather than a union with the no-fields branch erasing types.\n const merged = partialsObjectSchema.extend((config.fields ?? {}) as TFields);\n return merged as unknown as typeof merged;\n}\n\n// ---------------------------------------------------------------------------\n// Lenient variants — used by `nimbus-docs lint` (`nimbus/frontmatter-shape`).\n//\n// The standalone lint CLI can't yet see a site's extended\n// `content.config.ts` schema, so it validates the *types* of the fields\n// the framework owns while tolerating user-added fields (passthrough).\n// Unknown-key detection is deferred to when the engine can load the real\n// per-collection schema.\n// ---------------------------------------------------------------------------\n\n/** Docs frontmatter, framework fields type-checked, extra keys allowed. */\nexport const lenientDocsSchema = baseDocSchema().passthrough();\n\n/** Partials frontmatter, framework fields type-checked, extra keys allowed. */\nexport const lenientPartialsSchema = partialsObjectSchema.passthrough();\n\n// ---------------------------------------------------------------------------\n// Components collection — used by sites documenting their own UI components.\n// Pair with `componentsCollection()` from `nimbus-docs/content`. Authoring\n// pattern: hero `<Showcase>` block + `<Example>` blocks in the MDX body, with\n// `props` declared in frontmatter for a generated prop table.\n// ---------------------------------------------------------------------------\n\n/** One row in a component's `props` frontmatter array. */\nconst componentPropSchema = z.object({\n name: z.string({ error: 'prop needs a \"name\"' }),\n type: z.string({ error: 'prop needs a \"type\"' }),\n defaultValue: z.string().optional(),\n required: z.boolean().default(false),\n description: z.string({ error: 'prop needs a \"description\"' }),\n});\n\nexport type ComponentProp = z.infer<typeof componentPropSchema>;\n\n/** Default schema for the components collection. */\nexport const componentsSchema = z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"title\" in frontmatter — display name used in the sidebar and page header.'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n tagline: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"tagline\" in frontmatter — one-sentence summary shown under the title.'\n : `\"tagline\" must be a string, received ${typeof iss.input}`,\n }),\n props: z.array(componentPropSchema).default([]),\n});\n"],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ //#region src/_internal/url.ts
2
+ /**
3
+ * Internal URL helpers — one shape for matching, one shape for rendering.
4
+ *
5
+ * Static hosts that serve `page/index.html` (Astro's default `build.format:
6
+ * "directory"`) canonicalize to a trailing-slash URL. If framework helpers
7
+ * emit slashless hrefs, every sidebar click costs a 307 redirect before
8
+ * Astro's client router can pick up the page. The fix splits href shape
9
+ * into two forms:
10
+ *
11
+ * - `toRouteKey(href)` — slashless canonical form. Used wherever the
12
+ * framework compares paths for identity (active sidebar state,
13
+ * prev/next lookup, validation against the indexed route set).
14
+ *
15
+ * - `toBrowserHref(href)` — what we emit into `<a href>` / `<link>` for
16
+ * HTML document routes. Adds a trailing slash so the URL matches the
17
+ * directory-index page the host serves directly.
18
+ *
19
+ * Asset URLs (`.md`, `.png`, `.txt`, …), external URLs, and anchor-only
20
+ * hrefs are returned unchanged by `toBrowserHref` — they aren't HTML
21
+ * document routes and adding a slash would break them.
22
+ *
23
+ * Keep these out of the public API: starter components consume hrefs the
24
+ * framework already shaped. Authors don't (and shouldn't) call these
25
+ * directly.
26
+ */
27
+ /**
28
+ * True for hrefs that point off-site — anything with a URI scheme
29
+ * (`https:`, `mailto:`, `data:`, …) or a protocol-relative `//cdn.…`
30
+ * prefix. Bare relative paths like `"cli"` and `"./foo"` are NOT external
31
+ * — they resolve against the current page and the framework shouldn't
32
+ * second-guess them.
33
+ */
34
+ function isAbsoluteUrl(href) {
35
+ return /^([a-z][a-z0-9+\-.]*:|\/\/)/i.test(href);
36
+ }
37
+ /**
38
+ * Detect whether the final path segment looks like a file (has an
39
+ * extension). HTML document routes don't carry an extension under
40
+ * `build.format: "directory"`; assets like `/og/card.png`,
41
+ * `/llms.txt`, and `/cli/index.md` do.
42
+ *
43
+ * Conservative: only treats short, ASCII-letter-only extensions as files,
44
+ * so paths with dots inside a segment (`/v1.2/foo`, version slugs) still
45
+ * count as document routes.
46
+ */
47
+ function hasFileExtension(pathname) {
48
+ const lastSegment = pathname.slice(pathname.lastIndexOf("/") + 1);
49
+ const dot = lastSegment.lastIndexOf(".");
50
+ if (dot <= 0) return false;
51
+ const ext = lastSegment.slice(dot + 1);
52
+ return ext.length > 0 && ext.length <= 6 && /^[a-zA-Z0-9]+$/.test(ext);
53
+ }
54
+ /** Split an href into `[pathname, suffix]` where `suffix` is the `?…#…` tail. */
55
+ function splitSuffix(href) {
56
+ const queryAt = href.indexOf("?");
57
+ const hashAt = href.indexOf("#");
58
+ const cutAt = queryAt === -1 ? hashAt : hashAt === -1 ? queryAt : Math.min(queryAt, hashAt);
59
+ if (cutAt === -1) return [href, ""];
60
+ return [href.slice(0, cutAt), href.slice(cutAt)];
61
+ }
62
+ /**
63
+ * Slashless canonical form for path comparisons.
64
+ *
65
+ * /cli → /cli
66
+ * /cli/ → /cli
67
+ * /cli/?x=1#y → /cli
68
+ * / → /
69
+ * /guides/setup/ → /guides/setup
70
+ *
71
+ * Strips query and hash so callers can compare two hrefs that differ only
72
+ * in their tail. Root stays `"/"` — that's identity, not a trailing-slash
73
+ * artifact.
74
+ */
75
+ function toRouteKey(href) {
76
+ const [pathname] = splitSuffix(href);
77
+ if (pathname.length <= 1) return pathname || "/";
78
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
79
+ }
80
+ /**
81
+ * Trailing-slash form for browser-facing hrefs to HTML document routes.
82
+ * Preserves query and hash; root, external URLs, anchor-only hrefs, and
83
+ * asset URLs (paths with a file extension) are returned unchanged.
84
+ *
85
+ * /cli → /cli/
86
+ * /cli/ → /cli/
87
+ * /cli#install → /cli/#install
88
+ * /cli?v=1 → /cli/?v=1
89
+ * / → /
90
+ * /og/card.png → /og/card.png (asset, unchanged)
91
+ * /cli/index.md → /cli/index.md (asset, unchanged)
92
+ * https://x.com/a → https://x.com/a (external, unchanged)
93
+ * #anchor → #anchor (anchor-only, unchanged)
94
+ */
95
+ function toBrowserHref(href) {
96
+ if (isAbsoluteUrl(href)) return href;
97
+ if (href.startsWith("#") || href.startsWith("?")) return href;
98
+ if (!href.startsWith("/")) return href;
99
+ const [pathname, suffix] = splitSuffix(href);
100
+ if (pathname === "/") return href;
101
+ if (hasFileExtension(pathname)) return href;
102
+ if (pathname.endsWith("/")) return href;
103
+ return `${pathname}/${suffix}`;
104
+ }
105
+
106
+ //#endregion
107
+ //#region src/_internal/strict-keys.ts
108
+ /**
109
+ * Wrap `schema` so unknown keys raise issues at parse time. Captures
110
+ * `Object.keys(schema.shape)` eagerly (before turning the schema into a
111
+ * `ZodEffects` via `superRefine`) so the known-key set reflects the
112
+ * schema as passed in. Call this AFTER any `.extend()` / `.merge()` so
113
+ * user-added fields are recognized.
114
+ */
115
+ function withStrictKeys(schema, options) {
116
+ const knownKeys = new Set(Object.keys(schema.shape));
117
+ return schema.passthrough().superRefine((data, ctx) => {
118
+ if (!data || typeof data !== "object") return;
119
+ for (const key of Object.keys(data)) {
120
+ if (knownKeys.has(key)) continue;
121
+ const removal = options.removedKeys[key];
122
+ if (removal) ctx.addIssue({
123
+ code: "custom",
124
+ path: [key],
125
+ message: `${options.contextLabel} "${key}" ${removal}`
126
+ });
127
+ else {
128
+ const hint = options.unknownHint?.(key);
129
+ ctx.addIssue({
130
+ code: "custom",
131
+ path: [key],
132
+ message: hint ? `Unknown ${options.contextLabel.toLowerCase()} "${key}". ${hint}` : `Unknown ${options.contextLabel.toLowerCase()} "${key}".`
133
+ });
134
+ }
135
+ }
136
+ });
137
+ }
138
+
139
+ //#endregion
140
+ export { toRouteKey as i, isAbsoluteUrl as n, toBrowserHref as r, withStrictKeys as t };
141
+ //# sourceMappingURL=strict-keys-fbKKxxKL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strict-keys-fbKKxxKL.js","names":[],"sources":["../src/_internal/url.ts","../src/_internal/strict-keys.ts"],"sourcesContent":["/**\n * Internal URL helpers — one shape for matching, one shape for rendering.\n *\n * Static hosts that serve `page/index.html` (Astro's default `build.format:\n * \"directory\"`) canonicalize to a trailing-slash URL. If framework helpers\n * emit slashless hrefs, every sidebar click costs a 307 redirect before\n * Astro's client router can pick up the page. The fix splits href shape\n * into two forms:\n *\n * - `toRouteKey(href)` — slashless canonical form. Used wherever the\n * framework compares paths for identity (active sidebar state,\n * prev/next lookup, validation against the indexed route set).\n *\n * - `toBrowserHref(href)` — what we emit into `<a href>` / `<link>` for\n * HTML document routes. Adds a trailing slash so the URL matches the\n * directory-index page the host serves directly.\n *\n * Asset URLs (`.md`, `.png`, `.txt`, …), external URLs, and anchor-only\n * hrefs are returned unchanged by `toBrowserHref` — they aren't HTML\n * document routes and adding a slash would break them.\n *\n * Keep these out of the public API: starter components consume hrefs the\n * framework already shaped. Authors don't (and shouldn't) call these\n * directly.\n */\n\n/**\n * True for hrefs that point off-site — anything with a URI scheme\n * (`https:`, `mailto:`, `data:`, …) or a protocol-relative `//cdn.…`\n * prefix. Bare relative paths like `\"cli\"` and `\"./foo\"` are NOT external\n * — they resolve against the current page and the framework shouldn't\n * second-guess them.\n */\nexport function isAbsoluteUrl(href: string): boolean {\n return /^([a-z][a-z0-9+\\-.]*:|\\/\\/)/i.test(href);\n}\n\n/**\n * Detect whether the final path segment looks like a file (has an\n * extension). HTML document routes don't carry an extension under\n * `build.format: \"directory\"`; assets like `/og/card.png`,\n * `/llms.txt`, and `/cli/index.md` do.\n *\n * Conservative: only treats short, ASCII-letter-only extensions as files,\n * so paths with dots inside a segment (`/v1.2/foo`, version slugs) still\n * count as document routes.\n */\nfunction hasFileExtension(pathname: string): boolean {\n const lastSegment = pathname.slice(pathname.lastIndexOf(\"/\") + 1);\n const dot = lastSegment.lastIndexOf(\".\");\n if (dot <= 0) return false;\n const ext = lastSegment.slice(dot + 1);\n return ext.length > 0 && ext.length <= 6 && /^[a-zA-Z0-9]+$/.test(ext);\n}\n\n/** Split an href into `[pathname, suffix]` where `suffix` is the `?…#…` tail. */\nfunction splitSuffix(href: string): [string, string] {\n const queryAt = href.indexOf(\"?\");\n const hashAt = href.indexOf(\"#\");\n const cutAt =\n queryAt === -1 ? hashAt : hashAt === -1 ? queryAt : Math.min(queryAt, hashAt);\n if (cutAt === -1) return [href, \"\"];\n return [href.slice(0, cutAt), href.slice(cutAt)];\n}\n\n/**\n * Slashless canonical form for path comparisons.\n *\n * /cli → /cli\n * /cli/ → /cli\n * /cli/?x=1#y → /cli\n * / → /\n * /guides/setup/ → /guides/setup\n *\n * Strips query and hash so callers can compare two hrefs that differ only\n * in their tail. Root stays `\"/\"` — that's identity, not a trailing-slash\n * artifact.\n */\nexport function toRouteKey(href: string): string {\n const [pathname] = splitSuffix(href);\n if (pathname.length <= 1) return pathname || \"/\";\n return pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n}\n\n/**\n * Trailing-slash form for browser-facing hrefs to HTML document routes.\n * Preserves query and hash; root, external URLs, anchor-only hrefs, and\n * asset URLs (paths with a file extension) are returned unchanged.\n *\n * /cli → /cli/\n * /cli/ → /cli/\n * /cli#install → /cli/#install\n * /cli?v=1 → /cli/?v=1\n * / → /\n * /og/card.png → /og/card.png (asset, unchanged)\n * /cli/index.md → /cli/index.md (asset, unchanged)\n * https://x.com/a → https://x.com/a (external, unchanged)\n * #anchor → #anchor (anchor-only, unchanged)\n */\nexport function toBrowserHref(href: string): string {\n // External URLs (anything with a scheme, including `//cdn.example.com`)\n // and protocol-relative URLs aren't ours to normalize.\n if (isAbsoluteUrl(href)) return href;\n // Anchor-only and query-only hrefs stay relative to the current page.\n if (href.startsWith(\"#\") || href.startsWith(\"?\")) return href;\n // Anything that isn't an absolute site path: don't touch it.\n if (!href.startsWith(\"/\")) return href;\n\n const [pathname, suffix] = splitSuffix(href);\n if (pathname === \"/\") return href;\n if (hasFileExtension(pathname)) return href;\n if (pathname.endsWith(\"/\")) return href;\n return `${pathname}/${suffix}`;\n}\n","/**\n * Strict-key validation helper for Zod object schemas.\n *\n * Zod's default `.strip()` behavior silently drops unknown keys, which is\n * the wrong default for an authoring contract: a stale frontmatter or\n * config field that's been renamed or removed should fail loudly, not\n * vanish at parse time and produce subtly different behavior.\n *\n * This module wraps a `ZodObject` with `.passthrough().superRefine()` so\n * unknown keys survive the parse and get rejected with one issue per\n * key. Known-removed keys (passed via `removedKeys`) emit a friendly\n * migration message; everything else emits a generic \"unknown key\"\n * error with an actionable hint.\n *\n * Used by both the frontmatter schema (`src/schemas.ts`) and the config\n * schema (`src/_internal/validate.ts`). Each call site provides its own\n * `removedKeys` map and a `contextLabel` (\"Frontmatter key\" vs \"Config\n * field\" vs \"features.<key>\") so error messages read naturally.\n */\n\nimport type { z } from \"astro/zod\";\n\nexport interface StrictKeyOptions {\n /**\n * Map of removed-or-renamed keys → migration message. The message\n * follows the contextLabel + key prefix; phrase it as the back-half of\n * the sentence. Example: `'was renamed to \"mode\". Replace ...'`.\n */\n removedKeys: Record<string, string>;\n /**\n * Sentence-start label for the issue message. Examples: `Frontmatter\n * key`, `Config field`, `features sub-key`. The key name (quoted) is\n * appended automatically.\n */\n contextLabel: string;\n /**\n * Optional hint appended to the generic \"unknown key\" message for\n * keys NOT in `removedKeys`. Receives the offending key. Use this to\n * point users at the right escape hatch (e.g. how to add a custom\n * field in their schema).\n */\n unknownHint?: (key: string) => string;\n}\n\n/**\n * Wrap `schema` so unknown keys raise issues at parse time. Captures\n * `Object.keys(schema.shape)` eagerly (before turning the schema into a\n * `ZodEffects` via `superRefine`) so the known-key set reflects the\n * schema as passed in. Call this AFTER any `.extend()` / `.merge()` so\n * user-added fields are recognized.\n */\nexport function withStrictKeys<T extends z.ZodObject<z.ZodRawShape>>(\n schema: T,\n options: StrictKeyOptions,\n) {\n const knownKeys = new Set(Object.keys(schema.shape));\n return schema.passthrough().superRefine((data, ctx) => {\n if (!data || typeof data !== \"object\") return;\n for (const key of Object.keys(data as Record<string, unknown>)) {\n if (knownKeys.has(key)) continue;\n const removal = options.removedKeys[key];\n if (removal) {\n ctx.addIssue({\n code: \"custom\",\n path: [key],\n message: `${options.contextLabel} \"${key}\" ${removal}`,\n });\n } else {\n const hint = options.unknownHint?.(key);\n ctx.addIssue({\n code: \"custom\",\n path: [key],\n message: hint\n ? `Unknown ${options.contextLabel.toLowerCase()} \"${key}\". ${hint}`\n : `Unknown ${options.contextLabel.toLowerCase()} \"${key}\".`,\n });\n }\n }\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,cAAc,MAAuB;AACnD,QAAO,+BAA+B,KAAK,KAAK;;;;;;;;;;;;AAalD,SAAS,iBAAiB,UAA2B;CACnD,MAAM,cAAc,SAAS,MAAM,SAAS,YAAY,IAAI,GAAG,EAAE;CACjE,MAAM,MAAM,YAAY,YAAY,IAAI;AACxC,KAAI,OAAO,EAAG,QAAO;CACrB,MAAM,MAAM,YAAY,MAAM,MAAM,EAAE;AACtC,QAAO,IAAI,SAAS,KAAK,IAAI,UAAU,KAAK,iBAAiB,KAAK,IAAI;;;AAIxE,SAAS,YAAY,MAAgC;CACnD,MAAM,UAAU,KAAK,QAAQ,IAAI;CACjC,MAAM,SAAS,KAAK,QAAQ,IAAI;CAChC,MAAM,QACJ,YAAY,KAAK,SAAS,WAAW,KAAK,UAAU,KAAK,IAAI,SAAS,OAAO;AAC/E,KAAI,UAAU,GAAI,QAAO,CAAC,MAAM,GAAG;AACnC,QAAO,CAAC,KAAK,MAAM,GAAG,MAAM,EAAE,KAAK,MAAM,MAAM,CAAC;;;;;;;;;;;;;;;AAgBlD,SAAgB,WAAW,MAAsB;CAC/C,MAAM,CAAC,YAAY,YAAY,KAAK;AACpC,KAAI,SAAS,UAAU,EAAG,QAAO,YAAY;AAC7C,QAAO,SAAS,SAAS,IAAI,GAAG,SAAS,MAAM,GAAG,GAAG,GAAG;;;;;;;;;;;;;;;;;AAkB1D,SAAgB,cAAc,MAAsB;AAGlD,KAAI,cAAc,KAAK,CAAE,QAAO;AAEhC,KAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,CAAE,QAAO;AAEzD,KAAI,CAAC,KAAK,WAAW,IAAI,CAAE,QAAO;CAElC,MAAM,CAAC,UAAU,UAAU,YAAY,KAAK;AAC5C,KAAI,aAAa,IAAK,QAAO;AAC7B,KAAI,iBAAiB,SAAS,CAAE,QAAO;AACvC,KAAI,SAAS,SAAS,IAAI,CAAE,QAAO;AACnC,QAAO,GAAG,SAAS,GAAG;;;;;;;;;;;;AC7DxB,SAAgB,eACd,QACA,SACA;CACA,MAAM,YAAY,IAAI,IAAI,OAAO,KAAK,OAAO,MAAM,CAAC;AACpD,QAAO,OAAO,aAAa,CAAC,aAAa,MAAM,QAAQ;AACrD,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,OAAK,MAAM,OAAO,OAAO,KAAK,KAAgC,EAAE;AAC9D,OAAI,UAAU,IAAI,IAAI,CAAE;GACxB,MAAM,UAAU,QAAQ,YAAY;AACpC,OAAI,QACF,KAAI,SAAS;IACX,MAAM;IACN,MAAM,CAAC,IAAI;IACX,SAAS,GAAG,QAAQ,aAAa,IAAI,IAAI,IAAI;IAC9C,CAAC;QACG;IACL,MAAM,OAAO,QAAQ,cAAc,IAAI;AACvC,QAAI,SAAS;KACX,MAAM;KACN,MAAM,CAAC,IAAI;KACX,SAAS,OACL,WAAW,QAAQ,aAAa,aAAa,CAAC,IAAI,IAAI,KAAK,SAC3D,WAAW,QAAQ,aAAa,aAAa,CAAC,IAAI,IAAI;KAC3D,CAAC;;;GAGN"}
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Severity, i as RuleCode, n as Diagnostic, o as SeverityConfig, r as DiagnosticFix, t as AuthoringRuleCode } from "./diagnostic-C6OaBe_o.js";
1
+ import { a as Severity, i as RuleCode, n as Diagnostic, o as SeverityConfig, r as DiagnosticFix, t as AuthoringRuleCode } from "./diagnostic-ewiZxpSO.js";
2
2
 
3
3
  //#region src/types.d.ts
4
4
  /**
@@ -185,7 +185,7 @@ interface SearchProvider {
185
185
  }): Promise<SearchResult[]>;
186
186
  }
187
187
  interface HeadElement {
188
- tag: "meta" | "link" | "script" | "style";
188
+ tag: "meta" | "link" | "script" | "style" | "title" | "noscript" | "base";
189
189
  attrs?: Record<string, string>;
190
190
  content?: string;
191
191
  }
@@ -204,6 +204,32 @@ interface SidebarConfig {
204
204
  * @default "full"
205
205
  */
206
206
  scope?: "full" | "section";
207
+ /**
208
+ * Collapse every autogenerated group by default. When `true`, all
209
+ * groups in the sidebar render closed initially; the group that
210
+ * contains the current page still opens automatically (the
211
+ * active-descendant check in `SidebarGroup.astro` wins over the
212
+ * default). When omitted or `false`, groups render expanded by
213
+ * default — the current Nimbus behavior.
214
+ *
215
+ * Per-item overrides win: an explicit `collapsed: false` on a config
216
+ * item keeps that specific group expanded even when
217
+ * `defaultCollapsed: true` is set globally. Useful for keeping a
218
+ * "Getting started" group always visible while the rest of the rail
219
+ * stays compact.
220
+ *
221
+ * @default false
222
+ */
223
+ defaultCollapsed?: boolean;
224
+ /**
225
+ * @deprecated No-op under structural separation. The group label is
226
+ * now always the link to the index page, so there is no "first child
227
+ * representing the index" to relabel. Accepted but ignored. Future
228
+ * major can drop the field.
229
+ *
230
+ * @default false
231
+ */
232
+ overviewLabel?: boolean | string;
207
233
  }
208
234
  /**
209
235
  * A top-level section derived from the sidebar tree — used to render the
@@ -279,6 +305,27 @@ interface SidebarGroupItem {
279
305
  badge?: SidebarBadge;
280
306
  children: SidebarItem[];
281
307
  _indexId?: string;
308
+ /**
309
+ * URL of the group's landing page (the directory's `index.mdx`), when
310
+ * one exists. When set, the renderer should make the group label
311
+ * clickable (matching the Fumadocs / Fern / Docusaurus pattern where
312
+ * the group label IS the link to the landing page, and the landing
313
+ * page is NOT duplicated as a child of the group).
314
+ *
315
+ * When `undefined`, the group has no landing page and the label is
316
+ * a non-interactive header — children are the only navigable items.
317
+ */
318
+ indexHref?: string;
319
+ /** True when the group's landing page is the current route. */
320
+ indexIsCurrent?: boolean;
321
+ /**
322
+ * True when `indexHref` is an off-site URL (the directory's
323
+ * `index.mdx` declared an absolute `external_link`). Renderers
324
+ * should set `target="_blank" rel="noopener"` on the group label
325
+ * link, matching how normal external sidebar links are rendered.
326
+ * When omitted/false, `indexHref` is an in-site path.
327
+ */
328
+ indexIsExternal?: boolean;
282
329
  /**
283
330
  * Internal: the URL prefix where this group's content lives, when
284
331
  * derived from an `autogenerate` config item. `deriveSidebarSections`
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"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"}