UNPKG

@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
'use strict' 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