Add page routing and content fetchers

This commit is contained in:
itsfinniii
2026-03-15 18:55:30 +01:00
parent bc11be5669
commit 21d5ba23a4
22 changed files with 923 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
import { createDirectusConnection } from "@/lib/directus";
import { print } from 'graphql';
import getBlogs from '@/graphql/blogs/getBlogs.graphql';
import getBlogPost from '@/graphql/blogs/getBlog.graphql';
import { formatDate } from "@/lib/dates";
export async function getAllBlogs(settings: GlobalSettings): Promise<BlogPost[]> {
@@ -23,6 +24,8 @@ export async function getAllBlogs(settings: GlobalSettings): Promise<BlogPost[]>
];
const blog: BlogPost = {
type: "BlogPost",
id: blogRecord["id"],
lastModified: new Date(),
title: blogRecord["title"],
content: blogRecord["content"],
@@ -70,3 +73,69 @@ export async function getAllBlogs(settings: GlobalSettings): Promise<BlogPost[]>
return blogs;
}
export async function getBlog(settings: GlobalSettings, route: string): Promise<BlogPost> {
const client = await createDirectusConnection();
const result = await client.query(print(getBlogPost), {
route: route
});
const blogRecord = result["Blogs"][0];
let dates: string[] = [
settings.blog.lastModified.toISOString(),
settings.website.lastModified.toISOString(),
blogRecord["date_created"],
blogRecord["date_updated"],
blogRecord["search_engine"][0]["date_created"],
blogRecord["search_engine"][0]["date_updated"],
blogRecord["search_engine"][0]["thumbnail"]["created_on"]
];
const blog: BlogPost = {
type: "BlogPost",
id: blogRecord["id"],
lastModified: new Date(),
title: blogRecord["title"],
content: blogRecord["content"],
date: blogRecord["date"],
url: blogRecord["url"],
searchEngine: {
title: blogRecord["search_engine"][0]["title"],
description: blogRecord["search_engine"][0]["description"],
allowCrawlers: blogRecord["search_engine"][0]["allow_crawler"],
canonical: blogRecord["search_engine"][0]["canonical"],
priority: blogRecord["search_engine"][0]["priority"],
thumbnail: {
url: blogRecord["search_engine"][0]["thumbnail"]["filename_disk"],
height: blogRecord["search_engine"][0]["thumbnail"]["height"],
width: blogRecord["search_engine"][0]["thumbnail"]["width"]
}
},
tags: []
};
blogRecord["tags"].forEach((tagRecord: any) => {
blog["tags"].push({
text: tagRecord["Tags_id"]["text"],
code: tagRecord["Tags_id"]["code"],
color: tagRecord["Tags_id"]["color"]
});
dates.push(tagRecord["Tags_id"]["date_created"]);
dates.push(tagRecord["Tags_id"]["date_updated"]);
});
if (dates.filter(e => e !== null).length === 0) {
blog.lastModified = new Date();
}
else {
const sortedDates: string[] = dates.sort((a: string, b: string) => {
return new Date(b).getTime() - new Date(a).getTime();
});
blog.lastModified = new Date(sortedDates[0]);
}
return blog;
}

View File

