Last active
May 19, 2020 17:02
-
-
Save oncomouse/9d97929ad212963ed7061b0361afefa9 to your computer and use it in GitHub Desktop.
Restore Pandoc Citation Keys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
I use this to restore citeproc keys to my Pandoc MS's after de-compiling Word | |
documents that have been edited using track changes. | |
*/ | |
const fs = require('fs') | |
const child_process = require('child_process') | |
// Tiny ARGV Parser: | |
const TinyArgv = function (argv) { | |
this.__argv = argv | |
} | |
/** | |
* Figure out the location of an argument in ARGV based on a key and an alias. | |
* Returns -1 if neither is found. | |
*/ | |
TinyArgv.prototype.__argIndex = function (key, alias) { | |
const index = { | |
key: this.__argv.indexOf(`--${key}`), | |
alias: alias ? this.__argv.indexOf(`-${alias}`) : -1 | |
} | |
return index.key >= 0 ? index.key : index.alias >= 0 ? index.alias : -1 | |
} | |
/** | |
* Extracts the value of a switch, which may be more than one word. | |
*/ | |
TinyArgv.prototype.__extractValue = function (index) { | |
const nextSwitch = this.__argv.slice(index + 1).reduce((acc, cur, idx) => acc >= 0 ? acc : cur.indexOf('-') === 0 ? idx : acc, -1) | |
return this.__argv.slice(index + 1, nextSwitch < 0 ? undefined : index + 1 + nextSwitch).join(' ') | |
} | |
/** | |
* Extract a flag (boolean) argument. | |
* Can have a single-character alias and a default value (so can be true instead | |
* of false). | |
*/ | |
TinyArgv.prototype.flag = function ({key, defaultValue = false, alias = false}) { | |
const indexOf = this.__argIndex(key, alias) | |
this[key] = indexOf >= 0 ? !defaultValue : defaultValue | |
return this; | |
} | |
/* | |
* Extract a string-based argument. | |
* Can have a single-character alias or a default value. | |
*/ | |
TinyArgv.prototype.value = function ({key, defaultValue = null, alias = false}) { | |
const indexOf = this.__argIndex(key, alias) | |
this[key] = indexOf >= 0 ? this.__extractValue(indexOf) : defaultValue | |
return this; | |
} | |
/** | |
* Convenient chain-initiating function. Call this to start the processing. | |
* Optional argument: can process a different array than process.argv | |
*/ | |
const argv = function (argv) { | |
return new TinyArgv(argv ? argv : process.argv.slice(2)) | |
} | |
const arguments = argv() | |
.value({key: 'original', defaultValue: './chapter.md', alias: 'r'}) | |
.value({key: 'formatted', defaultValue: './chapter-revised.md', alias: 'f'}) | |
.value({key: 'output', defaultValue: './chapter-corrected.md', alias: 'o'}) | |
.value({key: 'csl', defaultValue: fs.readFileSync('./Rakefile').toString().match(/\$cite_style = \"(.+?)\"/)[1]}) | |
.value({key: 'bibliography', defaultValue: fs.readFileSync('./Rakefile').toString().match(/bib_file = \"(.+?)\"/)[1].replace('#{ENV[\'HOME\']}', process.env.HOME)}) | |
// Thanks, Stack Overflow: | |
// https://stackoverflow.com/questions/5069464/replace-multiple-strings-at-once/34560648#34560648 | |
function str_replace($f, $r, $s) { | |
return $s.replace(new RegExp("(" + (typeof ($f) === "string" ? $f.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&") : $f.map(function (i) {return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|")) + ")", "g"), typeof ($r) === "string" ? $r : typeof ($f) === "string" ? $r[0] : function (i) {return $r[$f.indexOf(i)]}); | |
} | |
const rawCitations = fs.readFileSync(arguments.original).toString().match(/\[\@[^\]]+\]/g) | |
const substitutions = {} | |
// Process the list of all the raw citations from the original file to find the cite keys: | |
process.stdout.write('Processing citations in Pandoc (this is slow)…') | |
rawCitations.forEach(cite => { | |
substitutions[cite] = child_process.execSync(`echo "${cite}" | pandoc -f markdown+smart -t plain+smart --bibliography="${arguments.bibliography}" --csl="${arguments.csl}.csl"`).toString().split(/\n/g)[0] | |
}) | |
console.log('done') | |
fs.readFile(arguments.formatted, (_err, text) => { | |
fs.writeFile(arguments.output, str_replace(Object.values(substitutions), Object.keys(substitutions), text.toString()), () => {}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment