Skip to content

Commit 79e1361

Browse files
committed
feat(routing): wip getStaticPathFromContentType & wip Chapter
getStaticPathFromContentType add a standardized way to get static path. But the function throw an obscure error when used in TS files, See this issue -> withastro/astro#5552
1 parent f1bcd4e commit 79e1361

14 files changed

+150
-49
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@example/basics",
2+
"name": "fairedesjeux",
33
"type": "module",
44
"version": "0.0.1",
55
"private": true,

src/data/chapters.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { MarkdownInstance } from "astro"
2+
import type { BaseFrontmatter } from "./shared"
3+
4+
export interface Chapter extends BaseFrontmatter {}
5+
6+
export type ChapterInstance = MarkdownInstance<Chapter>

src/data/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from "./chapters"
2+
export * from "./courses"
3+
export * from "./shared"

src/data/shared.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ export interface BaseFrontmatter {
33
description: string
44
opengraph_image: string | null
55
}
6+
7+
export type ContentType = "Course" | "Chapter" | "Page"

src/layouts/AppLayout.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
import Footer from "../components/footer/Footer.astro"
3-
import Header from "../components/header/Header.astro"
2+
import Footer from "$components/footer/Footer.astro"
3+
import Header from "$components/header/Header.astro"
44
55
export interface Props {
66
title: string

src/layouts/ContentLayout.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
import type { CourseInstance } from "../data/courses"
2+
import type { CourseInstance } from "$data"
33
import AppLayout from "./AppLayout.astro"
44
55
interface Props {

src/pages/[...chapter].astro

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
import type { Chapter, ChapterInstance } from "$data"
3+
import { getStaticPathFromContentType } from "./glob.astro"
4+
5+
interface Props {
6+
slug: ChapterInstance
7+
}
8+
const { content } = Astro.props
9+
10+
export async function getStaticPaths() {
11+
return await getStaticPathFromContentType(Astro, "Chapter")
12+
}
13+
---

src/pages/[course].astro

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
---
2-
import type { Course, CourseInstance } from "../data/courses"
3-
import ContentLayout from "../layouts/ContentLayout.astro"
4-
import { getSlugFromPath } from "../utils"
2+
import type { CourseInstance } from "$data"
3+
import { getStaticPathFromContentType } from "./glob.astro"
4+
import ContentLayout from "$layouts/ContentLayout.astro"
55
66
interface Props {
7-
course: CourseInstance
7+
content: CourseInstance
88
}
9-
const { course } = Astro.props
9+
const { content } = Astro.props
1010
1111
export async function getStaticPaths() {
12-
const courses = await Astro.glob<Course>("../../content/**/index.md")
13-
14-
return courses.map((course) => ({
15-
params: {
16-
course: getSlugFromPath(course.file, "Course"),
17-
},
18-
props: {
19-
course: { ...course },
20-
},
21-
}))
12+
return await getStaticPathFromContentType(Astro, "Course")
2213
}
2314
---
2415

25-
<ContentLayout content={course} />
16+
<ContentLayout content={content} />

src/pages/glob.astro

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
import type { Chapter, ContentType, Course } from "$data"
3+
import { getSlugFromFilePath } from "$utils"
4+
import type { AstroGlobal } from "astro"
5+
6+
/**
7+
* A standardized way to get all Static Paths of a given content type.
8+
* ==============================================
9+
* Temporarily moved from `src/utils/glob.ts`,
10+
* see this issue -> https://github.com/withastro/astro/issues/5552
11+
* @param Astro needed to use Astro.glob<t> inside a TypeScript file
12+
* @param contentType what's the type of content needed ?
13+
* @returns A promise of an array with all Static Paths
14+
*/
15+
export async function getStaticPathFromContentType(
16+
Astro: Readonly<AstroGlobal>,
17+
contentType: ContentType
18+
) {
19+
let contents: Array<any> = []
20+
21+
switch (contentType) {
22+
case "Course":
23+
contents = await Astro.glob<Course>("../../content/**/index.md")
24+
return contents.map((content) => ({
25+
params: {
26+
course: getSlugFromFilePath(content.file, contentType),
27+
},
28+
props: {
29+
content: { ...content },
30+
},
31+
}))
32+
33+
case "Chapter":
34+
contents = await Astro.glob<Chapter>(`../../content/**/**/chapter.md`)
35+
36+
return contents.map((content) => ({
37+
params: {
38+
chapter: getSlugFromFilePath(content.file, contentType),
39+
},
40+
props: {
41+
content: { ...content },
42+
},
43+
}))
44+
45+
case "Page":
46+
contents = await Astro.glob<Chapter>("../../content/**/**/*.md")
47+
48+
default:
49+
throw new Error(
50+
`[getStaticPathFromContentType] contentType not yet implemented: ${contentType}`
51+
)
52+
}
53+
}
54+
---

src/pages/index.astro

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
import type { Course } from "../data/courses"
3-
import MainLayout from "../layouts/MainLayout.astro"
4-
import { getSlugFromPath } from "../utils"
2+
import type { Course } from "$data"
3+
import { getSlugFromFilePath } from "$utils"
4+
import MainLayout from "$layouts/MainLayout.astro"
55
66
const courses = await Astro.glob<Course>("../../content/**/index.md")
77
---
@@ -12,7 +12,7 @@ const courses = await Astro.glob<Course>("../../content/**/index.md")
1212
{
1313
courses.map((course) => (
1414
<li>
15-
<a href={"/" + getSlugFromPath(course.file, "Course")}>
15+
<a href={"/" + getSlugFromFilePath(course.file, "Course")}>
1616
{course.frontmatter.title}
1717
</a>
1818
</li>

src/utils/files.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { ContentType } from "$data"
2+
3+
/**
4+
* Get content's slug from a content file path
5+
* @param path where is the content file ?
6+
* @param contentType what's the type of content ?
7+
* @returns
8+
*/
9+
export function getSlugFromFilePath(
10+
path: string,
11+
contentType: ContentType
12+
): string {
13+
switch (contentType) {
14+
case "Course":
15+
return extractSlugFromFilePath(path, "index.md")
16+
case "Chapter":
17+
return extractSlugFromFilePath(path, "chapter.md")
18+
default:
19+
throw new Error(
20+
`[getSlugFromFilePath] contentType not yet implemented: ${contentType}`
21+
)
22+
}
23+
}
24+
25+
/**
26+
* Private function, utils used by getSlugFromFilePath to substring path
27+
* @param path What's the path to substring ?
28+
* @param end What's the end of the subtring ?
29+
* @returns
30+
*/
31+
function extractSlugFromFilePath(path: string, end: string) {
32+
return path.substring(
33+
// there is probably a smarter way
34+
path.indexOf("content/") + 8,
35+
path.indexOf(`/${end}`)
36+
)
37+
}

src/utils/glob.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Temporarily moved to `src/pages/glob.astro`,
3+
* see this issue -> https://github.com/withastro/astro/issues/5552
4+
*/
5+
export async function getStaticPathFromContentType() {
6+
throw new Error("Temporarily moved to `src/pages/glob.astro`")
7+
}

src/utils/index.ts

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,2 @@
1-
/**
2-
* Get content's slug from a content file path
3-
* @param path where is the content file ?
4-
* @param contentType what's the type of content ?
5-
* @returns
6-
*/
7-
export function getSlugFromPath(
8-
path: string,
9-
contentType: contentType
10-
): string {
11-
switch (contentType) {
12-
case "Course":
13-
return path.substring(
14-
// there is probably a smarter way
15-
path.indexOf("content/") + 8,
16-
path.indexOf("/index.md")
17-
)
18-
default:
19-
throw new Error(`contentType not yet implemented: ${contentType}`)
20-
}
21-
}
22-
23-
type contentType = "Course" | "Chapter" | "Page"
1+
export * from "./files"
2+
export * from "./glob"

tsconfig.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
{
2-
"extends": "astro/tsconfigs/strict"
3-
}
2+
"extends": "astro/tsconfigs/strict",
3+
"compilerOptions": {
4+
"baseUrl": ".",
5+
"paths": {
6+
"$components/*": ["src/components/*"],
7+
"$data": ["src/data/index.ts"],
8+
"$layouts/*": ["src/layouts/*"],
9+
"$utils": ["src/utils/index.ts"]
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)