版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

121 строка
3.0 KiB

  1. import {Buffer} from 'node:buffer';
  2. import {ChildProcess} from 'node:child_process';
  3. const normalizeArgs = (file, args = []) => {
  4. if (!Array.isArray(args)) {
  5. return [file];
  6. }
  7. return [file, ...args];
  8. };
  9. const NO_ESCAPE_REGEXP = /^[\w.-]+$/;
  10. const DOUBLE_QUOTES_REGEXP = /"/g;
  11. const escapeArg = arg => {
  12. if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) {
  13. return arg;
  14. }
  15. return `"${arg.replace(DOUBLE_QUOTES_REGEXP, '\\"')}"`;
  16. };
  17. export const joinCommand = (file, args) => normalizeArgs(file, args).join(' ');
  18. export const getEscapedCommand = (file, args) => normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' ');
  19. const SPACES_REGEXP = / +/g;
  20. // Handle `execaCommand()`
  21. export const parseCommand = command => {
  22. const tokens = [];
  23. for (const token of command.trim().split(SPACES_REGEXP)) {
  24. // Allow spaces to be escaped by a backslash if not meant as a delimiter
  25. const previousToken = tokens[tokens.length - 1];
  26. if (previousToken && previousToken.endsWith('\\')) {
  27. // Merge previous token with current one
  28. tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`;
  29. } else {
  30. tokens.push(token);
  31. }
  32. }
  33. return tokens;
  34. };
  35. const parseExpression = expression => {
  36. const typeOfExpression = typeof expression;
  37. if (typeOfExpression === 'string') {
  38. return expression;
  39. }
  40. if (typeOfExpression === 'number') {
  41. return String(expression);
  42. }
  43. if (
  44. typeOfExpression === 'object'
  45. && expression !== null
  46. && !(expression instanceof ChildProcess)
  47. && 'stdout' in expression
  48. ) {
  49. const typeOfStdout = typeof expression.stdout;
  50. if (typeOfStdout === 'string') {
  51. return expression.stdout;
  52. }
  53. if (Buffer.isBuffer(expression.stdout)) {
  54. return expression.stdout.toString();
  55. }
  56. throw new TypeError(`Unexpected "${typeOfStdout}" stdout in template expression`);
  57. }
  58. throw new TypeError(`Unexpected "${typeOfExpression}" in template expression`);
  59. };
  60. const concatTokens = (tokens, nextTokens, isNew) => isNew || tokens.length === 0 || nextTokens.length === 0
  61. ? [...tokens, ...nextTokens]
  62. : [
  63. ...tokens.slice(0, -1),
  64. `${tokens[tokens.length - 1]}${nextTokens[0]}`,
  65. ...nextTokens.slice(1),
  66. ];
  67. const parseTemplate = ({templates, expressions, tokens, index, template}) => {
  68. const templateString = template ?? templates.raw[index];
  69. const templateTokens = templateString.split(SPACES_REGEXP).filter(Boolean);
  70. const newTokens = concatTokens(
  71. tokens,
  72. templateTokens,
  73. templateString.startsWith(' '),
  74. );
  75. if (index === expressions.length) {
  76. return newTokens;
  77. }
  78. const expression = expressions[index];
  79. const expressionTokens = Array.isArray(expression)
  80. ? expression.map(expression => parseExpression(expression))
  81. : [parseExpression(expression)];
  82. return concatTokens(
  83. newTokens,
  84. expressionTokens,
  85. templateString.endsWith(' '),
  86. );
  87. };
  88. export const parseTemplates = (templates, expressions) => {
  89. let tokens = [];
  90. for (const [index, template] of templates.entries()) {
  91. tokens = parseTemplate({templates, expressions, tokens, index, template});
  92. }
  93. return tokens;
  94. };