diff --git a/e2e/src/components/CurrentEntry.astro b/e2e/src/components/CurrentEntry.astro new file mode 100644 index 00000000..7132b66a --- /dev/null +++ b/e2e/src/components/CurrentEntry.astro @@ -0,0 +1,29 @@ +--- +import file from '@content/tutorial/tests/file-tree/allow-edits-disabled/_files/first-level/file'; +import { getCollection } from 'astro:content'; +import { getEntry, getEntries } from 'astro:content'; + +if (!Astro.locals.tk) { + throw new Error('Not in the context of a lesson, Astro.locals.tk is not defined'); +} +if (!Astro.locals.tk.lesson) { + throw new Error('Lesson not set in tutorialkit Astro.locals.tk context'); +} + +const { entrySlug } = Astro.locals.tk.lesson; + +const currentEntry = await getEntry('tutorial', entrySlug); +if (!currentEntry) { + throw new Error(`Entry not found for slug: ${entrySlug}.`); +} +--- + +
+

Lesson

+ { + // @ts-ignore + JSON.stringify(Astro.locals.tk.lesson, null, 2) + } +

Entry

+ {JSON.stringify(currentEntry, null, 2)} +
diff --git a/e2e/src/content/tutorial/tests/current-entry/basic/content.mdx b/e2e/src/content/tutorial/tests/current-entry/basic/content.mdx new file mode 100644 index 00000000..bd54903e --- /dev/null +++ b/e2e/src/content/tutorial/tests/current-entry/basic/content.mdx @@ -0,0 +1,10 @@ +--- +type: lesson +title: Basic +terminal: + panels: terminal +--- + +import CurrentEntry from "@components/CurrentEntry.astro" + + \ No newline at end of file diff --git a/e2e/src/content/tutorial/tests/current-entry/meta.md b/e2e/src/content/tutorial/tests/current-entry/meta.md new file mode 100644 index 00000000..ff89ab9e --- /dev/null +++ b/e2e/src/content/tutorial/tests/current-entry/meta.md @@ -0,0 +1,4 @@ +--- +type: chapter +title: Current Entry +--- diff --git a/e2e/src/env.d.ts b/e2e/src/env.d.ts index 9505823a..07d677d4 100644 --- a/e2e/src/env.d.ts +++ b/e2e/src/env.d.ts @@ -1,3 +1,13 @@ /// /// /// + +// copied from packages/astro/src/default/env-default.d.ts +// TODO: should probably be exposed by astro/types instead? +declare namespace App { + interface Locals { + tk: { + lesson: import('@tutorialkit/types').Lesson; + }; + } +} diff --git a/e2e/test/current-entry.test.ts b/e2e/test/current-entry.test.ts new file mode 100644 index 00000000..47ce4694 --- /dev/null +++ b/e2e/test/current-entry.test.ts @@ -0,0 +1,13 @@ +import { test, expect } from '@playwright/test'; + +const BASE_URL = '/tests/current-entry'; + +test('developer can access current lesson and collection entry from Astro.locals', async ({ page }) => { + await page.goto(`${BASE_URL}/basic`); + + // lesson id + await expect(page.getByText('"id": "basic"')).toBeVisible(); + + // astro collection entry id + await expect(page.getByText('"id": "tests/current-entry/basic/content.mdx"')).toBeVisible(); +}); diff --git a/packages/astro/src/default/env-default.d.ts b/packages/astro/src/default/env-default.d.ts index 303066a5..d8f085fa 100644 --- a/packages/astro/src/default/env-default.d.ts +++ b/packages/astro/src/default/env-default.d.ts @@ -17,3 +17,11 @@ declare module 'tutorialkit:override-components' { declare const __ENTERPRISE__: boolean; declare const __WC_CONFIG__: WebContainerConfig | undefined; + +declare namespace App { + interface Locals { + tk: { + lesson: import('@tutorialkit/types').Lesson; + }; + } +} diff --git a/packages/astro/src/default/pages/[...slug].astro b/packages/astro/src/default/pages/[...slug].astro index b03f55d7..0d610369 100644 --- a/packages/astro/src/default/pages/[...slug].astro +++ b/packages/astro/src/default/pages/[...slug].astro @@ -20,6 +20,7 @@ const meta = lesson.data?.meta ?? {}; // use lesson's default title and a default description for SEO metadata meta.title ??= title; meta.description ??= 'A TutorialKit interactive lesson'; +Astro.locals.tk = { lesson }; --- diff --git a/packages/astro/src/default/utils/content.ts b/packages/astro/src/default/utils/content.ts index b1665ba5..e72b26e6 100644 --- a/packages/astro/src/default/utils/content.ts +++ b/packages/astro/src/default/utils/content.ts @@ -18,7 +18,7 @@ export async function getTutorial(): Promise { let lessons: Lesson[] = []; for (const entry of collection) { - const { id, data } = entry; + const { id, data, slug: entrySlug } = entry; const { type } = data; const [partId, chapterId, lessonId] = id.split('/'); @@ -74,6 +74,7 @@ export async function getTutorial(): Promise { data, id: lessonId, filepath: id, + entrySlug, order: -1, part: { id: partId, diff --git a/packages/types/src/entities/index.ts b/packages/types/src/entities/index.ts index 3d0abf5f..a0fdaa83 100644 --- a/packages/types/src/entities/index.ts +++ b/packages/types/src/entities/index.ts @@ -45,6 +45,9 @@ export interface Lesson { part: { id: string; title: string }; chapter: { id: string; title: string }; slug: string; + + // slug to pass to astro:content `getEntry` + entrySlug: string; filepath: string; editPageLink?: string; files: FilesRefList;