Skip to content

Instantly share code, notes, and snippets.

@jfhbrook
Created December 21, 2021 07:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfhbrook/86febed361648ea0d4f455b5a2ad983b to your computer and use it in GitHub Desktop.
Save jfhbrook/86febed361648ea0d4f455b5a2ad983b to your computer and use it in GitHub Desktop.
*record scratch* *freeze frame* yup, that's me. you're probably wondering how I got in this situation
// I wanted to use https://npm.im/terminal-image in kitty. Kitty supports
// inline image functionality similar to iTerm2, and while I was too lazy
// to look up whether they're the same I *wasn't* too lazy to try and make
// terminal-image think it's running in iTerm2.
//
// So you dig down the dependency tree. terminal-image is by @sindresorhus,
// who is known for two things:
//
// 1. Going hard on es modules without support for require
// 2. Going hard on micro-modules with deep dependency trees
//
// The tree to get to the relevant logic looks like this:
//
// terminal-image
// |-term-img https://github.com/sindresorhus/terminal-image/blob/main/index.js#L4
// |- iterm2-version https://github.com/sindresorhus/term-img/blob/main/index.js#L2
//
// with term-img checking that `process.env.TERM_PROGRAM === "iterm2.app"; and
// iterm2-version additionally parsing process.env.TERM_PROGRAM_VERSION. OK, fine,
// set those env variables in the shell, right? Well no - iterm2-version *also*
// checks that `process.platform === "darwin"`.
//
// So well, like I haven't done sketchy shit before:
const __platform = process.platform;
const __TERM_PROGRAM = process.env.TERM_PROGRAM;
const __TERM_PROGRAM_VERSION = process.env.TERM_PROGRAM_VERSION;
function pretendToBeITerm() {
process.platform = "darwin";
process.env.TERM_PROGRAM = "iTerm.app";
process.env.TERM_PROGRAM_VERSION = "3.0.15";
return function done() {
process.platform = __platform;
process.env.TERM_PROGRAM = __TERM_PROGRAM;
process.env.TERM_PROGRAM_VERSION = __TERM_PROGRAM_VERSION;
};
}
// and sure we can try to wrap every method coming out of the
// library to *do* that sketchy shit...
module.exports = {
async load() {
if (!this._terminalImage) {
// ...keeping in mind that dynamic import is asynchronous, so
// if you're on commonjs have fun injecting dependencies lol
this._terminalImage = (await import('terminal-image')).default;
donePretending();
// Hold my beer!!
['buffer', 'file', 'gifBuffer', 'gifFile'].forEach(method => {
this[method] = (...args) => {
const donePretending = pretendToBeITerm();
const rv = this._terminalImage[method](...args);
if (typeof rv.then === "function") {
rv = rv.then(r => {
donePretending();
return r;
});
} else {
donePretending();
}
return rv
};
});
}
}
};
//
// So we've been really clever and it'll work, right? Well no - if only:
//
// TypeError: Cannot read property '0' of undefined
// at terminalImage (file:///home/josh/joshiverse/apps/gritty/node_modules/term-img/index.js:29:20)
// at Object.terminalImage.buffer (file:///home/josh/joshiverse/apps/gritty/node_modules/terminal-image/index.js:95:9)
// at Object.terminalImage.file (file:///home/josh/joshiverse/apps/gritty/node_modules/terminal-image/index.js:103:16)
// at async main (/home/josh/joshiverse/apps/gritty/banner.js:49:15)
//
// My gambit to monkey patch terminal-image has been foiled by me not
// knowing any way to monkey patch the process object in another module.
// C'est la vie.
async function main() {
await module.exports.load();
// It turns out I don't actually want to do this anyway, doing
// it with proper text will work better. Shrug.
console.log(await module.exports.file('test.png', {width: 80}));
}
main().then(console.log, console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment