wikicite/wcite

View on GitHub
lib/pwcite.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * Implements the pwcite script.
 */
const wcite = require('./wcite')
const pandoc = require('./util/pandoc')
const { metadata, metavalues, walk } = pandoc

/**
 * Process each citation in a Pandoc document in-place.
 */
function processCitations (doc, action) {
  const nocite = metavalues(doc, 'nocite')

  walk([doc, nocite], (type, value) => {
    if (type === 'Cite') {
      value[0].forEach(action)
    }
  })
}

/**
 * Extract citekeys from metadata fields `citekeys` and `nocite` and from
 * Wikidata identifiers used as citation identifiers in the document.
 */
function getCitekeys (doc) {
  let citekeys = metavalues(doc, 'citekeys') || {}

  processCitations(doc, c => {
    if (!(c.citationId in citekeys)) {
      citekeys[c.citationId] = true
    }
  })

  return citekeys
}

/**
 * Replace citation keys in a document.
 */
function replaceCitekeys (doc, citekeys) {
  processCitations(doc, c => {
    const key = citekeys[c.citationId]
    if (typeof key === 'string' && key !== '') {
      c.citationId = citekeys[c.citationId]
    }
  })
}

/**
 * The actual Pandoc filter.
 */
function filter (root, format, meta) {
  let { bibliography, nocite } = metavalues(root)
  if (Array.isArray(bibliography)) {
    bibliography = bibliography.find(f => f.match(/\.json$/))
  } else if (bibliography && !bibliography.match(/.json$/)) {
    bibliography = undefined
  }

  let citekeys = getCitekeys(root)

  // TODO: set output to quiet or specify logfile?
  let out = process.stderr
  let cite = wcite({ bibliography, citekeys, nocite, out })

  let missing = Object.keys(cite.doc.citekeys).filter(id => cite.doc.citekeys[id] === false)
  cite.add(missing)

  if (!bibliography) {
    let refs = cite.doc.bibliography.references
    refs = Object.keys(refs).reduce((arr, key) => { // Object.values
      arr.push(refs[key])
      return arr
    }, [])
    meta.references = metadata(refs)
  }

  replaceCitekeys(root, citekeys)

  if (format && format.match(/^html/)) {
    require('./inject-wikidata-links')(meta)
  }

  return root
}

module.exports = {
  processCitations,
  getCitekeys,

  replaceCitekeys,
  filter,
  run: args => pandoc.filter(filter, args)
}