@@ -2,6 +2,7 @@ import { createDirectusConnection } from "@/lib/directus";
import { print } from 'graphql';
import { formatDate } from "@/lib/dates";
import getAllPages from "@/graphql/pages/getAllPages.graphql";
import getPage from "@/graphql/pages/getPage.graphql";
export function dataToPage(pageRecord: any): WebPage {
let dates: string[] = [
@@ -285,6 +286,7 @@ export function dataToPage(pageRecord: any): WebPage {
}
let page: WebPage = {
type: "Webpage",
id: pageRecord["id"],
lastModified: lastModified,
url: pageRecord["url"],
@@ -320,3 +322,13 @@ export async function getAllWebpages(): Promise<WebPage[]> {
return pages;
}
export async function getWebpage(route: string): Promise<WebPage | null> {
const client = await createDirectusConnection();
const result = await client.query(print(getPage), {
date: formatDate(new Date(), "%Y-%M-%D"),
route: route
});
return dataToPage(result["Pages"][0]);
}

View File

@@ -1,6 +1,7 @@
import { createDirectusConnection } from "@/lib/directus";
import { print } from "graphql";
import getAlbums from '@/graphql/photos/getAlbums.graphql';
import getAlbumItem from '@/graphql/photos/getAlbum.graphql';
import { formatDate } from "@/lib/dates";
export async function getAllAlbums(settings: GlobalSettings): Promise<PhotoAlbum[]> {
@@ -21,6 +22,7 @@ export async function getAllAlbums(settings: GlobalSettings): Promise<PhotoAlbum
];
const album: PhotoAlbum = {
type: "PhotoAlbum",
title: albumRecord["title"],
description: albumRecord["description"],
url: albumRecord["url"],
@@ -78,3 +80,76 @@ export async function getAllAlbums(settings: GlobalSettings): Promise<PhotoAlbum
return albums;
}
export async function getAlbum(settings: GlobalSettings, route: string): Promise<PhotoAlbum> {
const client = await createDirectusConnection();
const result = await client.query(print(getAlbumItem), {
route: route
});
const albumRecord = result["Photo_Albums"][0];
let dates: string[] = [
settings.website.lastModified.toISOString(),
settings.photo.lastModified.toISOString(),
albumRecord["date_created"],
albumRecord["date_updated"],
albumRecord["thumbnail"]["created_on"],
];
const album: PhotoAlbum = {
type: "PhotoAlbum",
title: albumRecord["title"],
description: albumRecord["description"],
url: albumRecord["url"],
startDate: albumRecord["start_date"],
endDate: albumRecord["end_date"],
location: albumRecord["location"],
category: {
id: albumRecord["category"][0]["Photo_Categories_id"]["id"],
title: albumRecord["category"][0]["Photo_Categories_id"]["title"],
url: albumRecord["category"][0]["Photo_Categories_id"]["url"],
thumbnail: {
url: albumRecord["category"][0]["Photo_Categories_id"]["thumbnail"]["filename_disk"],
height: albumRecord["category"][0]["Photo_Categories_id"]["thumbnail"]["height"],
width: albumRecord["category"][0]["Photo_Categories_id"]["thumbnail"]["width"]
}
},
thumbnail: {
url: albumRecord["thumbnail"]["filename_download"],
height: albumRecord["thumbnail"]["height"],
width: albumRecord["thumbnail"]["width"]
},
photos: [],
lastModified: new Date()
};
albumRecord["photos"].forEach((photoRecord: any) => {
album.photos.push({
id: photoRecord["id"],
photo: {
url: photoRecord["photo"]["filename_disk"],
width: photoRecord["photo"]["width"],
height: photoRecord["photo"]["height"]
},
text: photoRecord["text"]
});
dates.push(photoRecord["date_created"]);
dates.push(photoRecord["date_updated"]);
dates.push(photoRecord["photo"]["created_on"]);
});
if (dates.filter(e => e !== null).length === 0) {
album.lastModified = new Date();
}
else {
const sortedDates: string[] = dates.sort((a: string, b: string) => {
return new Date(b).getTime() - new Date(a).getTime();
});
album.lastModified = new Date(sortedDates[0]);
}
return album;
}

View File

@@ -22,4 +22,4 @@ export async function getAllCategories(settings: GlobalSettings): Promise<PhotoA
});
return categories;
}
}

View File

@@ -0,0 +1,30 @@
import { createDirectusConnection } from "@/lib/directus";
import { print } from "graphql";
import getPhotos from '@/graphql/photos/getPhotos.graphql';
import md5 from "md5";
export async function getPhotoFromHash(albumUrl: string, hash: string): Promise<PhotoAlbumPhoto | null> {
const client = await createDirectusConnection();
const result = await client.query(print(getPhotos));
result["Photo_Albums"][0]["photos"].forEach((photo: any) => {
const hashObject = md5(JSON.stringify({
id: photo.id,
url: photo.photo.url,
width: photo.photo.width,
height: photo.photo.height
}));
if (hash.substring(hash.length - 10) === hash) {
return {
id: photo.id,
text: photo.text,
photo: {
url: photo.photo.url,
width: photo.photo.width,
height: photo.photo.height
}
}
}
});
}

View File

