remy / inliner

Node utility to inline images, CSS and JavaScript for a web page - useful for mobile sites
MIT License
1.1k stars 165 forks source link

Inliner outputs an empty web page when executed under the Node.js `exec` function #228

Open ashleydavis opened 2 years ago

ashleydavis commented 2 years ago

I've discovered an issue when you run inliner under the Node.js exec or execSync function.

Take a working inliner command line this:

npx inliner index.html > out/index.html

Put the same command line in a JavaScript file and run it through execSync:

const { execSync } = require("child_process");

const result = execSync("npx inliner index.html > out/index.html");
console.log(result);

This causes an empty file to be written to out/index.html.

I've created a simple example of the problem here, follow the readme for the repo case: https://github.com/ashleydavis/inliner-issue

The problem originates with this line of code: https://github.com/remy/inliner/blob/df3619f89b5b4b76bd1b1bca675a58b38bf7a5b7/cli/options.js#L55

When inliner is invoked under execSync it sets isTTY to false which sets useStdin to true.

When useStdin is enabled nothing is read because no standard input is actually applied. Because nothing is read nothing is output: https://github.com/remy/inliner/blob/df3619f89b5b4b76bd1b1bca675a58b38bf7a5b7/cli/index.js#L35

After I realised what this issue was I was able to construct a workaround which you can see in my example project.

The workaround requires rearranging the command to actually give it the input via standard input:

const { execSync } = require("child_process");

const result = execSync("cat index.html | npx inliner > out/index.html");
console.log(result);

A good fix to this problem would be to make reading of standard input explicitly enabled by the user. The user should explicitly enable it by adding a dash to the end of the inliner command:

cat index.html | npx inliner - > out/index.html

You can see an example here of how the Kubectl tool does it.