wikicite/wcite

View on GitHub
bin/wcite

Summary

Maintainability
Test Coverage
#!/usr/bin/env node
const cli = require('../lib/cli')
const cite = require('../lib/util/cite')
const wcite = require('../lib/wcite')
const guessFormat = require('../lib/guess-format')
const fs = require('fs')

const { version } = require('../package.json')

cli
.version(`wcite ${version} with @citation-js/core ` + cite.version())
.usage('[options] [command] [file] [ids...]')
.description(`Manage bibliographic data from Wikidata. Bibliography CSL JSON file
can be specified explicitly or via YAML header field 'bibliography'.`)

.option('-b, --bibliography <file>', 'Bibliography file (CSL JSON)')
.option('-d, --document <file>', 'Document file with YAML header')
.option('-f, --format <name>', 'Output format (text|html|bibtex|bibtxt|json|ndjson)')
.option('-o, --output <file>', 'Output file. Format can be guessed from extension')
.option('-t, --template <name>', 'Citation template (apa|vancouver|harvard1)')
.option('-l, --language <lang>', 'Language codes (separate with space or comma)')
.option('-i, --ids <file>', 'Read ids from (use `-` for stdin)')
.option('-q, --quiet', 'Avoid status output')

const commands = {
  get: [' [ids...]', 'get and show bibliographic records'],
  add: [' <ids...>', 'add records specified by Wikidata identifiers'],
  remove: [' <ids...>', 'remove records by Wikidata identifiers or aliases'],
  show: [' [ids...]', 'show bibliographic records'],
  update: [' [ids...]', 'update bibliographic records'],
  list: ['', 'list Wikidata identifiers and aliases'],
  help: ['', 'display this usage help']
}

for (let cmd in commands) {
  cli.command(cmd + commands[cmd][0]).description(commands[cmd][1])
}

cli
.example('refs.json          # list Wikidata ids in refs.json')
.example('update refs.json   # update all entries in refs.json')
.example('Q18507561          # get bibliographic data from Wikidata')

cli.parse(process.argv)

if (!cli.args.length) {
  cli.help()
}

if (cli.output && !cli.format) {
  cli.format = guessFormat(cli.output)
}

const { isQid, cutQid } = require('../lib/util/wikidata')
const isFile = path => path && path.match(/\.[a-z]/)

let args = cli.args.map(cutQid)
let command

function optionalFileArg() {
  if (args.length) {
    if (args[0].match(/\.json$/) && cli.bibliography === undefined) {
      cli.bibliography = args.shift()
    } else if (!isQid(args[0]) && args[0].match(/\.[a-z]+/) && cli.document === undefined) {
      cli.document = args.shift()
    }
  }
}

if (args[0].match(/^[a-z]+$/)) {  // <command> [file] [ids...]
  command = args.shift()
  optionalFileArg()
} else {                          // [file] [command] [ids...]
  optionalFileArg()
  if (args.length && args[0].match(/^[a-z]+$/)) {
    command = args.shift()
  } else if (cli.format || cli.template) {
    command = 'get'
  } else if ((cli.bibliography || cli.document) && !args.length) {
    command = 'list'
  } else {                        // fetch data and directly show it
    command = 'get'
  }
}

// allow to abbreviate commands
if (command && !(command in commands)) {
  let guess = Object.keys(commands).find(cmd => cmd.startsWith(command))
  if (guess) {
    command = guess
  }
}

if (command === 'help') {
  cli.help()
} else {
  if (!(command in commands)) {
    console.error(`unknown command "${command}". Try "wcite help"!`)
    process.exit(1)
  }
  if (cli.ids) {
    if (args.length) {
      console.error(`Provide ids either via option or as arguments, not both!`)
      process.exit(1)
    } else {
      let file = fs.readFileSync(cli.ids === '-' ? 0 : cli.ids).toString()
      args = file.split(/[\s+]+/).map(s => s.trim()).filter(s => s !== '')
    }
  }
  wcite(cli)[command](args)
}