Skip to content

Commit 6658812

Browse files
authored
[Style Guide] Generate custom frontmatter docs (#20718)
1 parent 69c1c86 commit 6658812

File tree

3 files changed

+116
-21
lines changed

3 files changed

+116
-21
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
import { z } from "astro:schema";
3+
import { baseSchema } from "~/schemas";
4+
import { marked } from "marked";
5+
6+
import Type from "./Type.astro";
7+
import MetaInfo from "./MetaInfo.astro";
8+
import AnchorHeading from "./AnchorHeading.astro";
9+
import Details from "./Details.astro";
10+
11+
const schema = baseSchema({
12+
// @ts-expect-error Normally passed in by Astro but we are using the schema standalone.
13+
image: () => z.function(),
14+
}).shape;
15+
16+
const getInnerType = ({ _def }: z.ZodTypeAny | z.ZodEffects<any>) => {
17+
if (_def.innerType) return getInnerType(_def.innerType);
18+
19+
return _def;
20+
};
21+
---
22+
23+
{
24+
Object.entries(schema)
25+
.sort()
26+
.map(([key, outer]) => {
27+
const outerType = outer._def.typeName;
28+
const outerDescription = outer._def.description;
29+
30+
const inner = getInnerType(outer);
31+
const innerType =
32+
key === "preview_image"
33+
? "string"
34+
: inner.typeName.split("Zod")[1].toLowerCase();
35+
36+
return (
37+
<>
38+
<AnchorHeading depth={3} title={key} />
39+
<p>
40+
<strong>Type: </strong>
41+
<Type text={innerType} />
42+
{outerType === "ZodOptional" && (
43+
<>
44+
{" "}
45+
<MetaInfo text="optional" />
46+
</>
47+
)}
48+
</p>
49+
{outerDescription && (
50+
<p>
51+
<strong>Description: </strong>
52+
<Fragment set:html={marked.parseInline(outerDescription)} />
53+
</p>
54+
)}
55+
{inner.typeName === "ZodUnion" && (
56+
<p>
57+
<Details header="Allowed values">
58+
<ul>
59+
{inner.options
60+
.filter(
61+
(option: any) => option._def.typeName === "ZodLiteral",
62+
)
63+
.map((option: any) => (
64+
<li>
65+
<code>{option._def.value}</code>
66+
</li>
67+
))}
68+
</ul>
69+
</Details>
70+
</p>
71+
)}
72+
</>
73+
);
74+
})
75+
}

src/content/docs/style-guide/frontmatter/custom-properties.mdx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,10 @@ sidebar:
55
---
66

77
import { Type, MetaInfo } from "~/components";
8+
import BaseSchemaProperties from "~/components/BaseSchemaProperties.astro";
89

9-
We have added specific custom [frontmatter](/style-guide/frontmatter/) to meet specific needs.
10+
We have added specific custom [frontmatter](/style-guide/frontmatter/) properties to meet specific needs.
1011

11-
- `difficulty` <Type text="string" /> <MetaInfo text="optional" />: Difficulty is displayed as a column in the [ListTutorials component](/style-guide/components/list-tutorials/).
12-
- `external_link` <Type text="string" /> <MetaInfo text="optional" />: Path to another page in our docs or elsewhere. Used to add a crosslink entry to the lefthand navigation sidebar.
13-
- `pcx_content_type` <Type text="string" /> <MetaInfo text="optional" />: The purpose of the page, and defined through specific pages in [Content strategy](/style-guide/documentation-content-strategy/content-types/).
14-
- `preview_image` <Type text="string" /> <MetaInfo text="optional" />: An `src` path to the image that you want to use as a custom preview image for social sharing.
15-
- `products` <Type text="Array<String>" /> <MetaInfo text="optional" />: The names of related products, which show on some grids for Examples, [Tutorials](/style-guide/documentation-content-strategy/content-types/tutorial/), and [Reference Architectures](/style-guide/documentation-content-strategy/content-types/reference-architecture/)
16-
- `tags` <Type text="Array<String>" /> <MetaInfo text="optional" />: A group of related keywords relating to the purpose of the page.
17-
- `updated` <Type text="Date" /> <MetaInfo text="optional" />: This is used to automatically add the [LastReviewed component](/style-guide/components/last-reviewed/).
18-
- `noindex` <Type text="Boolean" /> <MetaInfo text="optional" />: If true, this property adds a `noindex` declaration to the page, which will tell internal / external search crawlers to ignore this page. Helpful for pages that are historically accurate, but no longer recommended, such as [Workers Sites](/workers/configuration/sites/).
12+
## Properties
13+
14+
<BaseSchemaProperties />

src/schemas/base.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ const spotlightAuthorDetails = z
1010
})
1111
.optional()
1212
.describe(
13-
"These are used to automatically add the SpotlightAuthorDetails component to the page. Refer to https://developers.cloudflare.com/style-guide/components/spotlight-author-details/.",
13+
"These are used to automatically add the [SpotlightAuthorDetails component](/style-guide/components/spotlight-author-details/) to the page.",
1414
);
1515

