mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Add types and don't show unlisted posts in HTML, feeds and sitemap. Fix JSON feed URLs.
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
export interface MdsvexPage {
|
||||||
|
readingTime: ReadingTime
|
||||||
|
flattenedHeadings: FlattenedHeading[]
|
||||||
|
headings: NestedHeading[]
|
||||||
|
[key: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ReadingTime {
|
||||||
|
text: string
|
||||||
|
minutes: number
|
||||||
|
time: number
|
||||||
|
words: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FlattenedHeading {
|
||||||
|
level: number
|
||||||
|
title: string
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NestedHeading {
|
||||||
|
level: number
|
||||||
|
title: string
|
||||||
|
id: string
|
||||||
|
children: NestedHeading[]
|
||||||
|
}
|
||||||
@@ -3,6 +3,6 @@ import { pages } from './posts'
|
|||||||
export async function load({ params }) {
|
export async function load({ params }) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pages
|
pages: pages.filter((page) => page.listed !== "false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,12 +4,11 @@
|
|||||||
import SvelteSeo from "svelte-seo";
|
import SvelteSeo from "svelte-seo";
|
||||||
|
|
||||||
import type { WithContext, Thing } from "schema-dts";
|
import type { WithContext, Thing } from "schema-dts";
|
||||||
interface Props {
|
import type { BlogPage } from "./posts";
|
||||||
data: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
let { data }: Props = $props();
|
const { data }: { data: { pages: BlogPage[] } } = $props();
|
||||||
const { pages } = data;
|
const { pages } = data;
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
const jsonLd = {
|
const jsonLd = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
@@ -23,15 +22,15 @@
|
|||||||
"@type": "ListItem",
|
"@type": "ListItem",
|
||||||
position: 1,
|
position: 1,
|
||||||
name: "Blog",
|
name: "Blog",
|
||||||
item: SITE_URL + "/blog",
|
item: `${SITE_URL}/blog`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
mainEntity: {
|
mainEntity: {
|
||||||
"@type": "Blog",
|
"@type": "Blog",
|
||||||
"@id": SITE_URL + "/blog",
|
"@id": `${SITE_URL}/blog`,
|
||||||
name: "Jade's Blog",
|
name: "Jade's Blog",
|
||||||
mainEntityOfPage: SITE_URL + "/blog",
|
mainEntityOfPage: `${SITE_URL}/blog`,
|
||||||
},
|
},
|
||||||
} as WithContext<Thing>;
|
} as WithContext<Thing>;
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { pages } from '../posts'
|
import { pages, type BlogPage } from '../posts'
|
||||||
|
|
||||||
import type Feed from '@json-feed-types/1_1'
|
import type Feed from '@json-feed-types/1_1'
|
||||||
import {
|
import {
|
||||||
@@ -23,9 +23,9 @@ export async function GET({ params, url}) {
|
|||||||
.filter((post) => {
|
.filter((post) => {
|
||||||
const date = new Date(post.date)
|
const date = new Date(post.date)
|
||||||
return (
|
return (
|
||||||
(!dateParts[0] || date.getFullYear() == dateParts[0]) &&
|
(!dateParts[0] || date.getFullYear() === dateParts[0]) &&
|
||||||
(!dateParts[1] || date.getMonth()+1 == dateParts[1]) &&
|
(!dateParts[1] || date.getMonth()+1 === dateParts[1]) &&
|
||||||
(!dateParts[2] || date.getDate() == dateParts[2])
|
(!dateParts[2] || date.getDate() === dateParts[2])
|
||||||
)
|
)
|
||||||
}) : pages;
|
}) : pages;
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -37,7 +37,7 @@ export async function GET({ params, url}) {
|
|||||||
|
|
||||||
const AUTHOR = "Jade Ellis"
|
const AUTHOR = "Jade Ellis"
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
async function getJsonFeed(selfUrl: string, pages: any[]): Promise<string> {
|
async function getJsonFeed(selfUrl: string, pages: BlogPage[]): Promise<string> {
|
||||||
|
|
||||||
const feed: Feed = {
|
const feed: Feed = {
|
||||||
version: 'https://jsonfeed.org/version/1.1',
|
version: 'https://jsonfeed.org/version/1.1',
|
||||||
@@ -51,14 +51,16 @@ async function getJsonFeed(selfUrl: string, pages: any[]): Promise<string> {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
for await (const post of pages) {
|
const shownPages = pages.filter((page) => page.listed !== "false")
|
||||||
|
|
||||||
|
for await (const post of shownPages) {
|
||||||
const title = post.title;
|
const title = post.title;
|
||||||
const pubDate = post.date
|
const pubDate = post.date
|
||||||
const postUrl = SITE_URL + "/blog/" + post.canonical
|
const postUrl = `${SITE_URL}/blog/${post.canonical}`
|
||||||
// const postHtml =
|
// const postHtml =
|
||||||
const summary = post.description;
|
const summary = post.description;
|
||||||
const item: typeof feed.items[number] = {
|
const item: typeof feed.items[number] = {
|
||||||
id: post.postUrl,
|
id: postUrl,
|
||||||
title,
|
title,
|
||||||
url: postUrl,
|
url: postUrl,
|
||||||
date_published: pubDate,
|
date_published: pubDate,
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import { browser } from '$app/environment'
|
|||||||
// import { format } from 'date-fns'
|
// import { format } from 'date-fns'
|
||||||
|
|
||||||
import slugify from 'slugify';
|
import slugify from 'slugify';
|
||||||
import { parse, format, relative } from "node:path";
|
import { parse, type ParsedPath } from "node:path";
|
||||||
|
import type { MdsvexPage } from '$lib/pageTypes';
|
||||||
|
|
||||||
// we require some server-side APIs to parse all metadata
|
// we require some server-side APIs to parse all metadata
|
||||||
if (browser) {
|
if (browser) {
|
||||||
throw new Error(`posts can only be imported server-side`)
|
throw new Error("posts can only be imported server-side")
|
||||||
}
|
}
|
||||||
// import { browser } from '$app/environment'
|
// import { browser } from '$app/environment'
|
||||||
// import { format } from 'date-fns'
|
// import { format } from 'date-fns'
|
||||||
@@ -66,7 +67,17 @@ if (browser) {
|
|||||||
// }))
|
// }))
|
||||||
const dateRegex = /^((?<year>\d{4})-(?<month>[0][1-9]|1[0-2])-(?<day>[0][1-9]|[1-2]\d|3[01]))\s*/
|
const dateRegex = /^((?<year>\d{4})-(?<month>[0][1-9]|1[0-2])-(?<day>[0][1-9]|[1-2]\d|3[01]))\s*/
|
||||||
|
|
||||||
export const pages = (await Promise.all(Object.entries(import.meta.glob('$notes/Blogs/*.md', { eager: true}))
|
export interface BlogPage extends MdsvexPage {
|
||||||
|
title: string
|
||||||
|
date: string
|
||||||
|
canonical: string
|
||||||
|
slug: string
|
||||||
|
description: string
|
||||||
|
filepath: ParsedPath
|
||||||
|
syndication?: string[]
|
||||||
|
listed?: string
|
||||||
|
}
|
||||||
|
export const pages: BlogPage[] = (await Promise.all(Object.entries(import.meta.glob('$notes/Blogs/*.md', { eager: true }))
|
||||||
.map(async ([filepath, post]) => {
|
.map(async ([filepath, post]) => {
|
||||||
const path = parse(filepath);
|
const path = parse(filepath);
|
||||||
const title = path.name.replace(dateRegex, "")
|
const title = path.name.replace(dateRegex, "")
|
||||||
@@ -79,14 +90,15 @@ export const pages = (await Promise.all(Object.entries(import.meta.glob('$notes/
|
|||||||
const datePath = date.replaceAll("-", "/")
|
const datePath = date.replaceAll("-", "/")
|
||||||
const slug = slugify(title, { lower: true })
|
const slug = slugify(title, { lower: true })
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
date,
|
date,
|
||||||
canonical: datePath + "/" + slug,
|
canonical: `${datePath}/${slug}`,
|
||||||
|
slug,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
...post.metadata,
|
...post.metadata,
|
||||||
|
|
||||||
slug,
|
|
||||||
filepath: path
|
filepath: path
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
@@ -99,8 +111,6 @@ export const pages = (await Promise.all(Object.entries(import.meta.glob('$notes/
|
|||||||
// next: allPosts[index - 1],
|
// next: allPosts[index - 1],
|
||||||
// previous: allPosts[index + 1]
|
// previous: allPosts[index + 1]
|
||||||
// }))
|
// }))
|
||||||
|
|
||||||
|
|
||||||
// function addTimezoneOffset(date) {
|
// function addTimezoneOffset(date) {
|
||||||
// const offsetInMilliseconds = new Date().getTimezoneOffset() * 60 * 1000
|
// const offsetInMilliseconds = new Date().getTimezoneOffset() * 60 * 1000
|
||||||
// return new Date(new Date(date).getTime() + offsetInMilliseconds)
|
// return new Date(new Date(date).getTime() + offsetInMilliseconds)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { pages } from '../posts'
|
import { pages, type BlogPage } from '../posts'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SITE_DEFAULT_DESCRIPTION,
|
SITE_DEFAULT_DESCRIPTION,
|
||||||
@@ -25,9 +25,9 @@ export async function GET({ url, params }) {
|
|||||||
.filter((post) => {
|
.filter((post) => {
|
||||||
const date = new Date(post.date)
|
const date = new Date(post.date)
|
||||||
return (
|
return (
|
||||||
(!dateParts[0] || date.getFullYear() == dateParts[0]) &&
|
(!dateParts[0] || date.getFullYear() === dateParts[0]) &&
|
||||||
(!dateParts[1] || date.getMonth()+1 == dateParts[1]) &&
|
(!dateParts[1] || date.getMonth()+1 === dateParts[1]) &&
|
||||||
(!dateParts[2] || date.getDate() == dateParts[2])
|
(!dateParts[2] || date.getDate() === dateParts[2])
|
||||||
)
|
)
|
||||||
}) : pages;
|
}) : pages;
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -40,7 +40,7 @@ export async function GET({ url, params }) {
|
|||||||
|
|
||||||
const AUTHOR = "Jade Ellis"
|
const AUTHOR = "Jade Ellis"
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
async function getRssXml(selfUrl: string, pages: any[]): Promise<string> {
|
async function getRssXml(selfUrl: string, pages: BlogPage[]): Promise<string> {
|
||||||
// const rssUrl = `${SITE_URL}/rss.xml`;
|
// const rssUrl = `${SITE_URL}/rss.xml`;
|
||||||
const root = create({ version: '1.0', encoding: 'utf-8' })
|
const root = create({ version: '1.0', encoding: 'utf-8' })
|
||||||
.ins('xml-stylesheet', `type="text/xsl" href="${rssStyle}"`)
|
.ins('xml-stylesheet', `type="text/xsl" href="${rssStyle}"`)
|
||||||
@@ -59,10 +59,12 @@ async function getRssXml(selfUrl: string, pages: any[]): Promise<string> {
|
|||||||
.up()
|
.up()
|
||||||
.ele('subtitle').txt(SITE_DEFAULT_DESCRIPTION).up()
|
.ele('subtitle').txt(SITE_DEFAULT_DESCRIPTION).up()
|
||||||
|
|
||||||
for await (const post of pages) {
|
const shownPages = pages.filter((page) => page.listed !== "false")
|
||||||
|
|
||||||
|
for await (const post of shownPages) {
|
||||||
const title = post.title;
|
const title = post.title;
|
||||||
const pubDate = post.date
|
const pubDate = post.date
|
||||||
const postUrl = SITE_URL + "/blog/" + post.canonical
|
const postUrl = `${SITE_URL}/blog/${post.canonical}`
|
||||||
// const postHtml =
|
// const postHtml =
|
||||||
const summary = post.description;
|
const summary = post.description;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export const GET: RequestHandler = async ({ params }) => {
|
|||||||
page: params.page,
|
page: params.page,
|
||||||
paramValues: {
|
paramValues: {
|
||||||
'/projects/[slug]': projects,
|
'/projects/[slug]': projects,
|
||||||
'/blog/[...date]/[slug]': blogPosts.map((post) => post.canonical)
|
'/blog/[...date]/[slug]': blogPosts.filter((page) => page.listed !== "false").map((post) => post.canonical)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user