Skip to content

Commit 42b7de5

Browse files
authored
[Docs Site] Support EC props in GitHubCode and TypeScriptExample (#20267)
* [Docs Site] Support EC props in GitHubCode and TypeScriptExample * fix file usage
1 parent 4374164 commit 42b7de5

File tree

7 files changed

+126
-98
lines changed

7 files changed

+126
-98
lines changed

src/components/GitHubCode.astro

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
---
22
import { z } from "astro:schema";
33
import { Code } from "@astrojs/starlight/components";
4+
import TypeScriptExample from "./TypeScriptExample.astro";
5+
import type { ComponentProps } from "astro/types";
46
57
type Props = z.infer<typeof props>;
68
@@ -15,15 +17,17 @@ const props = z
1517
.transform((val) => val.split("-").map(Number))
1618
.optional(),
1719
tag: z.string().optional(),
20+
code: z.custom<ComponentProps<typeof Code>>().optional(),
1821
})
22+
.strict()
1923
.refine(
2024
(val) => {
2125
return !(val.lines && val.tag);
2226
},
2327
{ message: "Lines and tag are mutually exclusive filters." },
2428
);
2529
26-
const { repo, commit, file, lang, lines, tag } = props.parse(Astro.props);
30+
const { repo, commit, file, lang, lines, tag, code } = props.parse(Astro.props);
2731
2832
const res = await fetch(
2933
`https://gh-code.developers.cloudflare.com/${repo}/${commit}/${file}`,
@@ -64,6 +68,10 @@ if (lines) {
6468
contentLines = contentLines.filter(
6569
(line) => !/<[/]?docs-tag name=".*">/.test(line),
6670
);
71+
72+
const Wrapper = lang === "ts" ? TypeScriptExample : Fragment;
6773
---
6874

69-
<Code code={contentLines.join("\n")} lang={lang} />
75+
<Wrapper>
76+
<Code {...code} code={contentLines.join("\n")} lang={lang} />
77+
</Wrapper>

src/components/TypeScriptExample.astro

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,20 @@ import tsBlankSpace from "ts-blank-space";
44
import { format } from "prettier";
55
import { parse } from "node-html-parser";
66
import { Code, Tabs, TabItem } from "@astrojs/starlight/components";
7+
import type { ComponentProps } from "astro/types";
78
8-
type Props = z.infer<typeof props>;
9+
type Props = z.input<typeof props>;
910
1011
const props = z
1112
.object({
1213
filename: z.string().optional(),
13-
tabsWrapper: z.boolean().default(true),
1414
playground: z.boolean().default(false),
15+
code: z.custom<ComponentProps<typeof Code>>().optional(),
1516
})
16-
.or(
17-
z.object({
18-
filename: z.object({
19-
js: z.string(),
20-
ts: z.string(),
21-
}),
22-
tabsWrapper: z.boolean().default(true),
23-
playground: z.boolean().default(false),
24-
}),
25-
);
26-
27-
const { filename, tabsWrapper, playground } = props.parse(Astro.props);
17+
.strict();
2818
29-
let jsTitle, tsTitle;
19+
const { filename, playground, code } = props.parse(Astro.props);
3020
31-
if (filename) {
32-
if (typeof filename === "object") {
33-
jsTitle = filename.js;
34-
tsTitle = filename.ts;
35-
} else {
36-
jsTitle = filename.replace(".ts", ".js");
37-
tsTitle = filename;
38-
}
39-
}
4021
const slot = await Astro.slots.render("default");
4122
4223
const html = parse(slot);
@@ -49,31 +30,30 @@ if (!copy) {
4930
);
5031
}
5132
52-
let code = copy.attributes["data-code"];
33+
let raw = copy.attributes["data-code"];
5334
54-
if (!code) {
35+
if (!raw) {
5536
throw new Error(
5637
`[TypeScriptExample] Unable to find data-code attribute on copy button.`,
5738
);
5839
}
5940
60-
code = code.replace(/\u007f/g, "\n");
61-
62-
const js = await format(tsBlankSpace(code), { parser: "babel", useTabs: true });
41+
raw = raw.replace(/\u007f/g, "\n");
6342
64-
const TabsWrapper = tabsWrapper ? Tabs : Fragment;
43+
const js = await format(tsBlankSpace(raw), { parser: "babel", useTabs: true });
6544
---
6645

67-
<TabsWrapper syncKey="workersExamples">
46+
<Tabs syncKey="workersExamples">
6847
<TabItem label="JavaScript" icon="seti:javascript">
6948
<Code
49+
{...code}
7050
lang="js"
7151
code={js}
72-
title={jsTitle}
52+
title={filename?.replace(".ts", ".js")}
7353
meta={playground ? "playground" : undefined}
7454
/>
7555
</TabItem>
7656
<TabItem label="TypeScript" icon="seti:typescript">
77-
<Code lang="ts" code={code} title={tsTitle} />
57+
<Code {...code} lang="ts" code={raw} title={filename} />
7858
</TabItem>
79-
</TabsWrapper>
59+
</Tabs>

src/content/docs/agents/examples/using-ai-models.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Modern [reasoning models](https://platform.openai.com/docs/guides/reasoning) or
2626

2727
Instead of buffering the entire response, or risking the client disconecting, you can stream the response back to the client by using the [WebSocket API](/agents/examples/websockets/).
2828

29-
<TypeScriptExample file="src/index.ts">
29+
<TypeScriptExample filename="src/index.ts">
3030

3131
```ts
3232
import { Agent } from "agents-sdk"
@@ -85,7 +85,7 @@ You can use [any of the models available in Workers AI](/workers-ai/models/) wit
8585

8686
Workers AI supports streaming responses out-of-the-box by setting `stream: true`, and we strongly recommend using them to avoid buffering and delaying responses, especially for larger models or reasoning models that require more time to generate a response.
8787

88-
<TypeScriptExample file="src/index.ts">
88+
<TypeScriptExample filename="src/index.ts">
8989

9090
```ts
9191
import { Agent } from "agents-sdk"
@@ -135,7 +135,7 @@ Model routing allows you to route requests to different AI models based on wheth
135135

136136
:::
137137

138-
<TypeScriptExample file="src/index.ts">
138+
<TypeScriptExample filename="src/index.ts">
139139

140140
```ts
141141
import { Agent } from "agents-sdk"
@@ -189,7 +189,7 @@ To use the AI SDK, install the `ai` package and use it within your Agent. The ex
189189
npm install ai @ai-sdk/openai
190190
```
191191

192-
<TypeScriptExample file="src/index.ts">
192+
<TypeScriptExample filename="src/index.ts">
193193

194194
```ts
195195
import { Agent } from "agents-sdk"
@@ -216,7 +216,7 @@ Agents can call models across any service, including those that support the Open
216216

217217
Agents can stream responses back over HTTP using Server Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSockets](/agents/examples/websockets/) API in your Agent to responses back to a client, which is especially useful for larger models that can take over 30+ seconds to reply.
218218

219-
<TypeScriptExample file="src/index.ts">
219+
<TypeScriptExample filename="src/index.ts">
220220

221221
```ts
222222
import { Agent } from "agents-sdk"

src/content/docs/style-guide/components/code.mdx

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -100,55 +100,3 @@ export default {
100100
};
101101
```
102102
````
103-
104-
## TypeScript examples
105-
106-
The `TypeScriptExample` component uses [`ts-blank-space`](https://github.com/bloomberg/ts-blank-space) to remove TypeScript-specific syntax from your example and provide a JavaScript tab. This reduces maintenance burden by only having a single example to maintain.
107-
108-
:::note
109-
Some TypeScript syntax influences runtime behaviour, and cannot be stripped.
110-
111-
Please refer to the [Unsupported Syntax](https://github.com/bloomberg/ts-blank-space?tab=readme-ov-file#unsupported-syntax) section of the project's README.
112-
:::
113-
114-
### Input
115-
116-
* `filename` `string | { js: string, ts: string }` (optional)
117-
* If a single TypeScript filename is passed, this will be used for JavaScript but with a `.js` file extension.
118-
* `<TypeScriptExample filename="example.ts">`
119-
* To specify different filenames for the two languages, pass an object with a `js` and `ts` filename including extensions.
120-
* `<TypeScriptExample filename={{ js: "foo.js", ts: "bar.ts" }}>`
121-
* `tabsWrapper` `boolean` (optional)
122-
* When set to `false`, this component will not render `<Tabs>` components.
123-
* This allows you to include the JS/TS tabs in your own `<Tabs>` and add `<TabItem>`s before/after, i.e for Python examples.
124-
* `playground` `boolean` (optional)
125-
* When set to `true`, a "Open Worker in Playground" link will render on the JavaScript codeblock.
126-
127-
````mdx live
128-
import { TypeScriptExample } from "~/components";
129-
130-
<TypeScriptExample filename="index.ts">
131-
```ts
132-
interface Environment {
133-
KV: KVNamespace;
134-
}
135-
136-
export default {
137-
async fetch(req, env, ctx): Promise<Response> {
138-
if (req !== "POST") {
139-
return new Response("Method Not Allowed", {
140-
status: 405,
141-
headers: {
142-
"Allow": "POST"
143-
}
144-
});
145-
}
146-
147-
await env.KV.put("foo", "bar");
148-
149-
return new Response();
150-
}
151-
} satisfies ExportedHandler<Environment>
152-
```
153-
</TypeScriptExample>
154-
````

src/content/docs/style-guide/components/github-code.mdx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
title: GitHubCode
33
---
44

5+
import { GitHubCode } from "~/components";
6+
57
The `GitHubCode` component allows you to include files from Cloudflare repositories.
68

79
The remote content can be filtered by lines or a region enclosed in tags.
@@ -14,14 +16,25 @@ import { GitHubCode } from "~/components";
1416

1517
## Usage
1618

17-
```mdx live
18-
import { GitHubCode } from "~/components";
19+
<GitHubCode
20+
repo="cloudflare/workflows-starter"
21+
file="src/index.ts"
22+
commit="a844e629ec80968118d4b116d4b26f5dcb107137"
23+
lang="ts"
24+
code={{
25+
collapse: "3-6"
26+
}}
27+
/>
1928

29+
```mdx
2030
<GitHubCode
2131
repo="cloudflare/workflows-starter"
2232
file="src/index.ts"
2333
commit="a844e629ec80968118d4b116d4b26f5dcb107137"
2434
lang="ts"
35+
code={{
36+
collapse: "2-3"
37+
}}
2538
/>
2639
```
2740

@@ -109,6 +122,8 @@ The long (40-characters) Git commit hash to pull from, for example `ab3951b5c953
109122

110123
The language to use for the code block, for example `rs`.
111124

125+
If the `lang` is `ts`, the [`TypeScriptExample`](/style-guide/components/typescript-example/) component will be used to provide a JavaScript tab as well.
126+
112127
### `lines`
113128

114129
**type:** `string`
@@ -121,4 +136,10 @@ A range of lines to filter the content using, for example `1-3`.
121136

122137
A region to filter the content with, for example `no-logging`.
123138

124-
This should be represented as starting `<docs-tag name="no-logging">` and closing `</docs-tag name="no-logging">` comments in the source file.
139+
This should be represented as starting `<docs-tag name="no-logging">` and closing `</docs-tag name="no-logging">` comments in the source file.
140+
141+
### `code`
142+
143+
**type**: `object`
144+
145+
Props to pass to the [Expressive Code component](https://expressive-code.com/key-features/code-component/).
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: TypeScript example
3+
---
4+
5+
## TypeScript examples
6+
7+
The `TypeScriptExample` component uses [`ts-blank-space`](https://github.com/bloomberg/ts-blank-space) to remove TypeScript-specific syntax from your example and provide a JavaScript tab. This reduces maintenance burden by only having a single example to maintain.
8+
9+
This component is automatically used in the [`GitHubCode`](/style-guide/components/github-code/) component when the `lang` is set to `ts`.
10+
11+
:::note
12+
Some TypeScript syntax influences runtime behaviour, and cannot be stripped.
13+
14+
Please refer to the [Unsupported Syntax](https://github.com/bloomberg/ts-blank-space?tab=readme-ov-file#unsupported-syntax) section of the project's README.
15+
:::
16+
17+
## Component
18+
19+
````mdx live
20+
import { TypeScriptExample } from "~/components";
21+
22+
<TypeScriptExample>
23+
```ts
24+
interface Environment {
25+
KV: KVNamespace;
26+
}
27+
28+
export default {
29+
async fetch(req, env, ctx): Promise<Response> {
30+
if (req !== "POST") {
31+
return new Response("Method Not Allowed", {
32+
status: 405,
33+
headers: {
34+
"Allow": "POST"
35+
}
36+
});
37+
}
38+
39+
await env.KV.put("foo", "bar");
40+
41+
return new Response();
42+
}
43+
} satisfies ExportedHandler<Environment>
44+
```
45+
</TypeScriptExample>
46+
````
47+
48+
49+
## `<TypeScriptExample>` Props
50+
51+
### `filename`
52+
53+
**type:** `string`
54+
55+
An optional filename, ending in `.ts`.
56+
57+
`.ts` will be replaced by `.js` for the JavaScript tab.
58+
59+
### `playground`
60+
61+
**type:** `boolean`
62+
63+
If set to `true`, a [`Run Worker in Playground`](/style-guide/components/code/#playground) button will appear on the JavaScript tab.
64+
65+
### `code`
66+
67+
**type**: `object`
68+
69+
Props to pass to the [Expressive Code component](https://expressive-code.com/key-features/code-component/).
70+
71+
These props will apply to both code blocks and so options like `collapse` may not work as expected, as lines may be removed from the TypeScript code.

src/content/docs/workers/get-started/prompting.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,9 +1003,9 @@ Depending on the model and user prompt, it may generate invalid code, configurat
10031003

10041004
### Passing a system prompt
10051005

1006-
If you are building an AI application that will itself generate code, you can additionally use the prompt above as a "system prompt", which will give the LLM additional information on how to structure the output code. For example:
1006+
If you are building an AI application that will itself generate code, you can additionally use the prompt above as a "system prompt", which will give the LLM additional information on how to structure the output code. For example:
10071007

1008-
<TypeScriptExample file="index.ts">
1008+
<TypeScriptExample filename="index.ts">
10091009

10101010
```ts
10111011
import workersPrompt from "./workersPrompt.md"

0 commit comments

Comments
 (0)