mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig.space.git
synced 2026-04-19 06:08:44 +00:00
Paginate feed
This commit is contained in:
@@ -11,19 +11,122 @@ const json2xmlOpts = {
|
|||||||
cdataPropName: '__cdata',
|
cdataPropName: '__cdata',
|
||||||
indentBy: ' '
|
indentBy: ' '
|
||||||
}
|
}
|
||||||
const builder = new XMLBuilder(json2xmlOpts)
|
|
||||||
|
|
||||||
// Load and adapt feed
|
const PAGE_SIZE = 21
|
||||||
const outputXML = builder.build(feed)
|
|
||||||
const validation = XMLValidator.validate(outputXML)
|
function writePage(feedJson, itemsSlice, pageIndex, totalPages) {
|
||||||
if (validation) {
|
const builder = new XMLBuilder(json2xmlOpts)
|
||||||
write(
|
const feedCopy = JSON.parse(JSON.stringify(feedJson))
|
||||||
'dist/feed.xml',
|
|
||||||
xmlFormat(outputXML, {
|
// Ensure channel.item is the page slice
|
||||||
indentation: json2xmlOpts.indentBy,
|
feedCopy.rss = feedCopy.rss || {}
|
||||||
collapseContent: true
|
feedCopy.rss.channel = feedCopy.rss.channel || {}
|
||||||
})
|
feedCopy.rss.channel.item = itemsSlice
|
||||||
)
|
|
||||||
} else {
|
// Build atom links: adapt self, add prev/next where appropriate
|
||||||
console.error(validation.err)
|
const origAtom = (feedJson.rss && feedJson.rss.channel && feedJson.rss.channel['atom:link']) || []
|
||||||
|
const origSelf = Array.isArray(origAtom)
|
||||||
|
? (origAtom.find(l => l.__attr && l.__attr.rel === 'self') || {}).__attr
|
||||||
|
: (origAtom && origAtom.__attr) || {}
|
||||||
|
const originalHref = (origSelf && origSelf.href) || ''
|
||||||
|
const base = originalHref.replace(/\/feed(?:-page-\d+)?\.xml$/, '')
|
||||||
|
|
||||||
|
const pageNumber = pageIndex + 1
|
||||||
|
const selfHref = pageIndex === 0 ? `${base}/feed.xml` : `${base}/feed-page-${pageNumber}.xml`
|
||||||
|
|
||||||
|
const newAtom = []
|
||||||
|
newAtom.push({ __attr: { href: selfHref, rel: 'self', type: 'application/rss+xml' } })
|
||||||
|
// preserve hub if present
|
||||||
|
const hub = Array.isArray(origAtom) && origAtom.find(l => l.__attr && l.__attr.rel === 'hub')
|
||||||
|
if (hub) newAtom.push(hub)
|
||||||
|
|
||||||
|
if (pageIndex > 0) {
|
||||||
|
const prevHref = pageIndex === 1 ? `${base}/feed.xml` : `${base}/feed-page-${pageIndex}.xml`
|
||||||
|
newAtom.push({ __attr: { href: prevHref, rel: 'prev', type: 'application/rss+xml' } })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageIndex < totalPages - 1) {
|
||||||
|
const nextHref = `${base}/feed-page-${pageNumber + 1}.xml`
|
||||||
|
newAtom.push({ __attr: { href: nextHref, rel: 'next', type: 'application/rss+xml' } })
|
||||||
|
}
|
||||||
|
|
||||||
|
feedCopy.rss.channel['atom:link'] = newAtom
|
||||||
|
|
||||||
|
const outputXML = builder.build(feedCopy)
|
||||||
|
const validation = XMLValidator.validate(outputXML)
|
||||||
|
if (validation) {
|
||||||
|
const filename = pageIndex === 0 ? 'dist/feed.xml' : `dist/feed-page-${pageNumber}.xml`
|
||||||
|
write(
|
||||||
|
filename,
|
||||||
|
xmlFormat(outputXML, {
|
||||||
|
indentation: json2xmlOpts.indentBy,
|
||||||
|
collapseContent: true
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return filename
|
||||||
|
} else {
|
||||||
|
console.error('XML validation error:', validation.err)
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main: split items and write pages
|
||||||
|
const items = (feed.rss && feed.rss.channel && feed.rss.channel.item) || []
|
||||||
|
const totalPages = Math.max(1, Math.ceil(items.length / PAGE_SIZE))
|
||||||
|
const written = []
|
||||||
|
for (let i = 0; i < totalPages; i++) {
|
||||||
|
const start = i * PAGE_SIZE
|
||||||
|
const slice = items.slice(start, start + PAGE_SIZE)
|
||||||
|
const out = writePage(feed, slice, i, totalPages)
|
||||||
|
if (out) written.push(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (written.length) {
|
||||||
|
console.log('Wrote paginated feeds:', written.join(', '))
|
||||||
|
} else {
|
||||||
|
console.error('No feed files written')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additionally write a full archive feed with all items
|
||||||
|
function writeFullFeed(feedJson, allItems) {
|
||||||
|
const builder = new XMLBuilder(json2xmlOpts)
|
||||||
|
const feedCopy = JSON.parse(JSON.stringify(feedJson))
|
||||||
|
|
||||||
|
feedCopy.rss = feedCopy.rss || {}
|
||||||
|
feedCopy.rss.channel = feedCopy.rss.channel || {}
|
||||||
|
feedCopy.rss.channel.item = allItems
|
||||||
|
|
||||||
|
// preserve and adapt atom links
|
||||||
|
const origAtom = (feedJson.rss && feedJson.rss.channel && feedJson.rss.channel['atom:link']) || []
|
||||||
|
const origSelf = Array.isArray(origAtom)
|
||||||
|
? (origAtom.find(l => l.__attr && l.__attr.rel === 'self') || {}).__attr
|
||||||
|
: (origAtom && origAtom.__attr) || {}
|
||||||
|
const originalHref = (origSelf && origSelf.href) || ''
|
||||||
|
const base = originalHref.replace(/\/feed(?:-page-\d+)?\.xml$/, '')
|
||||||
|
|
||||||
|
const newAtom = []
|
||||||
|
newAtom.push({ __attr: { href: `${base}/feed-all.xml`, rel: 'self', type: 'application/rss+xml' } })
|
||||||
|
const hub = Array.isArray(origAtom) && origAtom.find(l => l.__attr && l.__attr.rel === 'hub')
|
||||||
|
if (hub) newAtom.push(hub)
|
||||||
|
feedCopy.rss.channel['atom:link'] = newAtom
|
||||||
|
|
||||||
|
const outputXML = builder.build(feedCopy)
|
||||||
|
const validation = XMLValidator.validate(outputXML)
|
||||||
|
if (validation) {
|
||||||
|
const filename = 'dist/feed-all.xml'
|
||||||
|
write(
|
||||||
|
filename,
|
||||||
|
xmlFormat(outputXML, {
|
||||||
|
indentation: json2xmlOpts.indentBy,
|
||||||
|
collapseContent: true
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return filename
|
||||||
|
} else {
|
||||||
|
console.error('XML validation error (feed-all):', validation.err)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const allOut = writeFullFeed(feed, items)
|
||||||
|
if (allOut) console.log('Wrote full archive feed:', allOut)
|
||||||
|
|||||||
Reference in New Issue
Block a user