feat: use astro files for slides
This commit is contained in:
parent
8ca43b3785
commit
0614e2b7ef
@ -1,14 +0,0 @@
|
||||
import { defineCollection, z } from "astro:content";
|
||||
import { glob } from "astro/loaders"; // Not available with legacy API
|
||||
|
||||
const slides = defineCollection({
|
||||
loader: glob({ pattern: "**/*.md", base: "./src/slides" }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
authors: z.array(z.string()),
|
||||
publishedAt: z.coerce.date(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { slides };
|
||||
@ -5,7 +5,7 @@ export interface Props {
|
||||
description?: string;
|
||||
}
|
||||
import Layout from "./BaseLayout.astro";
|
||||
import "@themes/hnrq.scss";
|
||||
import "@theme";
|
||||
|
||||
const { title, authors, description } = Astro.props;
|
||||
---
|
||||
|
||||
@ -1,21 +1,17 @@
|
||||
---
|
||||
import SlideLayout from "@layouts/SlideLayout.astro";
|
||||
import { getCollection, render } from "astro:content";
|
||||
import { getSlides } from "@utils/getSlides";
|
||||
|
||||
export const getStaticPaths = async () =>
|
||||
(await getCollection("slides")).map((slide) => ({
|
||||
params: { id: slide.id },
|
||||
props: { slide },
|
||||
}));
|
||||
export const getStaticPaths = () =>
|
||||
getSlides().map((slide) => ({ params: { id: slide.id }, props: { slide } }));
|
||||
|
||||
const { slide } = Astro.props;
|
||||
const { Content } = await render(slide);
|
||||
---
|
||||
|
||||
<SlideLayout
|
||||
title={slide.data.title}
|
||||
authors={slide.data.authors}
|
||||
description={slide.data.description}
|
||||
title={slide.title}
|
||||
authors={slide.authors}
|
||||
description={slide.description}
|
||||
>
|
||||
<Content />
|
||||
<slide.default />
|
||||
</SlideLayout>
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
---
|
||||
import Layout from "@layouts/BaseLayout.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import { getSlides } from "@utils/getSlides";
|
||||
|
||||
const slides = (await getCollection("slides")).sort((c1, c2) =>
|
||||
c1.data.title > c2.data.title ? -1 : 1
|
||||
);
|
||||
const slides = getSlides().sort((c1, c2) => (c1.title > c2.title ? -1 : 1));
|
||||
---
|
||||
|
||||
<Layout title="Home">
|
||||
@ -13,21 +11,21 @@ const slides = (await getCollection("slides")).sort((c1, c2) =>
|
||||
{
|
||||
slides.map((slide) => (
|
||||
<a href={`/${slide.id}`}>
|
||||
<h2>{slide.data.title}</h2>
|
||||
<p>{slide.data.description}</p>
|
||||
<small>{slide.data.publishedAt.toLocaleDateString()}</small>
|
||||
<h2>{slide.title}</h2>
|
||||
<p>{slide.description}</p>
|
||||
<small>{new Date(slide.publishedAt).toLocaleDateString()}</small>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</Layout>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@themes/hnrq";
|
||||
<style>
|
||||
@import "@theme";
|
||||
|
||||
body {
|
||||
background-color: hnrq.$backgroundColor;
|
||||
color: hnrq.$mainColor;
|
||||
font-family: hnrq.$mainFont;
|
||||
background-color: var(--background);
|
||||
color: var(--main-color);
|
||||
font-family: var(--main-font);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -43,17 +41,17 @@ const slides = (await getCollection("slides")).sort((c1, c2) =>
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: hnrq.$headingFont;
|
||||
font-family: var(--heading-font);
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 2rem;
|
||||
color: hnrq.$mainColor;
|
||||
color: var(--main-color);
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease-in-out;
|
||||
transition: filter 0.2s ease-in-out;
|
||||
background-color: var(--background);
|
||||
&:hover {
|
||||
background: hnrq.$mainColor;
|
||||
color: hnrq.$backgroundColor;
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
92
src/slides/flexbox/index.astro
Normal file
92
src/slides/flexbox/index.astro
Normal file
@ -0,0 +1,92 @@
|
||||
---
|
||||
export const title = "CSS Flexbox"
|
||||
export const authors = ["Henrique Ramos"]
|
||||
export const publishedAt = "2025-01-27"
|
||||
export const description = "Do you even flex?"
|
||||
---
|
||||
|
||||
<section>
|
||||
<h2>What is Flexbox?</h2>
|
||||
<ul>
|
||||
<li>One-dimensional layout model</li>
|
||||
<li>Distributes space along a single direction</li>
|
||||
<li>Powerful alignment capabilities</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Basic Flexbox Container</h2>
|
||||
<div class="demo">
|
||||
<div class="box">1</div>
|
||||
<div class="box">2</div>
|
||||
<div class="box">3</div>
|
||||
</div>
|
||||
<pre><code data-trim>
|
||||
.container {'{'}
|
||||
display: flex;
|
||||
{'}'}
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>justify-content</h2>
|
||||
<div class="demo" style="justify-content: space-between">
|
||||
<div class="box">1</div>
|
||||
<div class="box">2</div>
|
||||
<div class="box">3</div>
|
||||
</div>
|
||||
<pre><code data-trim>
|
||||
.container {'{'}
|
||||
justify-content: space-between;
|
||||
{'}'}
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>align-items</h2>
|
||||
<div class="demo" style="align-items: center; height: 300px">
|
||||
<div class="box">1</div>
|
||||
<div class="box">2</div>
|
||||
<div class="box">3</div>
|
||||
</div>
|
||||
<pre><code data-trim>
|
||||
.container {'{'}
|
||||
align-items: center;
|
||||
{'}'}
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>flex-direction</h2>
|
||||
<div class="demo" style="flex-direction: column">
|
||||
<div class="box">1</div>
|
||||
<div class="box">2</div>
|
||||
<div class="box">3</div>
|
||||
</div>
|
||||
<pre><code data-trim>
|
||||
.container {'{'}
|
||||
flex-direction: column;
|
||||
{'}'}
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.demo {
|
||||
display: flex;
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
border: 2px solid #fff;
|
||||
min-height: 200px;
|
||||
}
|
||||
.box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: #4a9eff;
|
||||
margin: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: "Finite State Machines with XState for Game Development using Three.js"
|
||||
authors: ["Henrique Ramos"]
|
||||
publishedAt: 2024-12-13
|
||||
description: "Using XState Finite State Machines to coordinate character actions in a Three.js game"
|
||||
export const title = "Finite State Machines with XState for Game Development using Three.js"
|
||||
export const authors = ["Henrique Ramos"]
|
||||
export const publishedAt = "2024-12-13"
|
||||
export const description = "Using XState Finite State Machines to coordinate character actions in a Three.js game"
|
||||
---
|
||||
|
||||
<section>
|
||||
38
src/utils/getAstroPages.ts
Normal file
38
src/utils/getAstroPages.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import type { AstroInstance } from "astro";
|
||||
|
||||
type Opts<T extends Record<string, unknown>> = {
|
||||
files: Record<string, T>;
|
||||
requiredFields?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all Astro pages from a given path.
|
||||
* @param opts - The options for the function.
|
||||
* @param opts.files - The files to get the Astro pages from. Use import.meta.glob eager: true.
|
||||
* @param opts.requiredFields - The required fields for the Astro pages.
|
||||
* @returns The Astro pages in the root of the given path, or looks for index.astro files in subdirectories (single level).
|
||||
*/
|
||||
const getAstroPages = <T extends Record<string, unknown> & AstroInstance>({
|
||||
files,
|
||||
requiredFields = [],
|
||||
}: Opts<T>) =>
|
||||
Object.values(files).map((module) => {
|
||||
if (!requiredFields.every((field) => module[field as keyof T])) {
|
||||
throw new Error(
|
||||
`Missing required fields for ${module.file}: ${requiredFields
|
||||
.filter((field) => !module[field as keyof T])
|
||||
.join(", ")}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: (
|
||||
module.file
|
||||
.split("/")
|
||||
.at(module.file.includes("index.astro") ? -2 : -1) ?? ""
|
||||
).replace(".astro", ""),
|
||||
...module,
|
||||
};
|
||||
});
|
||||
|
||||
export default getAstroPages;
|
||||
25
src/utils/getSlides.ts
Normal file
25
src/utils/getSlides.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import type { AstroInstance } from "astro";
|
||||
import getAstroPages from "./getAstroPages";
|
||||
|
||||
type Slide = AstroInstance & {
|
||||
[key: string]: unknown;
|
||||
title: string;
|
||||
description: string;
|
||||
authors: string[];
|
||||
publishedAt: string;
|
||||
};
|
||||
|
||||
const slideRequiredFields = ["title", "description", "authors", "publishedAt"];
|
||||
|
||||
/**
|
||||
* Get all slides from the slides directory.
|
||||
* @returns The slides.
|
||||
*/
|
||||
export const getSlides = () =>
|
||||
getAstroPages<Slide>({
|
||||
files: import.meta.glob<true, string, Slide>(
|
||||
["@slides/**/index.astro", "@slides/*.astro"],
|
||||
{ eager: true },
|
||||
),
|
||||
requiredFields: slideRequiredFields,
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user