From c861ea16dbd6eb26bced473b5a6aa2d5809b7620 Mon Sep 17 00:00:00 2001 From: Dan Allen Date: Fri, 17 Oct 2025 16:44:48 -0600 Subject: [PATCH] resolves #129 bundle Ruby script to support Asciidoctor log integration; automatically require if requested --- CHANGELOG.adoc | 5 ++++ .../modules/ROOT/pages/configure-build.adoc | 11 +++++++- .../adapters/asciidoctor/jsonl-logger.rb | 25 +++++++++++++++++++ packages/assembler/lib/assemble-content.js | 4 +++ packages/assembler/package.json | 2 ++ .../assembler/test/assemble-content-test.js | 20 +++++++++++++++ packages/test-harness/lib/assertx.js | 1 + 7 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 packages/assembler/adapters/asciidoctor/jsonl-logger.rb diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 2128331..c0f1fc3 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -6,6 +6,11 @@ For a detailed view of what's changed, refer to the {url-repo}/commits[commit hi == Unreleased +=== Added + +* bundle Ruby script to support Asciidoctor log integration (#129) +* automatically require Asciidoctor jsonl logger if `asciidoctor-log-integration` attribute is set (#129) + === Changed * convert page reference to internal reference for any page included in assembly (#127) diff --git a/docs/assembler/modules/ROOT/pages/configure-build.adoc b/docs/assembler/modules/ROOT/pages/configure-build.adoc index 450aef6..36b2291 100644 --- a/docs/assembler/modules/ROOT/pages/configure-build.adoc +++ b/docs/assembler/modules/ROOT/pages/configure-build.adoc @@ -144,7 +144,16 @@ The default value is `print`. IMPORTANT: The `convert` function *must* pass the value of this key to the `runCommand` helper and return its result in order for stderr handling to work. Alternately, the `convert` function must handle stderr itself according to the behavior requested. -If you are running a command based on Asciidoctor (e.g., Asciidoctor PDF), you can load the following extension to convert the log messages to jsonl. +If you're running a command based on Asciidoctor (e.g., Asciidoctor PDF), you can set the `asciidoctor-log-integration` attribute in the Assembler configuration file (or any location from which attributes are inherited), and Assember will automatically require the necessary adapter. + +[,yaml] +---- +asciidoc: + attributes: + asciidoctor-log-integration: '' +---- + +Alternately, you can require the following extension to convert the log messages to jsonl. .asciidoctor-jsonl-log-extension.rb [,ruby] diff --git a/packages/assembler/adapters/asciidoctor/jsonl-logger.rb b/packages/assembler/adapters/asciidoctor/jsonl-logger.rb new file mode 100644 index 0000000..a5496f3 --- /dev/null +++ b/packages/assembler/adapters/asciidoctor/jsonl-logger.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +autoload :JSON, 'json' + +class JsonlFormatter < Asciidoctor::Logger::BasicFormatter + def call severity, time, progname, msg + entry = { 'time' => time.utc.to_i, 'level' => severity.downcase, 'name' => progname } + if ::String === msg + entry['msg'] = msg + else + loc = msg[:source_location] + entry['file'] = { 'path' => loc.file, 'line' => loc.lineno } + entry['msg'] = msg[:text] + end + (JSON.generate entry) + ?\n + end +end + +proc do + logger = Asciidoctor::LoggerManager.logger + logger.formatter = JsonlFormatter.new + unless (progname = ::File.basename $PROGRAM_NAME).empty? + logger.progname = progname + end +end.call diff --git a/packages/assembler/lib/assemble-content.js b/packages/assembler/lib/assemble-content.js index 2b39c8d..3534117 100644 --- a/packages/assembler/lib/assemble-content.js +++ b/packages/assembler/lib/assemble-content.js @@ -199,6 +199,10 @@ function prepareConvertAttributes (doc, targetExtname, relativeToOutput, buildCo if (val) { val = `${name}=${padCharRef && typeof val.charAt === 'function' && val.charAt() === '&' ? ' ' : ''}${val}` } else if (val === '') { + if (name === 'asciidoctor-log-integration') { + args.push('-r', require.resolve('#asciidoctor-log-adapter')) + continue + } val = name } else { val = `!${name}${val === false ? '@' : ''}` diff --git a/packages/assembler/package.json b/packages/assembler/package.json index 8ea5e5b..41599bb 100644 --- a/packages/assembler/package.json +++ b/packages/assembler/package.json @@ -33,6 +33,7 @@ "./select-mutable-attributes": "./lib/select-mutable-attributes.js" }, "imports": { + "#asciidoctor-log-adapter": "./adapters/asciidoctor/jsonl-logger.rb", "#run-command": "@antora/run-command-helper", "#unconvert-inline-asciidoc": "./lib/util/unconvert-inline-asciidoc.js" }, @@ -52,6 +53,7 @@ "node": ">=16.0.0" }, "files": [ + "adapters/", "lib/" ], "keywords": [ diff --git a/packages/assembler/test/assemble-content-test.js b/packages/assembler/test/assemble-content-test.js index 9ea01aa..4c4d389 100644 --- a/packages/assembler/test/assemble-content-test.js +++ b/packages/assembler/test/assemble-content-test.js @@ -467,6 +467,26 @@ describe('assembleContent()', () => { assert.equal(nbhyArg, process.platform === 'win32' ? 'nbhy= ߛ' : 'nbhy=ߛ') }) + it('should require Asciidoctor log adapter if asciidoctor-log-integration attribute is set', async () => { + const scenario = 'insert-page' + const playbook = { dir: ospath.join(FIXTURES_DIR, 'project-with-command') } + const { contentCatalog, assemblerConfig: configSource } = await loadScenario(scenario, __dirname) + Object.assign(configSource.build, { command: 'bundle exec asciidoctor-pdf', publish: false }) + configSource.asciidoc.attributes['asciidoctor-log-integration'] = '' + let actualArgs + const convert = async (doc, convertAttributes, buildConfig) => { + actualArgs = convertAttributes.toArgs('-a', buildConfig.command) + return doc + } + const converter = { convert, extname: '.pdf', mediaType: 'application/pdf' } + await assembleContent(playbook, contentCatalog, converter, { configSource }) + assertx.notExist(actualArgs.find((it) => it.startsWith('asciidoctor-log-integration')) || null) + const expected = require.resolve('#asciidoctor-log-adapter') + const actualIdx = actualArgs.findIndex((it) => it === expected) + assertx.exist(actualArgs[actualIdx]) + assert.equal(actualArgs[actualIdx - 1], '-r') + }) + it('should keep assembled AsciiDoc documents in build directory if keep_source is true', async () => { const scenario = 'insert-page' const { playbook, contentCatalog, assemblerConfig: configSource } = await loadScenario(scenario, __dirname) diff --git a/packages/test-harness/lib/assertx.js b/packages/test-harness/lib/assertx.js index 32921c0..960d17f 100644 --- a/packages/test-harness/lib/assertx.js +++ b/packages/test-harness/lib/assertx.js @@ -58,6 +58,7 @@ const assertx = { assert(!stat.isDirectory(), `Expected value to not be a directory: ${actual}`) }, notEmpty: (actual) => assert.notEqual(actual.length, 0, `Expected ${actual} to not be empty`), + notExist: (actual) => assert.equal(actual, null, `Expected ${actual} to not exist`), partialDeepEqual: (actual, expected, msg) => assert.deepEqual(sliceObject(actual, ...Object.keys(expected)), expected, msg), } -- GitLab