command.js 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. 'use strict';
  2. const normalizeArgs = (file, args = []) => {
  3. if (!Array.isArray(args)) {
  4. return [file];
  5. }
  6. return [file, ...args];
  7. };
  8. const NO_ESCAPE_REGEXP = /^[\w.-]+$/;
  9. const DOUBLE_QUOTES_REGEXP = /"/g;
  10. const escapeArg = arg => {
  11. if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) {
  12. return arg;
  13. }
  14. return `"${arg.replace(DOUBLE_QUOTES_REGEXP, '\\"')}"`;
  15. };
  16. const joinCommand = (file, args) => {
  17. return normalizeArgs(file, args).join(' ');
  18. };
  19. const getEscapedCommand = (file, args) => {
  20. return normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' ');
  21. };
  22. const SPACES_REGEXP = / +/g;
  23. // Handle `execa.command()`
  24. const parseCommand = command => {
  25. const tokens = [];
  26. for (const token of command.trim().split(SPACES_REGEXP)) {
  27. // Allow spaces to be escaped by a backslash if not meant as a delimiter
  28. const previousToken = tokens[tokens.length - 1];
  29. if (previousToken && previousToken.endsWith('\\')) {
  30. // Merge previous token with current one
  31. tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`;
  32. } else {
  33. tokens.push(token);
  34. }
  35. }
  36. return tokens;
  37. };
  38. module.exports = {
  39. joinCommand,
  40. getEscapedCommand,
  41. parseCommand
  42. };