From 01adc8a31bb49b5f564a0b45dc950c7b84bb2640 Mon Sep 17 00:00:00 2001 From: eric-burel Date: Wed, 16 Oct 2024 19:00:54 +0200 Subject: [PATCH 1/3] allow passing custom fields --- .../content/docs/reference/configuration.mdx | 22 +++++++++++++++++++ .../1-introduction/1-welcome/content.md | 7 ++++-- packages/types/src/entities/index.ts | 4 +++- packages/types/src/schemas/common.ts | 5 +++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx index 619a4b4ca..e22dfc681 100644 --- a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx +++ b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx @@ -404,6 +404,28 @@ type TemplateType = "html" | "node" | "angular-cli" | "create-react-app" | "java ``` +##### `custom` + +Assign custom fields to a chapter/part/lesson. + + +This is useful when you want to consume items for the default `tutorial` collection +in order to implement custom features. + +```yaml +custom: + publishedAt: 2024-16-10 + tags: tutorialkit,astro,vite +``` + +```ts +import { getCollection } from 'astro:content'; +const collection = await getCollection('tutorial'); +for (const entry of collection) { + console.log("This part was published at:", entry.data?.custom?.publishedAt) +} +``` + ## Configure the Tutorialkit Astro integration `@tutorialkit/astro` is an integration for Astro. You can configure the integration in your `astro.config.ts` file. diff --git a/packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md b/packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md index cf48965a5..1acc9d03f 100644 --- a/packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md +++ b/packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md @@ -12,8 +12,11 @@ prepareCommands: terminal: panels: ['terminal', 'output'] meta: - description: "This is lesson 1" - image: "/logo.svg" + description: "This is lesson 1" + image: "/logo.svg" +custom: + publishedAt: "2024-10-16" + --- # Kitchen Sink [Heading 1] diff --git a/packages/types/src/entities/index.ts b/packages/types/src/entities/index.ts index 81c828701..3d0abf5f6 100644 --- a/packages/types/src/entities/index.ts +++ b/packages/types/src/entities/index.ts @@ -1,5 +1,5 @@ import type { I18nSchema } from '../schemas/i18n.js'; -import type { ChapterSchema, LessonSchema, PartSchema } from '../schemas/index.js'; +import type { ChapterSchema, CustomSchema, LessonSchema, PartSchema } from '../schemas/index.js'; import type { MetaTagsSchema } from '../schemas/metatags.js'; export type * from './nav.js'; @@ -60,6 +60,8 @@ export type I18n = Required>; export type MetaTagsConfig = MetaTagsSchema; +export type CustomConfig = CustomSchema; + export interface Tutorial { logoLink?: string; firstPartId?: string; diff --git a/packages/types/src/schemas/common.ts b/packages/types/src/schemas/common.ts index faa8be849..5388d897a 100644 --- a/packages/types/src/schemas/common.ts +++ b/packages/types/src/schemas/common.ts @@ -203,13 +203,18 @@ export const editorSchema = z.union([ }), ]); +const customSchema = z.record(z.string(), z.any()); + export type TerminalPanelType = z.infer; export type TerminalSchema = z.infer; export type EditorSchema = z.infer; +export type CustomSchema = z.infer; export const webcontainerSchema = commandsSchema.extend({ meta: metaTagsSchema.optional(), + custom: customSchema.optional(), + previews: previewSchema .optional() .describe( From db9ea50a4a8b7c98a3d0e1b6c693fa92eabd2f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Fri, 18 Oct 2024 11:01:33 +0300 Subject: [PATCH 2/3] test: custom metadata --- e2e/src/components/CustomMetadata.astro | 11 +++++++++++ .../tutorial/tests/metadata/custom/content.mdx | 15 +++++++++++++++ e2e/src/content/tutorial/tests/metadata/meta.md | 4 ++++ e2e/test/metadata.test.ts | 13 +++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 e2e/src/components/CustomMetadata.astro create mode 100644 e2e/src/content/tutorial/tests/metadata/custom/content.mdx create mode 100644 e2e/src/content/tutorial/tests/metadata/meta.md create mode 100644 e2e/test/metadata.test.ts diff --git a/e2e/src/components/CustomMetadata.astro b/e2e/src/components/CustomMetadata.astro new file mode 100644 index 000000000..8af5d7b4d --- /dev/null +++ b/e2e/src/components/CustomMetadata.astro @@ -0,0 +1,11 @@ +--- +import { getCollection } from 'astro:content'; +const collection = await getCollection('tutorial'); + +const lesson = collection.find((c) => c.data.type === 'lesson' && c.slug.startsWith(Astro.params.slug!))!; +const { custom } = lesson.data; +--- + +

Custom metadata

+ +
{JSON.stringify(custom, null,2)}
diff --git a/e2e/src/content/tutorial/tests/metadata/custom/content.mdx b/e2e/src/content/tutorial/tests/metadata/custom/content.mdx new file mode 100644 index 000000000..397dfdc4d --- /dev/null +++ b/e2e/src/content/tutorial/tests/metadata/custom/content.mdx @@ -0,0 +1,15 @@ +--- +type: lesson +title: Custom +terminal: + panels: terminal +custom: + custom-message: 'Hello world' + numeric-field: 5173 +--- + +import CustomMetaData from "@components/CustomMetadata.astro" + +# Metadata test - Custom + + \ No newline at end of file diff --git a/e2e/src/content/tutorial/tests/metadata/meta.md b/e2e/src/content/tutorial/tests/metadata/meta.md new file mode 100644 index 000000000..e13ff569b --- /dev/null +++ b/e2e/src/content/tutorial/tests/metadata/meta.md @@ -0,0 +1,4 @@ +--- +type: chapter +title: Metadata +--- diff --git a/e2e/test/metadata.test.ts b/e2e/test/metadata.test.ts new file mode 100644 index 000000000..541ebca5a --- /dev/null +++ b/e2e/test/metadata.test.ts @@ -0,0 +1,13 @@ +import { test, expect } from '@playwright/test'; + +const BASE_URL = '/tests/metadata'; + +test('developer can pass custom metadata to lesson', async ({ page }) => { + await page.goto(`${BASE_URL}/custom`); + await expect(page.getByRole('heading', { level: 1, name: 'Metadata test - Custom' })).toBeVisible(); + + await expect(page.getByRole('heading', { level: 2, name: 'Custom metadata' })).toBeVisible(); + + await expect(page.getByText('"custom-message": "Hello world"')).toBeVisible(); + await expect(page.getByText('"numeric-field": 5173')).toBeVisible(); +}); From a5ba2d8df5d82510ec67abfafe7b91668df332d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Fri, 18 Oct 2024 12:11:07 +0300 Subject: [PATCH 3/3] chore: review --- packages/types/src/schemas/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/types/src/schemas/common.ts b/packages/types/src/schemas/common.ts index 5388d897a..cd854b563 100644 --- a/packages/types/src/schemas/common.ts +++ b/packages/types/src/schemas/common.ts @@ -213,7 +213,7 @@ export type CustomSchema = z.infer; export const webcontainerSchema = commandsSchema.extend({ meta: metaTagsSchema.optional(), - custom: customSchema.optional(), + custom: customSchema.optional().describe('Assign custom fields to a chapter/part/lesson in the Astro collection'), previews: previewSchema .optional()