aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/shell-quote
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2025-06-28 17:26:46 -0700
committerPinapelz <yukais@pinapelz.com>2025-06-28 17:43:56 -0700
commite4fa1e69e7ebfb627c7198fd1a9881e9327ec4d4 (patch)
tree06284a538a6008eca75051399e47db4e5d50301c /node_modules/shell-quote
initial commit: scaffolding
Diffstat (limited to 'node_modules/shell-quote')
-rw-r--r--node_modules/shell-quote/.eslintrc30
-rw-r--r--node_modules/shell-quote/.github/FUNDING.yml12
-rw-r--r--node_modules/shell-quote/.nycrc14
-rw-r--r--node_modules/shell-quote/LICENSE24
-rw-r--r--node_modules/shell-quote/README.md161
-rw-r--r--node_modules/shell-quote/index.js4
-rw-r--r--node_modules/shell-quote/package.json72
-rw-r--r--node_modules/shell-quote/parse.js226
-rwxr-xr-xnode_modules/shell-quote/print.py3
-rw-r--r--node_modules/shell-quote/quote.js19
-rw-r--r--node_modules/shell-quote/security.md11
-rw-r--r--node_modules/shell-quote/test/comment.js16
-rw-r--r--node_modules/shell-quote/test/env.js52
-rw-r--r--node_modules/shell-quote/test/env_fn.js21
-rw-r--r--node_modules/shell-quote/test/op.js102
-rw-r--r--node_modules/shell-quote/test/parse.js44
-rw-r--r--node_modules/shell-quote/test/quote.js60
-rw-r--r--node_modules/shell-quote/test/set.js31
18 files changed, 902 insertions, 0 deletions
diff --git a/node_modules/shell-quote/.eslintrc b/node_modules/shell-quote/.eslintrc
new file mode 100644
index 0000000..9569d51
--- /dev/null
+++ b/node_modules/shell-quote/.eslintrc
@@ -0,0 +1,30 @@
+{
+ "root": true,
+
+ "extends": "@ljharb",
+
+ "rules": {
+ "array-bracket-newline": 0,
+ "complexity": 0,
+ "eqeqeq": 1,
+ "func-style": [2, "declaration"],
+ "max-depth": 0,
+ "max-lines-per-function": 0,
+ "max-statements": 0,
+ "multiline-comment-style": 0,
+ "no-negated-condition": 1,
+ "no-param-reassign": 1,
+ "no-lonely-if": 1,
+ "no-shadow": 1,
+ "no-template-curly-in-string": 0,
+ },
+
+ "overrides": [
+ {
+ "files": "example/**",
+ "rules": {
+ "no-console": 0,
+ },
+ },
+ ],
+}
diff --git a/node_modules/shell-quote/.github/FUNDING.yml b/node_modules/shell-quote/.github/FUNDING.yml
new file mode 100644
index 0000000..0b6b6b4
--- /dev/null
+++ b/node_modules/shell-quote/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: [ljharb]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: npm/shell-quote
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/node_modules/shell-quote/.nycrc b/node_modules/shell-quote/.nycrc
new file mode 100644
index 0000000..55c3d29
--- /dev/null
+++ b/node_modules/shell-quote/.nycrc
@@ -0,0 +1,14 @@
+{
+ "all": true,
+ "check-coverage": false,
+ "reporter": ["text-summary", "text", "html", "json"],
+ "lines": 86,
+ "statements": 85.93,
+ "functions": 82.43,
+ "branches": 76.06,
+ "exclude": [
+ "coverage",
+ "example",
+ "test"
+ ]
+}
diff --git a/node_modules/shell-quote/LICENSE b/node_modules/shell-quote/LICENSE
new file mode 100644
index 0000000..3d59c73
--- /dev/null
+++ b/node_modules/shell-quote/LICENSE
@@ -0,0 +1,24 @@
+The MIT License
+
+Copyright (c) 2013 James Halliday (mail@substack.net)
+
+Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to
+deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/node_modules/shell-quote/README.md b/node_modules/shell-quote/README.md
new file mode 100644
index 0000000..6b545c5
--- /dev/null
+++ b/node_modules/shell-quote/README.md
@@ -0,0 +1,161 @@
+# shell-quote <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
+
+[![github actions][actions-image]][actions-url]
+[![coverage][codecov-image]][codecov-url]
+[![License][license-image]][license-url]
+[![Downloads][downloads-image]][downloads-url]
+
+[![npm badge][npm-badge-png]][package-url]
+
+Parse and quote shell commands.
+
+# example
+
+## quote
+
+``` js
+var quote = require('shell-quote/quote');
+var s = quote([ 'a', 'b c d', '$f', '"g"' ]);
+console.log(s);
+```
+
+output
+
+```
+a 'b c d' \$f '"g"'
+```
+
+## parse
+
+``` js
+var parse = require('shell-quote/parse');
+var xs = parse('a "b c" \\$def \'it\\\'s great\'');
+console.dir(xs);
+```
+
+output
+
+```
+[ 'a', 'b c', '\\$def', 'it\'s great' ]
+```
+
+## parse with an environment variable
+
+``` js
+var parse = require('shell-quote/parse');
+var xs = parse('beep --boop="$PWD"', { PWD: '/home/robot' });
+console.dir(xs);
+```
+
+output
+
+```
+[ 'beep', '--boop=/home/robot' ]
+```
+
+## parse with custom escape character
+
+``` js
+var parse = require('shell-quote/parse');
+var xs = parse('beep ^--boop="$PWD"', { PWD: '/home/robot' }, { escape: '^' });
+console.dir(xs);
+```
+
+output
+
+```
+[ 'beep --boop=/home/robot' ]
+```
+
+## parsing shell operators
+
+``` js
+var parse = require('shell-quote/parse');
+var xs = parse('beep || boop > /byte');
+console.dir(xs);
+```
+
+output:
+
+```
+[ 'beep', { op: '||' }, 'boop', { op: '>' }, '/byte' ]
+```
+
+## parsing shell comment
+
+``` js
+var parse = require('shell-quote/parse');
+var xs = parse('beep > boop # > kaboom');
+console.dir(xs);
+```
+
+output:
+
+```
+[ 'beep', { op: '>' }, 'boop', { comment: '> kaboom' } ]
+```
+
+# methods
+
+``` js
+var quote = require('shell-quote/quote');
+var parse = require('shell-quote/parse');
+```
+
+## quote(args)
+
+Return a quoted string for the array `args` suitable for using in shell
+commands.
+
+## parse(cmd, env={})
+
+Return an array of arguments from the quoted string `cmd`.
+
+Interpolate embedded bash-style `$VARNAME` and `${VARNAME}` variables with
+the `env` object which like bash will replace undefined variables with `""`.
+
+`env` is usually an object but it can also be a function to perform lookups.
+When `env(key)` returns a string, its result will be output just like `env[key]`
+would. When `env(key)` returns an object, it will be inserted into the result
+array like the operator objects.
+
+When a bash operator is encountered, the element in the array with be an object
+with an `"op"` key set to the operator string. For example:
+
+```
+'beep || boop > /byte'
+```
+
+parses as:
+
+```
+[ 'beep', { op: '||' }, 'boop', { op: '>' }, '/byte' ]
+```
+
+# install
+
+With [npm](http://npmjs.org) do:
+
+```
+npm install shell-quote
+```
+
+# license
+
+MIT
+
+[package-url]: https://npmjs.org/package/shell-quote
+[npm-version-svg]: https://versionbadg.es/ljharb/shell-quote.svg
+[deps-svg]: https://david-dm.org/ljharb/shell-quote.svg
+[deps-url]: https://david-dm.org/ljharb/shell-quote
+[dev-deps-svg]: https://david-dm.org/ljharb/shell-quote/dev-status.svg
+[dev-deps-url]: https://david-dm.org/ljharb/shell-quote#info=devDependencies
+[npm-badge-png]: https://nodei.co/npm/shell-quote.png?downloads=true&stars=true
+[license-image]: https://img.shields.io/npm/l/shell-quote.svg
+[license-url]: LICENSE
+[downloads-image]: https://img.shields.io/npm/dm/shell-quote.svg
+[downloads-url]: https://npm-stat.com/charts.html?package=shell-quote
+[codecov-image]: https://codecov.io/gh/ljharb/shell-quote/branch/main/graphs/badge.svg
+[codecov-url]: https://app.codecov.io/gh/ljharb/shell-quote/
+[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/shell-quote
+[actions-url]: https://github.com/ljharb/shell-quote/actions
diff --git a/node_modules/shell-quote/index.js b/node_modules/shell-quote/index.js
new file mode 100644
index 0000000..28fb42d
--- /dev/null
+++ b/node_modules/shell-quote/index.js
@@ -0,0 +1,4 @@
+'use strict';
+
+exports.quote = require('./quote');
+exports.parse = require('./parse');
diff --git a/node_modules/shell-quote/package.json b/node_modules/shell-quote/package.json
new file mode 100644
index 0000000..b9bafdc
--- /dev/null
+++ b/node_modules/shell-quote/package.json
@@ -0,0 +1,72 @@
+{
+ "name": "shell-quote",
+ "description": "quote and parse shell commands",
+ "version": "1.8.3",
+ "author": {
+ "name": "James Halliday",
+ "email": "mail@substack.net",
+ "url": "http://substack.net"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ },
+ "bugs": "https://github.com/ljharb/shell-quote/issues",
+ "devDependencies": {
+ "@ljharb/eslint-config": "^21.1.1",
+ "auto-changelog": "^2.5.0",
+ "encoding": "^0.1.13",
+ "eslint": "=8.8.0",
+ "evalmd": "^0.0.19",
+ "in-publish": "^2.0.1",
+ "jackspeak": "=2.1.1",
+ "npmignore": "^0.3.1",
+ "nyc": "^10.3.2",
+ "safe-publish-latest": "^2.0.0",
+ "tape": "^5.9.0"
+ },
+ "homepage": "https://github.com/ljharb/shell-quote",
+ "keywords": [
+ "command",
+ "parse",
+ "quote",
+ "shell"
+ ],
+ "license": "MIT",
+ "main": "index.js",
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/ljharb/shell-quote.git"
+ },
+ "scripts": {
+ "prepack": "npmignore --auto --commentLines=autogenerated",
+ "prepublish": "not-in-publish || npm run prepublishOnly",
+ "prepublishOnly": "safe-publish-latest",
+ "prelint": "evalmd README.md",
+ "lint": "eslint --ext=js,mjs .",
+ "pretest": "npm run lint",
+ "tests-only": "nyc tape 'test/**/*.js'",
+ "test": "npm run tests-only",
+ "posttest": "npx npm@'>=10.2' audit --production",
+ "version": "auto-changelog && git add CHANGELOG.md",
+ "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
+ },
+ "auto-changelog": {
+ "output": "CHANGELOG.md",
+ "template": "keepachangelog",
+ "unreleased": false,
+ "commitLimit": false,
+ "backfillLimit": false,
+ "hideCredit": true,
+ "startingVersion": "1.7.4"
+ },
+ "publishConfig": {
+ "ignore": [
+ ".github/workflows",
+ "example",
+ "CHANGELOG.md"
+ ]
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+}
diff --git a/node_modules/shell-quote/parse.js b/node_modules/shell-quote/parse.js
new file mode 100644
index 0000000..71d2eea
--- /dev/null
+++ b/node_modules/shell-quote/parse.js
@@ -0,0 +1,226 @@
+'use strict';
+
+// '<(' is process substitution operator and
+// can be parsed the same as control operator
+var CONTROL = '(?:' + [
+ '\\|\\|',
+ '\\&\\&',
+ ';;',
+ '\\|\\&',
+ '\\<\\(',
+ '\\<\\<\\<',
+ '>>',
+ '>\\&',
+ '<\\&',
+ '[&;()|<>]'
+].join('|') + ')';
+var controlRE = new RegExp('^' + CONTROL + '$');
+var META = '|&;()<> \\t';
+var SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
+var DOUBLE_QUOTE = '\'((\\\\\'|[^\'])*?)\'';
+var hash = /^#$/;
+
+var SQ = "'";
+var DQ = '"';
+var DS = '$';
+
+var TOKEN = '';
+var mult = 0x100000000; // Math.pow(16, 8);
+for (var i = 0; i < 4; i++) {
+ TOKEN += (mult * Math.random()).toString(16);
+}
+var startsWithToken = new RegExp('^' + TOKEN);
+
+function matchAll(s, r) {
+ var origIndex = r.lastIndex;
+
+ var matches = [];
+ var matchObj;
+
+ while ((matchObj = r.exec(s))) {
+ matches.push(matchObj);
+ if (r.lastIndex === matchObj.index) {
+ r.lastIndex += 1;
+ }
+ }
+
+ r.lastIndex = origIndex;
+
+ return matches;
+}
+
+function getVar(env, pre, key) {
+ var r = typeof env === 'function' ? env(key) : env[key];
+ if (typeof r === 'undefined' && key != '') {
+ r = '';
+ } else if (typeof r === 'undefined') {
+ r = '$';
+ }
+
+ if (typeof r === 'object') {
+ return pre + TOKEN + JSON.stringify(r) + TOKEN;
+ }
+ return pre + r;
+}
+
+function parseInternal(string, env, opts) {
+ if (!opts) {
+ opts = {};
+ }
+ var BS = opts.escape || '\\';
+ var BAREWORD = '(\\' + BS + '[\'"' + META + ']|[^\\s\'"' + META + '])+';
+
+ var chunker = new RegExp([
+ '(' + CONTROL + ')', // control chars
+ '(' + BAREWORD + '|' + SINGLE_QUOTE + '|' + DOUBLE_QUOTE + ')+'
+ ].join('|'), 'g');
+
+ var matches = matchAll(string, chunker);
+
+ if (matches.length === 0) {
+ return [];
+ }
+ if (!env) {
+ env = {};
+ }
+
+ var commented = false;
+
+ return matches.map(function (match) {
+ var s = match[0];
+ if (!s || commented) {
+ return void undefined;
+ }
+ if (controlRE.test(s)) {
+ return { op: s };
+ }
+
+ // Hand-written scanner/parser for Bash quoting rules:
+ //
+ // 1. inside single quotes, all characters are printed literally.
+ // 2. inside double quotes, all characters are printed literally
+ // except variables prefixed by '$' and backslashes followed by
+ // either a double quote or another backslash.
+ // 3. outside of any quotes, backslashes are treated as escape
+ // characters and not printed (unless they are themselves escaped)
+ // 4. quote context can switch mid-token if there is no whitespace
+ // between the two quote contexts (e.g. all'one'"token" parses as
+ // "allonetoken")
+ var quote = false;
+ var esc = false;
+ var out = '';
+ var isGlob = false;
+ var i;
+
+ function parseEnvVar() {
+ i += 1;
+ var varend;
+ var varname;
+ var char = s.charAt(i);
+
+ if (char === '{') {
+ i += 1;
+ if (s.charAt(i) === '}') {
+ throw new Error('Bad substitution: ' + s.slice(i - 2, i + 1));
+ }
+ varend = s.indexOf('}', i);
+ if (varend < 0) {
+ throw new Error('Bad substitution: ' + s.slice(i));
+ }
+ varname = s.slice(i, varend);
+ i = varend;
+ } else if ((/[*@#?$!_-]/).test(char)) {
+ varname = char;
+ i += 1;
+ } else {
+ var slicedFromI = s.slice(i);
+ varend = slicedFromI.match(/[^\w\d_]/);
+ if (!varend) {
+ varname = slicedFromI;
+ i = s.length;
+ } else {
+ varname = slicedFromI.slice(0, varend.index);
+ i += varend.index - 1;
+ }
+ }
+ return getVar(env, '', varname);
+ }
+
+ for (i = 0; i < s.length; i++) {
+ var c = s.charAt(i);
+ isGlob = isGlob || (!quote && (c === '*' || c === '?'));
+ if (esc) {
+ out += c;
+ esc = false;
+ } else if (quote) {
+ if (c === quote) {
+ quote = false;
+ } else if (quote == SQ) {
+ out += c;
+ } else { // Double quote
+ if (c === BS) {
+ i += 1;
+ c = s.charAt(i);
+ if (c === DQ || c === BS || c === DS) {
+ out += c;
+ } else {
+ out += BS + c;
+ }
+ } else if (c === DS) {
+ out += parseEnvVar();
+ } else {
+ out += c;
+ }
+ }
+ } else if (c === DQ || c === SQ) {
+ quote = c;
+ } else if (controlRE.test(c)) {
+ return { op: s };
+ } else if (hash.test(c)) {
+ commented = true;
+ var commentObj = { comment: string.slice(match.index + i + 1) };
+ if (out.length) {
+ return [out, commentObj];
+ }
+ return [commentObj];
+ } else if (c === BS) {
+ esc = true;
+ } else if (c === DS) {
+ out += parseEnvVar();
+ } else {
+ out += c;
+ }
+ }
+
+ if (isGlob) {
+ return { op: 'glob', pattern: out };
+ }
+
+ return out;
+ }).reduce(function (prev, arg) { // finalize parsed arguments
+ // TODO: replace this whole reduce with a concat
+ return typeof arg === 'undefined' ? prev : prev.concat(arg);
+ }, []);
+}
+
+module.exports = function parse(s, env, opts) {
+ var mapped = parseInternal(s, env, opts);
+ if (typeof env !== 'function') {
+ return mapped;
+ }
+ return mapped.reduce(function (acc, s) {
+ if (typeof s === 'object') {
+ return acc.concat(s);
+ }
+ var xs = s.split(RegExp('(' + TOKEN + '.*?' + TOKEN + ')', 'g'));
+ if (xs.length === 1) {
+ return acc.concat(xs[0]);
+ }
+ return acc.concat(xs.filter(Boolean).map(function (x) {
+ if (startsWithToken.test(x)) {
+ return JSON.parse(x.split(TOKEN)[1]);
+ }
+ return x;
+ }));
+ }, []);
+};
diff --git a/node_modules/shell-quote/print.py b/node_modules/shell-quote/print.py
new file mode 100755
index 0000000..dc8e868
--- /dev/null
+++ b/node_modules/shell-quote/print.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python3
+import sys
+print(sys.argv[1])
diff --git a/node_modules/shell-quote/quote.js b/node_modules/shell-quote/quote.js
new file mode 100644
index 0000000..5152aed
--- /dev/null
+++ b/node_modules/shell-quote/quote.js
@@ -0,0 +1,19 @@
+'use strict';
+
+module.exports = function quote(xs) {
+ return xs.map(function (s) {
+ if (s === '') {
+ return '\'\'';
+ }
+ if (s && typeof s === 'object') {
+ return s.op.replace(/(.)/g, '\\$1');
+ }
+ if ((/["\s\\]/).test(s) && !(/'/).test(s)) {
+ return "'" + s.replace(/(['])/g, '\\$1') + "'";
+ }
+ if ((/["'\s]/).test(s)) {
+ return '"' + s.replace(/(["\\$`!])/g, '\\$1') + '"';
+ }
+ return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, '$1\\$2');
+ }).join(' ');
+};
diff --git a/node_modules/shell-quote/security.md b/node_modules/shell-quote/security.md
new file mode 100644
index 0000000..dc86413
--- /dev/null
+++ b/node_modules/shell-quote/security.md
@@ -0,0 +1,11 @@
+# Security Policy
+
+## Supported Versions
+
+Only the latest major version is supported at any given time.
+
+## Reporting a Vulnerability
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.
diff --git a/node_modules/shell-quote/test/comment.js b/node_modules/shell-quote/test/comment.js
new file mode 100644
index 0000000..fb15d5c
--- /dev/null
+++ b/node_modules/shell-quote/test/comment.js
@@ -0,0 +1,16 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../').parse;
+
+test('comment', function (t) {
+ t.same(parse('beep#boop'), ['beep', { comment: 'boop' }]);
+ t.same(parse('beep #boop'), ['beep', { comment: 'boop' }]);
+ t.same(parse('beep # boop'), ['beep', { comment: ' boop' }]);
+ t.same(parse('beep # > boop'), ['beep', { comment: ' > boop' }]);
+ t.same(parse('beep # "> boop"'), ['beep', { comment: ' "> boop"' }]);
+ t.same(parse('beep "#"'), ['beep', '#']);
+ t.same(parse('beep #"#"#'), ['beep', { comment: '"#"#' }]);
+ t.same(parse('beep > boop # > foo'), ['beep', { op: '>' }, 'boop', { comment: ' > foo' }]);
+ t.end();
+});
diff --git a/node_modules/shell-quote/test/env.js b/node_modules/shell-quote/test/env.js
new file mode 100644
index 0000000..4cc0a51
--- /dev/null
+++ b/node_modules/shell-quote/test/env.js
@@ -0,0 +1,52 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../').parse;
+
+test('expand environment variables', function (t) {
+ t.same(parse('a $XYZ c', { XYZ: 'b' }), ['a', 'b', 'c']);
+ t.same(parse('a${XYZ}c', { XYZ: 'b' }), ['abc']);
+ t.same(parse('a${XYZ}c $XYZ', { XYZ: 'b' }), ['abc', 'b']);
+ t.same(parse('"-$X-$Y-"', { X: 'a', Y: 'b' }), ['-a-b-']);
+ t.same(parse("'-$X-$Y-'", { X: 'a', Y: 'b' }), ['-$X-$Y-']);
+ t.same(parse('qrs"$zzz"wxy', { zzz: 'tuv' }), ['qrstuvwxy']);
+ t.same(parse("qrs'$zzz'wxy", { zzz: 'tuv' }), ['qrs$zzzwxy']);
+ t.same(parse('qrs${zzz}wxy'), ['qrswxy']);
+ t.same(parse('qrs$wxy $'), ['qrs', '$']);
+ t.same(parse('grep "xy$"'), ['grep', 'xy$']);
+ t.same(parse('ab$x', { x: 'c' }), ['abc']);
+ t.same(parse('ab\\$x', { x: 'c' }), ['ab$x']);
+ t.same(parse('ab${x}def', { x: 'c' }), ['abcdef']);
+ t.same(parse('ab\\${x}def', { x: 'c' }), ['ab${x}def']);
+ t.same(parse('"ab\\${x}def"', { x: 'c' }), ['ab${x}def']);
+
+ t.end();
+});
+
+test('expand environment variables within here-strings', function (t) {
+ t.same(parse('a <<< $x', { x: 'Joe' }), ['a', { op: '<<<' }, 'Joe']);
+ t.same(parse('a <<< ${x}', { x: 'Joe' }), ['a', { op: '<<<' }, 'Joe']);
+ t.same(parse('a <<< "$x"', { x: 'Joe' }), ['a', { op: '<<<' }, 'Joe']);
+ t.same(parse('a <<< "${x}"', { x: 'Joe' }), ['a', { op: '<<<' }, 'Joe']);
+
+ t.end();
+});
+
+test('environment variables with metacharacters', function (t) {
+ t.same(parse('a $XYZ c', { XYZ: '"b"' }), ['a', '"b"', 'c']);
+ t.same(parse('a $XYZ c', { XYZ: '$X', X: 5 }), ['a', '$X', 'c']);
+ t.same(parse('a"$XYZ"c', { XYZ: "'xyz'" }), ["a'xyz'c"]);
+
+ t.end();
+});
+
+test('special shell parameters', function (t) {
+ var chars = '*@#?-$!0_'.split('');
+ t.plan(chars.length);
+
+ chars.forEach(function (c) {
+ var env = {};
+ env[c] = 'xxx';
+ t.same(parse('a $' + c + ' c', env), ['a', 'xxx', 'c']);
+ });
+});
diff --git a/node_modules/shell-quote/test/env_fn.js b/node_modules/shell-quote/test/env_fn.js
new file mode 100644
index 0000000..968e912
--- /dev/null
+++ b/node_modules/shell-quote/test/env_fn.js
@@ -0,0 +1,21 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../').parse;
+
+function getEnv() {
+ return 'xxx';
+}
+
+function getEnvObj() {
+ return { op: '@@' };
+}
+
+test('functional env expansion', function (t) {
+ t.plan(4);
+
+ t.same(parse('a $XYZ c', getEnv), ['a', 'xxx', 'c']);
+ t.same(parse('a $XYZ c', getEnvObj), ['a', { op: '@@' }, 'c']);
+ t.same(parse('a${XYZ}c', getEnvObj), ['a', { op: '@@' }, 'c']);
+ t.same(parse('"a $XYZ c"', getEnvObj), ['a ', { op: '@@' }, ' c']);
+});
diff --git a/node_modules/shell-quote/test/op.js b/node_modules/shell-quote/test/op.js
new file mode 100644
index 0000000..38d3757
--- /dev/null
+++ b/node_modules/shell-quote/test/op.js
@@ -0,0 +1,102 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../').parse;
+
+test('single operators', function (t) {
+ t.same(parse('beep | boop'), ['beep', { op: '|' }, 'boop']);
+ t.same(parse('beep|boop'), ['beep', { op: '|' }, 'boop']);
+ t.same(parse('beep \\| boop'), ['beep', '|', 'boop']);
+ t.same(parse('beep "|boop"'), ['beep', '|boop']);
+
+ t.same(parse('echo zing &'), ['echo', 'zing', { op: '&' }]);
+ t.same(parse('echo zing&'), ['echo', 'zing', { op: '&' }]);
+ t.same(parse('echo zing\\&'), ['echo', 'zing&']);
+ t.same(parse('echo "zing\\&"'), ['echo', 'zing\\&']);
+
+ t.same(parse('beep;boop'), ['beep', { op: ';' }, 'boop']);
+ t.same(parse('(beep;boop)'), [
+ { op: '(' }, 'beep', { op: ';' }, 'boop', { op: ')' }
+ ]);
+
+ t.same(parse('beep>boop'), ['beep', { op: '>' }, 'boop']);
+ t.same(parse('beep 2>boop'), ['beep', '2', { op: '>' }, 'boop']);
+ t.same(parse('beep<boop'), ['beep', { op: '<' }, 'boop']);
+
+ t.end();
+});
+
+test('double operators', function (t) {
+ t.same(parse('beep || boop'), ['beep', { op: '||' }, 'boop']);
+ t.same(parse('beep||boop'), ['beep', { op: '||' }, 'boop']);
+ t.same(parse('beep ||boop'), ['beep', { op: '||' }, 'boop']);
+ t.same(parse('beep|| boop'), ['beep', { op: '||' }, 'boop']);
+ t.same(parse('beep || boop'), ['beep', { op: '||' }, 'boop']);
+
+ t.same(parse('beep && boop'), ['beep', { op: '&&' }, 'boop']);
+ t.same(
+ parse('beep && boop || byte'),
+ ['beep', { op: '&&' }, 'boop', { op: '||' }, 'byte']
+ );
+ t.same(
+ parse('beep&&boop||byte'),
+ ['beep', { op: '&&' }, 'boop', { op: '||' }, 'byte']
+ );
+ t.same(
+ parse('beep\\&\\&boop||byte'),
+ ['beep&&boop', { op: '||' }, 'byte']
+ );
+ t.same(
+ parse('beep\\&&boop||byte'),
+ ['beep&', { op: '&' }, 'boop', { op: '||' }, 'byte']
+ );
+ t.same(
+ parse('beep;;boop|&byte>>blip'),
+ ['beep', { op: ';;' }, 'boop', { op: '|&' }, 'byte', { op: '>>' }, 'blip']
+ );
+
+ t.same(parse('beep 2>&1'), ['beep', '2', { op: '>&' }, '1']);
+
+ t.same(
+ parse('beep<(boop)'),
+ ['beep', { op: '<(' }, 'boop', { op: ')' }]
+ );
+ t.same(
+ parse('beep<<(boop)'),
+ ['beep', { op: '<' }, { op: '<(' }, 'boop', { op: ')' }]
+ );
+
+ t.end();
+});
+
+test('duplicating input file descriptors', function (t) {
+ // duplicating stdout to file descriptor 3
+ t.same(parse('beep 3<&1'), ['beep', '3', { op: '<&' }, '1']);
+
+ // duplicating stdout to file descriptor 0, i.e. stdin
+ t.same(parse('beep <&1'), ['beep', { op: '<&' }, '1']);
+
+ // closes stdin
+ t.same(parse('beep <&-'), ['beep', { op: '<&' }, '-']);
+
+ t.end();
+});
+
+test('here strings', function (t) {
+ t.same(parse('cat <<< "hello world"'), ['cat', { op: '<<<' }, 'hello world']);
+ t.same(parse('cat <<< hello'), ['cat', { op: '<<<' }, 'hello']);
+ t.same(parse('cat<<<hello'), ['cat', { op: '<<<' }, 'hello']);
+ t.same(parse('cat<<<"hello world"'), ['cat', { op: '<<<' }, 'hello world']);
+
+ t.end();
+});
+
+test('glob patterns', function (t) {
+ t.same(
+ parse('tap test/*.test.js'),
+ ['tap', { op: 'glob', pattern: 'test/*.test.js' }]
+ );
+
+ t.same(parse('tap "test/*.test.js"'), ['tap', 'test/*.test.js']);
+ t.end();
+});
diff --git a/node_modules/shell-quote/test/parse.js b/node_modules/shell-quote/test/parse.js
new file mode 100644
index 0000000..e6c36b1
--- /dev/null
+++ b/node_modules/shell-quote/test/parse.js
@@ -0,0 +1,44 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../').parse;
+
+test('parse shell commands', function (t) {
+ t.same(parse(''), [], 'parses an empty string');
+
+ t['throws'](
+ function () { parse('${}'); },
+ Error,
+ 'empty substitution throws'
+ );
+ t['throws'](
+ function () { parse('${'); },
+ Error,
+ 'incomplete substitution throws'
+ );
+
+ t.same(parse('a \'b\' "c"'), ['a', 'b', 'c']);
+ t.same(
+ parse('beep "boop" \'foo bar baz\' "it\'s \\"so\\" groovy"'),
+ ['beep', 'boop', 'foo bar baz', 'it\'s "so" groovy']
+ );
+ t.same(parse('a b\\ c d'), ['a', 'b c', 'd']);
+ t.same(parse('\\$beep bo\\`op'), ['$beep', 'bo`op']);
+ t.same(parse('echo "foo = \\"foo\\""'), ['echo', 'foo = "foo"']);
+ t.same(parse(''), []);
+ t.same(parse(' '), []);
+ t.same(parse('\t'), []);
+ t.same(parse('a"b c d"e'), ['ab c de']);
+ t.same(parse('a\\ b"c d"\\ e f'), ['a bc d e', 'f']);
+ t.same(parse('a\\ b"c d"\\ e\'f g\' h'), ['a bc d ef g', 'h']);
+ t.same(parse("x \"bl'a\"'h'"), ['x', "bl'ah"]);
+ t.same(parse("x bl^'a^'h'", {}, { escape: '^' }), ['x', "bl'a'h"]);
+ t.same(parse('abcH def', {}, { escape: 'H' }), ['abc def']);
+
+ t.deepEqual(parse('# abc def ghi'), [{ comment: ' abc def ghi' }], 'start-of-line comment content is unparsed');
+ t.deepEqual(parse('xyz # abc def ghi'), ['xyz', { comment: ' abc def ghi' }], 'comment content is unparsed');
+
+ t.deepEqual(parse('-x "" -y'), ['-x', '', '-y'], 'empty string is preserved');
+
+ t.end();
+});
diff --git a/node_modules/shell-quote/test/quote.js b/node_modules/shell-quote/test/quote.js
new file mode 100644
index 0000000..814707f
--- /dev/null
+++ b/node_modules/shell-quote/test/quote.js
@@ -0,0 +1,60 @@
+'use strict';
+
+var test = require('tape');
+var quote = require('../').quote;
+
+test('quote', function (t) {
+ t.equal(quote(['a', 'b', 'c d']), 'a b \'c d\'');
+ t.equal(
+ quote(['a', 'b', "it's a \"neat thing\""]),
+ 'a b "it\'s a \\"neat thing\\""'
+ );
+ t.equal(
+ quote(['$', '`', '\'']),
+ '\\$ \\` "\'"'
+ );
+ t.equal(quote([]), '');
+ t.equal(quote(['a\nb']), "'a\nb'");
+ t.equal(quote([' #(){}*|][!']), "' #(){}*|][!'");
+ t.equal(quote(["'#(){}*|][!"]), '"\'#(){}*|][\\!"');
+ t.equal(quote(['X#(){}*|][!']), 'X\\#\\(\\)\\{\\}\\*\\|\\]\\[\\!');
+ t.equal(quote(['a\n#\nb']), "'a\n#\nb'");
+ t.equal(quote(['><;{}']), '\\>\\<\\;\\{\\}');
+ t.equal(quote(['a', 1, true, false]), 'a 1 true false');
+ t.equal(quote(['a', 1, null, undefined]), 'a 1 null undefined');
+ t.equal(quote(['a\\x']), "'a\\x'");
+ t.equal(quote(['a"b']), '\'a"b\'');
+ t.equal(quote(['"a"b"']), '\'"a"b"\'');
+ t.equal(quote(['a\\"b']), '\'a\\"b\'');
+ t.equal(quote(['a\\b']), '\'a\\b\'');
+ t.end();
+});
+
+test('quote ops', function (t) {
+ t.equal(quote(['a', { op: '|' }, 'b']), 'a \\| b');
+ t.equal(
+ quote(['a', { op: '&&' }, 'b', { op: ';' }, 'c']),
+ 'a \\&\\& b \\; c'
+ );
+ t.end();
+});
+
+test('quote windows paths', { skip: 'breaking change, disabled until 2.x' }, function (t) {
+ var path = 'C:\\projects\\node-shell-quote\\index.js';
+
+ t.equal(quote([path, 'b', 'c d']), 'C:\\projects\\node-shell-quote\\index.js b \'c d\'');
+
+ t.end();
+});
+
+test("chars for windows paths don't break out", function (t) {
+ var x = '`:\\a\\b';
+ t.equal(quote([x]), "'`:\\a\\b'");
+ t.end();
+});
+
+test('empty strings', function (t) {
+ t.equal(quote(['-x', '', 'y']), '-x \'\' y');
+
+ t.end();
+});
diff --git a/node_modules/shell-quote/test/set.js b/node_modules/shell-quote/test/set.js
new file mode 100644
index 0000000..9694538
--- /dev/null
+++ b/node_modules/shell-quote/test/set.js
@@ -0,0 +1,31 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../').parse;
+
+test('set env vars', function (t) {
+ t.same(
+ parse('ABC=444 x y z'),
+ ['ABC=444', 'x', 'y', 'z']
+ );
+ t.same(
+ parse('ABC=3\\ 4\\ 5 x y z'),
+ ['ABC=3 4 5', 'x', 'y', 'z']
+ );
+ t.same(
+ parse('X="7 8 9" printx'),
+ ['X=7 8 9', 'printx']
+ );
+ t.same(
+ parse('X="7 8 9"; printx'),
+ ['X=7 8 9', { op: ';' }, 'printx']
+ );
+ t.same(
+ parse('X="7 8 9"; printx', function () {
+ t.fail('should not have matched any keys');
+ }),
+ ['X=7 8 9', { op: ';' }, 'printx']
+ );
+
+ t.end();
+});
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage