@antora/atlas-extension
Version:
An Antora extension that manages references across discrete runs of Antora through the use of a site manifest.
86 lines (78 loc) • 3.49 kB
JavaScript
const { $id } = require('./schema')
function exportSiteManifest (contentCatalog, siteUrl, relativePath = 'site-manifest.json') {
const pagesByComponentVersion = contentCatalog
.getPages(({ pub, site }) => pub && !site)
.concat(contentCatalog.findBy({ family: 'alias' }).filter(({ pub }) => !pub.splat))
.reduce((accum, { asciidoc: { xreftext } = {}, title, pub, rel, src }) => {
const { component, version, family, module, relative } = src
const key = `${version}@${component}`
let alias
if (family === 'alias') {
;({ asciidoc: { xreftext } = {}, title } = rel)
alias = { ref: buildPageRef(rel.src, src), url: rel.pub.url }
}
const url = pub.url
if (xreftext === title) xreftext = undefined
const entry = { module: module === 'ROOT' ? undefined : module, path: relative, url, title, xreftext, alias }
;(accum[key] ??= []).push(entry)
return accum
}, {})
const manifestData = {
$id,
generated: currentDate().toJSON(),
url: siteUrl,
components: contentCatalog
.getComponentsSortedBy('name')
.filter(({ site }) => !site)
.reduce((componentsMap, { name: componentName, title, versions, latest: { version: latest } }) => {
const componentEntry = {
title,
latest,
versions: versions
.filter(({ site }) => !site)
.reduce((versionsMap, { version: versionName, prerelease, displayVersion, url }) => {
const pages = pagesByComponentVersion[`${versionName}@${componentName}`]
if (!pages) return versionsMap // skip version if is has no pages
pages.sort(comparePages)
return Object.assign(versionsMap, {
[versionName]: {
prerelease: prerelease == null ? undefined : true,
displayVersion: displayVersion === (versionName || 'default') ? undefined : displayVersion,
url: url ?? pages[0].url,
pages,
},
})
}, {}),
}
if (Object.keys(componentEntry.versions).length) componentsMap[componentName] = componentEntry
return componentsMap
}, {}),
}
return createSiteFile(relativePath, JSON.stringify(manifestData, null, 2) + '\n', 'application/json')
}
function createSiteFile (path, contents, mediaType) {
return {
contents: Buffer.from(contents),
mediaType,
out: { path },
path,
pub: { url: '/' + path, rootPath: '' },
src: { stem: path.slice(0, path.lastIndexOf('.')) },
}
}
function comparePages ({ module: moduleA = '', path: pathA }, { module: moduleB = '', path: pathB }) {
if (moduleA !== moduleB) return moduleA.localeCompare(moduleB)
pathA = pathA.slice(pathA.lastIndexOf('/') + 1) === 'index.adoc' ? pathA.slice(0, -10) : pathA
pathB = pathB.slice(pathB.lastIndexOf('/') + 1) === 'index.adoc' ? pathB.slice(0, -10) : pathB
return pathA.localeCompare(pathB)
}
function currentDate (now = new Date()) {
return new Date(now.getTime() - now.getTimezoneOffset() * 60000)
}
function buildPageRef ({ component, version, module, relative }, context) {
return component === context.component
? `${version === context.version ? '' : version + '@'}${module === context.module ? '' : module + ':'}${relative}`
: `${version || '_'}@${component}:${module === 'ROOT' ? '' : module}:${relative}`
}
module.exports = exportSiteManifest