279 lines
8.9 KiB
JavaScript
279 lines
8.9 KiB
JavaScript
/* global Opal */
|
|
const yargs = require('yargs')
|
|
const asciidoctor = require('@asciidoctor/core')()
|
|
|
|
const convertOptions = (args, attrs) => {
|
|
const attributes = attrs || []
|
|
const backend = args.backend
|
|
const doctype = args.doctype
|
|
const safeMode = args['safe-mode']
|
|
const embedded = args.embedded === true || args['no-header-footer'] === true || args.standalone === false
|
|
const standalone = !embedded
|
|
const sectionNumbers = args['section-numbers']
|
|
const baseDir = args['base-dir']
|
|
const destinationDir = args['destination-dir']
|
|
const outFile = args['out-file']
|
|
const templateDir = args['template-dir']
|
|
const templateEngine = args['template-engine']
|
|
const quiet = args.quiet
|
|
const verbose = args.verbose
|
|
const timings = args.timings
|
|
const trace = args.trace
|
|
const requireLib = args.require
|
|
let level = args['failure-level'].toUpperCase()
|
|
if (level === 'WARNING') {
|
|
level = 'WARN'
|
|
}
|
|
const failureLevel = asciidoctor.LoggerSeverity[level]
|
|
const debug = verbose && args['verbose-sole-argument'] !== true
|
|
if (debug) {
|
|
console.log('require ' + requireLib)
|
|
console.log('backend ' + backend)
|
|
console.log('doctype ' + doctype)
|
|
console.log('standalone ' + standalone)
|
|
console.log('section-numbers ' + sectionNumbers)
|
|
console.log('failure-level ' + level)
|
|
console.log('quiet ' + quiet)
|
|
console.log('verbose ' + verbose)
|
|
console.log('timings ' + timings)
|
|
console.log('trace ' + trace)
|
|
console.log('base-dir ' + baseDir)
|
|
console.log('destination-dir ' + destinationDir)
|
|
console.log('template-dir ' + templateDir)
|
|
console.log('template-engine ' + templateEngine)
|
|
}
|
|
const verboseMode = quiet ? 0 : verbose ? 2 : 1
|
|
if (sectionNumbers) {
|
|
attributes.push('sectnums')
|
|
}
|
|
const cliAttributes = args.attribute
|
|
if (cliAttributes) {
|
|
attributes.push(...cliAttributes)
|
|
}
|
|
if (debug) {
|
|
console.log('verbose-mode ' + verboseMode)
|
|
console.log('attributes ' + attributes)
|
|
}
|
|
const options = {
|
|
doctype: doctype,
|
|
safe: safeMode,
|
|
standalone: standalone,
|
|
failure_level: failureLevel,
|
|
verbose: verboseMode,
|
|
timings: timings,
|
|
trace: trace
|
|
}
|
|
if (backend) {
|
|
options.backend = backend
|
|
}
|
|
if (baseDir != null) {
|
|
options.base_dir = baseDir
|
|
}
|
|
if (destinationDir != null) {
|
|
options.to_dir = destinationDir
|
|
}
|
|
if (templateDir) {
|
|
options.template_dirs = templateDir
|
|
}
|
|
if (templateEngine) {
|
|
options.template_engine = templateEngine
|
|
}
|
|
if (typeof outFile !== 'undefined') {
|
|
if (outFile === '') {
|
|
options.to_file = '-'
|
|
} else {
|
|
options.to_file = outFile
|
|
options.mkdirs = true
|
|
}
|
|
} else {
|
|
options.mkdirs = true
|
|
}
|
|
options.attributes = attributes
|
|
if (debug) {
|
|
console.log('options ' + JSON.stringify(options))
|
|
}
|
|
if (options.to_file === '-') {
|
|
options.to_file = Opal.gvars.stdout
|
|
}
|
|
return options
|
|
}
|
|
|
|
class Options {
|
|
constructor (options) {
|
|
this.options = options || {}
|
|
this.args = {
|
|
standalone: typeof this.options.standalone !== 'undefined' ? this.options.standalone : true,
|
|
backend: this.options.backend,
|
|
'safe-mode': typeof this.options.safe !== 'undefined' ? this.options.safe : 'unsafe'
|
|
}
|
|
if (Array.isArray(this.options.attributes)) {
|
|
this.attributes = options.attributes
|
|
} else if (typeof this.options.attributes === 'object') {
|
|
const attrs = this.options.attributes
|
|
const attributes = []
|
|
Object.keys(attrs).forEach((key) => {
|
|
attributes.push(`${key}=${attrs[key]}`)
|
|
})
|
|
this.attributes = attributes
|
|
} else {
|
|
this.attributes = []
|
|
}
|
|
this.cmd = yargs
|
|
.option('backend', {
|
|
alias: 'b',
|
|
describe: 'set output format backend',
|
|
type: 'string'
|
|
})
|
|
.option('doctype', {
|
|
alias: 'd',
|
|
describe: 'document type to use when converting document',
|
|
choices: ['article', 'book', 'manpage', 'inline']
|
|
})
|
|
.option('out-file', {
|
|
alias: 'o',
|
|
describe: 'output file (default: based on path of input file) use \'\' to output to STDOUT',
|
|
type: 'string'
|
|
})
|
|
.option('safe-mode', {
|
|
alias: 'S',
|
|
describe: 'set safe mode level explicitly, disables potentially dangerous macros in source files, such as include::[]',
|
|
choices: ['unsafe', 'safe', 'server', 'secure']
|
|
})
|
|
.option('embedded', {
|
|
alias: 'e',
|
|
describe: 'suppress enclosing document structure and output an embedded document',
|
|
type: 'boolean'
|
|
})
|
|
.option('no-header-footer', {
|
|
alias: 's',
|
|
describe: 'suppress enclosing document structure and output an embedded document',
|
|
type: 'boolean'
|
|
})
|
|
.option('section-numbers', {
|
|
alias: 'n',
|
|
default: false,
|
|
describe: 'auto-number section titles in the HTML backend disabled by default',
|
|
type: 'boolean'
|
|
})
|
|
.option('base-dir', {
|
|
// QUESTION: should we check that the directory exists ? coerce to a directory ?
|
|
alias: 'B',
|
|
describe: 'base directory containing the document and resources (default: directory of source file)',
|
|
type: 'string'
|
|
})
|
|
.option('destination-dir', {
|
|
// QUESTION: should we check that the directory exists ? coerce to a directory ?
|
|
alias: 'D',
|
|
describe: 'destination output directory (default: directory of source file)',
|
|
type: 'string'
|
|
})
|
|
.option('failure-level', {
|
|
default: 'FATAL',
|
|
describe: 'set minimum logging level that triggers non-zero exit code',
|
|
choices: ['info', 'INFO', 'warn', 'WARN', 'warning', 'WARNING', 'error', 'ERROR', 'fatal', 'FATAL']
|
|
})
|
|
.option('quiet', {
|
|
alias: 'q',
|
|
default: false,
|
|
describe: 'suppress warnings',
|
|
type: 'boolean'
|
|
})
|
|
.option('trace', {
|
|
default: false,
|
|
describe: 'include backtrace information on errors',
|
|
type: 'boolean'
|
|
})
|
|
.option('verbose', {
|
|
alias: 'v',
|
|
default: false,
|
|
describe: 'enable verbose mode',
|
|
type: 'boolean'
|
|
})
|
|
.option('timings', {
|
|
alias: 't',
|
|
default: false,
|
|
describe: 'enable timings mode',
|
|
type: 'boolean'
|
|
})
|
|
.option('template-dir', {
|
|
alias: 'T',
|
|
array: true,
|
|
describe: 'a directory containing custom converter templates that override the built-in converter (may be specified multiple times)',
|
|
type: 'string'
|
|
})
|
|
.option('template-engine', {
|
|
alias: 'E',
|
|
describe: 'template engine to use for the custom converter templates',
|
|
type: 'string'
|
|
})
|
|
.option('attribute', {
|
|
alias: 'a',
|
|
array: true,
|
|
describe: 'a document attribute to set in the form of key, key! or key=value pair',
|
|
type: 'string'
|
|
})
|
|
.option('require', {
|
|
alias: 'r',
|
|
array: true,
|
|
describe: 'require the specified library before executing the processor, using the standard Node require',
|
|
type: 'string'
|
|
})
|
|
.version(false)
|
|
.option('version', {
|
|
alias: 'V',
|
|
default: false,
|
|
describe: 'display the version and runtime environment (or -v if no other flags or arguments)',
|
|
type: 'boolean'
|
|
})
|
|
.help(false)
|
|
.option('help', {
|
|
describe: `print a help message
|
|
show this usage if TOPIC is not specified or recognized
|
|
show an overview of the AsciiDoc syntax if TOPIC is syntax`,
|
|
type: 'string'
|
|
})
|
|
.nargs('template-dir', 1)
|
|
.nargs('attribute', 1)
|
|
.nargs('require', 1)
|
|
.usage(`$0 [options...] files...
|
|
Translate the AsciiDoc source file or file(s) into the backend output format (e.g., HTML 5, DocBook 5, etc.)
|
|
By default, the output is written to a file with the basename of the source file and the appropriate extension`)
|
|
.example('$0 -b html5 doc.asciidoc', 'convert an AsciiDoc file to HTML5; result will be written in a file named doc.html')
|
|
.epilogue('For more information, please visit https://asciidoctor.org/docs')
|
|
this.yargs = yargs
|
|
}
|
|
|
|
parse (argv) {
|
|
const processArgs = argv.slice(2)
|
|
this.argv = argv
|
|
const args = this.argsParser().parse(processArgs)
|
|
Object.assign(this.args, args)
|
|
const files = this.args.files
|
|
this.stdin = files && files.length === 0 && processArgs[processArgs.length - 1] === '-'
|
|
if (this.stdin) {
|
|
this.args['out-file'] = this.args['out-file'] || '-'
|
|
}
|
|
this.args['verbose-sole-argument'] = this.args.verbose && processArgs.length === 1
|
|
const options = convertOptions(this.args, this.attributes)
|
|
Object.assign(this.options, options)
|
|
return this
|
|
}
|
|
|
|
addOption (key, opt) {
|
|
this.cmd.option(key, opt)
|
|
return this
|
|
}
|
|
|
|
argsParser () {
|
|
return this.yargs
|
|
.detectLocale(false)
|
|
.wrap(Math.min(120, this.yargs.terminalWidth()))
|
|
.command('$0 [files...]', '', () => this.cmd)
|
|
.parserConfiguration({
|
|
'boolean-negation': false
|
|
})
|
|
}
|
|
}
|
|
|
|
module.exports = Options
|