@@ -2,7 +2,7 @@ import { formatDate } from "@/lib/dates";
import { createDirectusConnection } from "@/lib/directus";
import { print } from "graphql";
import getProjects from '@/graphql/projects/getProjects.graphql';
import getProjectPost from '@/graphql/projects/getProject.graphql';
export async function getAllProjects(settings: GlobalSettings): Promise<ProjectPost[]> {
const client = await createDirectusConnection();
@@ -71,3 +71,67 @@ export async function getAllProjects(settings: GlobalSettings): Promise<ProjectP
return projects;
}
export async function getProject(settings: GlobalSettings, route: string): Promise<ProjectPost> {
const client = await createDirectusConnection();
const result = await client.query(print(getProjectPost), {
route: route
});
const projectRecord = result["Projects"][0];
let dates: string[] = [
settings.project.lastModified.toISOString(),
settings.website.lastModified.toISOString(),
projectRecord["date_created"],
projectRecord["date_updated"],
projectRecord["search_engine"][0]["date_created"],
projectRecord["search_engine"][0]["date_updated"],
projectRecord["search_engine"][0]["thumbnail"]["created_on"]
];
const project: ProjectPost = {
lastModified: new Date(),
title: projectRecord["title"],
content: projectRecord["content"],
date: projectRecord["date"],
url: projectRecord["url"],
searchEngine: {
title: projectRecord["search_engine"][0]["title"],
description: projectRecord["search_engine"][0]["description"],
allowCrawlers: projectRecord["search_engine"][0]["allow_crawler"],
canonical: projectRecord["search_engine"][0]["canonical"],
priority: projectRecord["search_engine"][0]["priority"],
thumbnail: {
url: projectRecord["search_engine"][0]["thumbnail"]["filename_disk"],
height: projectRecord["search_engine"][0]["thumbnail"]["height"],
width: projectRecord["search_engine"][0]["thumbnail"]["width"]
}
},
tags: []
};
projectRecord["tags"].forEach((tagRecord: any) => {
project["tags"].push({
text: tagRecord["Tags_id"]["text"],
code: tagRecord["Tags_id"]["code"],
color: tagRecord["Tags_id"]["color"]
});
dates.push(tagRecord["Tags_id"]["date_created"]);
dates.push(tagRecord["Tags_id"]["date_updated"]);
});
if (dates.filter(e => e !== null).length === 0) {
project.lastModified = new Date();
}
else {
const sortedDates: string[] = dates.sort((a: string, b: string) => {
return new Date(b).getTime() - new Date(a).getTime();
});
project.lastModified = new Date(sortedDates[0]);
}
return project;
}

View File

@@ -0,0 +1,39 @@
query getAllBlogs($route: String!) {
Blogs(sort: ["-date", "-date_created"], filter: { status: { _eq: "published" }, url: { _eq: $route } }) {
id,
date_created,
date_updated,
status,
title,
url,
date,
content,
tags {
Tags_id {
id,
date_created,
date_updated,
text,
code,
color
}
},
search_engine {
id,
date_created,
date_updated,
title,
description,
thumbnail {
id,
created_on,
filename_disk,
width,
height
},
canonical,
allow_crawler,
priority
}
}
}

View File

