-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate-feed.ts
116 lines (107 loc) · 2.91 KB
/
generate-feed.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*!
* generate-feed.ts v1.0.0
*
* https://github.com/equk/
*
* Copyright (c) 2023 B.Walden. All rights reserved.
*
* Licensed under the MIT License
*
* (LICENSE file should be included with script)
*/
import type { FeedOptions, Item } from 'feed'
import { Feed } from 'feed'
import MarkdownIt from 'markdown-it'
import sanitizeHtml from 'sanitize-html'
import fs from 'fs/promises'
import fg from 'fast-glob'
import matter from 'gray-matter'
import { siteConfig } from '~/config'
import createSlug from '~/lib/createSlug'
import slugDate from '~/lib/slugDate'
const year = +new Date().getFullYear()
const markdown = MarkdownIt({
html: true,
breaks: true,
linkify: true,
})
/*
* Main Feed Options
*/
const output_dir = './dist/'
const options: FeedOptions = {
title: siteConfig.title,
description: siteConfig.description,
id: siteConfig.url + '/',
link: siteConfig.url + '/',
language: 'en',
copyright: `copyright ${year} equk.co.uk all rights reserved`,
author: {
name: siteConfig.author.name,
link: siteConfig.url,
},
favicon: siteConfig.url + '/favicon.svg',
image: siteConfig.url + '/media/images/social.png',
feedLinks: {
atom: siteConfig.url + '/atom.xml',
},
}
/*
* Build Feed From Posts
*/
async function buildBlogFeed() {
// Start time for cli stats
const start = +new Date()
// Find markdown files in blog
const files = await fg('src/content/blog/*.md')
// Map over array of blog post files
const posts: any[] = await Promise.all(
files.map(async (file_in) => {
const source = await fs.readFile(file_in, 'utf-8')
const { data, content } = matter(source)
const date = new Date(data.date)
const slugLink = `/${slugDate(date.toISOString())}${createSlug(
data.title
)}/`
// Generate excerpt from content
const excerpt = sanitizeHtml(
markdown
.render(content)
.replace('src="/', `src="${siteConfig.url}/`)
.replace('href="/', `href="${siteConfig.url}/`)
.split(' ')
.slice(0, 80)
.join(' ')
)
// Return data + add extra fields
return {
...data,
date: new Date(data.date),
id: siteConfig.url + slugLink,
link: siteConfig.url + slugLink,
description: excerpt,
}
})
)
// Sort posts
posts.sort((a, b) => +new Date(b.date) - +new Date(a.date))
// Generate feed
const feed = new Feed(options)
// Add post items
posts.forEach((item: Item) => feed.addItem(item))
// Check output directory exists
await fs.access(output_dir)
// Write output file
await fs.writeFile(`${output_dir}atom.xml`, feed.atom1(), 'utf-8')
// Show cli stats
const end = +new Date()
console.log(`\n ${output_dir}atom.xml created (+${end - start}ms)\n`)
}
/*
* Run Main Function
*/
buildBlogFeed().catch((error) => {
console.error(error)
// quit if error (eg: if output_dir does not exist)
process.exit(1)
})