diff --git a/website/.vitepress/blog.data.ts b/website/.vitepress/blog.data.ts new file mode 100644 index 0000000000..f6db8fc09f --- /dev/null +++ b/website/.vitepress/blog.data.ts @@ -0,0 +1,53 @@ +import { createContentLoader } from 'vitepress'; + +export interface Post { + title: string; + url: string; + date: { + time: number; + string: string; + }; + author: string; + tags: string[]; + excerpt?: string; +} + +declare const data: Post[]; +export { data }; + +// extractExcerpt renders the whole document first so that links which have +// `[ref]: url` style definitions outside of the excerpt still resolve. The +// rendered HTML is then cut at the `` marker leaving just the +// excerpt text. +function extractExcerpt(html: string): string | undefined { + const markerIndex = html.indexOf(''); + if (markerIndex === -1) return undefined; + return html + .slice(0, markerIndex) + .replace(/]*>[\s\S]*?<\/h1>/, '') + .replace(/]*\/?>/gi, '') + .trim(); +} + +export default createContentLoader('blog/*.md', { + render: true, + transform(raw) { + return raw + .filter(({ url }) => url !== '/blog/') + .map(({ frontmatter, html, url }) => { + const date = new Date(frontmatter.date); + return { + title: frontmatter.title, + url, + date: { + time: date.getTime(), + string: date.toISOString().slice(0, 10) + }, + author: frontmatter.author, + tags: frontmatter.tags ?? [], + excerpt: html ? extractExcerpt(html) : undefined + }; + }) + .sort((a, b) => b.date.time - a.date.time); + } +}); diff --git a/website/.vitepress/components/BlogPost.vue b/website/.vitepress/components/BlogPost.vue index b7a5007665..0ee8804a0a 100644 --- a/website/.vitepress/components/BlogPost.vue +++ b/website/.vitepress/components/BlogPost.vue @@ -20,7 +20,7 @@
-

{{ description }}

+