Skip to content

Commit cd2831f

Browse files
committed
feat: Add dev server support to the RSS feed plugin, refactor content extraction logic, and update dependency lock files.
1 parent ff310b2 commit cd2831f

4 files changed

Lines changed: 4397 additions & 818 deletions

File tree

.vuepress/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default defineUserConfig({
2626
rssFeedPlugin({
2727
username: 'lcomplete',
2828
hostname: 'https://tech.codelc.com',
29-
selector: '.content__default',
29+
selector: '#content',
3030
count: 50,
3131
filter: (page) => /^docs/.test(page.filePathRelative || '') && page.frontmatter.title
3232
})

.vuepress/plugins/rss-feed/index.js

Lines changed: 121 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,90 @@ const resolveOutDir = (app) => {
1818
return app.options?.dest || app.dir?.dest || process.cwd()
1919
}
2020

21+
const generateRSS = (app, options) => {
22+
const { filter, hostname, count, selector, language, username } = options
23+
const { pages } = app
24+
const outDir = resolveOutDir(app)
25+
const siteData = resolveSiteData(app)
26+
27+
const feed = new RSS({
28+
title: siteData.title,
29+
description: siteData.description,
30+
feed_url: `${hostname}/rss.xml`,
31+
site_url: hostname,
32+
copyright: `${username} ${new Date().getFullYear()}`,
33+
language
34+
})
35+
36+
pages
37+
.filter(filter)
38+
.map((page) => ({
39+
...page,
40+
date: new Date(page.frontmatter.date || '')
41+
}))
42+
.sort((a, b) => b.date - a.date)
43+
.slice(0, count)
44+
.map((page) => ({
45+
title: page.frontmatter.title,
46+
description: page.frontmatter.description,
47+
url: `${hostname}${page.path}`,
48+
date: new Date(page.frontmatter.date),
49+
custom_elements: [
50+
{
51+
'content:encoded': {
52+
_cdata: (() => {
53+
let htmlContent;
54+
if (app.env?.isBuild) {
55+
const outFilePath = path.join(
56+
outDir,
57+
page.path.replace(/\/$/, '/index.html').replace(/[^\.html]$/, '.html')
58+
)
59+
if (fs.existsSync(decodeURIComponent(outFilePath))) {
60+
htmlContent = fs.readFileSync(decodeURIComponent(outFilePath), 'utf8')
61+
const $ = load(htmlContent, { decodeEntities: false })
62+
$('.header-anchor').remove()
63+
$('h1').eq(0).remove()
64+
$('.sr-only').remove()
65+
$('a svg').remove()
66+
$(selector)
67+
.find('img')
68+
.each(function () {
69+
const src = $(this).attr('src')
70+
if (!/^(https?:)?\/\//.test(src)) {
71+
$(this).attr('src', hostname + src)
72+
}
73+
})
74+
return $(selector).html() || ''
75+
}
76+
}
77+
78+
htmlContent = page.contentRendered || page.content || ''
79+
if (!htmlContent) return ''
80+
81+
const $ = load(`<div id="rss-wrapper">${htmlContent}</div>`, { decodeEntities: false })
82+
$('.header-anchor').remove()
83+
$('h1').eq(0).remove()
84+
$('.sr-only').remove()
85+
$('a svg').remove()
86+
$('#rss-wrapper')
87+
.find('img')
88+
.each(function () {
89+
const src = $(this).attr('src')
90+
if (!/^(https?:)?\/\//.test(src)) {
91+
$(this).attr('src', hostname + src)
92+
}
93+
})
94+
return $('#rss-wrapper').html() || ''
95+
})()
96+
}
97+
}
98+
]
99+
}))
100+
.forEach((page) => feed.item(page))
101+
102+
return feed.xml({ indent: true })
103+
}
104+
21105
const rssFeedPlugin = (
22106
{
23107
filter = () => true,
@@ -27,77 +111,46 @@ const rssFeedPlugin = (
27111
language = 'zh-CN',
28112
username = ''
29113
} = {}
30-
) => ({
31-
name: 'rss-feed',
32-
async onGenerated(app) {
33-
if (!app.env?.isProd) {
34-
return
35-
}
114+
) => {
115+
const options = { filter, hostname, count, selector, language, username };
36116

37-
logger.wait('Generate rss.xml...')
38-
39-
const { pages } = app
40-
const outDir = resolveOutDir(app)
41-
const siteData = resolveSiteData(app)
42-
43-
const feed = new RSS({
44-
title: siteData.title,
45-
description: siteData.description,
46-
feed_url: `${hostname}/rss.xml`,
47-
site_url: hostname,
48-
copyright: `${username} ${new Date().getFullYear()}`,
49-
language
50-
})
51-
52-
pages
53-
.filter(filter)
54-
.map((page) => ({
55-
...page,
56-
date: new Date(page.frontmatter.date || '')
57-
}))
58-
.sort((a, b) => b.date - a.date)
59-
.slice(0, count)
60-
.map((page) => ({
61-
title: page.frontmatter.title,
62-
description: page.frontmatter.description,
63-
url: `${hostname}${page.path}`,
64-
date: new Date(page.frontmatter.date),
65-
custom_elements: [
66-
{
67-
'content:encoded': {
68-
_cdata: (() => {
69-
const outFilePath = path.join(
70-
outDir,
71-
page.path.replace(/\/$/, '/index.html').replace(/[^\.html]$/, '.html')
72-
)
73-
const htmlContent = fs.readFileSync(decodeURIComponent(outFilePath), 'utf8')
74-
const $ = load(htmlContent, { decodeEntities: false })
75-
$('.header-anchor').remove()
76-
$('h1').eq(0).remove()
77-
$('.sr-only').remove()
78-
$('a svg').remove()
79-
$(selector)
80-
.find('img')
81-
.each(function () {
82-
const src = $(this).attr('src')
83-
if (!/^(https?:)?\/\//.test(src)) {
84-
$(this).attr('src', hostname + src)
85-
}
86-
})
87-
return $(selector).html()
88-
})()
89-
}
117+
return {
118+
name: 'rss-feed',
119+
extendsBundlerOptions: (bundlerOptions, app) => {
120+
if (app.options.bundler.name === '@vuepress/bundler-vite') {
121+
bundlerOptions.viteOptions = bundlerOptions.viteOptions || {}
122+
bundlerOptions.viteOptions.plugins = bundlerOptions.viteOptions.plugins || []
123+
bundlerOptions.viteOptions.plugins.push({
124+
name: 'vite-plugin-rss-feed',
125+
configureServer(server) {
126+
server.middlewares.use((req, res, next) => {
127+
if (req.url === '/rss.xml') {
128+
res.setHeader('Content-Type', 'application/rss+xml; charset=utf-8')
129+
res.end(generateRSS(app, options))
130+
return
131+
}
132+
next()
133+
})
90134
}
91-
]
92-
}))
93-
.forEach((page) => feed.item(page))
94-
95-
fs.writeFile(path.join(outDir, 'rss.xml'), feed.xml({ indent: true }), (error) => {
96-
if (error) {
97-
console.error(error)
135+
})
136+
}
137+
},
138+
async onGenerated(app) {
139+
if (!app.env?.isBuild) {
140+
return
98141
}
99-
})
142+
143+
logger.info('Generate rss.xml...')
144+
const xml = generateRSS(app, options)
145+
const outDir = resolveOutDir(app)
146+
147+
fs.writeFile(path.join(outDir, 'rss.xml'), xml, (error) => {
148+
if (error) {
149+
console.error(error)
150+
}
151+
})
152+
}
100153
}
101-
})
154+
}
102155

103156
export default rssFeedPlugin

0 commit comments

Comments
 (0)