1616
export const baseSchema = ({ image }: SchemaContext) =>
1717
z.object({
18-
preview_image: image().optional(),
18+
preview_image: image()
19+
.optional()
20+
.describe(
21+
"A `src` path to the image that you want to use as a custom preview image for social sharing.",
22+
),
1923
pcx_content_type: z
2024
.union([
2125
z.literal("overview"),
@@ -41,15 +45,21 @@ export const baseSchema = ({ image }: SchemaContext) =>
4145
.catch((ctx) => ctx.input)
4246
.optional()
4347
.describe(
44-
"Refer to https://developers.cloudflare.com/style-guide/documentation-content-strategy/content-types/.",
48+
"The purpose of the page, and defined through specific pages in [Content strategy](/style-guide/documentation-content-strategy/content-types/).",
4549
),
4650
content_type: z.string().optional(),
47-
tags: z.string().array().optional(),
51+
tags: z
52+
.string()
53+
.array()
54+
.optional()
55+
.describe(
56+
"A group of related keywords relating to the purpose of the page. Refer to [Tags](/style-guide/frontmatter/tags/).",
57+
),
4858
external_link: z
4959
.string()
5060
.optional()
5161
.describe(
52-
"Links to this page (i.e sidebar, directory listing) will instead appear as the provided link.",
62+
"Path to another page in our docs or elsewhere. Used to add a crosslink entry to the lefthand navigation sidebar.",
5363
),
5464
difficulty: z
5565
.union([
@@ -60,23 +70,34 @@ export const baseSchema = ({ image }: SchemaContext) =>
6070
.catch((ctx) => ctx.input)
6171
.optional()
6272
.describe(
63-
"Difficulty is displayed as a column in the ListTutorials component.",
73+
"Difficulty is displayed as a column in the [ListTutorials component](/style-guide/components/list-tutorials/).",
6474
),
6575
updated: z
6676
.date()
6777
.optional()
6878
.describe(
69-
"This is used to automatically add the LastReviewed component to a page. Refer to https://developers.cloudflare.com/style-guide/components/last-reviewed/.",
79+
"This is used to automatically add the [LastReviewed component](/style-guide/components/last-reviewed/).",
7080
),
7181
spotlight: spotlightAuthorDetails,
7282
release_notes_file_name: z.string().array().optional(),
7383
release_notes_product_area_name: z.string().optional(),
74-
products: z.string().array().optional(),
84+
products: z
85+
.string()
86+
.array()
87+
.optional()
88+
.describe(
89+
"The names of related products, which show on some grids for Examples, [Tutorials](/style-guide/documentation-content-strategy/content-types/tutorial/), and [Reference Architectures](/style-guide/documentation-content-strategy/content-types/reference-architecture/)",
90+
),
7591
languages: z.string().array().optional(),
7692
summary: z.string().optional(),
7793
goal: z.string().array().optional(),
7894
operation: z.string().array().optional(),
79-
noindex: z.boolean().optional(),
95+
noindex: z
96+
.boolean()
97+
.optional()
98+
.describe(
99+
"If true, this property adds a `noindex` declaration to the page, which will tell internal / external search crawlers to ignore this page. Helpful for pages that are historically accurate, but no longer recommended, such as [Workers Sites](/workers/configuration/sites/).",
100+
),
80101
sidebar: z
81102
.object({
82103
order: z.number().optional(),
@@ -93,18 +114,21 @@ export const baseSchema = ({ image }: SchemaContext) =>
93114
.boolean()
94115
.default(false)
95116
.describe(
96-
"Hides the index page from the sidebar. Refer to https://developers.cloudflare.com/style-guide/frontmatter/sidebar/.",
117+
"Hides the index page from the sidebar. Refer to [Sidebar](/style-guide/frontmatter/sidebar/).",
97118
),
98119
badge: BadgeConfigSchema(),
99120
})
100121
.optional(),
101122
})
102-
.optional(),
123+
.optional()
124+
.describe(
125+
"Used to configure various sidebar options. Refer to [Sidebar](/style-guide/frontmatter/sidebar/).",
126+
),
103127
hideChildren: z
104128
.boolean()
105129
.optional()
106130
.describe(
107-
"Renders this group as a single link on the sidebar, to the index page. Refer to https://developers.cloudflare.com/style-guide/frontmatter/sidebar/.",
131+
"Renders this group as a single link on the sidebar, to the index page. Refer to [Sidebar](https://developers.cloudflare.com/style-guide/frontmatter/sidebar/).",
108132
),
109133
styleGuide: z
110134
.object({

0 commit comments

Comments
 (0)