Loading CHANGELOG.adoc +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ This project utilizes semantic versioning. === Added * *playbook-builder*: Allow extension to be switched off from CLI by negating value (#976) * *playbook-builder*: Allow CLI to control order of extensions declared in playbook (#1190) * *content-aggregator*: Allow content source to be filtered by commits (playbook model only) (#831) === Changed Loading docs/modules/extend/pages/enable-extension.adoc +30 −0 Original line number Diff line number Diff line Loading @@ -55,3 +55,33 @@ If you don't assign an ID to the extension entry, you can reference the value of In this case, Antora looks for the first entry in the list of extensions whose `require` key matches the value of the CLI option. If Antora can't locate an entry that matches the value of the `--extension` CLI option, it falls back to treating the value as a require request. == Load order By default, declaring and enabling an extension in the playbook also determines its load order. Any enabled extensions declared in the playbook are loaded first in playbook order, followed by any extensions enabled through the CLI. However, the CLI still has an opportunity to influence this load order. If the value of the `--extension` option matches an extension declared in the playbook, the load order of the extension is updated. That extension acts as though it's not declared in the playbook and enabled by the CLI instead. Yet, the configuration from the playbook is still used. Let's consider an example: .An extension declared in the playbook [,yaml] ---- antora: extensions: - require: ./from-playbook.js custom: value ---- Now, if we want to load an extension before this extension, we can do so using the CLI: $ antora --extension ./from-cli.js --extension ./from-playbook.js antora-playbook.yml The from-cli.js extension will be loaded first, followed by the from-playbook.js extension. Had we not referenced the from-playbook.js extension using the `--extension` option, it would have been loaded first. This technique also works for an extension declared in the playbook as not enabled (i.e., `enabled: false`). packages/playbook-builder/lib/solitary-convict.js +10 −4 Original line number Diff line number Diff line Loading @@ -132,21 +132,27 @@ function registerFormats (convict) { const accum = config?.has(name) ? config.get(name) : [] const byId = {} const byRequire = {} let orderIdx = 0 const order = new Map() for (const [idx, it] of accum.entries()) { const ext = it.constructor === Object ? it : (accum[idx] = { require: it }) byRequire[ext.require] ??= ext if ('id' in ext) byId[ext.id] ??= ext order.set(it, orderIdx++) } for (let request of val.split(',')) { const enable = request.charAt() === '!' ? (request = request.slice(1)) == null : true const match = byId[request] ?? byRequire[request] if (match) { let match if ((match = byId[request] ?? byRequire[request])) { if ((match.enabled ?? true) !== enable) match.enabled = enable } else { accum.push((byRequire[request] = { require: request })) accum.push((match = byRequire[request] = { require: request })) } order.set(match, orderIdx++) } return accum.map((it) => (Object.keys(it).length === 1 && 'require' in it ? it.require : it)) return accum .sort((a, b) => order.get(a) - order.get(b)) .map((it) => (Object.keys(it).length === 1 && 'require' in it ? it.require : it)) }, }) convict.addFormat({ Loading packages/playbook-builder/test/build-playbook-test.js +23 −4 Original line number Diff line number Diff line Loading @@ -607,10 +607,10 @@ describe('buildPlaybook()', () => { const args = ['--playbook', duplicateExtensionIdSchemaSpec, '--extension', '@antora/pdf-extension'] const playbook = buildPlaybook(args, {}) expect(playbook.antora.extensions).to.have.lengthOf(2) expect(playbook.antora.extensions[0].enabled).to.be.true() expect(playbook.antora.extensions[0].foo).to.equal('bar') expect(playbook.antora.extensions[1].enabled).to.be.false() expect(playbook.antora.extensions[1].foo).to.equal('baz') expect(playbook.antora.extensions[0].enabled).to.be.false() expect(playbook.antora.extensions[0].foo).to.equal('baz') expect(playbook.antora.extensions[1].enabled).to.be.true() expect(playbook.antora.extensions[1].foo).to.equal('bar') }) it('should not add duplicate entry to require-array', () => { Loading @@ -620,6 +620,25 @@ describe('buildPlaybook()', () => { expect(num).to.equal(1) }) it('should allow CLI to control load order of extension enabled in playbook', () => { const args = [ '--playbook', defaultSchemaSpec, '--extension', '@antora/pdf-extension', '--extension', 'antora-lunr', '--extension', '@namespace/the-extension', ] const playbook = buildPlaybook(args, {}) expect(playbook.antora.extensions).to.have.lengthOf(4) expect(playbook.antora.extensions[1]).to.equal('@antora/pdf-extension') expect(playbook.antora.extensions[2]).to.equal('antora-lunr') expect(playbook.antora.extensions[3].require).to.equal('@namespace/the-extension') expect(playbook.antora.extensions[3].enabled).to.be.true() }) it('should throw error if dir-or-virtual-files key is not a string or array', () => { Object.keys(schema).forEach((key) => { if (key !== 'playbook') delete schema[key] Loading Loading
CHANGELOG.adoc +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ This project utilizes semantic versioning. === Added * *playbook-builder*: Allow extension to be switched off from CLI by negating value (#976) * *playbook-builder*: Allow CLI to control order of extensions declared in playbook (#1190) * *content-aggregator*: Allow content source to be filtered by commits (playbook model only) (#831) === Changed Loading
docs/modules/extend/pages/enable-extension.adoc +30 −0 Original line number Diff line number Diff line Loading @@ -55,3 +55,33 @@ If you don't assign an ID to the extension entry, you can reference the value of In this case, Antora looks for the first entry in the list of extensions whose `require` key matches the value of the CLI option. If Antora can't locate an entry that matches the value of the `--extension` CLI option, it falls back to treating the value as a require request. == Load order By default, declaring and enabling an extension in the playbook also determines its load order. Any enabled extensions declared in the playbook are loaded first in playbook order, followed by any extensions enabled through the CLI. However, the CLI still has an opportunity to influence this load order. If the value of the `--extension` option matches an extension declared in the playbook, the load order of the extension is updated. That extension acts as though it's not declared in the playbook and enabled by the CLI instead. Yet, the configuration from the playbook is still used. Let's consider an example: .An extension declared in the playbook [,yaml] ---- antora: extensions: - require: ./from-playbook.js custom: value ---- Now, if we want to load an extension before this extension, we can do so using the CLI: $ antora --extension ./from-cli.js --extension ./from-playbook.js antora-playbook.yml The from-cli.js extension will be loaded first, followed by the from-playbook.js extension. Had we not referenced the from-playbook.js extension using the `--extension` option, it would have been loaded first. This technique also works for an extension declared in the playbook as not enabled (i.e., `enabled: false`).
packages/playbook-builder/lib/solitary-convict.js +10 −4 Original line number Diff line number Diff line Loading @@ -132,21 +132,27 @@ function registerFormats (convict) { const accum = config?.has(name) ? config.get(name) : [] const byId = {} const byRequire = {} let orderIdx = 0 const order = new Map() for (const [idx, it] of accum.entries()) { const ext = it.constructor === Object ? it : (accum[idx] = { require: it }) byRequire[ext.require] ??= ext if ('id' in ext) byId[ext.id] ??= ext order.set(it, orderIdx++) } for (let request of val.split(',')) { const enable = request.charAt() === '!' ? (request = request.slice(1)) == null : true const match = byId[request] ?? byRequire[request] if (match) { let match if ((match = byId[request] ?? byRequire[request])) { if ((match.enabled ?? true) !== enable) match.enabled = enable } else { accum.push((byRequire[request] = { require: request })) accum.push((match = byRequire[request] = { require: request })) } order.set(match, orderIdx++) } return accum.map((it) => (Object.keys(it).length === 1 && 'require' in it ? it.require : it)) return accum .sort((a, b) => order.get(a) - order.get(b)) .map((it) => (Object.keys(it).length === 1 && 'require' in it ? it.require : it)) }, }) convict.addFormat({ Loading
packages/playbook-builder/test/build-playbook-test.js +23 −4 Original line number Diff line number Diff line Loading @@ -607,10 +607,10 @@ describe('buildPlaybook()', () => { const args = ['--playbook', duplicateExtensionIdSchemaSpec, '--extension', '@antora/pdf-extension'] const playbook = buildPlaybook(args, {}) expect(playbook.antora.extensions).to.have.lengthOf(2) expect(playbook.antora.extensions[0].enabled).to.be.true() expect(playbook.antora.extensions[0].foo).to.equal('bar') expect(playbook.antora.extensions[1].enabled).to.be.false() expect(playbook.antora.extensions[1].foo).to.equal('baz') expect(playbook.antora.extensions[0].enabled).to.be.false() expect(playbook.antora.extensions[0].foo).to.equal('baz') expect(playbook.antora.extensions[1].enabled).to.be.true() expect(playbook.antora.extensions[1].foo).to.equal('bar') }) it('should not add duplicate entry to require-array', () => { Loading @@ -620,6 +620,25 @@ describe('buildPlaybook()', () => { expect(num).to.equal(1) }) it('should allow CLI to control load order of extension enabled in playbook', () => { const args = [ '--playbook', defaultSchemaSpec, '--extension', '@antora/pdf-extension', '--extension', 'antora-lunr', '--extension', '@namespace/the-extension', ] const playbook = buildPlaybook(args, {}) expect(playbook.antora.extensions).to.have.lengthOf(4) expect(playbook.antora.extensions[1]).to.equal('@antora/pdf-extension') expect(playbook.antora.extensions[2]).to.equal('antora-lunr') expect(playbook.antora.extensions[3].require).to.equal('@namespace/the-extension') expect(playbook.antora.extensions[3].enabled).to.be.true() }) it('should throw error if dir-or-virtual-files key is not a string or array', () => { Object.keys(schema).forEach((key) => { if (key !== 'playbook') delete schema[key] Loading