diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f2cfaae12f9fe0bc563747be5e45f55df9a31699..3e444f2d1ceb04d5f04e8ae9732f6ff98055da20 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -10,6 +10,7 @@ For a detailed view of what's changed, refer to the {url-repo}/commits[commit hi * add `build.stderr` key to Assembler config to control stderr lines emitted by command (`ignore`, `print`, `log`) (#112) * route stderr lines from command to Antora log if value of `build.stderr` key is `log` (#112) +* introduce `embedReferenceStyle` property on exporter's converter object to control how image targets are rewritten (when embedded or bundled) (#100) === Changed diff --git a/docs/assembler/modules/ROOT/pages/custom-exporter-extension.adoc b/docs/assembler/modules/ROOT/pages/custom-exporter-extension.adoc index 39841464d56ff0591a91487521463e479c213b69..d2788429d03e5bfd81bb12d08e6e11b8077d96a8 100644 --- a/docs/assembler/modules/ROOT/pages/custom-exporter-extension.adoc +++ b/docs/assembler/modules/ROOT/pages/custom-exporter-extension.adoc @@ -25,6 +25,9 @@ backend:: The target backend; the backend that will be set during conversion (e. (optional, default: the file extension without the leading dot) extname:: The file extension of the target format (e.g., `.epub`). mediaType:: The MIME type of the target format (e.g., `application/epub+zip`). +embedReferenceStyle:: Controls whether images are rewritten relative to the export file (`relative`) or the output directory (`output-relative`). +The `docdir` attribute passed to the convert function is set accordingly. +(optional, default: `relative`) loggerName:: The name of the Antora logger to use when logging messages captured from stderr of the command (e.g., `@antora/epub-extension`). (optional, default: `@antora/assembler`) diff --git a/packages/assembler/lib/assemble-content.js b/packages/assembler/lib/assemble-content.js index 6aeddbe39880149fe7684b47486d08f5216d9488..2dca8ec85f51b2bd4f29ed0dcbd0c9a147c66f37 100644 --- a/packages/assembler/lib/assemble-content.js +++ b/packages/assembler/lib/assemble-content.js @@ -31,10 +31,12 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou convert = converter, extname: targetExtname = '', backend: targetBackend = targetExtname.slice(1), + embedReferenceStyle = 'relative', mediaType: targetMediaType, loggerName = PACKAGE_NAME, } = converter ?? {} const { assembly: assemblyConfig, build: buildConfig } = assemblerConfig + assemblyConfig.embedReferenceStyle = embedReferenceStyle const { profile = targetBackend } = assemblyConfig const intrinsicAttributes = { 'loader-assembler': '' } buildConfig.cwd ??= process.cwd() @@ -63,7 +65,8 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou return new PromiseQueue({ concurrency: buildConfig.processLimit }) .add( assemblyFiles.map((doc) => async () => { - const convertAttributes = prepareConvertAttributes(doc, targetExtname, buildConfig) + const relativeToOutput = embedReferenceStyle === 'output-relative' + const convertAttributes = prepareConvertAttributes(doc, targetExtname, relativeToOutput, buildConfig) if (buildConfig.mkdirs) await fsp.mkdir(convertAttributes.outdir, { recursive: true, force: true }) return boundConvert(doc, convertAttributes, buildConfig).then((result) => { const fileOrContents = resolveFileOrContents.call(context, result, convertAttributes, buildConfig, loggerName) @@ -151,7 +154,7 @@ function createResolveAssemblyModel (context, contentCatalog, common, intrinsicA } } -function prepareConvertAttributes (doc, targetExtname, buildConfig) { +function prepareConvertAttributes (doc, targetExtname, relativeToOutput, buildConfig) { const { asciidoc: { attributes: docAttributes } = { attributes: {} }, extname: docfilesuffix, @@ -161,7 +164,8 @@ function prepareConvertAttributes (doc, targetExtname, buildConfig) { const { cwd = process.cwd(), dir = cwd } = buildConfig const docname = family + '$' + relative.slice(0, relative.length - docfilesuffix.length) const docfile = ospath.join(dir, reldocfile) - const docdir = dir + const outdir = ospath.dirname(docfile) + const docdir = relativeToOutput ? dir : outdir const imagesdir = '' const outfile = docfile.slice(0, docfile.length - docfilesuffix.length) + targetExtname const attributes = Object.assign({}, docAttributes, { @@ -170,7 +174,7 @@ function prepareConvertAttributes (doc, targetExtname, buildConfig) { docfilesuffix, 'docname@': docname, imagesdir, - outdir: ospath.dirname(docfile), + outdir, outfile, outfilesuffix: targetExtname, toArgs (optionFlag, command) { diff --git a/packages/assembler/lib/produce-assembly-file.js b/packages/assembler/lib/produce-assembly-file.js index 9a831d3b4b0f8974e8c57c82af0e35358587db7f..e34a0e5d0871e4df6d8b862a1ac0a560d90e576b 100644 --- a/packages/assembler/lib/produce-assembly-file.js +++ b/packages/assembler/lib/produce-assembly-file.js @@ -119,10 +119,12 @@ function mergeAsciiDoc ( const atDocumentRoot = !buffer.inBody const atBookRoot = atDocumentRoot && !level && assemblyModel.doctype === 'book' && (supportsParts = true) const hasItems = items.length > 0 + const outdir = asciidocConfig.attributes.outdir const siteUrl = ((val) => { if (!val) return return val.charAt(val.length - 1) === '/' ? val.slice(0, val.length - 1) : val })(asciidocConfig.attributes['site-url'] || asciidocConfig.attributes['primary-site-url']) + const embedRefStyle = assemblyModel.embedReferenceStyle const idSeparator = assemblyModel.xmlIds ? '-' : ':' const idScopeSeparator = idSeparator.repeat(3) const idCoordinateSeparator = idSeparator === '-' ? '----' : idSeparator @@ -458,7 +460,7 @@ function mergeAsciiDoc ( // TODO: handle (or report) unresolved image better if (image?.out) { pagesInOutline.assembled.assets.add(image) - return `image:${image.out.path.replace(/_/g, '{underscore}')}[${attrlist}]` + return `image:${resolveEmbedTarget(image, outdir, embedRefStyle, true)}[${attrlist}]` } } return m @@ -515,7 +517,7 @@ function mergeAsciiDoc ( if (image?.out) { const attrlist = line.slice(line.indexOf('[') + 1, -1) pagesInOutline.assembled.assets.add(image) - lines[idx] = `${prefix}image::${image.out.path}[${attrlist}]` + lines[idx] = `${prefix}image::${resolveEmbedTarget(image, outdir, embedRefStyle)}[${attrlist}]` } } lastImageMacroAt = [idx, imageMacroOffset] @@ -795,4 +797,10 @@ function resolveLinkTarget (resource, siteUrl) { return prefix + target.replace(/_/g, '{underscore}') } +function resolveEmbedTarget (resource, outdir, referenceStyle, escapeForInline) { + const target = + referenceStyle === 'output-relative' ? resource.out.path : path.relative(outdir + '/', resource.out.path) + return escapeForInline ? target.replace(/_/g, '{underscore}') : target +} + module.exports = produceAssemblyFile diff --git a/packages/assembler/lib/produce-assembly-files.js b/packages/assembler/lib/produce-assembly-files.js index 8da9e91bd50a812e9e1e2cdd86609f97766c9d3d..e660a5791f149bfd818e6608f085dd006ce7e67b 100644 --- a/packages/assembler/lib/produce-assembly-files.js +++ b/packages/assembler/lib/produce-assembly-files.js @@ -1,5 +1,6 @@ 'use strict' +const computeOut = require('./util/compute-out') const createAsciiDocFile = require('./util/create-asciidoc-file') const filterComponentVersions = require('./filter-component-versions') const produceAssemblyFile = require('./produce-assembly-file') @@ -17,6 +18,7 @@ function produceAssemblyFiles (loadAsciiDoc, contentCatalog, assemblerConfig, re sectionMergeStrategy: assemblyConfig.sectionMergeStrategy, navigation: componentVersion.navigation, xmlIds: assemblyConfig.xmlIds, + embedReferenceStyle: assemblyConfig.embedReferenceStyle, }) const assemblerAsciiDocAttributes = Object.assign({}, assemblerAsciiDocConfig.attributes) const { revdate, 'source-highlighter': sourceHighlighter } = assemblerAsciiDocAttributes @@ -35,6 +37,12 @@ function produceAssemblyFiles (loadAsciiDoc, contentCatalog, assemblerConfig, re assemblerAsciiDocAttributes, { logger: assemblyModel.logger, mdc: configMdc } ) + mergedAsciiDocAttributes.outdir = computeOut.call(contentCatalog, { + component: componentVersion.name, + version: componentVersion.version, + family: 'export', + relative: '.index.adoc', + }).dirname const mergedAsciiDocConfig = Object.assign({}, componentVersionAsciiDocConfig, { attributes: mergedAsciiDocAttributes, }) diff --git a/packages/assembler/test/assemble-content-test.js b/packages/assembler/test/assemble-content-test.js index a852387e2fe845a4126be67eaf1017efa453a9a7..011d9c035e90cf8af3e38bc2d9d8978945cd67fe 100644 --- a/packages/assembler/test/assemble-content-test.js +++ b/packages/assembler/test/assemble-content-test.js @@ -69,7 +69,7 @@ describe('assembleContent()', () => { 'assembler-backend-pdf': '', 'assembler-profile': 'pdf', 'assembler-profile-pdf': '', - docdir: buildDir, + docdir: ospath.dirname(ospath.join(expectedOutdir, 'index.adoc')), docfile: ospath.join(expectedOutdir, 'index.adoc'), docfilesuffix: '.adoc', 'docname@': 'export$index', @@ -97,6 +97,28 @@ describe('assembleContent()', () => { assert.equal(contentCatalog.getFiles().length, 1) }) + it('should set docdir to build dir if embedReferenceStyle is output-relative', async () => { + const scenario = 'insert-page' + const { playbook, contentCatalog, assemblerConfig: configSource } = await loadScenario(scenario, __dirname) + configSource.build.publish = false + const buildDir = configSource.build.dir + const convertCalls = [] + const convert = async (doc, ...rest) => { + convertCalls.push([doc].concat(rest)) + return doc + } + const converter = { + convert, + backend: 'pdf', + extname: '.pdf', + embedReferenceStyle: 'output-relative', + mediaType: 'application/pdf', + } + await assembleContent(playbook, contentCatalog, converter, { configSource }) + const actualConvertAttributes = convertCalls[0][1] + assert.equal(actualConvertAttributes.docdir, buildDir) + }) + it('should expand attribute references in attribute values defined in configuration', async () => { const scenario = 'expand-attribute-references' const playbook = { dir: ospath.join(FIXTURES_DIR, 'project-with-command') } diff --git a/packages/assembler/test/scenarios/process-asciidoc-table-cell/data.yml b/packages/assembler/test/scenarios/process-asciidoc-table-cell/data.yml index c3cc478905f837c38f1d32a241e72de56bae3a60..fa2519ff94d85f722daa533120199f52f78118dd 100644 --- a/packages/assembler/test/scenarios/process-asciidoc-table-cell/data.yml +++ b/packages/assembler/test/scenarios/process-asciidoc-table-cell/data.yml @@ -37,3 +37,6 @@ files: - relative: the-other-image.png module: shared family: image +assembler: + assembly: + embedReferenceStyle: output-relative diff --git a/packages/assembler/test/scenarios/resolve-image-targets/expects/index.adoc b/packages/assembler/test/scenarios/resolve-image-targets/expects/index.adoc index 27304a076fa2256639e9901a92ebea370ed89001..568d58b48a1448b42d6f2b023e40bfe327b431e0 100644 --- a/packages/assembler/test/scenarios/resolve-image-targets/expects/index.adoc +++ b/packages/assembler/test/scenarios/resolve-image-targets/expects/index.adoc @@ -19,9 +19,9 @@ [#the-page] == The Page Title -image::the-component/1.0/shared/_images/the-image.png[] +image::../shared/_images/the-image.png[] -Click image:the-component/1.0/{underscore}images/save.svg[] to save the document. +Click image:../{underscore}images/save.svg[] to save the document. :docname: the-other-page :page-module: ROOT @@ -34,6 +34,6 @@ Click image:the-component/1.0/{underscore}images/save.svg[] to save the document [#the-other-page] == The Other Page Title -image::common/_images/logo.png[] +image::../../../common/_images/logo.png[] -image::the-component/1.0/shared/_images/the-image.png[] +image::../shared/_images/the-image.png[] diff --git a/packages/assembler/test/scenarios/root-component/expects/index.adoc b/packages/assembler/test/scenarios/root-component/expects/index.adoc index 0720646b79c55fd1a13e8a856da9324af7d21281..fee2dc62b64ce30848f2f09857ebc36bbac7cb17 100644 --- a/packages/assembler/test/scenarios/root-component/expects/index.adoc +++ b/packages/assembler/test/scenarios/root-component/expects/index.adoc @@ -18,4 +18,4 @@ [#the-page] == The Page Title -image::_images/the-image.png[] +image::../_images/the-image.png[] diff --git a/packages/epub-extension/lib/converter.js b/packages/epub-extension/lib/converter.js index 9e026c79f7f8651de1fdf07bc8355c5a38460f02..842a92d12709f253245f7c71ed01d5bc7687563f 100644 --- a/packages/epub-extension/lib/converter.js +++ b/packages/epub-extension/lib/converter.js @@ -26,6 +26,7 @@ module.exports = { convert, backend: 'epub3', extname: '.epub', + embedReferenceStyle: 'output-relative', mediaType: 'application/epub+zip', loggerName: require('../package.json').name, }