// Helper for displaying edit changes so they can be manually verified import {execSync} from 'node:child_process'; /** * Converts a string from UTF-8 to base64. * @param {string} str * @returns {string} */ const toBase64 = str => Buffer.from(str, 'utf-8').toString('base64'); /** * terrible terrible terrible string diff helper for debugging * @param {string} a * @param {string} b * @param {object} page Page object from the API, used to generate diff labels */ export function diff (a, b, page) { let labels = null; if (page) { // generate diff labels based on labels = [ `${page.title} (${page.revid ? `revision ${page.revid}` : 'current revision'}${page.timestamp ? ` from ${page.timestamp}` : ''})`, `${page.title} (pending edit)`, ]; } // base64 input strings before passing to shell to avoid escaping issues // https://stackoverflow.com/a/60221847 // use tail to cut off file info lines and re-add with fake filenames/dates // this function is so extra now holy shit execSync(String.raw`bash <<- 'EOF' diff --color=always -u \ ${labels ? `--label="$(echo '${toBase64(labels[0])}' | base64 -d)" ` : ''}<(echo '${toBase64(a)}' | base64 -d) \ ${labels ? `--label="$(echo '${toBase64(labels[1])}' | base64 -d)" ` : ''}<(echo '${toBase64(b)}' | base64 -d) \ ${labels ? `|| true` : `| tail -n +3` /* cut off header if no labels */} EOF`, { // display result directly in terminal stdio: 'inherit', }); }