Learn Page and Content Pipeline Update #20

Merged
an.di merged 20 commits from adiallo/feature/LearnPage into main 2025-10-01 03:15:23 +00:00
3 changed files with 25 additions and 12 deletions
Showing only changes of commit 27692750a6 - Show all commits
+12
View File
@@ -48,6 +48,8 @@ related: ["slug-of-related-article-1", "slug-of-related-article-2"]
thumbnail: thumbnail:
vertical: "your-article-slug-vertical.svg" vertical: "your-article-slug-vertical.svg"
horizontal: "your-article-slug-horizontal.svg" horizontal: "your-article-slug-horizontal.svg"
background:
color: "#F4F3F1" # Page background color (hex)
--- ---
``` ```
@@ -59,6 +61,7 @@ thumbnail:
- **date**: Publication date in YYYY-MM-DD format - **date**: Publication date in YYYY-MM-DD format
- **related**: Array of article slugs (use filename without .md) - **related**: Array of article slugs (use filename without .md)
- **thumbnail**: Custom images for article thumbnails (optional) - **thumbnail**: Custom images for article thumbnails (optional)
- **background.color**: Page background color as a hex code (e.g., `#F4F3F1`)
### Related Articles ### Related Articles
@@ -101,6 +104,15 @@ Add custom thumbnail images to make your article stand out:
If no thumbnails are provided, default images will be used. If no thumbnails are provided, default images will be used.
## Background Color
Set the content page background using a hex color in frontmatter:
```yaml
background:
color: "#F4F3F1" # Use any valid hex code
```
## File Naming ## File Naming
Use descriptive, URL-friendly filenames: Use descriptive, URL-friendly filenames:
+1 -1
View File
@@ -20,7 +20,7 @@ export default {
docs: { docs: {
description: { description: {
component: component:
"The ContentBanner component displays the header information for blog articles, including title, description, author, and date.", "The ContentBanner component displays the header information for blog articles, including title, description, author, and date. Note: page background colors are applied at the blog page level using a hex color from frontmatter (background.color), not inside this component. Thumbnail images should be uploaded via the content pipeline to public/content/blog/ and referenced in frontmatter (thumbnail.horizontal / thumbnail.vertical).",
}, },
}, },
}, },
+12 -11
View File
@@ -129,10 +129,11 @@ describe("BlogPostPage", () => {
expect(mainContainer).toBeInTheDocument(); expect(mainContainer).toBeInTheDocument();
expect(mainContainer).toHaveClass( expect(mainContainer).toHaveClass(
"min-h-screen", "min-h-screen",
"bg-[#F4F3F1]",
"relative", "relative",
"overflow-hidden", "overflow-hidden"
); );
// Background color is applied via inline style from frontmatter hex
expect(mainContainer).toHaveStyle({ backgroundColor: expect.any(String) });
}); });
it("renders the content banner", async () => { it("renders the content banner", async () => {
@@ -144,7 +145,7 @@ describe("BlogPostPage", () => {
expect(screen.getByTestId("content-banner")).toBeInTheDocument(); expect(screen.getByTestId("content-banner")).toBeInTheDocument();
expect(screen.getByText("Test Article Title")).toBeInTheDocument(); expect(screen.getByText("Test Article Title")).toBeInTheDocument();
expect( expect(
screen.getByText("This is a test article description"), screen.getByText("This is a test article description")
).toBeInTheDocument(); ).toBeInTheDocument();
}); });
@@ -158,7 +159,7 @@ describe("BlogPostPage", () => {
expect(article).toBeInTheDocument(); expect(article).toBeInTheDocument();
expect(article).toHaveClass( expect(article).toHaveClass(
"p-[var(--spacing-scale-024)]", "p-[var(--spacing-scale-024)]",
"sm:py-[var(--spacing-scale-032)]", "sm:py-[var(--spacing-scale-032)]"
); );
// Check content is rendered // Check content is rendered
@@ -188,7 +189,7 @@ describe("BlogPostPage", () => {
expect(screen.getByTestId("ask-organizer")).toBeInTheDocument(); expect(screen.getByTestId("ask-organizer")).toBeInTheDocument();
expect(screen.getByText("Still have questions?")).toBeInTheDocument(); expect(screen.getByText("Still have questions?")).toBeInTheDocument();
expect( expect(
screen.getByText("Get answers from an experienced organizer"), screen.getByText("Get answers from an experienced organizer")
).toBeInTheDocument(); ).toBeInTheDocument();
expect(screen.getByText("Ask an organizer")).toBeInTheDocument(); expect(screen.getByText("Ask an organizer")).toBeInTheDocument();
}); });
@@ -220,7 +221,7 @@ describe("BlogPostPage", () => {
expect(contentDiv).toHaveClass("post-body"); expect(contentDiv).toHaveClass("post-body");
expect(contentDiv).toHaveClass("-mt-[var(--spacing-scale-048)]"); expect(contentDiv).toHaveClass("-mt-[var(--spacing-scale-048)]");
expect(contentDiv).toHaveClass( expect(contentDiv).toHaveClass(
"text-[var(--color-content-inverse-primary)]", "text-[var(--color-content-inverse-primary)]"
); );
expect(contentDiv).toHaveClass("text-[16px]"); expect(contentDiv).toHaveClass("text-[16px]");
expect(contentDiv).toHaveClass("leading-[24px]"); expect(contentDiv).toHaveClass("leading-[24px]");
@@ -267,7 +268,7 @@ describe("BlogPostPage", () => {
// Check for script elements using querySelector since RTL ignores them // Check for script elements using querySelector since RTL ignores them
const scripts = document.querySelectorAll( const scripts = document.querySelectorAll(
'script[type="application/ld+json"]', 'script[type="application/ld+json"]'
); );
expect(scripts).toHaveLength(2); expect(scripts).toHaveLength(2);
@@ -285,7 +286,7 @@ describe("BlogPostPage", () => {
// The component should throw an error when post is null // The component should throw an error when post is null
// This happens because notFound() is called // This happens because notFound() is called
await expect( await expect(
BlogPostPage({ params: { slug: "non-existent" } }), BlogPostPage({ params: { slug: "non-existent" } })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@@ -297,7 +298,7 @@ describe("BlogPostPage", () => {
// Current post should not appear in related articles // Current post should not appear in related articles
expect( expect(
screen.queryByTestId("related-test-article"), screen.queryByTestId("related-test-article")
).not.toBeInTheDocument(); ).not.toBeInTheDocument();
// Other related posts should appear // Other related posts should appear
@@ -322,7 +323,7 @@ describe("BlogPostPage", () => {
"top-1/4", "top-1/4",
"right-0", "right-0",
"pointer-events-none", "pointer-events-none",
"z-10", "z-10"
); );
// Second shape (left side) // Second shape (left side)
@@ -334,7 +335,7 @@ describe("BlogPostPage", () => {
"top-1/2", "top-1/2",
"left-0", "left-0",
"pointer-events-none", "pointer-events-none",
"z-10", "z-10"
); );
}); });