@antora/cli 3.0.0-alpha.6 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/cli.js +105 -60
- package/lib/commander/options-from-convict.js +12 -5
- package/lib/commander/track-options.js +14 -0
- package/lib/commander.js +1 -1
- package/package.json +9 -8
- package/lib/commander/condense-help.js +0 -17
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
The command line interface (CLI) for Antora.
|
|
4
4
|
|
|
5
5
|
[Antora](https://antora.org) is a modular static site generator designed for creating documentation sites from AsciiDoc documents.
|
|
6
|
-
Its site generator
|
|
6
|
+
Its site generator aggregates documents from versioned content repositories and processes them using [Asciidoctor](https://asciidoctor.org).
|
|
7
7
|
|
|
8
|
-
To run Antora, you need both the CLI and a site generator
|
|
8
|
+
To run Antora, you need both the CLI and a site generator.
|
|
9
9
|
Once these packages are installed, you can use the `antora` command to generate your site.
|
|
10
10
|
|
|
11
11
|
## How to Install
|
package/lib/cli.js
CHANGED
|
@@ -2,107 +2,158 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict'
|
|
4
4
|
|
|
5
|
+
const buildPlaybook = require('@antora/playbook-builder')
|
|
5
6
|
const cli = require('./commander')
|
|
6
|
-
// Q: can we ask the playbook builder for the config schema?
|
|
7
|
-
const configSchema = require('@antora/playbook-builder/lib/config/schema')
|
|
8
7
|
const convict = require('@antora/playbook-builder/lib/solitary-convict')
|
|
9
|
-
const { finalizeLogger } = require('@antora/logger')
|
|
8
|
+
const { configureLogger, getLogger, finalizeLogger } = require('@antora/logger')
|
|
10
9
|
const ospath = require('path')
|
|
10
|
+
const userRequire = require('@antora/user-require-helper')
|
|
11
11
|
|
|
12
|
-
const DOT_RELATIVE_RX = new RegExp(`^\\.{1,2}[/${ospath.sep.replace('/', '').replace('\\', '\\\\')}]`)
|
|
13
12
|
const { version: VERSION } = require('../package.json')
|
|
14
13
|
|
|
15
14
|
async function run (argv = process.argv) {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
if (cli._promise) await cli._promise
|
|
19
|
-
return result
|
|
15
|
+
const args = argv.slice(2)
|
|
16
|
+
return cli.parseAsync(args.length ? args : ['help'], { from: 'user' })
|
|
20
17
|
}
|
|
21
18
|
|
|
22
|
-
function exitWithError (err,
|
|
19
|
+
function exitWithError (err, opts, msg = undefined) {
|
|
23
20
|
if (!msg) msg = err.message || err
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const name = msg.startsWith('asciidoctor: FAILED: ') ? (msg = msg.slice(21)) && 'asciidoctor' : cli.name()
|
|
22
|
+
const logger = getLogger(null)
|
|
23
|
+
? getLogger(name)
|
|
24
|
+
: configureLogger({ format: 'pretty', level: opts.silent ? 'silent' : 'fatal', failureLevel: 'fatal' }).get(name)
|
|
25
|
+
if (opts.stacktrace) {
|
|
26
|
+
let loc, stack
|
|
26
27
|
if ((stack = err.backtrace)) {
|
|
27
|
-
|
|
28
|
+
err = Object.assign(new Error(msg), { stack: ['Error', ...stack.slice(1)].join('\n') })
|
|
28
29
|
} else if ((stack = err.stack)) {
|
|
29
|
-
|
|
30
|
+
if (err instanceof SyntaxError && stack.includes('\nSyntaxError: ')) {
|
|
31
|
+
;[loc, stack] = stack.split(/\n+SyntaxError: [^\n]+/)
|
|
32
|
+
err = Object.assign(new SyntaxError(msg), { stack: stack.replace('\n', `SyntaxError\n at ${loc}\n`) })
|
|
33
|
+
} else if (stack.startsWith(`${err.name}: ${msg}`)) {
|
|
34
|
+
stack = stack.replace(`${err.name}: ${msg}`, '').replace(/^\n/, '')
|
|
35
|
+
err = Object.assign(new err.constructor(msg), { stack: stack ? `${err.name}\n${stack}` : undefined })
|
|
36
|
+
}
|
|
30
37
|
} else {
|
|
31
|
-
|
|
38
|
+
err = Object.assign(new Error(msg), { stack: undefined })
|
|
32
39
|
}
|
|
33
|
-
|
|
40
|
+
if ({}.propertyIsEnumerable.call(err, 'name')) Object.defineProperty(err, 'name', { enumerable: false })
|
|
41
|
+
err.stack = `Cause: ${err.stack || '(no stacktrace)'}`
|
|
42
|
+
logger.fatal(err, msg)
|
|
34
43
|
} else {
|
|
35
|
-
|
|
44
|
+
logger.fatal(msg + '\nAdd the --stacktrace option to see the cause of the error.')
|
|
36
45
|
}
|
|
37
|
-
|
|
46
|
+
return exit()
|
|
38
47
|
}
|
|
39
48
|
|
|
40
|
-
function
|
|
41
|
-
|
|
49
|
+
function exit () {
|
|
50
|
+
return finalizeLogger().then((failOnExit) => process.exit(failOnExit ? 1 : process.exitCode))
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const paths = [cwd, ospath.dirname(__dirname)].map((start) => ospath.join(start, 'node_modules'))
|
|
51
|
-
requirePath = require.resolve(requirePath, { paths })
|
|
52
|
-
}
|
|
53
|
-
return require(requirePath)
|
|
53
|
+
function getTTYColumns () {
|
|
54
|
+
return process.env.COLUMNS || process.stdout.columns || 80
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function outputError (str, write) {
|
|
58
|
+
write(str.replace(/^error: /, cli.name() + ': '))
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
cli
|
|
62
|
+
.allowExcessArguments(false)
|
|
63
|
+
.configureOutput({ getOutHelpWidth: getTTYColumns, getErrHelpWidth: getTTYColumns, outputError })
|
|
64
|
+
.storeOptionsAsProperties()
|
|
57
65
|
.name('antora')
|
|
58
|
-
.version(
|
|
66
|
+
.version(
|
|
67
|
+
{
|
|
68
|
+
toString () {
|
|
69
|
+
const generator = cli._findCommand('generate').getOptionValue('generator')
|
|
70
|
+
const buffer = ['@antora/cli: ' + VERSION]
|
|
71
|
+
let generatorVersion
|
|
72
|
+
const generatorPackageJson = generator + '/package.json'
|
|
73
|
+
try {
|
|
74
|
+
generatorVersion = require(generatorPackageJson).version
|
|
75
|
+
} catch {
|
|
76
|
+
try {
|
|
77
|
+
generatorVersion = require(require.resolve(generatorPackageJson, { paths: [''] })).version
|
|
78
|
+
} catch {}
|
|
79
|
+
}
|
|
80
|
+
buffer.push(generator + ': ' + (generatorVersion || 'not installed'))
|
|
81
|
+
return buffer.join('\n')
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
'-v, --version',
|
|
85
|
+
'Output the version of the CLI and default site generator.'
|
|
86
|
+
)
|
|
59
87
|
.description('A modular, multi-repository documentation site generator for AsciiDoc.')
|
|
60
88
|
.usage('[options] [[command] [args]]')
|
|
61
89
|
.helpOption('-h, --help', 'Output usage information.')
|
|
62
|
-
.
|
|
63
|
-
|
|
90
|
+
.addHelpText('after', () => {
|
|
91
|
+
const name = cli.name()
|
|
92
|
+
return cli
|
|
93
|
+
.createHelp()
|
|
94
|
+
.wrap(
|
|
95
|
+
` \nRun '${name} <command> --help' to see options and examples for a command (e.g., ${name} generate --help).`,
|
|
96
|
+
getTTYColumns(),
|
|
97
|
+
0
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
.option('-r, --require <library>', 'Require library (aka node module) or script path before executing command.')
|
|
101
|
+
.on('option:require', (requireRequest) => (cli.requireRequests = cli.requireRequests || []).push(requireRequest))
|
|
64
102
|
.option('--stacktrace', 'Print the stacktrace to the console if the application fails.')
|
|
65
103
|
|
|
66
104
|
cli
|
|
67
105
|
.command('generate <playbook>', { isDefault: true })
|
|
68
|
-
.description('Generate a documentation site specified
|
|
69
|
-
.optionsFromConvict(convict(
|
|
70
|
-
.
|
|
71
|
-
.action(async (playbookFile, command) => {
|
|
106
|
+
.description('Generate a documentation site as specified by <playbook>.')
|
|
107
|
+
.optionsFromConvict(convict(buildPlaybook.defaultSchema), { exclude: 'playbook' })
|
|
108
|
+
.trackOptions()
|
|
109
|
+
.action(async (playbookFile, options, command) => {
|
|
110
|
+
const errorOpts = { stacktrace: cli.stacktrace, silent: command.silent }
|
|
111
|
+
const playbookDir = ospath.resolve(playbookFile, '..')
|
|
112
|
+
const userRequireContext = { dot: playbookDir, paths: [playbookDir, __dirname] }
|
|
113
|
+
if (cli.requireRequests) {
|
|
114
|
+
try {
|
|
115
|
+
cli.requireRequests.forEach((requireRequest) => userRequire(requireRequest, userRequireContext))
|
|
116
|
+
} catch (err) {
|
|
117
|
+
return exitWithError(err, errorOpts)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const args = command.optionArgs.concat('--playbook', playbookFile)
|
|
121
|
+
let playbook
|
|
72
122
|
try {
|
|
73
|
-
|
|
123
|
+
playbook = buildPlaybook(args, process.env, buildPlaybook.defaultSchema, (config) => {
|
|
124
|
+
try {
|
|
125
|
+
configureLogger(config.getModel('runtime.log'), playbookDir)
|
|
126
|
+
} catch {}
|
|
127
|
+
})
|
|
74
128
|
} catch (err) {
|
|
75
|
-
exitWithError(err,
|
|
129
|
+
return exitWithError(err, errorOpts)
|
|
76
130
|
}
|
|
77
|
-
const generator =
|
|
131
|
+
const generator = playbook.antora.generator
|
|
78
132
|
let generateSite
|
|
79
133
|
try {
|
|
80
|
-
generateSite =
|
|
134
|
+
generateSite =
|
|
135
|
+
(generateSite = userRequire(generator, userRequireContext)).length === 1
|
|
136
|
+
? generateSite.bind(null, playbook)
|
|
137
|
+
: generateSite.bind(null, args, process.env)
|
|
81
138
|
} catch (err) {
|
|
82
139
|
let msg = 'Generator not found or failed to load.'
|
|
83
140
|
if (generator && generator.charAt() !== '.') msg += ` Try installing the '${generator}' package.`
|
|
84
|
-
exitWithError(err,
|
|
141
|
+
return exitWithError(err, errorOpts, msg)
|
|
85
142
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
cli._promise = generateSite(args, process.env)
|
|
90
|
-
.then(finalizeLogger)
|
|
91
|
-
.then((failOnExit) => process.exit(failOnExit ? 1 : process.exitCode))
|
|
92
|
-
.catch((err) => finalizeLogger().then(() => exitWithError(err, cli.stacktrace)))
|
|
143
|
+
return generateSite()
|
|
144
|
+
.then(exit)
|
|
145
|
+
.catch((err) => exitWithError(err, errorOpts))
|
|
93
146
|
})
|
|
94
147
|
.options.sort((a, b) => a.long.localeCompare(b.long))
|
|
95
148
|
|
|
96
|
-
cli.command('help [command]', { hidden: true }).action((name, command) => {
|
|
149
|
+
cli.command('help [command]', { hidden: true }).action((name, options, command) => {
|
|
97
150
|
if (name) {
|
|
98
|
-
const helpCommand = cli.
|
|
151
|
+
const helpCommand = cli._findCommand(name)
|
|
99
152
|
if (helpCommand) {
|
|
100
153
|
helpCommand.help()
|
|
101
154
|
} else {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
105
|
-
process.exit(1)
|
|
155
|
+
const message = `error: unknown command '${name}'. See '${cli.name()} --help' for a list of commands.`
|
|
156
|
+
cli._displayError(1, 'commander.unknownCommand', message)
|
|
106
157
|
}
|
|
107
158
|
} else {
|
|
108
159
|
cli.help()
|
|
@@ -111,10 +162,4 @@ cli.command('help [command]', { hidden: true }).action((name, command) => {
|
|
|
111
162
|
|
|
112
163
|
cli.command('version', { hidden: true }).action(() => cli.emit('option:version'))
|
|
113
164
|
|
|
114
|
-
cli.on('--help', () => {
|
|
115
|
-
console.log(
|
|
116
|
-
`\nRun '${cli.name()} <command> --help' to see options and examples for a command (e.g., ${cli.name()} generate --help).`
|
|
117
|
-
)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
165
|
module.exports = run
|
|
@@ -5,8 +5,15 @@ const { Command } = require('commander')
|
|
|
5
5
|
Command.prototype.optionsFromConvict = function (convictConfig, opts = {}) {
|
|
6
6
|
let exclude = opts.exclude
|
|
7
7
|
if (exclude && !Array.isArray(exclude)) exclude = [exclude]
|
|
8
|
-
getOptions(convictConfig).forEach((
|
|
9
|
-
if (
|
|
8
|
+
getOptions(convictConfig).forEach(({ name, form, description, default: default_, choices }) => {
|
|
9
|
+
if (exclude && exclude.includes(name)) return
|
|
10
|
+
this.addOption(
|
|
11
|
+
choices
|
|
12
|
+
? this.createOption(form, description)
|
|
13
|
+
.default(default_, default_)
|
|
14
|
+
.choices(choices)
|
|
15
|
+
: this.createOption(form, description).default(default_, default_)
|
|
16
|
+
)
|
|
10
17
|
})
|
|
11
18
|
return this
|
|
12
19
|
}
|
|
@@ -24,15 +31,15 @@ function collectOptions (props, context = undefined) {
|
|
|
24
31
|
const { arg, format, default: default_ } = value
|
|
25
32
|
const option = { name: arg, form: `--${arg}`, description: value.doc, format: format }
|
|
26
33
|
if (Array.isArray(format)) {
|
|
27
|
-
option.form += ' <
|
|
28
|
-
option.
|
|
34
|
+
option.form += ' <choice>'
|
|
35
|
+
option.choices = Object.defineProperty(format.slice(), 'map', { value: () => format })
|
|
29
36
|
} else if (format !== 'boolean') {
|
|
30
37
|
option.form += ` <${arg.substr(arg.lastIndexOf('-') + 1, arg.length)}>`
|
|
31
38
|
}
|
|
32
39
|
if (default_ === null) {
|
|
33
40
|
//option.mandatory = true
|
|
34
41
|
option.description += ' (required)'
|
|
35
|
-
} else if (default_ &&
|
|
42
|
+
} else if (default_ && default_.constructor !== Object) {
|
|
36
43
|
option.default = default_
|
|
37
44
|
}
|
|
38
45
|
accum.push(option)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Command } = require('commander')
|
|
4
|
+
|
|
5
|
+
Command.prototype.trackOptions = function () {
|
|
6
|
+
const optionArgs = (this.optionArgs = [])
|
|
7
|
+
for (const eventName of this.eventNames().filter((name) => name.startsWith('option:'))) {
|
|
8
|
+
this.on(eventName, function () {
|
|
9
|
+
optionArgs.push(`--${eventName.slice(7)}`)
|
|
10
|
+
if (arguments.length) optionArgs.push(arguments[0])
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
return this
|
|
14
|
+
}
|
package/lib/commander.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antora/cli",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
4
|
"description": "The command line interface for Antora.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "OpenDevise Inc. (https://opendevise.com)",
|
|
@@ -18,17 +18,18 @@
|
|
|
18
18
|
"antora": "bin/antora"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@antora/logger": "3.0.0-
|
|
22
|
-
"@antora/playbook-builder": "3.0.0-
|
|
23
|
-
"
|
|
21
|
+
"@antora/logger": "3.0.0-beta.1",
|
|
22
|
+
"@antora/playbook-builder": "3.0.0-beta.1",
|
|
23
|
+
"@antora/user-require-helper": "~2.0",
|
|
24
|
+
"commander": "~8.3"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"@antora/site-publisher": "3.0.0-
|
|
27
|
-
"convict": "~6.
|
|
27
|
+
"@antora/site-publisher": "3.0.0-beta.1",
|
|
28
|
+
"convict": "~6.2",
|
|
28
29
|
"kapok-js": "~0.10"
|
|
29
30
|
},
|
|
30
31
|
"engines": {
|
|
31
|
-
"node": ">=
|
|
32
|
+
"node": ">=12.21.0"
|
|
32
33
|
},
|
|
33
34
|
"files": [
|
|
34
35
|
"bin/",
|
|
@@ -42,5 +43,5 @@
|
|
|
42
43
|
"static site",
|
|
43
44
|
"web publishing"
|
|
44
45
|
],
|
|
45
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "7c5ef1ea93dd489af533c80a936c736013c41769"
|
|
46
47
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Command } = require('commander')
|
|
4
|
-
const { helpInformation } = Command.prototype
|
|
5
|
-
const { stringify } = JSON
|
|
6
|
-
|
|
7
|
-
// TODO include common options when outputting help for a (sub)command
|
|
8
|
-
Command.prototype.helpInformation = function () {
|
|
9
|
-
const nonTTYColumns = 'columns' in process.stdout ? undefined : (process.stdout.columns = process.env.COLUMNS || 80)
|
|
10
|
-
// NOTE override stringify to coerce to string normally
|
|
11
|
-
JSON.stringify = (val) => `${val}`
|
|
12
|
-
const helpInfo = helpInformation.call(this)
|
|
13
|
-
//const helpInfo = helpInformation.call(this).split('\n').filter((line) => !line.includes('--no-')).join('\n')
|
|
14
|
-
JSON.stringify = stringify
|
|
15
|
-
if (nonTTYColumns) delete process.stdout.columns
|
|
16
|
-
return helpInfo
|
|
17
|
-
}
|