@antora/assembler
Version:
A JavaScript library that merges AsciiDoc content from multiple pages in an Antora site into assembly files and delegates to an exporter to convert those files to another format, such as PDF.
115 lines (104 loc) • 4.89 kB
JavaScript
function configure (context, ...args) {
internalConfigure.apply(context, args)
}
function internalConfigure (converter, config = {}, providers = {}) {
this.once('componentsRegistered', ({ contentCatalog, assemblerProfiles }) => {
if (assemblerProfiles) return
this.updateVariables({ assemblerProfiles: getAssemblerProfiles(contentCatalog) })
})
this.once('beforeProcess', enableKeepSource)
this.once('navigationBuilt', async ({ playbook, contentCatalog }) => {
const { assembleContent = require('./assemble-content'), ...assembleContentConfig } = providers
if (assembleContentConfig.configSource?.constructor === Object) {
await assembleContent.call(this, playbook, contentCatalog, converter, assembleContentConfig)
} else {
const singleConfig = !('configFiles' in config)
const configFiles = singleConfig ? config.configFile : config.configFiles
for (const configSource of Array.isArray(configFiles) ? configFiles : [configFiles]) {
const assembleContentConfigWithConfigSource = Object.assign({}, assembleContentConfig, { configSource })
await assembleContent.call(this, playbook, contentCatalog, converter, assembleContentConfigWithConfigSource)
if (singleConfig) break
}
}
})
}
function enableKeepSource ({ siteAsciiDocConfig }) {
if (siteAsciiDocConfig.keepSource instanceof Boolean) return
siteAsciiDocConfig.keepSource = Object.assign(new Boolean(true), { oldValue: siteAsciiDocConfig.keepSource })
this.once('navigationBuilt', restoreKeepSource)
}
function restoreKeepSource ({ siteAsciiDocConfig, contentCatalog }) {
if (!(siteAsciiDocConfig.keepSource instanceof Boolean)) return
if ((siteAsciiDocConfig.keepSource = siteAsciiDocConfig.keepSource.oldValue)) return
contentCatalog.getPages((page) => delete page.src.contents)
}
function getAssemblerProfiles (contentCatalog, assemblerProfiles = new Map()) {
contentCatalog.getComponents().forEach((component) => {
component.versions.forEach((componentVersion) => {
const source =
componentVersion.nav?.origin ??
[...(componentVersion.origins ?? [])].find((it) => it.descriptor?.ext?.assembler)
const assemblerConfig = getAssemblerConfigFromDescriptor(source?.descriptor)
if (!assemblerConfig) return
const componentVersionRef = `${componentVersion.version}@${componentVersion.name}`
const filesByPath = componentVersion.files.reduce((accum, it) => accum.set(it.path, it), new Map())
const componentVersionProfiles = assemblerConfig.reduce((accum, entry) => {
const data = {}
const profile = entry.profile ?? undefined
if (accum.has(profile)) return accum
const nav = entry.nav
Object.entries(entry).forEach(([key, val]) => {
if (key === 'profile' || key === 'nav') return
const camelKey = key.toLowerCase().replace(/[_-]([a-z0-9])/g, (_, l, idx) => (idx ? l.toUpperCase() : l))
data[camelKey] = val
})
if (nav) {
data.navFiles = (nav.length ? [...new Set(nav)] : nav).reduce((navFiles, path_) => {
const navFile = filesByPath.get(path_)
if (navFile) {
navFiles.push(initNavFile(navFile, component.name, componentVersion.version, navFiles.length))
} else {
;(data.messages ??= []).push([
'warn',
{ source },
`Could not resolve nav file for ${profile || '<default>'} profile in ${componentVersionRef}: ${path_}`,
])
}
return navFiles
}, [])
} else if (!Object.keys(data).length) {
return accum
}
return accum.set(profile, data)
}, new Map())
assemblerProfiles.set(componentVersionRef, componentVersionProfiles)
})
})
return assemblerProfiles
}
function getAssemblerConfigFromDescriptor (descriptor = {}) {
const assemblerConfig = descriptor.ext?.assembler
if (!assemblerConfig) return
if (!Array.isArray(assemblerConfig)) return [assemblerConfig]
if (assemblerConfig.length) return assemblerConfig
}
function initNavFile (file, component, version, index) {
const src = Object.assign({}, file.src, { component, version, module: 'ROOT', family: 'nav' })
const filePathSegments = file.path.split('/')
let relativeStartIdx = 0
if (filePathSegments[0] === 'modules') {
relativeStartIdx += 1
if (filePathSegments.length > 2) {
relativeStartIdx += 1
src.module = filePathSegments[1]
if (filePathSegments.length > 3 && filePathSegments[2] === 'partials') {
relativeStartIdx += 1
src.family = 'partial'
}
}
}
src.relative = filePathSegments.slice(relativeStartIdx).join('/')
return Object.assign(new file.constructor(file), { nav: { index }, src })
}
module.exports = configure