@@ -1,5 +1,5 @@
query getAllBlogs($date: String!) {
Blogs(sort: ["-date", "-date_created"], filter: { status: { _eq: "published" }, date: { _gte: $date } }) {
Blogs(sort: ["-date", "-date_created"], filter: { status: { _eq: "published" }, date: { _lte: $date } }) {
id,
date_created,
date_updated,

View File

@@ -0,0 +1,216 @@
query getAllPages($date: String!, $route: String!) {
Pages(filter: { status: { _eq: "published" }, url: { _eq: $route } }) {
id,
date_created,
date_updated,
status,
url,
search_engine {
id,
date_created,
date_updated,
title,
description,
thumbnail {
id,
created_on,
filename_disk,
width,
height
},
canonical,
allow_crawler,
priority
},
components {
id,
__typename,
item {
__typename,
...on Hero {
hero_id: id,
hero_created: date_created,
hero_updated: date_updated,
hero_title: title,
hero_text: subtext,
background_image {
id,
created_on,
filename_disk,
width,
height
}
hero_image: background_image {
id,
created_on,
filename_disk,
width,
height
}
background_image {
id,
created_on,
filename_disk,
width,
height
}
}
...on Text_With_Side_Image {
twsi_id: id,
twsi_created: date_created,
twsi_updated: date_updated,
twsi_title: title,
twsi_text: text,
image {
id,
created_on,
filename_disk,
width,
height
},
twsi_image_side: image_side
}
...on Wall_Of_Text {
wot_id: id,
wot_created: date_created,
wot_updated: date_updated,
wot_title: title,
wot_text: text
}
...on Frequently_Asked_Questions {
faq_id: id,
faq_created: date_created,
faq_updated: date_updated,
faq_title: title,
faq_text: text,
questions {
id,
date_created,
date_updated,
question,
answer
}
}
...on Upcoming_Events {
ue_id: id,
ue_created: date_created,
ue_updated: date_updated,
ue_title: title,
ue_text: text,
events(filter: { start_date: { _gte: $date } }) {
id,
date_created,
date_updated,
title,
description,
location,
map_location,
start_date,
end_date
}
}
...on Equipment_Table {
et_id: id,
et_created: date_created,
et_updated: date_updated,
et_title: title,
et_text: text,
items {
id,
date_created,
date_updated,
title,
text,
icon {
id,
created_on,
filename_disk,
width,
height
}
}
}
...on Review_List {
rl_id: id,
rl_created: date_created,
rl_updated: date_updated,
rl_title: title,
rl_text: text,
reviews(sort: ["date"], filter: { status: { _eq: "published" } }) {
id,
date_created,
date_updated,
name,
review,
date,
stars,
thumbnail {
id,
created_on,
filename_disk,
width,
height
}
}
}
...on Contact {
c_id: id,
c_created: date_created,
c_updated: date_updated,
c_title: title,
c_text: text,
methods {
id,
date_created,
date_updated,
title,
text,
icon {
id,
created_on,
filename_disk,
width,
height
},
color
}
}
...on Last_Blogs {
lb_id: id,
lb_created: date_created,
lb_updated: date_updated,
lb_title: title,
lb_read_more_button_text: read_more_button_text,
lb_amount: amount
}
...on Last_Projects {
lp_id: id,
lp_created: date_created,
lp_updated: date_updated,
lp_title: title,
lp_read_more_button_text: read_more_button_text,
lp_amount: amount
}
...on Last_Galleries {
lg_id: id,
lg_created: date_created,
lg_updated: date_updated,
lg_title: title,
lg_read_more_button_text: read_more_button_text,
lg_amount: amount
}
}
}
}
}

View File

@@ -0,0 +1,51 @@
query getAllAlbums($route: String!) {
Photo_Albums(sort: ["-start_date", "-date_created"], filter: { status: { _eq: "published" }, url: { _eq: $route }, category: { Photo_Categories_id: { status: { _eq: "published" } } } }) {
id,
date_created,
date_updated,
title,
description,
url,
thumbnail {
id,
created_on,
filename_download,
width,
height
},
start_date,
end_date,
location,
category {
Photo_Categories_id {
id,
status,
date_created,
date_updated,
title,
url,
thumbnail {
id,
created_on,
filename_download,
width,
height
}
}
},
photos(filter: { status: { _eq: "published" } }) {
id,
date_created,
date_updated,
photo {
id,
created_on,
filename_disk,
width,
height
},
text,
sort
}
}
}

View File

@@ -0,0 +1,51 @@
query getPhotos {
Photo_Albums(sort: ["-start_date", "-date_created"], filter: { status: { _eq: "published" }, url: { _eq: "/mirai-nexus-2026" }, category: { Photo_Categories_id: { status: { _eq: "published" } } } }) {
id,
date_created,
date_updated,
title,
description,
url,
thumbnail {
id,
created_on,
filename_download,
width,
height
},
start_date,
end_date,
location,
category {
Photo_Categories_id {
id,
status,
date_created,
date_updated,
title,
url,
thumbnail {
id,
created_on,
filename_download,
width,
height
}
}
},
photos(filter: { status: { _eq: "published" } }) {
id,
date_created,
date_updated,
photo {
id,
created_on,
filename_disk,
width,
height
},
text,
sort
}
}
}

View File

@@ -0,0 +1,39 @@
query getAllProjects($route: String!) {
Projects(sort: ["-date", "-date_created"], filter: { status: { _eq: "published" }, url: { _eq: $route } }) {
id,
date_created,
date_updated,
status,
title,
url,
date,
content,
tags {
Tags_id {
id,
date_created,
date_updated,
text,
code,
color
}
},
search_engine {
id,
date_created,
date_updated,
title,
description,
thumbnail {
id,
created_on,
filename_download,
width,
height
},
canonical,
allow_crawler,
priority
}
}
}

View File

@@ -1,5 +1,5 @@
query getAllProjects($date: String!) {
Projects(sort: ["-date", "-date_created"], filter: { status: { _eq: "published" }, date: { _gte: $date } }) {
Projects(sort: ["-date", "-date_created"], filter: { status: { _eq: "published" }, date: { _lte: $date } }) {
id,
date_created,
date_updated,

203
astro/src/lib/pages.ts Normal file
View File

@@ -0,0 +1,203 @@
import { getBlog } from "@/content/blogs/blogs";
import { getWebpage } from "@/content/pages/pages";
import { getAlbum } from "@/content/photos/albums";
import { getPhotoFromHash } from "@/content/photos/photos";
import { getProject } from "@/content/projects/projects";
export async function getPage(settings: GlobalSettings, route: string): Promise<PageType | null> {
// Blog Index
if (regexToRoute({ template: settings.blog.indexRouteTemplate, allowPagination: true }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.blog.indexRouteTemplate, allowPagination: true });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
return {
route: route,
pageType: "BlogIndex",
page: {
type: "BlogIndex",
pageNumber: params["page"] !== undefined ? Number(params["page"]) : 1
}
};
}
// Blog Post
else if (regexToRoute({ template: settings.blog.blogRouteTemplate, allowPagination: false }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.blog.blogRouteTemplate, allowPagination: false });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
const blog = await getBlog(settings, `/${params["R"]}`);
return {
route: route,
pageType: "BlogPost",
page: blog
};
}
// Project Index
else if (regexToRoute({ template: settings.project.indexRouteTemplate, allowPagination: true }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.project.indexRouteTemplate, allowPagination: true });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
return {
route: route,
pageType: "ProjectIndex",
page: null
};
}
// Project Post
else if (regexToRoute({ template: settings.project.projectRouteTemplate, allowPagination: false }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.project.projectRouteTemplate, allowPagination: false });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
const project = await getProject(settings, `/${params["R"]}`);
return {
route: route,
pageType: "ProjectPost",
page: project
};
}
// Photo Category Index
else if (regexToRoute({ template: settings.photo.categoryIndex.indexRouteTemplate, allowPagination: false }).regex.test(route)) {
return {
route: route,
pageType: "PhotoCategoryIndex",
page: {
type: "PhotoCategoryIndex"
}
};
}
// Photo Category / Album List
else if (regexToRoute({ template: settings.photo.category.routeTemplate, allowPagination: true }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.photo.category.routeTemplate, allowPagination: true });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
return {
route: route,
pageType: "PhotoCategory",
page: {
type: "PhotoCategory",
category: params["category"],
pageNumber: params["page"] !== undefined ? Number(params["page"]) : 1
}
};
}
// Photo Album
else if (regexToRoute({ template: settings.photo.album.routeTemplate, allowPagination: true }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.photo.album.routeTemplate, allowPagination: true });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
const photoAlbum = await getAlbum(settings, `/${params["R"]}`);
return {
route: route,
pageType: "PhotoAlbum",
page: photoAlbum
};
}
// Photograph
else if (regexToRoute({ template: settings.photo.photo.routeTemplate, allowPagination: false }).regex.test(route)) {
const { regex, keys } = regexToRoute({ template: settings.photo.photo.routeTemplate, allowPagination: false });
const match = route.match(regex);
const params: Record<string, string> = {};
if (!match) return null;
keys.forEach((key, i) => {
params[key] = match[i + 1];
});
console.log(params);
const photo = await getPhotoFromHash(`/${params["R"]}`, params["H"]);
if (photo === null) {}
return {
route: route,
pageType: "Photo",
page: {
type: "PhotoPage",
id: photo!.id,
photo: photo!.photo,
text: photo!.text
}
};
}
else if (regexToRoute({ template: "/", allowPagination: false }).regex.test(route) ||
regexToRoute({ template: "/%R", allowPagination: false }).regex.test(route)) {
const webpageContent = await getWebpage(route);
return {
route: route,
pageType: "Webpage",
page: webpageContent
};
}
else {
return null;
}
}
function regexToRoute(template: PageRegexMatchProps) {
const keys: string[] = [];
let pattern = template.template
.replaceAll("%Y", () => { keys.push("Y"); return "(\\d{4})"; })
.replaceAll("%M", () => { keys.push("M"); return "(\\d{2})"; })
.replaceAll("%D", () => { keys.push("D"); return "(\\d{2})"; })
.replaceAll("%R", () => { keys.push("R"); return "([^/]+)"; })
.replaceAll("%C", () => { keys.push("C"); return "([^/]+)"; })
.replaceAll("%H", () => { keys.push("H"); return "([^/]+)"; })
.replace(/\/+/g, "/");
if (template.allowPagination) {
keys.push("page");
pattern += "(?:\\/(\\d+))?";
}
return {
regex: new RegExp(`^${pattern}$`),
keys
};
}

