feat(rss): hot introducing rss feature as seperate utility module after docs is built

This commit is contained in:
andatoshiki 2023-03-25 20:02:47 +08:00
parent f190716978
commit 148c74c957
4 changed files with 119 additions and 2 deletions

View File

@ -0,0 +1,50 @@
const fs = require('fs')
const path = require('path')
const { Feed } = require('feed')
const { load } = require('./posts.data')
const { resolveSiteData } = require('vitepress')
const url = `https://note.toshiki.dev`
genFeed()
async function genFeed() {
const siteData = await resolveSiteData('.')
const posts = await load(true)
const cwd = process.cwd()
const feed = new Feed({
title: siteData.title,
description: siteData.description,
id: url,
link: url,
language: siteData.lang,
image: `${url}/logos/logo-308px.png`,
favicon: `${url}/favicon.ico`,
copyright: siteData.themeConfig.name || '-',
})
posts.forEach((post) => {
const file = path.resolve(cwd, `dist/${post.href}`)
const rendered = fs.readFileSync(file, 'utf-8')
const content = rendered.match(
/<body>([\s\S]*)<\/body>/
)
feed.addItem({
title: post.title,
id: `${url}${post.href}`,
link: `${url}${post.href}`,
description: post.excerpt,
content: content[1],
author: [
{
name: post.data.author,
link: post.data.twitter
? `https://twitter.com/${post.data.twitter}`
: undefined
}
],
})
})
fs.writeFileSync(path.resolve(cwd, 'dist/feed.rss'), feed.rss2())
}

10
docs/.vitepress/utils/posts.data.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
export interface PostData {
title: string,
href: string,
create: number,
update: number,
tags?: string[],
cover?: string,
excerpt: string,
}
export declare const data: PostData[]

View File

@ -0,0 +1,56 @@
// from https://github.com/vuejs/blog
const fs = require('fs')
const path = require('path')
const matter = require('gray-matter')
const { createMarkdownRenderer } = require('vitepress')
const cwd = process.cwd()
module.exports = {
watch: path.relative(__dirname, cwd + '/docs/*.md').replace(/\\/g, '/'),
async load(asFeed = false) {
const md = await createMarkdownRenderer(cwd)
const postDir = path.join(cwd, 'docs')
return fs
.readdirSync(postDir)
.filter((file) => file.endsWith('.md'))
.map((file) => getPost(md, file, postDir, asFeed))
.sort((a, b) => b.create - a.create)
}
}
const cache = new Map()
function getPost(md, file, postDir, asFeed = false) {
const fullePath = path.join(postDir, file)
const timestamp = Math.floor(fs.statSync(fullePath).mtimeMs)
const cached = cache.get(fullePath)
if (cached && timestamp === cached.timestamp) {
return cached.post
}
const src = fs.readFileSync(fullePath, 'utf-8')
const { data, excerpt } = matter(src, { excerpt: true })
const post = {
title: data.title,
href: `${file.replace(/\.md$/, '.html')}`,
create: +new Date(data.date) || timestamp,
update: timestamp,
tags: data.tags,
cover: data.cover,
excerpt: md.render(excerpt)
}
if (asFeed) {
// only attach these when building the RSS feed to avoid bloating the
// client bundle size
post.data = data
}
cache.set(fullePath, {
timestamp,
post
})
return post
}

View File

@ -9,14 +9,15 @@
"private": true, "private": true,
"scripts": { "scripts": {
"docs:dev": "vitepress dev docs", "docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs", "docs:build": "vitepress build docs && node docs/.vitepress/utils/genFeed.js",
"docs:preview": "vitepress preview docs", "docs:preview": "vitepress preview docs",
"docs:host": "vitepress dev docs --host", "docs:host": "vitepress dev docs --host",
"rm:dist": "rm -rf /docs/.vitepress/dist", "rm:dist": "rm -rf /docs/.vitepress/dist",
"rm:cache": "rm -rf /docs/.vitepress/cache", "rm:cache": "rm -rf /docs/.vitepress/cache",
"prepare": "husky install", "prepare": "husky install",
"lint": "prettier --write .", "lint": "prettier --write .",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0" "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"feed": "node docs/.vitepress/utils/genFeed.js"
}, },
"lint-staged": { "lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [ "*.{js,jsx,vue,ts,tsx}": [