├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── bin ├── parse-arguments.js ├── replace.js ├── search.js └── shared-options.js ├── defaultignore ├── out.txt ├── package.json ├── pnpm-lock.yaml ├── replace.js ├── test ├── README.md ├── cli.js ├── index.js ├── paths.js ├── sanity.js └── test_files │ ├── test_basic.txt │ ├── test_case.txt │ ├── test_multiline.txt │ ├── test_numbers.txt │ ├── test_paths │ ├── sample1.txt │ ├── test.png │ ├── test1.txt │ └── test2.txt │ └── test_preview.txt └── testfunc.js /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [6.x, 8.x, 9.x, 10.x, 11.x, 12.x] 12 | 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - run: npm install 20 | - run: npm test 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .idea 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2014 Heather Arthur and contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # COMMON ISSUE ON WINDOWS 2 | There is a built-in replace command on windows, if you get an error like this 3 | 4 | ```shell 5 | Invalid switch - -h 6 | No files replaced 7 | ``` 8 | 9 | You are using the windows replace 10 | 11 | # replace 12 | `replace` is a command line utility for performing search-and-replace on files. It's similar to sed but there are a few differences: 13 | 14 | * Modifies files when matches are found 15 | * Recursive search on directories with -r 16 | * Uses [JavaScript syntax](https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions#Using_Simple_Patterns) for regular expressions and [replacement strings](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter). 17 | 18 | # Install 19 | With [node.js](http://nodejs.org/) and [npm](http://github.com/isaacs/npm): 20 | 21 | npm install replace -g 22 | 23 | You can now use `replace` and `search` from the command line. 24 | 25 | 26 | ## Examples 27 | 28 | Replace all occurrences of "foo" with "bar" in files in the current directory: 29 | 30 | ``` 31 | replace 'foo' 'bar' * 32 | ``` 33 | 34 | Replace in all files in a recursive search of the current directory: 35 | 36 | ``` 37 | replace 'foo' 'bar' . -r 38 | ``` 39 | 40 | Replace only in test/file1.js and test/file2.js: 41 | 42 | ``` 43 | replace 'foo' 'bar' test/file1.js test/file2.js 44 | ``` 45 | 46 | Replace all word pairs with "_" in middle with a "-": 47 | 48 | ``` 49 | replace '(\w+)_(\w+)' '$1-$2' * 50 | ``` 51 | 52 | Replace only in files with names matching *.js: 53 | 54 | ``` 55 | replace 'foo' 'bar' . -r --include="*.js" 56 | ``` 57 | 58 | Don't replace in files with names matching *.min.js and *.py: 59 | 60 | ``` 61 | replace 'foo' 'bar' . -r --exclude="*.min.js,*.py" 62 | ``` 63 | 64 | Preview the replacements without modifying any files: 65 | 66 | ``` 67 | replace 'foo' 'bar' . -r --preview 68 | ``` 69 | 70 | Replace using stdin: 71 | 72 | ``` 73 | echo "asd" | replace "asd" "dsa" -z 74 | ``` 75 | 76 | See all the options: 77 | 78 | ``` 79 | replace -h 80 | ``` 81 | 82 | ## Search 83 | There's also a `search` command. It's like `grep`, but with `replace`'s syntax. 84 | 85 | ``` 86 | search "setTimeout" . -r 87 | ``` 88 | 89 | ## Programmatic Usage 90 | You can use replace from your JS program: 91 | 92 | ```javascript 93 | var replace = require("replace"); 94 | 95 | replace({ 96 | regex: "foo", 97 | replacement: "bar", 98 | paths: ['./Test/'], 99 | recursive: false, 100 | silent: false, 101 | }); 102 | ``` 103 | 104 | ## More Details 105 | 106 | ### Excludes 107 | By default, `replace` and `search` will exclude files (binaries, images, etc) that match patterns in the `"defaultignore"` located in this directory. 108 | 109 | ### On huge directories 110 | If `replace` is taking too long on a large directory, try turning on the quiet flag with `-q`, only including the necessary file types with `--include` or limiting the lines shown in a preview with `-n`. 111 | 112 | 113 | ## What it looks like 114 | ![replace](http://i.imgur.com/qmJjS.png) 115 | 116 | -------------------------------------------------------------------------------- /bin/parse-arguments.js: -------------------------------------------------------------------------------- 1 | var sharedOptions = require("./shared-options"); 2 | 3 | module.exports = function(scriptName, addlPosArgs, addlOpts) { 4 | addlPosArgs = addlPosArgs || []; 5 | addlOpts = addlOpts || {}; 6 | 7 | var posArgs = {}; 8 | var opts = {}; 9 | Object.keys(sharedOptions).forEach(function(name) { 10 | var option = sharedOptions[name]; 11 | if (typeof option.position === 'number') { 12 | posArgs[name] = option; 13 | } else { 14 | opts[name] = option; 15 | } 16 | }); 17 | 18 | var options = Object.assign({}, opts, addlOpts); 19 | 20 | var positionalArgs = []; 21 | [posArgs, addlPosArgs].forEach(function(posArgs) { 22 | Object.keys(posArgs).forEach(function(name) { 23 | var posArg = posArgs[name]; 24 | posArg.name = name; 25 | positionalArgs[posArg.position] = posArg; 26 | }); 27 | }); 28 | 29 | var command = "$0"; 30 | positionalArgs.forEach(function(positionalArg) { 31 | var option = positionalArg.name; 32 | 33 | if (positionalArg.array) { 34 | option += ".."; 35 | } 36 | if (positionalArg.demandOption) { 37 | option = "<" + option + ">"; 38 | } else { 39 | option = "[" + option + "]"; 40 | } 41 | 42 | command += " " + option; 43 | }); 44 | 45 | 46 | return require("yargs") 47 | .scriptName(scriptName) 48 | .command(command, "", function(yargs) { 49 | positionalArgs.forEach(function(positionalArg) { 50 | yargs.positional(positionalArg.name, positionalArg); 51 | }); 52 | }) 53 | .options(options) 54 | .argv; 55 | }; 56 | -------------------------------------------------------------------------------- /bin/replace.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var parseArguments = require("./parse-arguments"), 4 | replace = require("../replace"); 5 | 6 | /* Additional options that apply to `replace`, but not `search` */ 7 | var positionalArgs = { 8 | replacement: { 9 | position: 1, 10 | string: true, 11 | describe: "Replacement string for matches", 12 | demandOption: true 13 | }, 14 | paths: { 15 | position: 2, 16 | array: true, 17 | describe: "File or directory to search", 18 | default: ["*"] 19 | } 20 | }; 21 | 22 | var addlOptions = { 23 | 'function-file': { 24 | alias: 'f', 25 | describe: "Path of file containing JS replacement function", 26 | hidden: true 27 | }, 28 | silent: { 29 | abbr: 's', 30 | boolean: true, 31 | describe: "Don't print out anything" 32 | }, 33 | preview: { 34 | abbr: 'p', 35 | boolean: true, 36 | describe: "Preview the replacements, but don't modify files" 37 | } 38 | } 39 | 40 | var options = parseArguments("replace", positionalArgs, addlOptions); 41 | 42 | replace(options); 43 | -------------------------------------------------------------------------------- /bin/search.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var parseArguments = require("./parse-arguments"), 4 | replace = require("../replace"); 5 | 6 | var options = parseArguments("search"); 7 | 8 | replace(options); 9 | -------------------------------------------------------------------------------- /bin/shared-options.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | 3 | module.exports = { 4 | regex: { 5 | position: 0, 6 | string: true, 7 | describe: "JavaScript regex for searching file e.g. '\\d+'", 8 | demandOption: true 9 | }, 10 | paths: { 11 | position: 1, 12 | array: true, 13 | describe: "File or directory to search", 14 | default: ["*"] 15 | }, 16 | stdin: { 17 | abbr: 'z', 18 | boolean: true, 19 | describe: 'Use standard in for input' 20 | }, 21 | recursive: { 22 | abbr: 'r', 23 | boolean: true, 24 | describe: "Recursively search directories" 25 | }, 26 | ignoreCase: { 27 | abbr: 'i', 28 | boolean: true, 29 | describe: "Ignore case when searching" 30 | }, 31 | multiline: { 32 | abbr: 'm', 33 | boolean: true, 34 | describe: "Match line by line", 35 | default: true 36 | }, 37 | include: { 38 | string: true, 39 | describe: "Only search in these files, e.g. '*.js,*.foo'" 40 | }, 41 | exclude: { 42 | string: true, 43 | describe: "Don't search in these files, e.g. '*.min.js'" 44 | }, 45 | 'exclude-list': { 46 | string: true, 47 | describe: "Path of file containing a new-line separated list of files to ignore", 48 | default: path.join(__dirname, "..", "defaultignore"), 49 | hidden: true 50 | }, 51 | n: { 52 | number: true, 53 | describe: "Limit the number of lines to preview" 54 | }, 55 | count: { 56 | abbr: 'c', 57 | boolean: true, 58 | describe: 'Display count of occurances in each file' 59 | }, 60 | quiet: { 61 | abbr: 'q', 62 | boolean: true, 63 | describe: "Just print the names of the files matches occured in (faster)" 64 | }, 65 | color: { 66 | string: true, 67 | describe: "Highlight color", 68 | choices: ['red', 'green', 'blue', 'cyan', 'yellow', 'magenta', 'bold', 'italic'], 69 | default: 'cyan' 70 | }, 71 | fileColor: { 72 | string: true, 73 | describe: "Highlight matching file's name in color", 74 | choices: ['red', 'green', 'blue', 'cyan', 'yellow', 'magenta', 'bold', 'italic'], 75 | default: 'yellow' 76 | }, 77 | async: { 78 | abbr: 'a', 79 | boolean: true, 80 | describe: "Asynchronously read/write files in directory (faster)", 81 | hidden: true 82 | }, 83 | noColor: { 84 | boolean: true, 85 | describe: "Disable color output" 86 | } 87 | }; 88 | -------------------------------------------------------------------------------- /defaultignore: -------------------------------------------------------------------------------- 1 | # Repositories # 2 | .git 3 | .hg 4 | .svn 5 | 6 | # Font files # 7 | *.ttf 8 | *.eot 9 | *.woff 10 | 11 | # Data # 12 | *.bson 13 | 14 | # Image files # 15 | *.xcf 16 | *.psd 17 | *.jpg 18 | *.png 19 | *.gif 20 | *.jpeg 21 | *.ico 22 | *.bmp 23 | *.tiff 24 | *.swp 25 | *.mpg 26 | *.swf 27 | *.flv 28 | *.avi 29 | *.mov 30 | *.wav 31 | *.wmv 32 | *.mp3 33 | *.flac 34 | *.ogg 35 | 36 | # Compiled source # 37 | *.com 38 | *.class 39 | *.dll 40 | *.exe 41 | *.a 42 | *.o 43 | *.so 44 | *.pyc 45 | *.pyo 46 | 47 | # Packages # 48 | *.7z 49 | *.dmg 50 | *.gz 51 | *.iso 52 | *.jar 53 | *.rar 54 | *.tar 55 | *.zip 56 | 57 | # Logs and databases # 58 | *.sql 59 | *.sqlite 60 | 61 | # OS generated files # 62 | .DS_Store 63 | ehthumbs.db 64 | Thumbs.db 65 | -------------------------------------------------------------------------------- /out.txt: -------------------------------------------------------------------------------- 1 | _,multiline,exclude-list,excludeList,color,fileColor,file-color,paths,$0,regex,replacement -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "replace", 3 | "description": "Command line search and replace utility", 4 | "license": "MIT", 5 | "version": "1.2.2", 6 | "author": "Alessandro Maclaine ", 7 | "main": "replace.js", 8 | "engines": { 9 | "node": ">= 6" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/ALMaclaine/replace" 14 | }, 15 | "scripts": { 16 | "test": "node test" 17 | }, 18 | "dependencies": { 19 | "chalk": "2.4.2", 20 | "minimatch": "3.0.5", 21 | "yargs": "^15.3.1" 22 | }, 23 | "devDependencies": { 24 | "tape": "4.11.0" 25 | }, 26 | "bin": { 27 | "replace": "./bin/replace.js", 28 | "search": "./bin/search.js" 29 | }, 30 | "keywords": [ 31 | "sed", 32 | "grep", 33 | "search", 34 | "replace" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | chalk: 2.4.2 5 | minimatch: 3.0.5 6 | tape: 4.11.0 7 | yargs: ^15.3.1 8 | 9 | dependencies: 10 | chalk: 2.4.2 11 | minimatch: 3.0.5 12 | yargs: 15.4.1 13 | 14 | devDependencies: 15 | tape: 4.11.0 16 | 17 | packages: 18 | 19 | /ansi-regex/5.0.1: 20 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 21 | engines: {node: '>=8'} 22 | dev: false 23 | 24 | /ansi-styles/3.2.1: 25 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 26 | engines: {node: '>=4'} 27 | dependencies: 28 | color-convert: 1.9.3 29 | dev: false 30 | 31 | /ansi-styles/4.3.0: 32 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 33 | engines: {node: '>=8'} 34 | dependencies: 35 | color-convert: 2.0.1 36 | dev: false 37 | 38 | /balanced-match/1.0.2: 39 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 40 | 41 | /brace-expansion/1.1.11: 42 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 43 | dependencies: 44 | balanced-match: 1.0.2 45 | concat-map: 0.0.1 46 | 47 | /call-bind/1.0.2: 48 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} 49 | dependencies: 50 | function-bind: 1.1.1 51 | get-intrinsic: 1.1.3 52 | dev: true 53 | 54 | /camelcase/5.3.1: 55 | resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} 56 | engines: {node: '>=6'} 57 | dev: false 58 | 59 | /chalk/2.4.2: 60 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} 61 | engines: {node: '>=4'} 62 | dependencies: 63 | ansi-styles: 3.2.1 64 | escape-string-regexp: 1.0.5 65 | supports-color: 5.5.0 66 | dev: false 67 | 68 | /cliui/6.0.0: 69 | resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} 70 | dependencies: 71 | string-width: 4.2.3 72 | strip-ansi: 6.0.1 73 | wrap-ansi: 6.2.0 74 | dev: false 75 | 76 | /color-convert/1.9.3: 77 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 78 | dependencies: 79 | color-name: 1.1.3 80 | dev: false 81 | 82 | /color-convert/2.0.1: 83 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 84 | engines: {node: '>=7.0.0'} 85 | dependencies: 86 | color-name: 1.1.4 87 | dev: false 88 | 89 | /color-name/1.1.3: 90 | resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} 91 | dev: false 92 | 93 | /color-name/1.1.4: 94 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 95 | dev: false 96 | 97 | /concat-map/0.0.1: 98 | resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} 99 | 100 | /decamelize/1.2.0: 101 | resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=} 102 | engines: {node: '>=0.10.0'} 103 | dev: false 104 | 105 | /deep-equal/1.0.1: 106 | resolution: {integrity: sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=} 107 | dev: true 108 | 109 | /define-properties/1.1.4: 110 | resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} 111 | engines: {node: '>= 0.4'} 112 | dependencies: 113 | has-property-descriptors: 1.0.0 114 | object-keys: 1.1.1 115 | dev: true 116 | 117 | /defined/1.0.1: 118 | resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} 119 | dev: true 120 | 121 | /emoji-regex/8.0.0: 122 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 123 | dev: false 124 | 125 | /es-abstract/1.20.4: 126 | resolution: {integrity: sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==} 127 | engines: {node: '>= 0.4'} 128 | dependencies: 129 | call-bind: 1.0.2 130 | es-to-primitive: 1.2.1 131 | function-bind: 1.1.1 132 | function.prototype.name: 1.1.5 133 | get-intrinsic: 1.1.3 134 | get-symbol-description: 1.0.0 135 | has: 1.0.3 136 | has-property-descriptors: 1.0.0 137 | has-symbols: 1.0.3 138 | internal-slot: 1.0.3 139 | is-callable: 1.2.7 140 | is-negative-zero: 2.0.2 141 | is-regex: 1.1.4 142 | is-shared-array-buffer: 1.0.2 143 | is-string: 1.0.7 144 | is-weakref: 1.0.2 145 | object-inspect: 1.12.2 146 | object-keys: 1.1.1 147 | object.assign: 4.1.4 148 | regexp.prototype.flags: 1.4.3 149 | safe-regex-test: 1.0.0 150 | string.prototype.trimend: 1.0.5 151 | string.prototype.trimstart: 1.0.5 152 | unbox-primitive: 1.0.2 153 | dev: true 154 | 155 | /es-to-primitive/1.2.1: 156 | resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} 157 | engines: {node: '>= 0.4'} 158 | dependencies: 159 | is-callable: 1.2.7 160 | is-date-object: 1.0.5 161 | is-symbol: 1.0.4 162 | dev: true 163 | 164 | /escape-string-regexp/1.0.5: 165 | resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} 166 | engines: {node: '>=0.8.0'} 167 | dev: false 168 | 169 | /find-up/4.1.0: 170 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 171 | engines: {node: '>=8'} 172 | dependencies: 173 | locate-path: 5.0.0 174 | path-exists: 4.0.0 175 | dev: false 176 | 177 | /for-each/0.3.3: 178 | resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} 179 | dependencies: 180 | is-callable: 1.2.7 181 | dev: true 182 | 183 | /fs.realpath/1.0.0: 184 | resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} 185 | dev: true 186 | 187 | /function-bind/1.1.1: 188 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 189 | dev: true 190 | 191 | /function.prototype.name/1.1.5: 192 | resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} 193 | engines: {node: '>= 0.4'} 194 | dependencies: 195 | call-bind: 1.0.2 196 | define-properties: 1.1.4 197 | es-abstract: 1.20.4 198 | functions-have-names: 1.2.3 199 | dev: true 200 | 201 | /functions-have-names/1.2.3: 202 | resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 203 | dev: true 204 | 205 | /get-caller-file/2.0.5: 206 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 207 | engines: {node: 6.* || 8.* || >= 10.*} 208 | dev: false 209 | 210 | /get-intrinsic/1.1.3: 211 | resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} 212 | dependencies: 213 | function-bind: 1.1.1 214 | has: 1.0.3 215 | has-symbols: 1.0.3 216 | dev: true 217 | 218 | /get-symbol-description/1.0.0: 219 | resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} 220 | engines: {node: '>= 0.4'} 221 | dependencies: 222 | call-bind: 1.0.2 223 | get-intrinsic: 1.1.3 224 | dev: true 225 | 226 | /glob/7.1.7: 227 | resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} 228 | dependencies: 229 | fs.realpath: 1.0.0 230 | inflight: 1.0.6 231 | inherits: 2.0.4 232 | minimatch: 3.0.5 233 | once: 1.4.0 234 | path-is-absolute: 1.0.1 235 | dev: true 236 | 237 | /has-bigints/1.0.2: 238 | resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} 239 | dev: true 240 | 241 | /has-flag/3.0.0: 242 | resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} 243 | engines: {node: '>=4'} 244 | dev: false 245 | 246 | /has-property-descriptors/1.0.0: 247 | resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} 248 | dependencies: 249 | get-intrinsic: 1.1.3 250 | dev: true 251 | 252 | /has-symbols/1.0.3: 253 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 254 | engines: {node: '>= 0.4'} 255 | dev: true 256 | 257 | /has-tostringtag/1.0.0: 258 | resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} 259 | engines: {node: '>= 0.4'} 260 | dependencies: 261 | has-symbols: 1.0.3 262 | dev: true 263 | 264 | /has/1.0.3: 265 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 266 | engines: {node: '>= 0.4.0'} 267 | dependencies: 268 | function-bind: 1.1.1 269 | dev: true 270 | 271 | /inflight/1.0.6: 272 | resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} 273 | dependencies: 274 | once: 1.4.0 275 | wrappy: 1.0.2 276 | dev: true 277 | 278 | /inherits/2.0.4: 279 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 280 | dev: true 281 | 282 | /internal-slot/1.0.3: 283 | resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} 284 | engines: {node: '>= 0.4'} 285 | dependencies: 286 | get-intrinsic: 1.1.3 287 | has: 1.0.3 288 | side-channel: 1.0.4 289 | dev: true 290 | 291 | /is-bigint/1.0.4: 292 | resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} 293 | dependencies: 294 | has-bigints: 1.0.2 295 | dev: true 296 | 297 | /is-boolean-object/1.1.2: 298 | resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} 299 | engines: {node: '>= 0.4'} 300 | dependencies: 301 | call-bind: 1.0.2 302 | has-tostringtag: 1.0.0 303 | dev: true 304 | 305 | /is-callable/1.2.7: 306 | resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 307 | engines: {node: '>= 0.4'} 308 | dev: true 309 | 310 | /is-date-object/1.0.5: 311 | resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} 312 | engines: {node: '>= 0.4'} 313 | dependencies: 314 | has-tostringtag: 1.0.0 315 | dev: true 316 | 317 | /is-fullwidth-code-point/3.0.0: 318 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 319 | engines: {node: '>=8'} 320 | dev: false 321 | 322 | /is-negative-zero/2.0.2: 323 | resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} 324 | engines: {node: '>= 0.4'} 325 | dev: true 326 | 327 | /is-number-object/1.0.7: 328 | resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} 329 | engines: {node: '>= 0.4'} 330 | dependencies: 331 | has-tostringtag: 1.0.0 332 | dev: true 333 | 334 | /is-regex/1.1.4: 335 | resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} 336 | engines: {node: '>= 0.4'} 337 | dependencies: 338 | call-bind: 1.0.2 339 | has-tostringtag: 1.0.0 340 | dev: true 341 | 342 | /is-shared-array-buffer/1.0.2: 343 | resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} 344 | dependencies: 345 | call-bind: 1.0.2 346 | dev: true 347 | 348 | /is-string/1.0.7: 349 | resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} 350 | engines: {node: '>= 0.4'} 351 | dependencies: 352 | has-tostringtag: 1.0.0 353 | dev: true 354 | 355 | /is-symbol/1.0.4: 356 | resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} 357 | engines: {node: '>= 0.4'} 358 | dependencies: 359 | has-symbols: 1.0.3 360 | dev: true 361 | 362 | /is-weakref/1.0.2: 363 | resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} 364 | dependencies: 365 | call-bind: 1.0.2 366 | dev: true 367 | 368 | /locate-path/5.0.0: 369 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 370 | engines: {node: '>=8'} 371 | dependencies: 372 | p-locate: 4.1.0 373 | dev: false 374 | 375 | /minimatch/3.0.5: 376 | resolution: {integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==} 377 | dependencies: 378 | brace-expansion: 1.1.11 379 | 380 | /minimist/1.2.7: 381 | resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} 382 | dev: true 383 | 384 | /object-inspect/1.12.2: 385 | resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} 386 | dev: true 387 | 388 | /object-inspect/1.6.0: 389 | resolution: {integrity: sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==} 390 | dev: true 391 | 392 | /object-keys/1.1.1: 393 | resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 394 | engines: {node: '>= 0.4'} 395 | dev: true 396 | 397 | /object.assign/4.1.4: 398 | resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} 399 | engines: {node: '>= 0.4'} 400 | dependencies: 401 | call-bind: 1.0.2 402 | define-properties: 1.1.4 403 | has-symbols: 1.0.3 404 | object-keys: 1.1.1 405 | dev: true 406 | 407 | /once/1.4.0: 408 | resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} 409 | dependencies: 410 | wrappy: 1.0.2 411 | dev: true 412 | 413 | /p-limit/2.3.0: 414 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 415 | engines: {node: '>=6'} 416 | dependencies: 417 | p-try: 2.2.0 418 | dev: false 419 | 420 | /p-locate/4.1.0: 421 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 422 | engines: {node: '>=8'} 423 | dependencies: 424 | p-limit: 2.3.0 425 | dev: false 426 | 427 | /p-try/2.2.0: 428 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 429 | engines: {node: '>=6'} 430 | dev: false 431 | 432 | /path-exists/4.0.0: 433 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 434 | engines: {node: '>=8'} 435 | dev: false 436 | 437 | /path-is-absolute/1.0.1: 438 | resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} 439 | engines: {node: '>=0.10.0'} 440 | dev: true 441 | 442 | /path-parse/1.0.7: 443 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 444 | dev: true 445 | 446 | /regexp.prototype.flags/1.4.3: 447 | resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} 448 | engines: {node: '>= 0.4'} 449 | dependencies: 450 | call-bind: 1.0.2 451 | define-properties: 1.1.4 452 | functions-have-names: 1.2.3 453 | dev: true 454 | 455 | /require-directory/2.1.1: 456 | resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} 457 | engines: {node: '>=0.10.0'} 458 | dev: false 459 | 460 | /require-main-filename/2.0.0: 461 | resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} 462 | dev: false 463 | 464 | /resolve/1.11.1: 465 | resolution: {integrity: sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==} 466 | dependencies: 467 | path-parse: 1.0.7 468 | dev: true 469 | 470 | /resumer/0.0.0: 471 | resolution: {integrity: sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w==} 472 | dependencies: 473 | through: 2.3.8 474 | dev: true 475 | 476 | /safe-regex-test/1.0.0: 477 | resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} 478 | dependencies: 479 | call-bind: 1.0.2 480 | get-intrinsic: 1.1.3 481 | is-regex: 1.1.4 482 | dev: true 483 | 484 | /set-blocking/2.0.0: 485 | resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} 486 | dev: false 487 | 488 | /side-channel/1.0.4: 489 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} 490 | dependencies: 491 | call-bind: 1.0.2 492 | get-intrinsic: 1.1.3 493 | object-inspect: 1.12.2 494 | dev: true 495 | 496 | /string-width/4.2.3: 497 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 498 | engines: {node: '>=8'} 499 | dependencies: 500 | emoji-regex: 8.0.0 501 | is-fullwidth-code-point: 3.0.0 502 | strip-ansi: 6.0.1 503 | dev: false 504 | 505 | /string.prototype.trim/1.1.2: 506 | resolution: {integrity: sha512-IlEfUereZQqIcv/LJFNPUygFkq0HJCQMnaDr5i+zyRXpeYvF4F8J8u4UFxXICLMY+O3SEfJeaye5AO5miS6a9g==} 507 | engines: {node: '>= 0.4'} 508 | dependencies: 509 | define-properties: 1.1.4 510 | es-abstract: 1.20.4 511 | function-bind: 1.1.1 512 | dev: true 513 | 514 | /string.prototype.trimend/1.0.5: 515 | resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==} 516 | dependencies: 517 | call-bind: 1.0.2 518 | define-properties: 1.1.4 519 | es-abstract: 1.20.4 520 | dev: true 521 | 522 | /string.prototype.trimstart/1.0.5: 523 | resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==} 524 | dependencies: 525 | call-bind: 1.0.2 526 | define-properties: 1.1.4 527 | es-abstract: 1.20.4 528 | dev: true 529 | 530 | /strip-ansi/6.0.1: 531 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 532 | engines: {node: '>=8'} 533 | dependencies: 534 | ansi-regex: 5.0.1 535 | dev: false 536 | 537 | /supports-color/5.5.0: 538 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 539 | engines: {node: '>=4'} 540 | dependencies: 541 | has-flag: 3.0.0 542 | dev: false 543 | 544 | /tape/4.11.0: 545 | resolution: {integrity: sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==} 546 | hasBin: true 547 | dependencies: 548 | deep-equal: 1.0.1 549 | defined: 1.0.1 550 | for-each: 0.3.3 551 | function-bind: 1.1.1 552 | glob: 7.1.7 553 | has: 1.0.3 554 | inherits: 2.0.4 555 | minimist: 1.2.7 556 | object-inspect: 1.6.0 557 | resolve: 1.11.1 558 | resumer: 0.0.0 559 | string.prototype.trim: 1.1.2 560 | through: 2.3.8 561 | dev: true 562 | 563 | /through/2.3.8: 564 | resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=} 565 | dev: true 566 | 567 | /unbox-primitive/1.0.2: 568 | resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} 569 | dependencies: 570 | call-bind: 1.0.2 571 | has-bigints: 1.0.2 572 | has-symbols: 1.0.3 573 | which-boxed-primitive: 1.0.2 574 | dev: true 575 | 576 | /which-boxed-primitive/1.0.2: 577 | resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} 578 | dependencies: 579 | is-bigint: 1.0.4 580 | is-boolean-object: 1.1.2 581 | is-number-object: 1.0.7 582 | is-string: 1.0.7 583 | is-symbol: 1.0.4 584 | dev: true 585 | 586 | /which-module/2.0.0: 587 | resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} 588 | dev: false 589 | 590 | /wrap-ansi/6.2.0: 591 | resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} 592 | engines: {node: '>=8'} 593 | dependencies: 594 | ansi-styles: 4.3.0 595 | string-width: 4.2.3 596 | strip-ansi: 6.0.1 597 | dev: false 598 | 599 | /wrappy/1.0.2: 600 | resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} 601 | dev: true 602 | 603 | /y18n/4.0.3: 604 | resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} 605 | dev: false 606 | 607 | /yargs-parser/18.1.3: 608 | resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} 609 | engines: {node: '>=6'} 610 | dependencies: 611 | camelcase: 5.3.1 612 | decamelize: 1.2.0 613 | dev: false 614 | 615 | /yargs/15.4.1: 616 | resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} 617 | engines: {node: '>=8'} 618 | dependencies: 619 | cliui: 6.0.0 620 | decamelize: 1.2.0 621 | find-up: 4.1.0 622 | get-caller-file: 2.0.5 623 | require-directory: 2.1.1 624 | require-main-filename: 2.0.0 625 | set-blocking: 2.0.0 626 | string-width: 4.2.3 627 | which-module: 2.0.0 628 | y18n: 4.0.3 629 | yargs-parser: 18.1.3 630 | dev: false 631 | -------------------------------------------------------------------------------- /replace.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | path = require("path"), 3 | chalk = require("chalk"), 4 | minimatch = require("minimatch"), 5 | sharedOptions = require("./bin/shared-options"); 6 | 7 | module.exports = function(options) { 8 | var matched = []; 9 | // If the path is the same as the default and the recursive option was not 10 | // specified, search recursively under the current directory as a 11 | // convenience. 12 | if (options.paths.length === 1 && 13 | options.paths[0] === sharedOptions.paths.default[0] && 14 | !options.hasOwnProperty('recursive')) { 15 | options.paths = ['.']; 16 | } 17 | 18 | var lineCount = 0, 19 | limit = 400; // chars per line 20 | 21 | if (options.r) { 22 | options.recursive = true; 23 | } 24 | 25 | if (!options.color) { 26 | options.color = "cyan"; 27 | } 28 | 29 | var flags = "g"; // global multiline 30 | if (options.ignoreCase) { 31 | flags += "i"; 32 | } 33 | if (options.multiline) { 34 | flags += "m"; 35 | } 36 | 37 | var regex; 38 | if (options.regex instanceof RegExp) { 39 | regex = options.regex; 40 | } 41 | else { 42 | regex = new RegExp(options.regex, flags); 43 | } 44 | var canReplace = !options.preview && options.replacement !== undefined; 45 | 46 | var includes; 47 | if (options.include) { 48 | includes = options.include.split(","); 49 | } 50 | var excludes = []; 51 | if (options.exclude) { 52 | excludes = options.exclude.split(","); 53 | } 54 | var ignoreFile = options.excludeList || path.join(__dirname, '/defaultignore'); 55 | var ignores = fs.readFileSync(ignoreFile, "utf-8").split("\n"); 56 | excludes = excludes.concat(ignores); 57 | 58 | var replaceFunc; 59 | if (options.funcFile) { 60 | eval('replaceFunc = ' + fs.readFileSync(options.funcFile, "utf-8")); 61 | } 62 | 63 | if(options.z) { 64 | process.stdin.resume(); 65 | _input = ""; 66 | process.stdin.on("data", function (input) { 67 | _input += input; 68 | }); 69 | 70 | process.stdin.on("end", function () { 71 | const text = replacizeText(_input); 72 | process.stdout.write(text); 73 | }); 74 | } else { 75 | for (var i = 0; i < options.paths.length; i++) { 76 | if (options.async) { 77 | replacizeFile(options.paths[i]); 78 | } 79 | else { 80 | replacizeFileSync(options.paths[i]); 81 | } 82 | } 83 | } 84 | 85 | return matched; 86 | 87 | function canSearch(file, isFile) { 88 | var inIncludes = includes && includes.some(function(include) { 89 | return minimatch(file, include, { matchBase: true }); 90 | }) 91 | var inExcludes = excludes.some(function(exclude) { 92 | return minimatch(file, exclude, { matchBase: true }); 93 | }) 94 | 95 | return ((!includes || !isFile || inIncludes) && (!excludes || !inExcludes)); 96 | } 97 | 98 | function replacizeFile(file) { 99 | fs.lstat(file, function(err, stats) { 100 | if (err) throw err; 101 | 102 | if (stats.isSymbolicLink()) { 103 | // don't follow symbolic links for now 104 | return; 105 | } 106 | var isFile = stats.isFile(); 107 | if (!canSearch(file, isFile)) { 108 | return; 109 | } 110 | if (isFile) { 111 | fs.readFile(file, "utf-8", function(err, text) { 112 | if (err) { 113 | if (err.code == 'EMFILE') { 114 | console.log('Too many files, try running `replace` without --async'); 115 | process.exit(1); 116 | } 117 | throw err; 118 | } 119 | 120 | text = replacizeText(text, file); 121 | if (canReplace && text !== null) { 122 | fs.writeFile(file, text, function(err) { 123 | if (err) throw err; 124 | }); 125 | } 126 | }); 127 | } 128 | else if (stats.isDirectory() && options.recursive) { 129 | fs.readdir(file, function(err, files) { 130 | if (err) throw err; 131 | for (var i = 0; i < files.length; i++) { 132 | replacizeFile(path.join(file, files[i])); 133 | } 134 | }); 135 | } 136 | }); 137 | } 138 | 139 | function replacizeFileSync(file) { 140 | var stats = fs.lstatSync(file); 141 | if (stats.isSymbolicLink()) { 142 | // don't follow symbolic links for now 143 | return; 144 | } 145 | var isFile = stats.isFile(); 146 | if (!canSearch(file, isFile)) { 147 | return; 148 | } 149 | if (isFile) { 150 | var text = fs.readFileSync(file, "utf-8"); 151 | 152 | var replacizedText = replacizeText(text, file); 153 | 154 | if (replacizedText !== null) { 155 | if (canReplace) { 156 | fs.writeFileSync(file, replacizedText); 157 | } else { 158 | matched.push({ text, path: file }); 159 | } 160 | } 161 | } 162 | else if (stats.isDirectory() && options.recursive) { 163 | var files = fs.readdirSync(file); 164 | for (var i = 0; i < files.length; i++) { 165 | replacizeFileSync(path.join(file, files[i])); 166 | } 167 | } 168 | } 169 | 170 | function replacizeText(text, file) { 171 | var match = text.match(regex); 172 | if (!match) { 173 | return null; 174 | } 175 | 176 | if (!options.silent && file) { 177 | var printout = options.noColor ? file : options.fileColor ? chalk[options.fileColor](file) : file; 178 | if (options.count) { 179 | var count = " (" + match.length + ")"; 180 | count = options.noColor ? count : chalk.grey(count); 181 | printout += count; 182 | } 183 | console.log(printout); 184 | } 185 | if (!options.silent && !options.quiet 186 | && !(lineCount > options.maxLines) 187 | && options.multiline) { 188 | var lines = text.split("\n"); 189 | for (var i = 0; i < lines.length; i++) { 190 | var line = lines[i]; 191 | if (line.match(regex)) { 192 | if (++lineCount > options.maxLines) { 193 | break; 194 | } 195 | var replacement = options.replacement || "$&"; 196 | if (!options.noColor) { 197 | replacement = chalk[options.color](replacement); 198 | } 199 | line = line.replace(regex, replaceFunc || replacement); 200 | // only console log if file not stdin 201 | file && console.log(" " + (i + 1) + ": " + line.slice(0, limit)); 202 | } 203 | } 204 | } 205 | if (canReplace) { 206 | return text.replace(regex, replaceFunc || options.replacement); 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # testing 2 | 3 | To run the tests in this directory, first install the dev dependencies with this command from the top-level directory: 4 | 5 | ``` 6 | npm install --dev 7 | ``` 8 | 9 | You'll also have to globally install [tap](https://github.com/isaacs/node-tap). `npm install tap -g`. 10 | 11 | Run the unit tests with: 12 | 13 | ``` 14 | tap . 15 | ``` -------------------------------------------------------------------------------- /test/cli.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | test = require("tape"), 3 | child_process = require("child_process"), 4 | path = require("path"), 5 | bin = require.resolve("../bin/replace"); 6 | 7 | function getText(file) { 8 | var content = fs.readFileSync(file, "utf-8"); 9 | return content; 10 | } 11 | 12 | function join(file) { 13 | return path.join(__dirname, file); 14 | } 15 | 16 | // 17 | // test('quotes parsing', function (t) { 18 | // t.plan(1); 19 | // 20 | // var input = join("test_files/test_basic.txt"); 21 | // var original = getText(input); 22 | // t.on("end", function () { 23 | // fs.writeFileSync(input, original, "utf-8"); 24 | // }); 25 | // 26 | // child_process.spawnSync(process.execPath, [bin, "ac", "'single'", input]); 27 | // 28 | // t.equal(getText(input), "aa'single'cc"); 29 | // }); 30 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('./cli') 2 | require('./paths') 3 | require('./sanity') 4 | -------------------------------------------------------------------------------- /test/paths.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | test = require('tape'), 3 | replace = require('../replace'), 4 | path = require("path"); 5 | 6 | function getText(file) { 7 | var content = fs.readFileSync(file, "utf-8"); 8 | return content; 9 | } 10 | 11 | function join(file) { 12 | return path.join(__dirname, file); 13 | } 14 | 15 | test('recursive', function (t) { 16 | t.plan(7); 17 | 18 | replace({ 19 | regex: "a", 20 | replacement: "b", 21 | paths: [join("test_files/test_paths")], 22 | recursive: true 23 | }); 24 | 25 | var changedFiles = [ 26 | join("test_files/test_paths/test1.txt"), 27 | join("test_files/test_paths/test2.txt"), 28 | join("test_files/test_paths/sample1.txt")]; 29 | var expected = "bbbb"; 30 | changedFiles.forEach(function(file) { 31 | t.equal(getText(file), expected, "recursive replace on directory " + file); 32 | }) 33 | 34 | var expected = "aaaa"; 35 | var ignored = join("test_files/test_paths/test.png"); 36 | t.equal(getText(ignored), expected, "skip file with match in defaultignore"); 37 | 38 | replace({ 39 | regex: "b", 40 | replacement: "a", 41 | paths: [join("test_files/test_paths")], 42 | recursive: true 43 | }); 44 | 45 | changedFiles.forEach(function(file) { 46 | t.equal(getText(file), expected, "reverting worked"); 47 | }); 48 | }); 49 | 50 | test('include', function(t) { 51 | t.plan(5); 52 | 53 | replace({ 54 | regex: "a", 55 | replacement: "b", 56 | paths: [join("test_files/test_paths")], 57 | recursive: true, 58 | include: "sample*.txt" 59 | }); 60 | 61 | var changedFiles = [ 62 | join("test_files/test_paths/sample1.txt"), 63 | ]; 64 | var expected = "bbbb"; 65 | changedFiles.forEach(function(file) { 66 | t.equal(getText(file), expected, "replace in included file " + file); 67 | }); 68 | 69 | var ignoredFiles = [ 70 | join("test_files/test_paths/test1.txt"), 71 | join("test_files/test_paths/test2.txt"), 72 | join("test_files/test_paths/test.png")]; 73 | var expected = "aaaa"; 74 | ignoredFiles.forEach(function(file) { 75 | t.equal(getText(file), expected, "don't replace in not-included file " + file); 76 | }); 77 | 78 | replace({ 79 | regex: "b", 80 | replacement: "a", 81 | paths: [join("test_files/test_paths")], 82 | recursive: true 83 | }); 84 | 85 | var expected = "aaaa"; 86 | changedFiles.forEach(function(file) { 87 | t.equal(getText(file), expected, "reverting worked"); 88 | }); 89 | }) 90 | 91 | test('exclude', function(t) { 92 | t.plan(6); 93 | 94 | replace({ 95 | regex: "a", 96 | replacement: "b", 97 | paths: [join("test_files/test_paths")], 98 | recursive: true, 99 | exclude: "*sample*.txt" 100 | }); 101 | 102 | var changedFiles = [ 103 | join("test_files/test_paths/test1.txt"), 104 | join("test_files/test_paths/test2.txt")]; 105 | var expected = "bbbb"; 106 | changedFiles.forEach(function(file) { 107 | t.equal(getText(file), expected, "replace in non-excluded file " + file); 108 | }); 109 | 110 | var ignoredFiles = [ 111 | join("test_files/test_paths/sample1.txt"), 112 | join("test_files/test_paths/test.png")]; 113 | var expected = "aaaa"; 114 | ignoredFiles.forEach(function(file) { 115 | t.equal(getText(file), expected, "don't replace in excluded file " + file); 116 | }); 117 | 118 | replace({ 119 | regex: "b", 120 | replacement: "a", 121 | paths: [join("test_files/test_paths")], 122 | recursive: true 123 | }); 124 | 125 | var expected = "aaaa"; 126 | changedFiles.forEach(function(file) { 127 | t.equal(getText(file), expected, "reverting worked"); 128 | }); 129 | }) -------------------------------------------------------------------------------- /test/sanity.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | test = require('tape'), 3 | replace = require('../replace'), 4 | path = require("path"); 5 | 6 | function getText(file) { 7 | var content = fs.readFileSync(file, "utf-8"); 8 | return content; 9 | } 10 | 11 | function join(file) { 12 | return path.join(__dirname, file); 13 | } 14 | 15 | test('basic', function (t) { 16 | t.plan(2); 17 | 18 | var file = join("test_files/test_basic.txt"); 19 | 20 | replace({ 21 | regex: "a", 22 | replacement: "b", 23 | paths:[file] 24 | }); 25 | 26 | var expected = "bbbccc"; 27 | t.equal(getText(file), expected, "single letter replace works"); 28 | 29 | replace({ 30 | regex: "b", 31 | replacement: "a", 32 | paths:[file] 33 | }); 34 | 35 | var expected = "aaaccc"; 36 | t.equal(getText(file), expected, "reverting worked"); 37 | }); 38 | 39 | test('numbers', function(t) { 40 | t.plan(2); 41 | 42 | var file = join("test_files/test_numbers.txt"); 43 | 44 | replace({ 45 | regex: "123", 46 | replacement: "456", 47 | paths:[file] 48 | }); 49 | 50 | var expected = "a456b"; 51 | t.equal(getText(file), expected, "number replace works"); 52 | 53 | replace({ 54 | regex: "456", 55 | replacement: "123", 56 | paths:[file] 57 | }); 58 | 59 | var expected = "a123b"; 60 | t.equal(getText(file), expected, "reverting worked"); 61 | }) 62 | 63 | 64 | test('multiline', function(t) { 65 | t.plan(3); 66 | 67 | var file = join("test_files/test_multiline.txt"); 68 | 69 | replace({ 70 | regex: "c$", 71 | replacement: "t", 72 | paths:[file], 73 | multiline: false 74 | }); 75 | 76 | var expected = "abc\ndef"; 77 | t.equal(getText(file), expected, "$ shouldn't match without multiline"); 78 | 79 | replace({ 80 | regex: "c$", 81 | replacement: "t", 82 | paths:[file], 83 | multiline: true 84 | }); 85 | 86 | var expected = "abt\ndef"; 87 | t.equal(getText(file), expected, "with multiline, $ should match eol"); 88 | 89 | replace({ 90 | regex: "t$", 91 | replacement: "c", 92 | paths:[file], 93 | multiline: true 94 | }); 95 | 96 | var expected = "abc\ndef"; 97 | t.equal(getText(file), expected, "reverting worked"); 98 | }); 99 | 100 | test('case insensitive', function(t) { 101 | t.plan(2); 102 | 103 | var file = join("test_files/test_case.txt"); 104 | 105 | replace({ 106 | regex: "a", 107 | replacement: "c", 108 | paths:[file], 109 | ignoreCase: true 110 | }); 111 | 112 | var expected = "cccc"; 113 | t.equal(getText(file), expected, "case insensitive replace"); 114 | 115 | replace({ 116 | regex: "c", 117 | replacement: "A", 118 | paths:[file] 119 | }); 120 | 121 | var expected = "AAAA"; 122 | t.equal(getText(file), expected, "reverting worked"); 123 | }) 124 | 125 | test('preview', function(t) { 126 | t.plan(1); 127 | 128 | var file = join("test_files/test_preview.txt"); 129 | 130 | replace({ 131 | regex: "a", 132 | replacement: "c", 133 | paths:[file], 134 | preview: true 135 | }); 136 | 137 | var expected = "aaaa"; 138 | t.equal(getText(file), expected, "no replacement if 'preview' is true"); 139 | }) 140 | -------------------------------------------------------------------------------- /test/test_files/test_basic.txt: -------------------------------------------------------------------------------- 1 | aaaccc -------------------------------------------------------------------------------- /test/test_files/test_case.txt: -------------------------------------------------------------------------------- 1 | AAAA -------------------------------------------------------------------------------- /test/test_files/test_multiline.txt: -------------------------------------------------------------------------------- 1 | abc 2 | def -------------------------------------------------------------------------------- /test/test_files/test_numbers.txt: -------------------------------------------------------------------------------- 1 | a123b -------------------------------------------------------------------------------- /test/test_files/test_paths/sample1.txt: -------------------------------------------------------------------------------- 1 | aaaa -------------------------------------------------------------------------------- /test/test_files/test_paths/test.png: -------------------------------------------------------------------------------- 1 | aaaa -------------------------------------------------------------------------------- /test/test_files/test_paths/test1.txt: -------------------------------------------------------------------------------- 1 | aaaa -------------------------------------------------------------------------------- /test/test_files/test_paths/test2.txt: -------------------------------------------------------------------------------- 1 | aaaa -------------------------------------------------------------------------------- /test/test_files/test_preview.txt: -------------------------------------------------------------------------------- 1 | aaaa -------------------------------------------------------------------------------- /testfunc.js: -------------------------------------------------------------------------------- 1 | function(match) { 2 | return match.toLowerCase(); 3 | } --------------------------------------------------------------------------------