View File

@@ -17,6 +17,15 @@ export async function getAllRoutesList(settings: GlobalSettings): Promise<string
if (settings.blog.enabled) {
const blogs = await getAllBlogs(settings);
for (let i = 0; i < Math.ceil(blogs.length / 6); i++) {
if (i !== 0) {
routes.push(`${settings.blog.indexRouteTemplate}/${i + 1}`);
}
else {
routes.push(settings.blog.indexRouteTemplate);
}
}
blogs.forEach((blog) => {
routes.push(getBlogRoute(settings.blog, blog));
});
@@ -24,6 +33,15 @@ export async function getAllRoutesList(settings: GlobalSettings): Promise<string
if (settings.project.enabled) {
const projects = await getAllProjects(settings);
for (let i = 0; i < Math.ceil(projects.length / 4); i++) {
if (i !== 0) {
routes.push(`${settings.project.indexRouteTemplate}/${i + 1}`);
}
else {
routes.push(settings.project.indexRouteTemplate);
}
}
projects.forEach((project) => {
routes.push(getProjectRoute(settings.project, project));
});
@@ -32,6 +50,8 @@ export async function getAllRoutesList(settings: GlobalSettings): Promise<string
const categories = await getAllCategories(settings);
const galleries = await getAllAlbums(settings);
routes.push(settings.photo.categoryIndex.indexRouteTemplate);
categories.forEach((category) => {
let albums = galleries.filter(g => g.category.id === category.id);
const pages = Math.ceil(albums.length / settings.photo.category.perPage);

View File

@@ -1,12 +1,14 @@
---
import { getAllWebpages } from "@/content/pages/pages";
import { getAllRoutesList } from "@/lib/routing";
import { getPage } from "@/lib/pages";
import { getSettings } from "@/content/settings/settings"
import WebpageLayout from "@/layouts/WebpageLayout.astro";
const settings = await getSettings();
const routes = await getAllRoutesList(settings);
console.log(routes);
const page = await getPage(settings, "/album/2026/mirai-nexus-2026/6c0e4453ab");
console.log(page);
---
<WebpageLayout>

View File

@@ -1,4 +1,7 @@
type BlogPost = {
type: "BlogPost";
id: string;
title: string;
url: string;
date: string;
@@ -10,3 +13,8 @@ type BlogPost = {
lastModified: Date;
}
type BlogIndex = {
type: "BlogIndex";
pageNumber: number;
}

View File

@@ -1,4 +1,6 @@
type WebPage = {
type: "Webpage";
id: string;
lastModified: Date;
@@ -19,3 +21,20 @@ type WebpageComponent =
ReviewListComponent |
TextWithImageComponent |
WallOfTextComponent;
type PageRegexMatchProps = {
template: string;
allowPagination: boolean;
}
type PageType = {
route: string;
pageType: "Webpage" | "BlogIndex" | "BlogPost" |
"ProjectIndex" | "ProjectPost" | "PhotoCategoryIndex" |
"PhotoCategory" | "PhotoAlbum" | "Photo";
page: WebPage | BlogPost | ProjectPost | BlogIndex |
ProjectIndex | PhotoCategoryIndex | PhotoCategory |
PhotoAlbum | PhotoPage | null;
}

View File

@@ -1,4 +1,6 @@
type PhotoAlbum = {
type: "PhotoAlbum";
title: string;
url: string;
description: string | null;
@@ -27,3 +29,9 @@ type PhotoAlbumPhoto = {
photo: PhotoProps;
text: string | null;
}
type PhotoCategory = {
type: "PhotoCategory";
category: string;
pageNumber: number;
}

View File

@@ -1,3 +1,3 @@
type PhotoCategory = {
type PhotoCategoryIndex = {
type: "PhotoCategoryIndex";
}

View File

@@ -1,3 +1,6 @@
type PhotoPhoto = {
type PhotoPage = {
type: "PhotoPage";
id: string;
photo: PhotoProps;
text: string | null;
}

View File

@@ -10,3 +10,8 @@ type ProjectPost = {
lastModified: Date;
}
type ProjectIndex = {
type: "ProjectIndex";
pageNumber: number;
}