command-join
Version:
Escape and join command-line arguments, cross-platform.
114 lines • 3.71 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const NEEDS_QUOTE = /[\s\\*\?\[\]`$()#<>|&;]/;
function joinNix(arr) {
const out = [];
for (const command of arr) {
// if it is an empty string then append an empty string indicator
if (command.length === 0) {
out.push("''");
continue;
}
// whether we need a quote for the current block
let needsQuote = false;
// collection of quoted strings and escaped single quotes
const blocks = [];
// string collector
let currentBlock = [];
const flushCurrentBlock = () => {
// skip if we don't have anything collected as the current block
if (!currentBlock.length) {
return;
}
if (needsQuote) {
currentBlock.unshift("'");
currentBlock.push("'");
}
blocks.push(currentBlock.join(''));
currentBlock = [];
};
for (const char of command) {
if (char === "'") { // if single quote
// flush the current block
flushCurrentBlock();
// escape a single quote
blocks.push("\\'");
continue;
}
if (NEEDS_QUOTE.test(char)) {
needsQuote = true;
}
currentBlock.push(char);
}
// flush last block
flushCurrentBlock();
const escapedCommand = blocks.join('');
out.push(escapedCommand);
}
return out.join(' ');
}
exports.joinNix = joinNix;
function joinWin(arr) {
const out = [];
for (const command of arr) {
// if it is an empty string then append an empty string indicator
if (command.length === 0) {
out.push('""');
continue;
}
if (!/[\s\\"<>|&]/.test(command)) {
out.push(command);
continue;
}
let backslashes = 0;
// start escape quote
const outString = ["\""];
const flushBackslashes = (n) => {
outString.push("\\".repeat(n * backslashes));
backslashes = 0;
};
for (let char of command) {
// if char is a backslash
if (char === "\\") {
// enqueue backslash
backslashes++;
}
// if char is a double quote
else if (char === "\"") {
// doubly end backslash sequence if any
flushBackslashes(2);
// push string \" to escape quote
outString.push("\\\"");
}
else {
// singly end backslash sequence if any
flushBackslashes(1);
outString.push(char);
}
}
// flush any remaining backslashes
flushBackslashes(2);
// end escape quote
outString.push("\"");
let escapedCommand = outString.join('');
// escape some special characters
escapedCommand = escapedCommand.replace(/[&|<>;%^]/g, match => `^${match}`);
out.push(escapedCommand);
}
return out.join(' ');
}
exports.joinWin = joinWin;
function commandJoin(arg) {
if (typeof arg === 'string') {
arg = [arg];
}
arg = Array.from(arg);
if (process.platform === 'win32') {
return joinWin(arg);
}
else {
return joinNix(arg);
}
}
exports.commandJoin = commandJoin;
//# sourceMappingURL=command-join.js.map
;