From d5cacc71aacca59a022ce556ecd2697272d66053 Mon Sep 17 00:00:00 2001 From: Dan Allen Date: Mon, 22 Sep 2025 00:10:11 -0600 Subject: [PATCH] resolves #100 introduce embedReferenceStyle on converter to control how image references are rewritten --- CHANGELOG.adoc | 1 + .../ROOT/pages/custom-exporter-extension.adoc | 3 +++ packages/assembler/lib/assemble-content.js | 12 ++++++---- .../assembler/lib/produce-assembly-file.js | 12 ++++++++-- .../assembler/lib/produce-assembly-files.js | 8 +++++++ .../assembler/test/assemble-content-test.js | 24 ++++++++++++++++++- .../process-asciidoc-table-cell/data.yml | 3 +++ .../resolve-image-targets/expects/index.adoc | 8 +++---- .../root-component/expects/index.adoc | 2 +- packages/epub-extension/lib/converter.js | 1 + 10 files changed, 62 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f2cfaae..3e444f2 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 3984146..d278842 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 6aeddbe..2dca8ec 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 9a831d3..e34a0e5 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 8da9e91..e660a57 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 a852387..011d9c0 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 c3cc478..fa2519f 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 27304a0..568d58b 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 0720646..fee2dc6 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 9e026c7..842a92d 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, } -- GitLab