Skip to content

Commit 7c6ede9

Browse files
authored
feat(astro): add custom configuration option for passing custom fields (#378)
1 parent 0af3848 commit 7c6ede9

File tree

8 files changed

+78
-3
lines changed

8 files changed

+78
-3
lines changed

docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,28 @@ type TemplateType = "html" | "node" | "angular-cli" | "create-react-app" | "java
404404
405405
```
406406

407+
##### `custom`
408+
409+
Assign custom fields to a chapter/part/lesson.
410+
<PropertyTable inherited type="Record<string,any>" />
411+
412+
This is useful when you want to consume items for the default `tutorial` collection
413+
in order to implement custom features.
414+
415+
```yaml
416+
custom:
417+
publishedAt: 2024-16-10
418+
tags: tutorialkit,astro,vite
419+
```
420+
421+
```ts
422+
import { getCollection } from 'astro:content';
423+
const collection = await getCollection('tutorial');
424+
for (const entry of collection) {
425+
console.log("This part was published at:", entry.data?.custom?.publishedAt)
426+
}
427+
```
428+
407429
## Configure the Tutorialkit Astro integration
408430

409431
`@tutorialkit/astro` is an integration for Astro. You can configure the integration in your `astro.config.ts` file.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
import { getCollection } from 'astro:content';
3+
const collection = await getCollection('tutorial');
4+
5+
const lesson = collection.find((c) => c.data.type === 'lesson' && c.slug.startsWith(Astro.params.slug!))!;
6+
const { custom } = lesson.data;
7+
---
8+
9+
<h2>Custom metadata</h2>
10+
11+
<pre>{JSON.stringify(custom, null,2)}</pre>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
type: lesson
3+
title: Custom
4+
terminal:
5+
panels: terminal
6+
custom:
7+
custom-message: 'Hello world'
8+
numeric-field: 5173
9+
---
10+
11+
import CustomMetaData from "@components/CustomMetadata.astro"
12+
13+
# Metadata test - Custom
14+
15+
<CustomMetaData />
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
type: chapter
3+
title: Metadata
4+
---

e2e/test/metadata.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
const BASE_URL = '/tests/metadata';
4+
5+
test('developer can pass custom metadata to lesson', async ({ page }) => {
6+
await page.goto(`${BASE_URL}/custom`);
7+
await expect(page.getByRole('heading', { level: 1, name: 'Metadata test - Custom' })).toBeVisible();
8+
9+
await expect(page.getByRole('heading', { level: 2, name: 'Custom metadata' })).toBeVisible();
10+
11+
await expect(page.getByText('"custom-message": "Hello world"')).toBeVisible();
12+
await expect(page.getByText('"numeric-field": 5173')).toBeVisible();
13+
});

packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ prepareCommands:
1212
terminal:
1313
panels: ['terminal', 'output']
1414
meta:
15-
description: "This is lesson 1"
16-
image: "/logo.svg"
15+
description: "This is lesson 1"
16+
image: "/logo.svg"
17+
custom:
18+
publishedAt: "2024-10-16"
19+
1720
---
1821

1922
# Kitchen Sink [Heading 1]

packages/types/src/entities/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { I18nSchema } from '../schemas/i18n.js';
2-
import type { ChapterSchema, LessonSchema, PartSchema } from '../schemas/index.js';
2+
import type { ChapterSchema, CustomSchema, LessonSchema, PartSchema } from '../schemas/index.js';
33
import type { MetaTagsSchema } from '../schemas/metatags.js';
44

55
export type * from './nav.js';
@@ -60,6 +60,8 @@ export type I18n = Required<NonNullable<I18nSchema>>;
6060

6161
export type MetaTagsConfig = MetaTagsSchema;
6262

63+
export type CustomConfig = CustomSchema;
64+
6365
export interface Tutorial {
6466
logoLink?: string;
6567
firstPartId?: string;

packages/types/src/schemas/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,18 @@ export const editorSchema = z.union([
203203
}),
204204
]);
205205

206+
const customSchema = z.record(z.string(), z.any());
207+
206208
export type TerminalPanelType = z.infer<typeof panelTypeSchema>;
207209
export type TerminalSchema = z.infer<typeof terminalSchema>;
208210
export type EditorSchema = z.infer<typeof editorSchema>;
211+
export type CustomSchema = z.infer<typeof customSchema>;
209212

210213
export const webcontainerSchema = commandsSchema.extend({
211214
meta: metaTagsSchema.optional(),
212215

216+
custom: customSchema.optional().describe('Assign custom fields to a chapter/part/lesson in the Astro collection'),
217+
213218
previews: previewSchema
214219
.optional()
215220
.describe(

0 commit comments

Comments
 (0)