quote.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. 'use strict';
  2. /** @import { ControlOperator } from './parse' */
  3. /** @type {ControlOperator['op'][]} */
  4. var OPS = /** @type {const} */ ([
  5. '||',
  6. '&&',
  7. ';;',
  8. '|&',
  9. '<(',
  10. '<<<',
  11. '>>',
  12. '>&',
  13. '<&',
  14. '&',
  15. ';',
  16. '(',
  17. ')',
  18. '|',
  19. '<',
  20. '>'
  21. ]);
  22. var LINE_TERMINATORS = /[\n\r\u2028\u2029]/;
  23. var GLOB_SHELL_SPECIAL = /[\s#!"$&'():;<=>@\\^`|]/g;
  24. /** @type {typeof import('./quote')} */
  25. module.exports = function quote(xs) {
  26. return xs.map(function (s) {
  27. if (s === '') {
  28. return /** @type {const} */ ('\'\'');
  29. }
  30. if (s && typeof s === 'object') {
  31. if ('op' in s && s.op === 'glob') {
  32. if (typeof s.pattern !== 'string') {
  33. throw new TypeError('glob token requires a string `pattern`');
  34. }
  35. if (LINE_TERMINATORS.test(s.pattern)) {
  36. throw new TypeError('glob `pattern` must not contain line terminators');
  37. }
  38. return s.pattern.replace(GLOB_SHELL_SPECIAL, '\\$&');
  39. }
  40. if ('op' in s && typeof s.op === 'string') {
  41. if (OPS.indexOf(s.op) < 0) {
  42. throw new TypeError('invalid `op` value: ' + JSON.stringify(s.op));
  43. }
  44. return s.op.replace(/[\s\S]/g, '\\$&');
  45. }
  46. if ('comment' in s && typeof s.comment === 'string') {
  47. if (LINE_TERMINATORS.test(s.comment)) {
  48. throw new TypeError('`comment` must not contain line terminators');
  49. }
  50. return '#' + s.comment;
  51. }
  52. throw new TypeError('unrecognized object token shape');
  53. }
  54. if ((/["\s\\]/).test(s) && !(/'/).test(s)) {
  55. return "'" + s.replace(/(['])/g, '\\$1') + "'";
  56. }
  57. if ((/["'\s]/).test(s)) {
  58. return '"' + s.replace(/(["\\$`!])/g, '\\$1') + '"';
  59. }
  60. return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}~])/g, '$1\\$2');
  61. }).join(' ');
  62. };