UNPKG

@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.

132 lines (124 loc) 5.06 kB
'use strict' const expandPath = require('@antora/expand-path-helper') const fsp = require('node:fs/promises') const os = require('node:os') const yaml = require('js-yaml') const PACKAGE_NAME = require('../package.json').name const ASSEMBLY_KEYS = [ 'rootLevel', 'insertStartPage', 'sectionMergeStrategy', 'linkReferenceStyle', 'dropExplicitXrefText', ] function loadConfig (playbook, configSource) { let resolvedConfigSource return ( configSource?.constructor === Object ? Promise.resolve(configSource) : fsp .access((resolvedConfigSource = expandPath(configSource ?? './antora-assembler.yml', { dot: playbook.dir }))) .then( () => true, () => false ) .then((exists) => { if (!exists) { let logger if (configSource && (logger = this?.getLogger?.(PACKAGE_NAME))) { const ctx = { file: { path: configSource } } logger.warn(ctx, 'Could not resolve config file; reverting to default settings') } return {} } return fsp .readFile(resolvedConfigSource) .then((data) => Object.assign(camelCaseKeys(yaml.load(data), ['asciidoc']), { file: resolvedConfigSource }) ) }) ).then((config) => { if (config.enabled === false) return config let asciidocAttrs if (!config.asciidoc) { config.asciidoc = { attributes: (asciidocAttrs = {}) } } else if (!(asciidocAttrs = config.asciidoc.attributes)) { config.asciidoc.attributes = asciidocAttrs = {} } if (!('revdate' in asciidocAttrs)) asciidocAttrs.revdate = getLocalDate() asciidocAttrs['page-partial'] = null const remapComponentVersionsKey = !('componentVersionFilter' in config) const componentVersionFilter = (config.componentVersionFilter ??= {}) if (remapComponentVersionsKey && 'componentVersions' in config) { componentVersionFilter.names = config.componentVersions delete config.componentVersions } if (componentVersionFilter.names == null) { componentVersionFilter.names = ['*'] } else if (typeof componentVersionFilter.names === 'string') { componentVersionFilter.names = componentVersionFilter.names.split(', ') } const remapAssemblyKeys = !('assembly' in config) const assembly = (config.assembly ??= {}) if (remapAssemblyKeys) { for (const key of ASSEMBLY_KEYS) { if (!(key in config)) continue assembly[key] = config[key] delete config[key] } } if (!('doctype' in assembly)) assembly.doctype = 'doctype' in asciidocAttrs ? asciidocAttrs.doctype : 'book' delete asciidocAttrs.doctype if (!('rootLevel' in assembly)) assembly.rootLevel = 0 if (!('insertStartPage' in assembly)) assembly.insertStartPage = true if (['discrete', 'fuse', 'enclose'].indexOf(assembly.sectionMergeStrategy) < 0) { assembly.sectionMergeStrategy = 'discrete' } if (['relative', 'root-relative', 'absolute'].indexOf(assembly.linkReferenceStyle) < 0) { assembly.linkReferenceStyle = 'absolute' } if (['always', 'if-redundant', 'never'].indexOf(assembly.dropExplicitXrefText) < 0) { assembly.dropExplicitXrefText = 'never' } const build = (config.build ??= {}) if (build.dir === '$' + '{playbook.output.dir}') { throw new Error('Not implemented') } build.dir &&= expandPath(build.dir, { dot: playbook.dir }) // used as cwd of command (and any scripts it requires) build.cwd = build.cwd == null ? playbook.dir : expandPath(build.cwd, { dot: playbook.dir }) if (!('clean' in build) && 'output' in playbook) build.clean = playbook.output.clean if (!('publish' in build)) build.publish = true if ('keepAggregateSource' in build) { build.keepSource = build.keepAggregateSource delete build.keepAggregateSource } if (!build.processLimit) { build.processLimit = 'processLimit' in build ? Infinity : Math.round(os.cpus().length * 0.5) } if ('stderr' in build) { if (build.stderr === 'log') { build.stderr = 'buffer' build.stderrSink = 'log' } else if (!['ignore', 'print'].includes(build.stderr)) { delete build.stderr } } return config }) } function camelCaseKeys (o, stopPaths = [], p = undefined) { if (Array.isArray(o)) return o.map((it) => camelCaseKeys(it, stopPaths, p)) if (o == null || o.constructor !== Object) return o const pathPrefix = p ? p + '.' : '' const accum = {} for (const [k, v] of Object.entries(o)) { const camelKey = k.charAt() + k.slice(1).replace(/_([a-z])/g, (_, l) => l.toUpperCase()) accum[camelKey] = ~stopPaths.indexOf(pathPrefix + camelKey) ? v : camelCaseKeys(v, stopPaths, pathPrefix + camelKey) } return accum } function getLocalDate (now = new Date()) { return new Date(now - now.getTimezoneOffset() * 60000).toISOString().split('T')[0] } module.exports = loadConfig