Files
tabler/docs/content.config.ts

80 lines
3.7 KiB
TypeScript

import { defineCollection } from 'astro:content'
import { glob } from 'astro/loaders'
// `z` re-exported from astro:content is deprecated and slated for removal.
import { z } from 'astro/zod'
// Docs pages live in ./content (not ./pages) so they are not routed by the file
// system — pages/[...slug].astro renders them from this collection instead.
/** One row of the class reference: the class, what it does, and whether it is the default. */
const classnameEntry = z.object({
class: z.string(),
desc: z.string(),
default: z.boolean().default(false),
})
/** Accepts both `docs-libs: apexcharts` and `docs-libs: [apexcharts]`. */
const stringList = z.union([z.string(), z.array(z.string())]).transform((value) => (Array.isArray(value) ? value : [value]))
const docs = defineCollection({
loader: glob({
pattern: '**/*.mdx',
base: './content',
// Ids mirror the page URL without the leading slash: `ui/components/button`,
// `ui/components` (from ui/components/index.mdx), `index` for the home page.
// Explicit so ids never depend on Astro's default slugification.
generateId: ({ entry }) => entry.replace(/\.mdx$/, '').replace(/\/index$/, ''),
}),
schema: z
.object({
/** the page's h1 heading */
'title': z.string(),
/** lead paragraph below the title */
'summary': z.string(),
/** SEO description */
'description': z.string(),
'seoTitle': z.string().optional(),
'seoDescription': z.string().optional(),
/** icon name for the card this page gets on its parent index page */
'icon': z.string().optional(),
/** position among sibling pages; unordered pages sort last, then by title */
'order': z.number().default(999),
/** docs URLs of related pages, rendered above the pagination */
'related': z.array(z.string()).default([]),
/** extra libraries from libs.json (css+js) */
'docs-libs': stringList.default([]),
/** extra tabler-<name>.css sheets for this page's demos */
'css-plugins': stringList.default([]),
'hide-pagination': z.boolean().default(false),
/** renders the "Added in X" badge next to the h1 */
'added-in': z.string().optional(),
/** repo-relative path of the file that implements this component, e.g. "core/scss/ui/_alerts.scss" */
'source': z.string().optional(),
/**
* Class reference for the component, grouped by kind. Rendered above the
* page body by DocsClassnames. Colors that come from a palette loop are
* listed once as `alert-{color}` rather than one row per generated class.
*/
'classnames': z.record(z.string(), z.array(classnameEntry)).optional(),
/**
* Custom-property family the component exposes, as the part after
* `--tblr-`: `badge` lists every `--tblr-badge-*` variable. Rendered
* below the class reference by DocsCssVars from the compiled CSS.
*/
'css-vars': z.string().optional(),
/**
* Sass defaults block: the `<name>-variables` marker in `_variables.scss`.
* Defaults to the `css-vars` name; set it when the marker is named
* differently (`nav` for nav-tabs) or when the component has Sass
* variables but no custom properties of its own.
*/
'sass-vars': z.string().optional(),
})
// strict so a mistyped key fails the build instead of being silently dropped
.strict()
// kebab-case front matter keys → the camelCase props DocsLayout expects
.transform(({ 'docs-libs': docsLibs, 'css-plugins': cssPlugins, 'hide-pagination': hidePagination, 'added-in': addedIn, 'css-vars': cssVars, 'sass-vars': sassVars, ...rest }) => ({ ...rest, docsLibs, cssPlugins, hidePagination, addedIn, cssVars, sassVars })),
})
export const collections = { docs }