85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
|
import * as RSSFeed from 'feed'
|
||
|
import {Awaitable, collect, Collection, Inject, Maybe, Singleton} from '@extollo/lib'
|
||
|
import {AbstractBlog, BlogBackend, BlogPost, BlogPostFrontMatter, isBlogPostFrontMatter} from './AbstractBlog.service'
|
||
|
import {MarkMarkService} from '../MarkMark.service'
|
||
|
import {Link} from '../../../markmark/types'
|
||
|
import {MarkMarkRenderer} from '../../../markmark/markmark.renderer'
|
||
|
|
||
|
@Singleton()
|
||
|
export class MarkMarkBlog extends AbstractBlog<BlogPostFrontMatter> {
|
||
|
@Inject()
|
||
|
protected readonly mark!: MarkMarkService
|
||
|
|
||
|
protected getBackend(): BlogBackend<BlogPostFrontMatter> {
|
||
|
return {
|
||
|
routePrefix: '/links',
|
||
|
resourcePath: [],
|
||
|
author: {
|
||
|
name: 'Garrett Mills',
|
||
|
email: 'shout@garrettmills.dev',
|
||
|
link: 'https://garrettmills.dev/#about',
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected isValidFrontMatter(what: unknown): what is BlogPostFrontMatter {
|
||
|
return isBlogPostFrontMatter(what)
|
||
|
}
|
||
|
|
||
|
async getAllPosts(): Promise<Collection<BlogPost>> {
|
||
|
const mm = await this.mark.getLinks()
|
||
|
|
||
|
const links = mm.sections
|
||
|
.map(s => s.links)
|
||
|
.reduce((l, c): Link[] => [...c, ...l], [])
|
||
|
|
||
|
return collect(links)
|
||
|
.filter(l => l.date)
|
||
|
.sort((a, b) => b.date!.getTime() - a.date!.getTime())
|
||
|
.map(l => ({
|
||
|
title: l.title,
|
||
|
slug: l.hash,
|
||
|
date: l.date!,
|
||
|
tags: l.tags,
|
||
|
file: l.hash, // not used
|
||
|
markdown: (new MarkMarkRenderer()).render({
|
||
|
...mm,
|
||
|
sections: [{
|
||
|
links: [l],
|
||
|
}],
|
||
|
}, false),
|
||
|
}))
|
||
|
}
|
||
|
|
||
|
protected createFeed(lastUpdated: Maybe<Date>): Awaitable<RSSFeed.Feed> {
|
||
|
return new RSSFeed.Feed({
|
||
|
title: 'Garrett\'s Bookmarks',
|
||
|
description: 'Links to articles, projects, and sites I found interesting',
|
||
|
id: this.routing.getNamedPath('links').toRemote,
|
||
|
link: this.routing.getNamedPath('links').toRemote,
|
||
|
language: 'en',
|
||
|
image: this.routing.getAssetPath('favicon', 'apple-touch-icon.png').toRemote,
|
||
|
favicon: this.routing.getAssetPath('favicon', 'favicon.ico').toRemote,
|
||
|
copyright: `Copyright (c) ${(new Date).getFullYear()} Garrett Mills. See website for licensing details.`,
|
||
|
updated: lastUpdated,
|
||
|
generator: '',
|
||
|
feedLinks: {
|
||
|
json: this.routing.getNamedPath('links:json').toRemote,
|
||
|
atom: this.routing.getNamedPath('links:atom').toRemote,
|
||
|
rss: this.routing.getNamedPath('links:rss').toRemote,
|
||
|
},
|
||
|
author: {
|
||
|
name: 'Garrett Mills',
|
||
|
email: 'shout@garrettmills.dev',
|
||
|
link: 'https://garrettmills.dev/#about',
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
getUrl(post: BlogPost): string {
|
||
|
let prefix = this.getBackend().routePrefix
|
||
|
if ( !prefix.startsWith('/') ) prefix = `/${prefix}`
|
||
|
return `${prefix}/#link-${post.slug}`
|
||
|
}
|
||
|
}
|