├── .gitattributes ├── .github ├── renovate.json5 └── workflows │ ├── nodejs.yml │ └── publishOnBump.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── README.md ├── gfx ├── Benny-350.png ├── Benny-82.png ├── Benny.pdf └── Benny.png ├── legacy ├── .gitignore ├── README.md ├── package.json ├── rreplace.js └── test.sh ├── package.json ├── rollup.config.js ├── src ├── cli.ts ├── engine.ts ├── multiversion.cli.js └── output.ts ├── test ├── cli │ ├── aserta.sh │ ├── run.ai.sh │ └── run.sh ├── debug.js ├── encoding.js ├── halt.js ├── help.js ├── helper.js ├── mocha.opts ├── output.js ├── pattern-file.js ├── quiet-total.js ├── quiet.js ├── replacement-file.js ├── replacement-js-dynamic.js ├── replacement-js.js ├── speed │ ├── 1984.surge.sh.html │ ├── run.sh │ ├── speed-code-test │ ├── speed-code-test-v2 │ ├── speed-code-test-v3 │ ├── speed-test │ ├── tesopi.js │ ├── testlog.speed.md │ └── unicode.js ├── test.js.stub ├── unicode.js ├── version.js ├── void-euro.js ├── void-ignore-case.js └── void-multiline.js └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.min.js binary 2 | yarn.lock binary -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: 'https://docs.renovatebot.com/renovate-schema.json', 3 | extends: ['config:base'], 4 | packageRules: [ 5 | { 6 | // Rule for security patches (patch updates) 7 | matchUpdateTypes: ['patch'], 8 | automerge: true, 9 | schedule: ['on the first day of the month'], // Monthly for patches 10 | }, 11 | { 12 | // Rule for other updates (minor, pin, digest) 13 | matchUpdateTypes: ['minor', 'pin', 'digest'], 14 | automerge: true, 15 | schedule: ['on the first day of the month every 3rd month'], // Quarterly for others 16 | }, 17 | ], 18 | automerge: true, 19 | automergeStrategy: 'squash', 20 | dependencyDashboard: true, 21 | ignorePaths: ['legacy/**/*'], 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: CI-test 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [18.x, 20.x, 22.x, 23.x, latest] 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: yarn install 24 | - run: yarn test-ci 25 | -------------------------------------------------------------------------------- /.github/workflows/publishOnBump.yml: -------------------------------------------------------------------------------- 1 | name: Publish on bump 2 | 3 | on: 4 | push: 5 | branches: 6 | - Qmaster 7 | 8 | jobs: 9 | build: 10 | if: ${{ null || !github.event.pusher.email }} 11 | name: Autopublish dependabot 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checking the who pushed 15 | run: | 16 | echo "The github.event.pusher is:" 17 | echo "${{ toJson(github.event) }}" 18 | echo "And I must publish!!!" 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | myfile 3 | *.log 4 | *.file 5 | .rpt2_cache 6 | tmp/* 7 | package-lock.json 8 | .vscode 9 | /dist 10 | /bin -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/* 2 | gfx/* 3 | rollup.config.js 4 | tmp/* 5 | .* 6 | *.log 7 | *.txt 8 | *.file 9 | *.lock 10 | legacy/ -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | legacy/ 2 | dist/ 3 | bin/ 4 | *.md 5 | *.html -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | printWidth: 100 2 | tabWidth: 4 3 | useTabs: true 4 | bracketSpacing: false 5 | trailingComma: es5 6 | singleQuote: true 7 | -------------------------------------------------------------------------------- /gfx/Benny-350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathiasrw/rexreplace/fdd701bfc0246800a5218fc0d97cc6bef7cedc7b/gfx/Benny-350.png -------------------------------------------------------------------------------- /gfx/Benny-82.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathiasrw/rexreplace/fdd701bfc0246800a5218fc0d97cc6bef7cedc7b/gfx/Benny-82.png -------------------------------------------------------------------------------- /gfx/Benny.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathiasrw/rexreplace/fdd701bfc0246800a5218fc0d97cc6bef7cedc7b/gfx/Benny.pdf -------------------------------------------------------------------------------- /gfx/Benny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathiasrw/rexreplace/fdd701bfc0246800a5218fc0d97cc6bef7cedc7b/gfx/Benny.png -------------------------------------------------------------------------------- /legacy/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | myfile 3 | -------------------------------------------------------------------------------- /legacy/README.md: -------------------------------------------------------------------------------- 1 | _This is the legacy version of [RexReplace](https://www.npmjs.com/package/rexreplace)_ 2 | 3 | # rreplace 4 | 5 | Regex replace in files from your CLI - with a tiny footprint. 6 | 7 | ### Installation 8 | 9 | ```bash 10 | > npm install -g rreplace 11 | ``` 12 | 13 | Works on any version of Node.js since 0.6 14 | 15 | ### Usage 16 | 17 | ```bash 18 | > rreplace pattern replace filepath [regexFlags [encoding]] 19 | ``` 20 | 21 | - Pattern is a regex and may capture groups 22 | 23 | - Replacement may refer to captured groups. The first group is named `$1` 24 | 25 | - Filepath can only contain a path to one particular file (no globs) 26 | 27 | - Default is global case-insensitive multiline search (regexFlags is default `gmi`) 28 | 29 | - Default file encoding is `utf8` 30 | 31 | ### Example 32 | 33 | ```bash 34 | > rreplace '(foo)(.*)' '$2$1' myfile.md 35 | # 'foobar' is now 'barfoo' in myfile.md 36 | ``` 37 | 38 | --- 39 | 40 | MIT License 41 | -------------------------------------------------------------------------------- /legacy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rreplace", 3 | "version": "2.0.1", 4 | "description": "Regex replace in a file from CLI.", 5 | "main": "rreplace.js", 6 | "scripts": { 7 | "test": "npm install -g ./ && bash test.sh" 8 | }, 9 | "bin": { 10 | "rreplace": "rreplace.js" 11 | }, 12 | "keywords": [ 13 | "replace", 14 | "in", 15 | "files" 16 | ], 17 | "author": "MRW", 18 | "license": "MIT" 19 | } 20 | -------------------------------------------------------------------------------- /legacy/rreplace.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // This file must only be edited with 'vim' 4 | 5 | fs = require('fs'); 6 | 7 | var usage = 8 | '\n\n> ' + 9 | process.argv[1].split('/').pop() + 10 | ' pattern replace filepath [regexFlags [encoding]]' + 11 | '\n' + 12 | '\nDefault regexFlags is gmi' + 13 | '\nDefault encoding is utf8'; 14 | if (process.argv.length < 5) throw 'Too few arguments given.' + usage; 15 | 16 | if (7 < process.argv.length) throw 'Too many arguments given.' + usage; 17 | 18 | var pattern = process.argv[2]; 19 | 20 | var replacement = process.argv[3]; 21 | 22 | var file = process.cwd() + '/' + process.argv[4]; 23 | 24 | if (!fs.existsSync(file)) throw 'File not found: ' + file; 25 | 26 | var flags = 'gmi'; 27 | 28 | if (6 <= process.argv.length) flags = process.argv[5]; 29 | 30 | var encoding = 'utf8'; 31 | 32 | if (7 === process.argv.length) encoding = process.argv[6]; 33 | 34 | try { 35 | var regex = new RegExp(pattern, flags); 36 | } catch (err) { 37 | throw 'Wrongly formatted regexp: ' + err; 38 | } 39 | 40 | fs.writeFileSync(file, fs.readFileSync(file, encoding).replace(regex, replacement)); 41 | -------------------------------------------------------------------------------- /legacy/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo 'foobar' > myfile 4 | rreplace '(F?(O))O(.*)' '$3$1$2' myfile 5 | grep -q 'barfoo' myfile || exit 101 6 | 7 | echo 'foobar' > myfile 8 | rreplace '(F?(O))O(.*)' '$3$1$2' myfile gm utf8 9 | grep -q 'foobar' myfile || exit 102 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rexreplace", 3 | "version": "7.1.13", 4 | "description": "Search & replace across files with a CLI tool that makes you trust what you are doing.", 5 | "author": "Mathias Rangel Wulff", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/mathiasrw/rexreplace.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/mathiasrw/rexreplace/issues" 13 | }, 14 | "homepage": "https://github.com/mathiasrw/rexreplace#readme", 15 | "bin": { 16 | "rr": "bin/rexreplace.cli.min.js", 17 | "rexreplace": "bin/rexreplace.cli.js" 18 | }, 19 | "main": "src/engine.js", 20 | "scripts": { 21 | "test": "yarn build && yarn test-cli && yarn test-js", 22 | "postbuild": "cp bin/rexreplace.cli.js bin/rexreplace.cli.min.js", 23 | "version": "yarn build-minify", 24 | "build": "rollup -c --bundleConfigAsCjs", 25 | "build-minify": "yarn build && yarn minify", 26 | "minify": "cat bin/rexreplace.cli.js > bin/rexreplace.cli.min.js", 27 | "prebuild": "rm -fr bin && yarn format", 28 | "test-js": "echo todo: async mocha", 29 | "test-minify": "yarn build-minify && yarn test-cli && yarn test-js", 30 | "test-cli": "npm uninstall --location=global rexreplace && npm --location=global install ./ && yarn test-cli-only # why on earth are they depricating the -g flag", 31 | "test-cli-only": "bash test/cli/run.sh && bash test/cli/run.ai.sh ", 32 | "test-ci": "yarn test-format && yarn test && yarn test-minify", 33 | "test-speed": "bash test/speed/run.sh", 34 | "rebase": "yarn is-git-clean && git fetch && git rebase origin/main", 35 | "load-options": "# rr -h | rr 'Options:(.+)Examples:' _ -ms | rr '\\n {26,}|\\n\\n *' ' ' | rr \"'\" '`' | rr '^ (-.+?), (--[^ ]+) *' '`€1` | **`€2`** ' | rr '(^---- . ----).+?(## Good to know)' '€1 + nl + pipe + nl + nl + €2' readme.md -jsT", 36 | "test-format": "prettier . --list-different || (echo 'Please correct file formatting using `yarn format` and try again.' && exit 1)", 37 | "format": "prettier . --write", 38 | "is-git-clean": "(git diff --quiet --exit-code --cached && git diff --quiet --exit-code) || (echo Please commit or stash changes && exit 1)", 39 | "release": "yarn version", 40 | "prerelease": "yarn is-git-clean && yarn test && yarn test-minify && yarn load-options", 41 | "postrelease": "npm publish && git push && git push --tags && echo \"Successfully released version $npm_package_version\" && (open https://github.com/mathiasrw/rexreplace/releases || 1)" 42 | }, 43 | "keywords": [ 44 | "search", 45 | "find", 46 | "replace", 47 | "regex", 48 | "regexp", 49 | "regular expression", 50 | "sed" 51 | ], 52 | "devDependencies": { 53 | "@rollup/plugin-replace": "6.0.2", 54 | "@rollup/plugin-swc": "^0.4.0", 55 | "@swc/core": "1.11.24", 56 | "@types/node": "22.15.17", 57 | "assert": "^2.0.0", 58 | "mocha": "11.2.2", 59 | "prettier": "3.5.3", 60 | "rollup": "4.40.2", 61 | "yarn": "1.22.22" 62 | }, 63 | "resolutions": { 64 | "glob": "9" 65 | }, 66 | "directories": { 67 | "test": "test" 68 | }, 69 | "dependencies": { 70 | "globs": "0.1.4", 71 | "yargs": "16" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import swc from '@rollup/plugin-swc'; 2 | import replace from '@rollup/plugin-replace'; 3 | 4 | export default [ 5 | { 6 | input: 'src/cli.ts', 7 | output: { 8 | banner: '#!/usr/bin/env node', 9 | file: 'bin/rexreplace.cli.js', 10 | name: 'rexreplace', 11 | format: 'iife', 12 | }, 13 | plugins: [ 14 | swc({jsc: {target: 'es5'}}), 15 | replace({ 16 | PACKAGE_VERSION: require('./package.json').version, 17 | preventAssignment: true, 18 | }), 19 | 20 | //progress(), 21 | /*closure({ 22 | languageIn: 'ECMASCRIPT6', 23 | languageOut: 'ECMASCRIPT5', 24 | compilationLevel: 'ADVANCED', 25 | warningLevel: 'QUIET', 26 | env:'CUSTOM', 27 | //externs: ['externs.js'], 28 | }),//*/ 29 | 30 | //uglify(), 31 | //filesize(), 32 | ], 33 | } /*{ 34 | input: 'src/multiversion.cli.js', 35 | output: { 36 | name: 'rexreplace_cli', 37 | file: 'build/rexreplace.cli.js', 38 | format: 'iife' 39 | } 40 | },*/, 41 | ]; 42 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | // CLI interface for rexreplace 2 | 3 | import * as rexreplace from './engine.ts'; 4 | 5 | let pattern, replacement; 6 | 7 | // To avoid problems with patterns or replacements starting with '-' the two first arguments can not contain flags and are removed before yargs does it magic - but we still need to handle -version and -help 8 | let needHelp = 0; 9 | if (process.argv.length < 4) { 10 | if (/-v|--?version$/i.test(process.argv[process.argv.length - 1])) { 11 | console.log(rexreplace.version); 12 | process.exitCode = 0; 13 | process.exit(); 14 | } else if (/-h|--?help$/i.test(process.argv[process.argv.length - 1])) { 15 | needHelp = 1; 16 | } else { 17 | needHelp = 2; 18 | } 19 | } else { 20 | [pattern, replacement] = process.argv.splice(2, 2); 21 | } 22 | 23 | const yargs = require('yargs') 24 | .strict() 25 | 26 | .usage( 27 | 'RexReplace ' + 28 | rexreplace.version + 29 | ': Regexp search and replace for files using lookahead and backreference to matching groups in the replacement. Defaults to global multiline case-insensitive search.\n\n' + 30 | '> rexreplace pattern replacement [fileGlob|option]+' 31 | ) 32 | 33 | .example(`> rexreplace 'Foo' 'xxx' myfile.md`, `'foobar' in myfile.md will become 'xxxbar'`) 34 | .example('') 35 | .example(`> rr xxx Foo myfile.md`, `The alias 'rr' can be used instead of 'rexreplace'`) 36 | .example('') 37 | 38 | .example( 39 | `> rexreplace '(f?(o))o(.*)' '$3$1€2' myfile.md`, 40 | `'foobar' in myfile.md will become 'barfoo'` 41 | ) 42 | .example('') 43 | .example( 44 | `> rexreplace '^#' '##' *.md`, 45 | `All markdown files in this dir got all headlines moved one level deeper` 46 | ) 47 | .example('') 48 | .example( 49 | `> rexreplace 'a' 'b' 'myfile.md' 'src/**/*.*' `, 50 | `Provide multiple files or glob if needed` 51 | ) 52 | .version('v', 'Print rexreplace version (can be given as only argument)', rexreplace.version) 53 | .alias('v', 'version') 54 | 55 | .boolean('V') 56 | .describe('V', 'More chatty output') 57 | .alias('V', 'verbose') 58 | //.conflicts('V', 'q') 59 | //.conflicts('V', 'Q') 60 | 61 | .boolean('L') 62 | .describe('L', 'Literal string search (no regex used when searching)') 63 | .alias('L', 'literal') 64 | 65 | .boolean('I') 66 | .describe('I', 'Void case insensitive search pattern.') 67 | .alias('I', 'void-ignore-case') 68 | 69 | .boolean('G') 70 | .describe('G', 'Void global search (stop looking after the first match).') 71 | .alias('G', 'void-global') 72 | 73 | .boolean('s') 74 | .describe('s', 'Have `.` also match newline.') 75 | .alias('s', 'dot-all') 76 | 77 | .boolean('M') 78 | .describe( 79 | 'M', 80 | 'Void multiline search pattern. Makes ^ and $ match start/end of whole content rather than each line.' 81 | ) 82 | .alias('M', 'void-multiline') 83 | 84 | .boolean('u') 85 | .describe('u', 'Treat pattern as a sequence of unicode code points.') 86 | .alias('u', 'unicode') 87 | 88 | .default('e', 'utf8') 89 | .alias('e', 'encoding') 90 | .describe('e', 'Encoding of files/piped data.') 91 | 92 | .alias('E', 'engine') 93 | .describe('E', 'What regex engine to use:') 94 | .choices('E', ['V8' /*'RE2' /*'sd', 'stream'*/]) 95 | .default('E', 'V8') 96 | 97 | .boolean('q') 98 | .describe('q', 'Only display errors (no other info)') 99 | .alias('q', 'quiet') 100 | 101 | .boolean('Q') 102 | .describe('Q', 'Never display errors or info') 103 | .alias('Q', 'quiet-total') 104 | 105 | .boolean('H') 106 | .describe('H', 'Halt on first error') 107 | .alias('H', 'halt') 108 | .default('H', false) 109 | 110 | .boolean('d') 111 | .describe('d', 'Print debug info') 112 | .alias('d', 'debug') 113 | 114 | .boolean('€') 115 | .describe('€', "Void having '€' as alias for '$' in pattern and replacement parameters") 116 | .alias('€', 'void-euro') 117 | 118 | .boolean('§') 119 | .describe('§', "Void having '§' as alias for '\\' in pattern and replacement parameters") 120 | .alias('§', 'void-section') 121 | 122 | .boolean('o') 123 | .describe( 124 | 'o', 125 | 'Output the final result instead of saving to file. Will also output content even if no replacement has taken place.' 126 | ) 127 | .alias('o', 'output') 128 | //.conflicts('o','O') 129 | 130 | .boolean('A') 131 | .alias('A', 'void-async') 132 | .describe( 133 | 'A', 134 | `Handle files in a synchronous flow. Good to limit memory usage when handling large files. ` + 135 | '' 136 | ) 137 | 138 | .boolean('B') 139 | .describe( 140 | 'B', 141 | 'Avoid temporary backing up file. Works async (independent of -A flag) and will speed up things but at one point data lives only in memory, and you will lose the content if the process is abrupted.' 142 | ) 143 | .alias('B', 'void-backup') 144 | 145 | .boolean('b') 146 | .describe('b', 'Keep a backup file of the original content.') 147 | .alias('b', 'keep-backup') 148 | 149 | .boolean('m') 150 | .describe( 151 | 'm', 152 | `Output each match on a new line. ` + 153 | `Will not replace any content but you still need to provide a dummy value (like \`_\`) as replacement parameter. ` + 154 | `If search pattern does not contain matching groups the full match will be outputted. ` + 155 | `If search pattern does contain matching groups only matching groups will be outputted (same line with no delimiter). ` + 156 | `` 157 | ) 158 | .alias('m', 'output-match') 159 | 160 | .boolean('T') 161 | .alias('T', 'trim-pipe') 162 | .describe( 163 | 'T', 164 | `Trim piped data before processing. ` + 165 | `If piped data only consists of chars that can be trimmed (new line, space, tabs...) it will become an empty string. ` + 166 | '' 167 | ) 168 | 169 | .boolean('R') 170 | .alias('R', 'replacement-pipe') 171 | .describe( 172 | 'R', 173 | `Replacement will be piped in. You still need to provide a dummy value (like \`_\`) as replacement parameter.` + 174 | '' 175 | ) 176 | 177 | .boolean('j') 178 | .alias('j', 'replacement-js') 179 | .describe( 180 | 'j', 181 | `Treat replacement as javascript source code. 182 | The statement from the last expression will become the replacement string. 183 | Purposefully implemented the most insecure way possible to remove _any_ incentive to consider running code from an untrusted part. 184 | The full match will be available as a javascript variable named $0 while each captured group will be available as $1, $2, $3, ... and so on. 185 | At some point, the $ char _will_ give you a headache when used from the command line, so use €0, €1, €2, €3... instead. 186 | If the javascript source code references to the full match or a captured group the code will run once per match. Otherwise, it will run once per file. 187 | 188 | The code has access to the following variables: 189 | \`r\` as an alias for \`require\` with both expanded to understand a relative path even if it is not starting with \`./\`, 190 | \`fs\` from node, 191 | \`path\` from node, 192 | \`globs\` from npm, 193 | \`pipe\`: the data piped into the command (null if no piped data), 194 | \`find\`: pattern searched for (the needle), 195 | \`text\`: full text being searched i.e. file content or piped data (the haystack), 196 | \`bytes\`: total size of the haystack in bytes, 197 | \`size\`: human-friendly representation of the total size of the haystack, 198 | \`time\`: String representing the local time when the command was invoked, 199 | \`time_obj\`: date object representing \`time\`, 200 | \`now\`: alias for \`time\`, 201 | \`cwd\`: current process working dir, 202 | \`nl\`: a new-line char, 203 | \`_\`: a single space char (for easy string concatenation). 204 | 205 | The following values defaults to \`❌\` if haystack does not originate from a file: 206 | \`file\`: contains the full path of the active file being searched (including full filename), 207 | \`file_rel\`: contains \`file\` relative to current process working dir, 208 | \`dirpath\`: contains the full path without filename of the active file being searched, 209 | \`dirpath_rel\`: contains \`dirpath\` relative to current process working dir, 210 | \`filename\`: is the full filename of the active file being searched without path, 211 | \`name\`: filename of the active file being searched with no extension, 212 | \`ext\`: extension of the filename including leading dot, 213 | \`mtime\`: ISO inspired representation of the last local modification time of the current file, 214 | \`ctime\`: ISO representation of the local creation time of the current file. 215 | \`mtime_obj\`: date object representing \`mtime\`, 216 | \`ctime_obj\`: date object representing \`ctime\`. 217 | 218 | All variables, except from module, date objects, \`nl\` and \`_\`, has a corresponding variable name followed by \`_\` where the content has an extra space at the end (for easy concatenation). 219 | ` 220 | ) 221 | .string('x') 222 | .describe( 223 | 'x', 224 | 'Exclude files with a path that matches this regular expression. Will follow same regex flags and setup as the main search. Can be used multiple times.' 225 | ) 226 | .alias('x', 'exclude-re') 227 | 228 | .string('X') 229 | .describe('X', 'Exclude files found with this glob. Can be used multiple times.') 230 | .alias('X', 'exclude-glob') 231 | 232 | /* 233 | .boolean('N') 234 | .alias('N', 'void-newline') 235 | .describe('N', 236 | `Avoid having newline when outputting data (or when piping). `+ 237 | `Normally . `+ 238 | '' 239 | ) 240 | 241 | 242 | -E (Expect there to be no match and return exit 1 if found) 243 | -e (Expect there to be batch and return exit 1 if not found) 244 | */ 245 | 246 | /* .boolean('P') 247 | .describe('P', "Pattern is a filename from where the pattern will be generated. If more than one line is found in the file the pattern will be defined by each line trimmed and having newlines removed followed by other all rules (like -€).)") 248 | .alias('P', 'pattern-file') 249 | 250 | .boolean('R') 251 | .alias('R', 'replacement-file') 252 | .describe('R', 253 | `Replacement is a filename from where the replacement will be generated. ` + 254 | `If more than one line is found in the file the final replacement will be defined by each line trimmed and having newlines removed followed by all other rules (like -€).` 255 | ) 256 | 257 | */ 258 | 259 | /* // Ideas 260 | 261 | .boolean('n') 262 | .describe('n', "Do replacement on file path/names instead of file content (rename/move the files)") 263 | .alias('n', 'name') 264 | 265 | // https://github.com/eugeneware/replacestream 266 | .integer('M') 267 | .describe('M', "Maximum length of match. Set this value only if any single file of your ") 268 | .alias('M', 'max-match-len') 269 | .default('M', false) 270 | 271 | 272 | 273 | .boolean('G') 274 | .describe('G', "filename/globas are filename(s) for files containing one filename/globs on each line to be search/replaced") 275 | .alias('G', 'globs-file') 276 | 277 | .boolean('g') 278 | .describe('g', "filename/globs will be piped in. If any filename/globs are given in command the piped data will be prepened") 279 | .alias('g', 'glob-pipe') 280 | 281 | 282 | .boolean('j') 283 | .describe('j', "Pattern is javascript source that will return a string giving the pattern to use") 284 | .alias('j', 'pattern-js') 285 | 286 | 287 | .boolean('glob-js') 288 | .describe('glob-js', "filename/globs are javascript source that will return a string with newline seperating each glob to work on") 289 | 290 | 291 | */ 292 | 293 | .help('h') 294 | .describe('h', 'Display help.') 295 | .alias('h', 'help') 296 | 297 | .epilog(`Inspiration: .oO(What should 'sed' have been by now?)`); 298 | 299 | function backOut(exitcode = 1) { 300 | const help = yargs.showHelp(); 301 | const io = exitcode ? console.error : console.log; 302 | //io(help); 303 | process.exitCode = exitcode; 304 | process.exit(); 305 | } 306 | 307 | function unescapeString(str = '') { 308 | return new Function(`return '${str.replace(/'/g, "\\'")}'`)(); 309 | } 310 | 311 | (function () { 312 | if (0 < needHelp) { 313 | return backOut(needHelp - 1); 314 | } 315 | 316 | // All options into one big config object for the rexreplace core 317 | let config: any = {}; 318 | 319 | // Use only camelCase full lenght version of settings so we make sure the core can be documented propperly 320 | Object.keys(yargs.argv).forEach((key) => { 321 | if (1 < key.length && key.indexOf('-') < 0) { 322 | config[key] = yargs.argv[key]; 323 | } 324 | }); 325 | 326 | let pipeInUse = false; 327 | let pipeData = ''; 328 | 329 | config.pipedData = null; 330 | 331 | config.showHelp = yargs.showHelp; 332 | 333 | config.pattern = pattern; 334 | 335 | config.includeGlob = yargs.argv._; 336 | 337 | config.excludeGlob = [].concat(yargs.argv.excludeGlob).filter(Boolean); 338 | 339 | config.excludeRe = [].concat(yargs.argv.excludeRe).filter(Boolean); 340 | 341 | if (config.replacementJs) { 342 | config.replacement = replacement; 343 | } else { 344 | config.replacement = unescapeString(replacement); 345 | } 346 | 347 | /*if(Boolean(process.stdout.isTTY)){ 348 | config.output = true; 349 | }*/ 350 | if (Boolean(process.stdin.isTTY)) { 351 | if (config.replacementPipe) { 352 | return backOut(); 353 | } 354 | rexreplace.engine(config); 355 | } else { 356 | process.stdin.setEncoding(config.encoding); 357 | 358 | process.stdin.on('readable', () => { 359 | let chunk = process.stdin.read(); 360 | 361 | if (null !== chunk) { 362 | pipeInUse = true; 363 | pipeData += chunk; 364 | while ((chunk = process.stdin.read())) { 365 | pipeData += chunk; 366 | } 367 | } 368 | }); 369 | 370 | process.stdin.on('end', () => { 371 | if (pipeInUse) { 372 | if (yargs.argv.trimPipe) { 373 | pipeData = pipeData.trim(); 374 | } 375 | config.pipedData = pipeData; 376 | } 377 | rexreplace.engine(config); 378 | }); 379 | } 380 | })(); 381 | -------------------------------------------------------------------------------- /src/engine.ts: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const path = require('path'); 4 | 5 | const globs = require('globs'); 6 | 7 | const now = new Date(); 8 | 9 | import {outputConfig, step, debug, chat, info, error, die} from './output.ts'; 10 | 11 | const re = { 12 | euro: /€/g, 13 | section: /§/g, 14 | mctime: /[mc]time/, 15 | colon: /:/g, 16 | capturedGroupRef: /\$\d/, 17 | regexSpecialChars: /[-\[\]{}()*+?.,\/\\^$|#\s]/g, 18 | byteOrSize: /bytes|size/, 19 | folderName: /[\\\/]+([^\\\/]+)[\\\/]+[^\\\/]+$/, 20 | }; 21 | 22 | export const version = 'PACKAGE_VERSION'; 23 | 24 | export function engine(config: any = {engine: 'V8'}) { 25 | outputConfig(config); 26 | 27 | step('Displaying steps for:'); 28 | step(config); 29 | 30 | config.pattern = getFinalPattern(config.pattern, config) || ''; 31 | 32 | config.replacement = getFinalReplacement(config.replacement, config) || ''; 33 | 34 | config.replacementOri = config.replacement; 35 | 36 | config.regex = getFinalRegex(config.pattern, config) || ''; 37 | 38 | step(config); 39 | 40 | if (handlePipedData(config)) { 41 | return doReplacement('Piped data', config, config.pipedData); 42 | } 43 | 44 | config.files = getFilePaths(config); 45 | 46 | if (!config.files.length) { 47 | return error(config.files.length + ' files found'); 48 | } 49 | 50 | chat(config.files.length + ' files found'); 51 | 52 | // Ensure predictable sequence of output 53 | if (config.files.length > 1) { 54 | config.voidAsync = config.voidAsync || config.outputMatch || config.output; 55 | } 56 | 57 | step(config); 58 | 59 | config.files 60 | // Correct filepath 61 | //.map(filepath=>path.normalize(process.cwd()+'/'+filepath)) 62 | // Find out if any filepaths are invalid 63 | .filter((filepath) => (fs.existsSync(filepath) ? true : error('File not found:', filepath))) 64 | 65 | // Do the replacement 66 | .forEach((filepath) => openFile(filepath, config)); 67 | } 68 | 69 | function openFile(file, config) { 70 | if (config.voidAsync) { 71 | chat('Open sync: ' + file); 72 | var data = fs.readFileSync(file, config.encoding); 73 | return doReplacement(file, config, data); 74 | } else { 75 | chat('Open async: ' + file); 76 | fs.readFile(file, config.encoding, function (err, data) { 77 | if (err) { 78 | return error(err); 79 | } 80 | 81 | return doReplacement(file, config, data); 82 | }); 83 | } 84 | } 85 | 86 | // postfix argument names to limit the probabillity of user inputted javascript accidently using same values 87 | function doReplacement(_file_rr: string, _config_rr: any, _data_rr: string) { 88 | debug('Work on content from: ' + _file_rr); 89 | 90 | // Main regexp of the whole thing 91 | const result = _data_rr.replace( 92 | _config_rr.regex, 93 | _config_rr.replacementJs 94 | ? dynamicReplacement(_file_rr, _config_rr, _data_rr) 95 | : _config_rr.replacement 96 | ); 97 | 98 | // The output of matched strings is done from the replacement, so no need to continue 99 | if (_config_rr.outputMatch) { 100 | return; 101 | } 102 | 103 | if (_config_rr.output) { 104 | debug('Output result from: ' + _file_rr); 105 | return process.stdout.write(result); 106 | } 107 | 108 | // Nothing replaced = no need for writing file again 109 | if (result === _data_rr) { 110 | chat('Nothing changed in: ' + _file_rr); 111 | return; 112 | } 113 | 114 | // Release the memory while storing files 115 | _data_rr = ''; 116 | 117 | debug('Write new content to: ' + _file_rr); 118 | 119 | // Write directly to the same file (if the process is killed all new and old data is lost) 120 | if (_config_rr.voidBackup) { 121 | return fs.writeFile(_file_rr, result, _config_rr.encoding, function (err) { 122 | if (err) { 123 | return error(err); 124 | } 125 | info(_file_rr); 126 | }); 127 | } 128 | 129 | //Make sure data is always on disk 130 | const oriFile = path.normalize(path.join(process.cwd(), _file_rr)); 131 | const salt = new Date().toISOString().replace(re.colon, '_').replace('Z', ''); 132 | const backupFile = oriFile + '.' + salt + '.backup'; 133 | 134 | if (_config_rr.voidAsync) { 135 | try { 136 | fs.renameSync(oriFile, backupFile); 137 | fs.writeFileSync(oriFile, result, _config_rr.encoding); 138 | if (!_config_rr.keepBackup) { 139 | fs.unlinkSync(backupFile); 140 | } 141 | } catch (e) { 142 | return error(e); 143 | } 144 | return info(_file_rr); 145 | } 146 | 147 | // Let me know when fs gets promise'fied 148 | fs.rename(oriFile, backupFile, (err) => { 149 | if (err) { 150 | return error(err); 151 | } 152 | 153 | fs.writeFile(oriFile, result, _config_rr.encoding, (err) => { 154 | if (err) { 155 | return error(err); 156 | } 157 | 158 | if (!_config_rr.keepBackup) { 159 | fs.unlink(backupFile, (err) => { 160 | if (err) { 161 | return error(err); 162 | } 163 | info(_file_rr); 164 | }); 165 | } else { 166 | info(_file_rr); 167 | } 168 | }); 169 | }); 170 | } 171 | 172 | function handlePipedData(config) { 173 | step('Check Piped Data'); 174 | 175 | if (config.includeGlob.length) { 176 | if (!config.replacementJs && config.pipedData) { 177 | chat('Piped data never used.'); 178 | } 179 | 180 | return false; 181 | } 182 | 183 | if (null !== config.pipedData && !config.pipedDataUsed) { 184 | config.dataIsPiped = true; 185 | config.output = true; 186 | return true; 187 | } 188 | 189 | return false; 190 | } 191 | 192 | function getFinalPattern(pattern, conf: any) { 193 | step('Get final pattern'); 194 | pattern = replacePlaceholders(pattern, conf); 195 | 196 | if (conf.literal) { 197 | pattern = pattern.replace(re.regexSpecialChars, '\\$&'); 198 | } 199 | 200 | /*if (config.patternFile) { 201 | pattern = fs.readFileSync(pattern, 'utf8'); 202 | pattern = new Function('return '+pattern)(); 203 | }*/ 204 | 205 | step(pattern); 206 | return pattern; 207 | } 208 | 209 | function getFinalReplacement(replacement, conf: any) { 210 | step('Get final replacement'); 211 | /*if(config.replacementFile){ 212 | return oneLinerFromFile(fs.readFileSync(replacement,'utf8')); 213 | }*/ 214 | 215 | replacement = replacePlaceholders(replacement, conf); 216 | 217 | if (conf.replacementPipe) { 218 | step('Piping replacement'); 219 | conf.pipedDataUsed = true; 220 | if (null === conf.pipedData) { 221 | return die('No data piped into replacement'); 222 | } 223 | replacement = conf.pipedData; 224 | } 225 | 226 | if (conf.outputMatch) { 227 | step('Output match'); 228 | 229 | if (parseInt(process.versions.node) < 6) { 230 | return die('outputMatch is only supported in node 6+'); 231 | } 232 | 233 | return function () { 234 | step(arguments); 235 | 236 | if (arguments.length === 3) { 237 | step('Printing full match'); 238 | process.stdout.write(arguments[0] + '\n'); 239 | return ''; 240 | } 241 | 242 | for (var i = 1; i < arguments.length - 2; i++) { 243 | process.stdout.write(arguments[i]); 244 | } 245 | process.stdout.write('\n'); 246 | return ''; 247 | }; 248 | } 249 | 250 | // If captured groups then run dynamicly 251 | //console.log(process); 252 | if ( 253 | conf.replacementJs && 254 | re.capturedGroupRef.test(conf.replacement) && 255 | parseInt(process.versions.node) < 6 256 | ) { 257 | return die('Captured groups for javascript replacement is only supported in node 6+'); 258 | } 259 | 260 | step(replacement); 261 | 262 | return replacement; 263 | } 264 | 265 | /*function oneLinerFromFile(str){ 266 | let lines = str.split("\n"); 267 | if(lines.length===1){ 268 | return str; 269 | } 270 | return lines.map(function (line) { 271 | return line.trim(); 272 | }).join(' '); 273 | }*/ 274 | 275 | function getFinalRegex(pattern, config) { 276 | step('Get final regex with engine: ' + config.engine); 277 | 278 | let regex; 279 | 280 | let flags = getFlags(config); 281 | 282 | switch (config.engine) { 283 | case 'V8': 284 | try { 285 | regex = new RegExp(pattern, flags); 286 | } catch (e) { 287 | if (config.debug) throw new Error(e); 288 | die(e.message); 289 | } 290 | break; 291 | case 'RE2': 292 | try { 293 | //const RE2 = require('re2'); 294 | //regex = new RE2(pattern, flags); 295 | regex = new RegExp(pattern, flags); 296 | } catch (e) { 297 | if (config.debug) throw new Error(e); 298 | die(e.message); 299 | } 300 | break; 301 | default: 302 | die(`Engine ${config.engine} not supported`); 303 | } 304 | 305 | step(regex); 306 | 307 | return regex; 308 | } 309 | 310 | function getFlags(config) { 311 | step('Get flags'); 312 | 313 | let flags = ''; 314 | 315 | if (!config.voidGlobal) { 316 | flags += 'g'; 317 | } 318 | 319 | if (!config.voidIgnoreCase) { 320 | flags += 'i'; 321 | } 322 | 323 | if (!config.voidMultiline) { 324 | flags += 'm'; 325 | } 326 | 327 | if (config.dotAll) { 328 | flags += 's'; 329 | } 330 | 331 | if (config.unicode) { 332 | flags += 'u'; 333 | } 334 | 335 | step(flags); 336 | 337 | return flags; 338 | } 339 | 340 | function readableSize(size) { 341 | if (1 === size) { 342 | return '1 Byte'; 343 | } 344 | const i = Math.floor(Math.log(size) / Math.log(1024)); 345 | return ( 346 | (size / Math.pow(1024, i)).toFixed(!!i ? 1 : 0) + ' ' + ['Bytes', 'KB', 'MB', 'GB', 'TB'][i] 347 | ); 348 | } 349 | 350 | function dynamicReplacement(_file_rr, _config_rr, _data_rr) { 351 | const _time_obj = now; 352 | const _time = localTimeString(_time_obj); 353 | const _pipe = _config_rr.pipedData, 354 | _text = _data_rr, 355 | _find = _config_rr.pattern, 356 | code_rr = _config_rr.replacementOri, 357 | _cwd = process.cwd(), 358 | _now = _time, 359 | _ = ' ', 360 | _nl = '\n'; 361 | 362 | // prettier-ignore 363 | let _file = '❌', 364 | _file_rel = '❌', 365 | _dirpath = '❌', 366 | _dirpath_rel = '❌', 367 | _dirname = '❌', 368 | _filename = '❌', 369 | _name = '❌', 370 | _ext = '❌', 371 | _mtime = '❌', 372 | _ctime = '❌', 373 | _mtime_obj = new Date(0), 374 | _ctime_obj = new Date(0), 375 | _bytes = -1, 376 | _size = '❌', 377 | dynamicContent = new Function( 378 | 'require', 379 | 'fs', 380 | 'globs', 381 | 'path', 382 | 383 | 'pipe', 384 | 'pipe_', 385 | 386 | 'find', 387 | 'find_', 388 | 'text', 389 | 'text_', 390 | 391 | 'file', 392 | 'file_', 393 | 'file_rel', 394 | 'file_rel_', 395 | 396 | 'dirpath', 397 | 'dirpath_', 398 | 'dirpath_rel', 399 | 'dirpath_rel_', 400 | 401 | 'dirname', 402 | 'dirname_', 403 | 'filename', 404 | 'filename_', 405 | 'name', 406 | 'name_', 407 | 'ext', 408 | 'ext_', 409 | 'cwd', 410 | 'cwd_', 411 | 412 | 'now', 413 | 'now_', 414 | 'time_obj', 415 | 'time', 416 | 'time_', 417 | 'mtime_obj', 418 | 'mtime', 419 | 'mtime_', 420 | 'ctime_obj', 421 | 'ctime', 422 | 'ctime_', 423 | 424 | 'bytes', 425 | 'bytes_', 426 | 'size', 427 | 'size_', 428 | 'nl', 429 | '_', 430 | '__code_rr', 431 | 'var path = require("path");' + 432 | 'var __require_ = require;' + 433 | 'var r = function(file){' + 434 | 'var result = null;' + 435 | 'try{' + 436 | 'result = __require_(file);' + 437 | '} catch (e){' + 438 | 'var dir = /^[\\\/]/.test(file) ? "" : cwd;' + 439 | 'result = __require_(path.resolve(dir, file));' + 440 | '};' + 441 | 'return result;' + 442 | '};' + 443 | 'require = r;' + 444 | 'return eval(__code_rr);' 445 | ); 446 | 447 | const needsByteOrSize = re.byteOrSize.test(_config_rr.replacement); 448 | const betterToReadfromFile = needsByteOrSize && 50000000 < _text.length; // around 50 Mb will lead to reading filezise from file instead of copying into buffer 449 | 450 | if (!_config_rr.dataIsPiped) { 451 | _file = path.normalize(path.join(_cwd, _file_rr)); 452 | _file_rel = path.relative(_cwd, _file); 453 | const pathInfo = path.parse(_file); 454 | _dirpath = pathInfo.dir; 455 | _dirpath_rel = path.relative(_cwd, _dirpath); 456 | _dirname = (_file.match(re.folderName) || ' _')[1]; 457 | _filename = pathInfo.base; 458 | _name = pathInfo.name; 459 | _ext = pathInfo.ext; 460 | 461 | if (betterToReadfromFile || re.mctime.test(_config_rr.replacement)) { 462 | const fileStats = fs.statSync(_file); 463 | _bytes = fileStats.size; 464 | _size = readableSize(_bytes); 465 | _mtime_obj = fileStats.mtime; 466 | _ctime_obj = fileStats.ctime; 467 | _mtime = localTimeString(_mtime_obj); 468 | _ctime = localTimeString(_ctime_obj); 469 | 470 | //console.log('filesize: ', fileStats.size); 471 | //console.log('dataSize: ', _bytes); 472 | } 473 | } 474 | 475 | if (needsByteOrSize && -1 === _bytes) { 476 | _bytes = Buffer.from(_text).length; 477 | _size = readableSize(_bytes); 478 | } 479 | 480 | // Run only once if no captured groups (replacement cant change) 481 | if (!/\$\d/.test(_config_rr.replacement)) { 482 | return dynamicContent( 483 | require, 484 | fs, 485 | globs, 486 | path, 487 | _pipe, 488 | _pipe + _, 489 | _find, 490 | _find + _, 491 | _text, 492 | _text + _, 493 | _file, 494 | _file + _, 495 | _file_rel, 496 | _file_rel + _, 497 | _dirpath, 498 | _dirpath + _, 499 | _dirpath_rel, 500 | _dirpath_rel + _, 501 | _dirname, 502 | _dirname + _, 503 | _filename, 504 | _filename + _, 505 | _name, 506 | _name + _, 507 | _ext, 508 | _ext + _, 509 | _cwd, 510 | _cwd + _, 511 | _now, 512 | _now + _, 513 | _time_obj, 514 | _time, 515 | _time + _, 516 | _mtime_obj, 517 | _mtime, 518 | _mtime + _, 519 | _ctime_obj, 520 | _ctime, 521 | _ctime + _, 522 | _bytes, 523 | _bytes + _, 524 | _size, 525 | _size + _, 526 | _nl, 527 | _, 528 | code_rr 529 | ); 530 | } 531 | // Capture groups used, so need to run once per match 532 | return function () { 533 | step(arguments); 534 | 535 | const __pipe = _pipe, 536 | __text = _text, 537 | __find = _find, 538 | __file = _file, 539 | __file_rel = _file_rel, 540 | __dirpath = _dirpath, 541 | __dirpath_rel = _dirpath_rel, 542 | __dirname = _dirname, 543 | __filename = _filename, 544 | __name = _name, 545 | __ext = _ext, 546 | __cwd = _cwd, 547 | __now = _now, 548 | __time_obj = _time_obj, 549 | __time = _time, 550 | __mtime_obj = _mtime_obj, 551 | __mtime = _mtime, 552 | __ctime_obj = _ctime_obj, 553 | __ctime = _ctime, 554 | __bytes = _bytes, 555 | __size = _size, 556 | __nl = _nl, 557 | __ = _, 558 | __code_rr = code_rr; 559 | 560 | var capturedGroups = ''; 561 | for (var i = 0; i < arguments.length - 2; i++) { 562 | capturedGroups += 'var $' + i + '=' + JSON.stringify(arguments[i]) + '; '; 563 | } 564 | 565 | return dynamicContent( 566 | require, 567 | fs, 568 | globs, 569 | path, 570 | 571 | __pipe, 572 | __pipe + __, 573 | 574 | __find, 575 | __find + __, 576 | __text, 577 | __text + __, 578 | 579 | __file, 580 | __file + __, 581 | __file_rel, 582 | __file_rel + __, 583 | 584 | __dirpath, 585 | __dirpath + __, 586 | __dirpath_rel, 587 | __dirpath_rel + __, 588 | 589 | __dirname, 590 | __dirname + __, 591 | __filename, 592 | __filename + __, 593 | __name, 594 | __name + __, 595 | __ext, 596 | __ext + __, 597 | __cwd, 598 | __cwd + __, 599 | 600 | __now, 601 | __now + _, 602 | __time_obj, 603 | __time, 604 | __time + _, 605 | __mtime_obj, 606 | __mtime, 607 | __mtime + _, 608 | __ctime_obj, 609 | __ctime, 610 | __ctime + _, 611 | 612 | __bytes, 613 | __bytes + __, 614 | __size, 615 | __size + __, 616 | __nl, 617 | __, 618 | capturedGroups + __code_rr 619 | ); 620 | }; 621 | } 622 | 623 | function localTimeString(dateObj = new Date()) { 624 | return `${dateObj.getFullYear()}-${('0' + (dateObj.getMonth() + 1)).slice(-2)}-${( 625 | '0' + dateObj.getDate() 626 | ).slice( 627 | -2 628 | )} ${('0' + dateObj.getHours()).slice(-2)}:${('0' + dateObj.getMinutes()).slice(-2)}:${( 629 | '0' + dateObj.getSeconds() 630 | ).slice(-2)}.${('00' + dateObj.getMilliseconds()).slice(-3)}`; 631 | } 632 | 633 | function replacePlaceholders(str = '', conf: any) { 634 | if (!conf.voidEuro) { 635 | str = str.replace(re.euro, '$'); 636 | } 637 | 638 | if (!conf.voidSection) { 639 | str = str.replace(re.section, '\\'); 640 | } 641 | 642 | return str; 643 | } 644 | 645 | function getFilePaths(conf) { 646 | let {includeGlob, excludeGlob, excludeRe} = conf; 647 | 648 | let filesToInclude = globs.sync(includeGlob); 649 | 650 | if (excludeRe.length) { 651 | excludeRe 652 | .map((el) => getFinalPattern(el, conf)) 653 | .forEach((re) => { 654 | filesToInclude = filesToInclude.filter((el) => !el.match(re)); 655 | }); 656 | } 657 | 658 | if (excludeGlob.length) { 659 | const filesToExclude = globs.sync(excludeGlob); 660 | filesToInclude = filesToInclude.filter((el) => !filesToExclude.includes(el)); 661 | } 662 | 663 | return filesToInclude.sort(); 664 | } 665 | -------------------------------------------------------------------------------- /src/multiversion.cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | if ('6' <= process.versions.node) { 4 | require('./ES6/rexreplace.cli.bundle.js'); 5 | } else if ('0.12' <= process.versions.node) { 6 | require('./ES5/rexreplace.cli.bundle.js'); 7 | } else { 8 | console.error( 9 | 'Your Node is old so this will run on a legacy version of RexReplace only supporting one single file per replacement and no options allowed. See https://www.npmjs.com/package/rreplace for more info.' 10 | ); 11 | require('../legacy/rreplace.js'); 12 | } 13 | -------------------------------------------------------------------------------- /src/output.ts: -------------------------------------------------------------------------------- 1 | let font: any = {}; 2 | font.red = font.green = font.gray = (str) => str; 3 | // check for node version supporting chalk - if so overwrite `font` 4 | //const font = import('chalk'); 5 | 6 | let config: any = null; 7 | 8 | export const outputConfig = function (_config) { 9 | config = _config; 10 | }; 11 | 12 | export const info = function (msg, data = '') { 13 | if (config.quiet || config.quietTotal) { 14 | return; 15 | } 16 | console.error(font.gray(msg), data); 17 | }; 18 | 19 | export const chat = function (msg, data = '') { 20 | if (config.verbose) { 21 | info(msg, data); 22 | } else { 23 | debug(msg + ' ' + data); 24 | } 25 | }; 26 | 27 | export const die = function (msg = '', data = '', displayHelp = false) { 28 | if (displayHelp && !config.quietTotal) { 29 | config.showHelp(); 30 | } 31 | msg && error(' ❌ ' + msg, data); 32 | kill(); 33 | }; 34 | 35 | export const error = function (msg, data = '') { 36 | if (!config.quiet && !config.quietTotal) { 37 | console.error(font.red(msg), data); 38 | } 39 | if (config.halt) { 40 | kill(msg); 41 | } 42 | return false; 43 | }; 44 | 45 | export function debug(data) { 46 | if (config.debug) { 47 | console.error(font.gray(JSON.stringify(data, null, 4))); 48 | } 49 | } 50 | 51 | export function step(data) { 52 | if (config.verbose) { 53 | debug(data); 54 | } 55 | } 56 | 57 | function kill(error = 1, msg = '') { 58 | msg && console.error(+msg); 59 | process.exit(error); 60 | } 61 | -------------------------------------------------------------------------------- /test/cli/aserta.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # name : aserta 4 | # description : a handy unit testing framework 5 | # repository : http://github.com/andamira/aserta 6 | # author : José Luis Cruz © 2016-2017 7 | # Robert Lehmann © 2009-2015 (assert.sh) 8 | # license : MIT & LGPLv3 9 | _ASERTA_VERSION=2.2.1 10 | 11 | 12 | #------------------------------------------------------------------------------- 13 | # main 14 | # 15 | # shellcheck disable=SC2155 16 | main() { 17 | 18 | export DISCOVERONLY="${DISCOVERONLY:-}" 19 | export DEBUG="${DEBUG:-}" 20 | export STOP="${STOP:-}" 21 | export INVARIANT="${INVARIANT:-}" 22 | export CONTINUE="${CONTINUE:-}" 23 | 24 | # Commands substitutions 25 | export __GREP=$(__gnuCmd grep) 26 | export __DATE=$(__gnuCmd date) 27 | 28 | _assert_reset 29 | : "${tests_suite_status:=0}" # remember if any of the tests failed so far 30 | : "${tests_ran_total:=0}" # remember total number of tests (inc. failures) 31 | : "${tests_failed_total:=0}" # remember the total number of test failures 32 | 33 | trap _assert_cleanup EXIT 34 | 35 | _indent=$'\n\t' # local format helper 36 | 37 | parseArguments "$@" 38 | 39 | } # main() 40 | 41 | 42 | #------------------------------------------------------------------------------- 43 | # parseArguments 44 | # 45 | # Parses the arguments received by the script and sets the pertinent options. 46 | # 47 | # Arguments: 48 | # $@ - all the arguments passed to the script 49 | # 50 | parseArguments() { 51 | local OPTIND option function 52 | local optspec=":cdivxh-:" 53 | 54 | # Show usage and exit if: 55 | # - the script has not been sourced 56 | # - no arguments has been passed 57 | [[ "$0" == "${BASH_SOURCE[0]}" && -z "$@" ]] && usage && exit 0 58 | 59 | # Parse the options 60 | 61 | while getopts "$optspec" option; do 62 | case "$option" in 63 | 64 | # long options 65 | # http://stackoverflow.com/a/7680682/940200 66 | 67 | -) 68 | case "$OPTARG" in 69 | continue) CONTINUE=1 ;; 70 | discover) DISCOVERONLY=1 ;; 71 | invariant) INVARIANT=1 ;; 72 | verbose) DEBUG=1 ;; 73 | stop) STOP=1 ;; 74 | 75 | help) usage ; exit 0 ;; 76 | version) version; exit 0 ;; 77 | 78 | *) # error 79 | if [[ "$OPTERR" == 1 ]]; then 80 | printf 'Unknown option --%s\n' "$OPTARG" >&2 81 | exit 255 82 | fi ;; 83 | esac ;; 84 | 85 | # short options 86 | 87 | c) CONTINUE=1 ;; 88 | d) DISCOVERONLY=1 ;; 89 | i) INVARIANT=1 ;; 90 | v) DEBUG=1 ;; 91 | x) STOP=1 ;; 92 | 93 | h) usage false; exit 0 ;; 94 | 95 | *) # error 96 | if [[ "$OPTERR" != 1 || "${optspec:0:1}" == ":" ]]; then 97 | printf "Non-option argument: '-%s'\n" "$OPTARG" >&2 98 | exit 255 99 | fi ;; 100 | esac 101 | done 102 | shift $((OPTIND-1)) 103 | 104 | 105 | 106 | # Finally parse an optional test function 107 | 108 | function="$1"; shift 109 | case "$function" in 110 | 111 | # supported functions 112 | 113 | assert_raises) assert_raises "$1" "$2" ;; 114 | assert_success) assert_success "$1" ;; 115 | assert_failure) assert_failure "$1" ;; 116 | 117 | assert) assert "$1" "$2" ;; 118 | assert_startswith) assert_startswith "$1" "$2" ;; 119 | assert_endswith) assert_endswith "$1" "$2" ;; 120 | assert_contains) assert_contains "$1" "$2" ;; 121 | assert_NOTcontains) assert_NOTcontains "$1" "$2" ;; 122 | assert_matches) assert_matches "$1" "$2" ;; 123 | 124 | assert_str_equals) assert_str_equals "$1" "$2" ;; 125 | assert_str_NOTequals) assert_str_NOTequals "$1" "$2" ;; 126 | assert_str_startswith) assert_str_startswith "$1" "$2" ;; 127 | assert_str_endswith) assert_str_endswith "$1" "$2" ;; 128 | assert_str_contains) assert_str_contains "$1" "$2" ;; 129 | assert_str_NOTcontains) assert_str_NOTcontains "$1" "$2" ;; 130 | assert_str_matches) assert_str_matches "$1" "$2" ;; 131 | 132 | # unsupported functions 133 | 134 | assert_end|skip|skip_if) 135 | printf "Test function '%s' not supported as a script argument\n" \ 136 | "$function" 137 | exit 254 ;; 138 | 139 | '') ;; # no function 140 | 141 | *) # error 142 | printf "Unknown test function: '%s'\n" "$function" 143 | exit 255 ;; 144 | esac 145 | 146 | } # parseArgs() 147 | 148 | 149 | #------------------------------------------------------------------------------- 150 | # usage 151 | # 152 | # Print usage information 153 | # 154 | usage() { 155 | 156 | cat <<- ENDUSAGE 157 | Usage: $(basename "$0") [options] [assert_function] [arguments] 158 | 159 | > a handy unit testing framework < 160 | 161 | OPTION FLAGS 162 | 163 | -v, --verbose generate output for every individual test case 164 | -x, --stop stop running tests after the first failure 165 | -i, --invariant do not measure timings to remain invariant between runs 166 | -d, --discover collect test suites only, do not run any tests 167 | -c, --continue do not modify exit code to test suite status 168 | 169 | -h, --help display this help and exit 170 | --version show version info and exit 171 | ENDUSAGE 172 | 173 | } # usage() 174 | 175 | 176 | #------------------------------------------------------------------------------- 177 | # version 178 | # 179 | # Print version information 180 | # 181 | version() { 182 | 183 | cat <<- ENDVERSION 184 | aserta v$_ASERTA_VERSION 185 | 186 | 187 | 188 | Copyright (C) 2016-2017 José Luis Cruz 189 | Released under the MIT license. 190 | Copyright (C) 2009-2015 Robert Lehmann 191 | Released under the LGPLv3 license 192 | 193 | Dependencies found: 194 | $__GREP, $__DATE 195 | 196 | ENDVERSION 197 | 198 | } #version() 199 | 200 | 201 | #------------------------------------------------------------------------------- 202 | # __gnuCmd 203 | # 204 | # Returns the resolved command, preferring the GNU versions 205 | # and falling back to the standard version when not found. 206 | # 207 | __gnuCmd() { 208 | local default_cmd="$1" 209 | local gnu_cmd="g$default_cmd" 210 | 211 | if [[ "$(which "$gnu_cmd" 2> /dev/null)" ]]; then 212 | printf '%s' "$gnu_cmd" 213 | else 214 | printf '%s' "$default_cmd" 215 | fi 216 | 217 | } #__gnuCmd() 218 | 219 | 220 | #------------------------------------------------------------------------------- 221 | # _assert_cleanup 222 | # 223 | # gets called on script exit 224 | # 225 | _assert_cleanup() { 226 | local status=$? 227 | 228 | # modify exit code if it's not already non-zero 229 | [[ $status -eq 0 && -z $CONTINUE ]] && exit "$tests_suite_status" 230 | 231 | } # _assert_cleanup() 232 | 233 | 234 | #------------------------------------------------------------------------------- 235 | # _assert_fail 236 | # 237 | _assert_fail() { 238 | [[ -n "$DEBUG" ]] && printf 'X' 239 | report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1" 240 | if [[ -n "$STOP" ]]; then 241 | [[ -n "$DEBUG" ]] && printf '\n' 242 | printf '%s\n' "$report" 243 | exit 1 244 | fi 245 | tests_errors[$tests_failed]="$report" 246 | (( tests_failed++ )) || : 247 | return 1 248 | 249 | } # _assert_fail() 250 | 251 | 252 | #------------------------------------------------------------------------------- 253 | # _assert_reset 254 | # 255 | _assert_reset() { 256 | tests_ran=0 257 | tests_failed=0 258 | tests_errors=() 259 | tests_starttime="$($__DATE +%s%N)" # nanoseconds_since_epoch 260 | 261 | } # _assert_reset() 262 | 263 | 264 | #------------------------------------------------------------------------------- 265 | # _assert_with_grep 266 | # 267 | # NOTE: doesn't support newlines in the pattern 268 | # 269 | _assert_with_grep() { 270 | local modifier="$1" 271 | local string="$2" 272 | local pattern="$3" 273 | 274 | assert_success "printf '$string' | $__GREP $modifier '$pattern'" || return 1 275 | 276 | } # _assert_with_grep() 277 | 278 | 279 | 280 | # TEST FUNCTIONS: FLOW CONTROL 281 | # ============================ 282 | 283 | 284 | #------------------------------------------------------------------------------- 285 | # skip_if 286 | # 287 | skip_if() { 288 | (eval "$@") > /dev/null 2>&1 && status=0 || status="$?" 289 | [[ "$status" -eq 0 ]] || return 290 | skip 291 | 292 | } # skip_if() 293 | 294 | 295 | #------------------------------------------------------------------------------- 296 | # skip (no arguments) 297 | # 298 | skip() { 299 | shopt -q extdebug && tests_extdebug=0 || tests_extdebug=1 300 | shopt -q -o errexit && tests_errexit=0 || tests_errexit=1 301 | 302 | # enable extdebug so returning 1 in a DEBUG trap handler skips next command 303 | shopt -s extdebug 304 | 305 | # disable errexit (set -e) so we can safely return 1 without causing exit 306 | set +o errexit 307 | tests_trapped=0 308 | trap _skip DEBUG 309 | 310 | } # skip() 311 | 312 | 313 | #------------------------------------------------------------------------------- 314 | # _skip 315 | # 316 | _skip() { 317 | if [[ $tests_trapped -eq 0 ]]; then 318 | # DEBUG trap for command we want to skip. Do not remove the handler 319 | # yet because *after* the command we need to reset extdebug/errexit 320 | # (in another DEBUG trap). 321 | tests_trapped=1 322 | [[ -z "$DEBUG" ]] || printf 's' 323 | return 1 324 | else 325 | trap - DEBUG 326 | [[ $tests_extdebug -eq 0 ]] || shopt -u extdebug 327 | [[ $tests_errexit -eq 1 ]] || set -o errexit 328 | return 0 329 | fi 330 | 331 | } # _skip() 332 | 333 | 334 | #------------------------------------------------------------------------------- 335 | # assert_end [suite ..] 336 | # 337 | assert_end() { 338 | tests_endtime="$($__DATE +%s%N)" 339 | 340 | # required visible decimal place for seconds (leading zeros if needed) 341 | local tests_time; tests_time="$( printf "%010d" \ 342 | "$(( ${tests_endtime/%N/000000000} 343 | - ${tests_starttime/%N/000000000} ))")" # in ns 344 | tests="$tests_ran ${*:+$* }tests" 345 | 346 | [[ -n "$DISCOVERONLY" ]] && printf 'collected %s.\n' "$tests" \ 347 | && _assert_reset && return 348 | [[ -n "$DEBUG" ]] && printf '\n' 349 | 350 | # to get report_time split tests_time on 2 substrings: 351 | # ${tests_time:0:${#tests_time}-9} - seconds 352 | # ${tests_time:${#tests_time}-9:3} - milliseconds 353 | if [[ -z "$INVARIANT" ]]; then 354 | report_time=" in ${tests_time:0:${#tests_time}-9}.${tests_time:${#tests_time}-9:3}s" 355 | else report_time=; fi 356 | 357 | if [[ "$tests_failed" -eq 0 ]]; then 358 | printf 'all %s passed%s.\n' "$tests" "$report_time" 359 | else 360 | for error in "${tests_errors[@]}"; do printf '%s\n' "$error"; done 361 | printf '%d of %s failed%s.\n' "$tests_failed" "$tests" "$report_time" 362 | fi 363 | 364 | tests_ran_total=$((tests_ran_total + tests_ran)) 365 | tests_failed_total=$((tests_failed_total + tests_failed)) 366 | [[ $tests_failed -gt 0 ]] && tests_suite_status=1 367 | _assert_reset 368 | 369 | } # assert_end() 370 | 371 | 372 | 373 | # TEST FUNCTIONS: RETURN STATUS 374 | # ============================= 375 | 376 | 377 | #------------------------------------------------------------------------------- 378 | # assert_raises [stdin] 379 | # 380 | assert_raises() { 381 | (( tests_ran++ )) || : 382 | [[ -z "$DISCOVERONLY" ]] || return 383 | status=0 384 | (eval "$1" <<< "${3:-}") > /dev/null 2>&1 || status="$?" 385 | expected=${2:-0} 386 | if [[ "$status" -eq "$expected" ]]; then 387 | [[ -z "$DEBUG" ]] || printf '.' 388 | return 389 | fi 390 | _assert_fail "program terminated with code $status instead of $expected" \ 391 | "$1" "$3" 392 | 393 | } # assert_raises() 394 | 395 | 396 | #------------------------------------------------------------------------------- 397 | # assert_success [stdin] 398 | # 399 | assert_success() { 400 | assert_raises "$1" 0 "${2:-}" 401 | } 402 | 403 | 404 | #------------------------------------------------------------------------------- 405 | # assert_failure [stdin] 406 | # 407 | assert_failure() { 408 | (( tests_ran++ )) || : 409 | [[ -z "$DISCOVERONLY" ]] || return 410 | status=0 411 | (eval "$1" <<< "${2:-}") > /dev/null 2>&1 || status="$?" 412 | if [[ "$status" != "0" ]]; then 413 | [[ -z "$DEBUG" ]] || printf '.' 414 | return 415 | fi 416 | _assert_fail "program terminated with a zero return code; expecting non-zero return code" \ 417 | "$1" "$2" 418 | 419 | } # assert_failure() 420 | 421 | 422 | 423 | # TEST FUNCTIONS: EXPECTED OUTPUT 424 | # =============================== 425 | 426 | 427 | #------------------------------------------------------------------------------- 428 | # assert [stdin] 429 | # 430 | assert() { 431 | (( tests_ran++ )) || : 432 | [[ -z "$DISCOVERONLY" ]] || return 433 | # shellcheck disable=SC2059 434 | expected=$(printf "${2:-}") 435 | # shellcheck disable=SC2059 436 | result=$(printf "$(eval 2>/dev/null "$1" <<< "${3:-}")") 437 | if [[ "$result" == "$expected" ]]; then 438 | [[ -z "$DEBUG" ]] || printf '.' 439 | return 440 | fi 441 | result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")" 442 | [[ -z "$result" ]] && result="nothing" || result="\"$result\"" 443 | [[ -z "$2" ]] && expected="nothing" || expected="\"$2\"" 444 | _assert_fail "expected $expected${_indent}got $result" "$1" "${3:-}" 445 | 446 | } # assert() 447 | 448 | 449 | #------------------------------------------------------------------------------- 450 | # assert_contains 451 | # 452 | assert_contains() { 453 | assert_success "[[ '$($1)' == *'$2'* ]]" 454 | } 455 | 456 | #------------------------------------------------------------------------------- 457 | # assert_NOTcontains 458 | # 459 | assert_NOTcontains() { 460 | assert_success "[[ '$($1)' != *'$2'* ]]" 461 | } 462 | 463 | 464 | #------------------------------------------------------------------------------- 465 | # assert_startswith 466 | # 467 | assert_startswith() { 468 | assert_success "[[ '$($1)' == '$2'* ]]" 469 | } 470 | 471 | 472 | #------------------------------------------------------------------------------- 473 | # assert_endswith 474 | # 475 | assert_endswith() { 476 | assert_success "[[ '$($1)' == *'$2' ]]" 477 | } 478 | 479 | 480 | #------------------------------------------------------------------------------- 481 | # assert_matches 482 | # 483 | assert_matches() { 484 | _assert_with_grep '-E' "$($1)" "$2" 485 | } 486 | 487 | 488 | 489 | # TEST FUNCTIONS: STRING COMPARISON 490 | # ============================ 491 | 492 | 493 | #------------------------------------------------------------------------------- 494 | # assert_str_equals 495 | # 496 | assert_str_equals() { 497 | assert_success "[[ '$1' == '$2' ]]" 498 | } 499 | 500 | 501 | #------------------------------------------------------------------------------- 502 | # assert_str_NOTequals 503 | # 504 | assert_str_NOTequals() { 505 | assert_success "[[ '$1' != '$2' ]]" 506 | } 507 | 508 | 509 | #------------------------------------------------------------------------------- 510 | # assert_str_startswith 511 | # 512 | assert_str_startswith() { 513 | assert_success "[[ '$1' == '$2'* ]]" 514 | } 515 | 516 | 517 | #------------------------------------------------------------------------------- 518 | # assert_str_endswith 519 | # 520 | assert_str_endswith() { 521 | assert_success "[[ '$1' == *'$2' ]]" 522 | } 523 | 524 | 525 | #------------------------------------------------------------------------------- 526 | # assert_str_contains 527 | # 528 | assert_str_contains() { 529 | assert_success "[[ '$1' == *'$2'* ]]" 530 | } 531 | 532 | #------------------------------------------------------------------------------- 533 | # assert_str_NOTcontains 534 | # 535 | assert_str_NOTcontains() { 536 | assert_success "[[ '$1' != *'$2'* ]]" 537 | } 538 | 539 | 540 | #------------------------------------------------------------------------------- 541 | # assert_str_matches 542 | # 543 | assert_str_matches() { 544 | _assert_with_grep '-E' "$1" "$2" 545 | } 546 | 547 | 548 | main "$@" 549 | -------------------------------------------------------------------------------- /test/cli/run.ai.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo 4 | echo "################## AI generated tests #################" 5 | echo 6 | 7 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | 9 | # Source the assertion library, assuming it's in the same directory 10 | source "$DIR/aserta.sh" 11 | 12 | # Helper function to reset test files to a known state 13 | reset() { 14 | echo 15 | echo "$(date +'%Y-%m-%d %H:%M:%S') - Reset AI test data " 16 | 17 | # Clean up potential leftovers from previous runs 18 | rm -f my.file.* your.file.* unicode.file.* trim.file.* read_only.file my.latin1.file file?.txt *.bak *.tmp *.log 19 | 20 | echo 'foobar' > my.file 21 | echo 'bazqux' > your.file 22 | echo 'file with unicode 😊' > unicode.file 23 | echo ' leading and trailing space ' > trim.file 24 | 25 | # Ensure write permissions are reset if changed by tests 26 | chmod u+w my.file your.file unicode.file trim.file 2>/dev/null 27 | } 28 | 29 | # Helper to create a read-only file for testing -H 30 | setup_readonly_error() { 31 | echo "error content" > read_only.file 32 | chmod u-w read_only.file 33 | } 34 | 35 | # Helper to clean up read-only file 36 | cleanup_readonly_error() { 37 | chmod u+w read_only.file 2>/dev/null 38 | rm -f read_only.file 39 | } 40 | 41 | # Helper to create a file with latin1 encoding (requires iconv) 42 | setup_latin1_file() { 43 | if command -v iconv &> /dev/null; then 44 | printf 'café' | iconv -f utf-8 -t latin1 > my.latin1.file 45 | return 0 46 | else 47 | echo "Skipping encoding test: iconv command not found" >&2 48 | return 1 # Indicate setup failed 49 | fi 50 | } 51 | 52 | 53 | 54 | # --- Start of Tests --- 55 | 56 | # -V, --verbose 57 | reset 58 | echo assert_contains "rexreplace foo bar my.file -V" "my.file" # Verbose should mention the file processed 59 | echo assert_contains "rexreplace foo bar my.file --verbose" "Matched" # Should mention match details 60 | 61 | # -u, --unicode 62 | reset 63 | echo assert "rexreplace 😊 xxx unicode.file -o -u" "file with unicode xxx" 64 | echo assert "rexreplace '😊' '😃' unicode.file -o --unicode" "file with unicode 😃" 65 | # Test without -u (might fail or behave differently depending on default) 66 | reset 67 | echo assert_NOTcontains "rexreplace 😊 xxx unicode.file -o" "xxx" # Expecting it to NOT match without -u 68 | 69 | # -e, --encoding (using latin1/iso-8859-1 as an example) 70 | reset 71 | if setup_latin1_file; then 72 | # This assertion assumes rexreplace outputs utf8 by default when using -o 73 | # And that the pattern needs to be specified in the file's encoding without -e 74 | # The exact bytes for 'café' in latin1 are 63 61 66 e9 75 | echo assert "rexreplace $(printf '\xe9') bar my.latin1.file -o" "cafbar" # Match latin1 char without -e 76 | # Now test WITH -e 77 | echo assert "rexreplace é bar my.latin1.file -o -e latin1" "cafbar" 78 | # Test invalid encoding 79 | echo assert_raises "rexreplace foo bar my.file -o -e invalid-encoding" 1 # Expecting non-zero exit code for bad encoding 80 | rm -f my.latin1.file 81 | else 82 | skip # Skip encoding tests if iconv not found 83 | skip 84 | skip 85 | fi 86 | 87 | # -q, --quiet 88 | reset 89 | # Successful run should have NO stdout 90 | echo assert "rexreplace foo xxx my.file -q" "" 91 | # Error run (file not found) should still print error to stderr (tested indirectly via assert_raises failure message) 92 | # We can't easily assert stderr content with aserta, but we can check it doesn't suppress errors needed for failure 93 | echo assert_raises "rexreplace foo xxx non_existent_file.txt -q" 1 # Exit code should still be non-zero 94 | 95 | # -Q, --quiet-total 96 | reset 97 | # Successful run should have NO stdout 98 | echo assert "rexreplace foo xxx my.file -Q" "" 99 | # Error run should have NO output at all (stdout or stderr) 100 | # Check exit code is still non-zero, but no output should be printed by aserta on failure if rexreplace is truly quiet 101 | echo assert_raises "rexreplace foo xxx non_existent_file.txt -Q" 1 102 | 103 | # -H, --halt 104 | reset 105 | echo "halt test 1" > file1.txt 106 | setup_readonly_error # file 'read_only.file' is now read-only 107 | echo "halt test 3" > file3.txt 108 | # Run command that succeeds on file1, fails on read_only.file, and should halt before file3 109 | # Use -V to see progress in manual runs if needed. Using simple replacement 'test' -> 'HALTED' 110 | echo assert_raises "rexreplace test HALTED *.txt read_only.file -H" 1 # Expect non-zero exit due to error 111 | # Check file1 was modified 112 | echo assert "cat file1.txt" "halt HALTED 1" 113 | # Check file3 was NOT modified 114 | echo assert "cat file3.txt" "halt test 3" 115 | cleanup_readonly_error 116 | rm -f file?.txt 117 | 118 | # -d, --debug 119 | reset 120 | # Check for specific debug messages (these might change based on implementation) 121 | echo assert_contains "rexreplace foo bar my.file -d" "\[DEBUG\]" # General debug flag marker 122 | echo assert_contains "rexreplace foo bar my.file --debug" "Options:" # Example debug output 123 | 124 | # -A, --void-async 125 | reset 126 | # Ensure it runs and produces correct result, even if we can't test synchronicity easily 127 | echo assert "rexreplace foo XXX my.file -A -o" "XXXbar" 128 | echo assert "cat my.file" "foobar" # Should not modify file when -o is used 129 | reset 130 | rexreplace foo XXX my.file -A 131 | echo assert "cat my.file" "XXXbar" # Should modify file without -o 132 | 133 | # -B, --void-backup 134 | reset 135 | rexreplace foo YYY my.file -B 136 | echo assert "cat my.file" "YYYbar" # File should be modified 137 | # Assert that NO backup file exists (e.g., my.file.bak or similar) 138 | echo assert_raises "ls my.file.*" 1 # ls should fail if no other my.file.* exists 139 | 140 | # Check interaction with -b (keep backup) - B should likely override b 141 | reset 142 | rexreplace foo ZZZ my.file -B -b 143 | echo assert "cat my.file" "ZZZbar" 144 | echo assert_raises "ls my.file.*" 1 # Still no backup expected 145 | 146 | # -T, --trim-pipe 147 | reset 148 | echo assert "printf ' foo bar 149 | ' | rexreplace 'foo bar' xxx -T" "xxx" 150 | echo assert "printf ' 151 | ' | rexreplace ' ' yyy -T" "" # Replace space in empty string (after trim) -> no change "" 152 | echo assert "printf ' 153 | ' | rexreplace '^$' yyy -T" "yyy" # Replace empty string (after trim) 154 | 155 | # --- Combination Tests --- 156 | 157 | # -L and -I (Literal and Void Case Insensitive - should ignore -I) 158 | reset 159 | echo assert "rexreplace FOO xxx my.file -L -I -o" "foobar" # -L takes precedence, FOO != foo 160 | 161 | # -s and -M (Dot All and Void Multiline) 162 | reset 163 | echo $'line1 164 | line2' > multiline.file 165 | echo assert "rexreplace '^line.line.$' xxx multiline.file -s -M -o" "xxx" # -s makes . match 166 | , -M makes ^$ match whole string 167 | rm -f multiline.file 168 | 169 | # -o and -q (Output and Quiet - quiet should suppress normal output message, but -o still prints result) 170 | reset 171 | echo assert "rexreplace foo xxx my.file -o -q" "xxxbar" 172 | 173 | # -m and -V (Output Match and Verbose) 174 | reset 175 | echo assert_contains "rexreplace '(o.)' _ my.file -m -V" "Match: ob" # Verbose output should exist alongside match output 176 | echo assert_contains "rexreplace '(o.)' _ my.file -m -V" "Match: oo" 177 | 178 | # -x and -b (Exclude and Keep Backup) 179 | reset 180 | cp my.file my_excluded.file 181 | rexreplace foo xxx *.file -x 'excluded' -b 182 | echo assert "cat my.file" "xxxbar" # my.file modified 183 | echo assert_success "ls my.file.*" # Backup of my.file exists 184 | echo assert "cat my_excluded.file" "foobar" # excluded file untouched 185 | echo assert_raises "ls my_excluded.file.*" 1 # No backup for excluded file 186 | rm -f my_excluded.file* my.file.* 187 | 188 | # -X and -j (Exclude Glob and JS Replacement) 189 | reset 190 | cp my.file my_excluded.file 191 | rexreplace foo '1+1' *.file -X '*excluded*' -j 192 | echo assert "cat my.file" "2bar" # my.file modified via JS 193 | echo assert "cat my_excluded.file" "foobar" # excluded file untouched 194 | rm -f my_excluded.file 195 | 196 | # --- Edge Cases --- 197 | 198 | # Empty file 199 | reset 200 | > empty.file 201 | echo assert "rexreplace foo bar empty.file -o" "" # Output empty string 202 | rexreplace foo bar empty.file 203 | echo assert "cat empty.file" "" # File remains empty 204 | rm -f empty.file 205 | 206 | # Empty Pipe 207 | echo assert "printf '' | rexreplace foo bar" "" 208 | 209 | # No Matches 210 | reset 211 | echo assert "rexreplace nomatch xxx my.file -o" "foobar" # -o outputs even if no match 212 | echo assert_NOTcontains "rexreplace nomatch xxx my.file -V" "Matched" # Verbose shows no match 213 | reset 214 | rexreplace nomatch xxx my.file # Run without -o 215 | echo assert "cat my.file" "foobar" # File should be unchanged 216 | 217 | # Shell Metacharacters (ensure quoting in test script works) 218 | reset 219 | echo 'dollar$ star* question?' > meta.file 220 | # Test literal replacement OF metacharacters 221 | echo assert "rexreplace '$' '£' meta.file -L -o" "dollar£ star* question?" 222 | echo assert "rexreplace '*' '+' meta.file -L -o" "dollar$ star+ question?" 223 | echo assert "rexreplace '?' '!' meta.file -L -o" "dollar$ star* question!" 224 | # Test literal replacement WITH metacharacters 225 | echo assert "rexreplace star '$*' meta.file -L -o" "dollar$ $* question?" 226 | rm -f meta.file 227 | 228 | # --- Error Handling --- 229 | 230 | # Invalid Regex 231 | reset 232 | echo assert_raises "rexreplace '(' ')' my.file" 1 # Invalid regex '(' should cause error 233 | 234 | # Non-existent file (without -H) 235 | reset 236 | echo assert_raises "rexreplace foo bar non_existent_file.txt" 1 # Should report error for the missing file 237 | 238 | # Invalid Option 239 | reset 240 | echo assert_raises "rexreplace foo bar --invalid-option my.file" 255 # Standard exit code for bad args often 255, but depends on parser 241 | 242 | # Permission Error (using setup_readonly_error) 243 | reset 244 | setup_readonly_error 245 | echo assert_raises "rexreplace 'error' 'denied' read_only.file" 1 # Expect error when trying to write 246 | cleanup_readonly_error 247 | 248 | # --- Final Cleanup --- 249 | reset # Run reset one last time to clean up standard files 250 | rm -f *.file *.bak *.tmp *.log # General cleanup 251 | 252 | 253 | # --- End of Tests --- 254 | assert_end "rexreplace AI extended" 255 | -------------------------------------------------------------------------------- /test/cli/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | source $DIR/aserta.sh 6 | 7 | # # Command exit codes 8 | # assert_success "true" 9 | # assert_failure "false" 10 | # assert_raises "unknown_cmd" 127 11 | # 12 | # Expected output 13 | # assert "echo test" "test" 14 | # assert "seq 3" "1\n2\n3" 15 | # assert_contains "echo foobar" "oba" 16 | # assert_startswith "echo foobar" "foo" 17 | # assert_endswith "echo foobar" "bar" 18 | # assert_matches "echo foobar" "^f.*r$" 19 | # 20 | # assert_end "example" 21 | 22 | reset() { 23 | echo 24 | echo "$(date +'%Y-%m-%d %H:%M:%S') - Reset test data " 25 | rm -f *.file 26 | echo 'foobar' > my.file 27 | echo 'abc123' > your.file 28 | } 29 | 30 | 31 | 32 | # Plain usage 33 | reset 34 | rexreplace x x my.file 35 | assert "cat my.file" "foobar" 36 | 37 | reset 38 | rexreplace o x my.file 39 | assert "cat my.file" "fxxbar" 40 | 41 | reset 42 | rexreplace "b" "\n" my.file 43 | assert "cat my.file" "foo\nar" 44 | 45 | 46 | # rr can handle a pattern and replcaement starting with '-' 47 | reset 48 | rexreplace '^(.+)$' '- $1' my.file 49 | rexreplace '- f' '_' my.file 50 | assert "cat my.file" "_oobar" 51 | 52 | 53 | # Piped data 54 | reset 55 | assert "cat my.file | rexreplace foo xxx" "xxxbar" 56 | 57 | 58 | 59 | # -v 60 | reset 61 | assert_success "rexreplace -version" 62 | 63 | 64 | # -h 65 | reset 66 | assert_success "rexreplace -help" 67 | 68 | 69 | # -o 70 | reset 71 | assert "rexreplace x x my.file --output" "foobar" 72 | 73 | reset 74 | assert "rexreplace o x my.file --output" "fxxbar" 75 | 76 | 77 | # -E 78 | reset 79 | # assert "rexreplace o x my.file --output --engine RE2" "fxxbar" # RE2 depricated 80 | assert "rexreplace o x my.file --output --engine V8" "fxxbar" 81 | 82 | 83 | # -b 84 | reset 85 | rexreplace o x my.file --keep-backup 86 | assert "cat my.file" "fxxbar" 87 | assert "cat my.file.*" "foobar" 88 | rm my.file.* 89 | 90 | # -I 91 | reset 92 | assert "rexreplace Foo xxx my.file -o" "xxxbar" 93 | 94 | reset 95 | assert "rexreplace Foo xxx my.file -o --void-ignore-case" "foobar" 96 | 97 | 98 | # -G 99 | reset 100 | assert "rexreplace o x my.file -o --void-global" "fxobar" 101 | 102 | 103 | # -O 104 | reset 105 | assert "rexreplace [fb]. _ my.file --output-match" "fo\\nba" 106 | 107 | reset 108 | assert "rexreplace '([fb](.))' _ my.file --output-match" "foo\\nbaa" 109 | 110 | # -GO 111 | reset 112 | assert "rexreplace [fb]. _ my.file --output-match --voidGlobal" "fo" 113 | 114 | 115 | 116 | # -s 117 | reset 118 | echo foobar >> my.file 119 | assert "rexreplace ar.foo _ my.file -o --dot-all " "foob_bar" 120 | 121 | 122 | 123 | 124 | # -M 125 | reset 126 | echo foobar >> my.file 127 | assert "rexreplace '^.' 'x' my.file -o" "xoobar\nxoobar" 128 | 129 | reset 130 | echo foobar >> my.file 131 | assert "rexreplace '^.' 'x' my.file -o --void-multiline" "xoobar\nfoobar" 132 | 133 | 134 | # back reference 135 | reset 136 | assert "rexreplace '(f?(o))o(.*)' '\$3\$1\$2' my.file -o" "barfoo" 137 | 138 | reset 139 | assert "rexreplace '(f?(o))o(.*)' '€3€1€2' my.file -o" "barfoo" 140 | 141 | 142 | # globs 143 | reset 144 | echo foobar >> my_file 145 | assert "rexreplace o x my*le -o" "fxxbar\nfxxbar" 146 | rm my_file 147 | 148 | 149 | # -€ 150 | reset 151 | assert "rexreplace '.$' '$' my.file -o" 'fooba$' 152 | 153 | reset 154 | assert "rexreplace '.€' '€' my.file -o" 'fooba$' 155 | 156 | reset 157 | assert "rexreplace '.€' '€' my.file -o --void-euro" 'foobar' 158 | 159 | 160 | # -§ 161 | reset 162 | echo foo[bar] > my.file 163 | assert "rexreplace '[\]]' '[' my.file -o" 'foo[bar[' 164 | 165 | 166 | reset 167 | echo foo[bar] > my.file 168 | assert "rexreplace '[§]]' '[' my.file -o" 'foo[bar[' 169 | 170 | reset 171 | echo foo[bar] > my.file 172 | assert "rexreplace '[§]]' '[' my.file -o --void-section" 'foo[bar]' 173 | 174 | 175 | # -j 176 | reset 177 | assert "rexreplace 'foo' '2+2' my.file -o --replacement-js" '4bar' 178 | 179 | reset 180 | assert "rexreplace 'foo' 'var i = 2; i + 2' my.file -o --replacement-js" '4bar' 181 | 182 | reset 183 | #assert "rexreplace '[fb](.)' '€1.toUpperCase();' my.file -o --replacement-js" 'OoAr' 184 | 185 | 186 | # Access to js variables 187 | reset 188 | assert "rexreplace 'fo(o)bar' '[!!fs,!!globs,find,text.trim()].join(\":\")' my.file -o --replacement-js" 'true:true:fo(o)bar:foobar' 189 | 190 | 191 | reset 192 | assert "printf foobar | rexreplace 'foobar' \"['file:'+file,'dirpath:'+dirpath,'filename:'+filename,'name:'+name,'ext:'+ext,'text:'+text].join(':')\" -o --replacement-js" 'file:❌:dirpath:❌:filename:❌:name:❌:ext:❌:text:foobar' 193 | 194 | 195 | reset 196 | assert "rexreplace 'foobar' \"['filename:'+filename,'name:'+name,'ext:'+ext,'text:'+text].join(':')\" my.file -o --replacement-js" 'filename:my.file:name:my:ext:.file:text:foobar' 197 | 198 | reset 199 | assert "rexreplace 'foo((b)ar)' '€1+€2' my.file -o --replacement-js" 'barb' 200 | 201 | ## Test replacement-js on multiple files 202 | reset 203 | assert "rexreplace 'foo((b)ar)' '€1+€2' *.file -o --replacement-js" 'barb\nabc123' 204 | 205 | reset 206 | assert "rexreplace 'a(.+)' '\"_replace_\"+€1' *.file -o --replacement-js" 'foob_replace_r\n_replace_bc123' 207 | 208 | # Content manually testes 209 | # todo: automate test of content 210 | reset 211 | assert "rexreplace 'foobar' '[require, fs, globs, path, pipe, pipe_, find, find_, text, text_, file, file_, file_rel, file_rel_, dirpath, dirpath_, dirpath_rel, dirpath_rel_, dirname, dirname_, filename, filename_, name, name_, ext, ext_, cwd, cwd_, now, now_, time_obj, time, time_, mtime_obj, mtime, mtime_, ctime_obj, ctime, ctime_, bytes, bytes_, size, size_, _].length' my.file -o --replacement-js" '44' 212 | 213 | 214 | # -R 215 | reset 216 | assert "printf x | rexreplace 'b' _ my.file -o --replacement-pipe" 'fooxar' 217 | 218 | 219 | 220 | 221 | # -L 222 | reset 223 | assert "rexreplace 'b' '*+*' my.file -o" 'foo*+*ar' 224 | assert "rexreplace '*+*' 'b' my.file -o --literal" 'foobar' 225 | 226 | 227 | 228 | # -x 229 | reset 230 | rexreplace 'b' '*+*' my.file 231 | assert "cat my.file" 'foo*+*ar' 232 | assert "cat your.file" 'abc123' 233 | reset 234 | rexreplace 'b' '*+*' '*.file' 235 | assert "cat my.file" 'foo*+*ar' 236 | assert "cat your.file" 'a*+*c123' 237 | reset 238 | rexreplace 'b' '*+*' '*.file' -x y 239 | assert "cat my.file" 'foobar' 240 | assert "cat your.file" 'abc123' 241 | reset 242 | rexreplace 'b' '*+*' '*.file' -x ^y 243 | assert "cat my.file" 'foo*+*ar' 244 | assert "cat your.file" 'abc123' 245 | 246 | 247 | # -X 248 | reset 249 | rexreplace 'b' '*+*' '*.file' -X '*.file' 250 | assert "cat my.file" 'foobar' 251 | assert "cat your.file" 'abc123' 252 | reset 253 | rexreplace 'b' '*+*' '*.file' -X 'y*' 254 | assert "cat my.file" 'foo*+*ar' 255 | assert "cat your.file" 'abc123' 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | # # -P 267 | # reset 268 | # echo '.€' > pattern.txt 269 | # echo '€' > replacement.txt 270 | # assert "rexreplace 'pattern.txt' 'replacement.txt' my.file -o --pattern-file --replacement-file" 'fooba$' 271 | # rm pattern.txt 272 | # rm replacement.txt 273 | 274 | # # Multiply lines in files! 275 | # reset 276 | # echo " . \n € " > pattern.txt 277 | # echo " €\n " > replacement.txt 278 | # assert "rexreplace 'pattern.txt' 'replacement.txt' my.file -o --pattern-file --replacement-file" 'fooba$' 279 | # rm pattern.txt 280 | # rm replacement.txt 281 | 282 | 283 | # # Singe line file (with space) 284 | # reset 285 | # echo 'fooba r' > my.file 286 | # echo ' .€' > pattern.txt 287 | # echo ' €' > replacement.txt 288 | # assert "rexreplace 'pattern.txt' 'replacement.txt' my.file -o --pattern-file --replacement-file" 'fooba $' 289 | # rm pattern.txt 290 | # rm replacement.txt 291 | 292 | 293 | 294 | 295 | # Todo: test -e 296 | # assert "rexreplace ??? ??? my.file -e" "foobar" 297 | # reset 298 | 299 | # Todo: test -q 300 | # assert "rexreplace ??? ??? my.file -q" "foobar" 301 | # reset 302 | 303 | # Todo: test -Q 304 | # assert "rexreplace ??? ??? my.file -Q" "foobar" 305 | # reset 306 | 307 | # Todo: test -H 308 | # assert "rexreplace ??? ??? my.file -H" "foobar" 309 | # reset 310 | 311 | # Todo: test -d 312 | # assert "rexreplace ??? ??? my.file -d" "foobar" 313 | # reset 314 | 315 | rm my.file 316 | rm your.file 317 | 318 | assert_end "rexreplace" 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /test/debug.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/encoding.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/halt.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/help.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/helper.js: -------------------------------------------------------------------------------- 1 | global.rexreplace = require('../src/core'); 2 | 3 | global.assert = require('assert'); 4 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require assert 2 | --require test/helper 3 | --ui bdd 4 | -------------------------------------------------------------------------------- /test/output.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/pattern-file.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/quiet-total.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/quiet.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/replacement-file.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/replacement-js-dynamic.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/replacement-js.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/speed/run.sh: -------------------------------------------------------------------------------- 1 | 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 3 | 4 | # bash $DIR/speed-test ; exit # for debug 5 | 6 | echo Running tests 7 | bash $DIR/speed-test &> $DIR/testlog.speed.md 8 | cat $DIR/testlog.speed.md 9 | echo '' 10 | echo Tests stored in testlog.speed.md 11 | open $DIR/testlog.speed.md || true 12 | -------------------------------------------------------------------------------- /test/speed/speed-code-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DATETIME=`date '+%Y-%m-%d %H:%M'` 4 | RR_VERSION="v`rr -v`" 5 | NODE_VERSION=`NODE -v` 6 | echo '' 7 | echo "# RexReplace vs \`sed\` speed test" 8 | printf "\n\t%s\n\t%s\n\t%s\n\n" "$DATETIME" "RexReplace $RR_VERSION" "Node $NODE_VERSION" 9 | 10 | echo "This test will remove HTML tags from the HTML sorce of George Orwell's 1984 to get the pure text version." 11 | 12 | echo 'All testresults printed are the sum of 10 rounds given in seconds.' 13 | 14 | TIMEFORMAT=%R 15 | 16 | create_testdata(){ 17 | #return # for debug 18 | 19 | curl -s 1984.surge.sh > source.file 20 | head -c $((1*1024)) source.file > 1Kb.file 21 | head -c $((5*1024)) source.file > 5Kb.file 22 | head -c $((10*1024)) source.file > 10Kb.file 23 | head -c $((100*1024)) source.file > 100Kb.file 24 | head -c $((500*1024)) source.file > 500Kb.file 25 | echo '' > 1Mb.file; for i in {1..2}; do cat 500Kb.file >> 1Mb.file; done 26 | echo '' > 5Mb.file; for i in {1..5}; do cat 1Mb.file >> 5Mb.file; done 27 | echo '' > 10Mb.file; for i in {1..10}; do cat 1Mb.file >> 10Mb.file; done 28 | echo '' > 25Mb.file; for i in {1..25}; do cat 1Mb.file >> 25Mb.file; done 29 | echo '' > 50Mb.file; for i in {1..50}; do cat 1Mb.file >> 50Mb.file; done 30 | echo '' > 100Mb.file; for i in {1..100}; do cat 1Mb.file >> 100Mb.file; done 31 | 32 | 33 | } 34 | 35 | remove_testdata(){ 36 | #return # for debug 37 | 38 | rm source.file 39 | rm 1Kb.file 40 | rm 5Kb.file 41 | rm 10Kb.file 42 | rm 100Kb.file 43 | # rm 500Kb.file 44 | # rm 1Mb.file 45 | # rm 5Mb.file 46 | # rm 10Mb.file 47 | # rm 25Mb.file 48 | # rm 50Mb.file 49 | # rm 100Mb.file 50 | 51 | 52 | 53 | } 54 | 55 | 56 | run_rr(){ 57 | 58 | echo '' 59 | printf " - RexReplace $2 on a %s file: \t" $1 60 | time for i in {1..100}; do 61 | $2 '<.*?>' '' "$1.file" -o > /dev/null 62 | done 63 | echo '' 64 | 65 | } 66 | 67 | 68 | 69 | do_test(){ 70 | 71 | # Do tests 72 | echo '' 73 | echo "## A single $1 file" 74 | echo '' 75 | 76 | echo '_100 rounds of:_' 77 | echo '' 78 | printf " - sed on %s file: \t" $1 79 | time for i in {1..100}; do 80 | cat "$1.file" | sed 's/<.*?>//g' > /dev/null 81 | done 82 | 83 | #run_rr $1 rr_3_m 84 | # run_rr $1 rr_5_m 85 | # run_rr $1 rr_6_m 86 | #run_rr $1 rr_6_b 87 | #run_rr $1 rr_6_b_u 88 | #run_rr $1 rr_6_c 89 | #run_rr $1 rr_6_c_js 90 | #run_rr $1 rr_6 91 | #run_rr $1 rr_6_b_c 92 | # run_rr $1 rr_6_b_c_js 93 | #run_rr $1 rr_6_b_u_c 94 | #run_rr $1 rr_6_b_u_c_js 95 | 96 | 97 | # Total 1,977 98,141 94,509 95,242 96,773 95,887 95,728 97,053 94,747 94,314 95,418 96,743 98 | # Compination sed rr_3_m rr_5_m rr_6_b rr_6_b_u rr_6_c rr_6_c_js rr_6 rr_6_b_c rr_6_b_c_js rr_6_b_u_c rr_6_b_u_c_js 99 | # 1kb 0,633 24,249 23,337 24,131 24,392 24,705 24,553 24,673 23,645 23,322 23,384 25,703 100 | # 5kb 0,498 26,377 23,582 23,448 25,37 23,79 23,734 24,218 23,792 23,895 23,559 23,768 101 | # 10kb 0,401 23,889 23,837 23,909 23,506 23,818 23,961 24,217 23,807 23,434 24,984 23,757 102 | # 100kb 0,445 23,626 23,753 23,754 23,505 23,574 23,48 23,945 23,503 23,663 23,491 23,515 103 | 104 | 105 | # run_rr $1 rr_5_b 106 | # run_rr $1 rr_5_b_c_js 107 | 108 | 109 | run_rr $1 rr 110 | 111 | } 112 | 113 | 114 | create_testdata 115 | 116 | do_test '1Kb' 117 | do_test '5Kb' 118 | do_test '10Kb' 119 | do_test '100Kb' 120 | # do_test '500Kb' 121 | # do_test '1Mb' 122 | # do_test '5Mb' 123 | # do_test '10Mb' 124 | # do_test '25Mb' 125 | # do_test '50Mb' 126 | # do_test '100Mb' 127 | 128 | 129 | 130 | 131 | echo '' 132 | echo '----' 133 | echo '' 134 | echo "_All tests completed_" 135 | 136 | remove_testdata 137 | 138 | 139 | -------------------------------------------------------------------------------- /test/speed/speed-code-test-v2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DATETIME=`date '+%Y-%m-%d %H:%M'` 4 | RR_VERSION="v`rr -v`" 5 | NODE_VERSION=`NODE -v` 6 | echo '' 7 | echo "# RexReplace vs \`sed\` speed test" 8 | printf "\n\t%s\n\t%s\n\t%s\n\n" "$DATETIME" "RexReplace $RR_VERSION" "Node $NODE_VERSION" 9 | 10 | echo "This test will remove HTML tags from the HTML sorce of George Orwell's 1984 to get the pure text version." 11 | 12 | echo 'All testresults printed are the sum of 10 rounds given in seconds.' 13 | 14 | TIMEFORMAT=%R 15 | 16 | create_testdata(){ 17 | #return # for debug 18 | 19 | curl -s 1984.surge.sh > source.file 20 | head -c $((1*1024)) source.file > 1Kb.file 21 | head -c $((5*1024)) source.file > 5Kb.file 22 | head -c $((10*1024)) source.file > 10Kb.file 23 | head -c $((100*1024)) source.file > 100Kb.file 24 | head -c $((500*1024)) source.file > 500Kb.file 25 | echo '' > 1Mb.file; for i in {1..2}; do cat 500Kb.file >> 1Mb.file; done 26 | echo '' > 5Mb.file; for i in {1..5}; do cat 1Mb.file >> 5Mb.file; done 27 | echo '' > 10Mb.file; for i in {1..10}; do cat 1Mb.file >> 10Mb.file; done 28 | echo '' > 25Mb.file; for i in {1..25}; do cat 1Mb.file >> 25Mb.file; done 29 | echo '' > 50Mb.file; for i in {1..50}; do cat 1Mb.file >> 50Mb.file; done 30 | echo '' > 100Mb.file; for i in {1..100}; do cat 1Mb.file >> 100Mb.file; done 31 | 32 | 33 | } 34 | 35 | remove_testdata(){ 36 | #return # for debug 37 | 38 | rm source.file 39 | rm 1Kb.file 40 | rm 5Kb.file 41 | rm 10Kb.file 42 | rm 100Kb.file 43 | # rm 500Kb.file 44 | # rm 1Mb.file 45 | # rm 5Mb.file 46 | # rm 10Mb.file 47 | # rm 25Mb.file 48 | # rm 50Mb.file 49 | # rm 100Mb.file 50 | 51 | 52 | 53 | } 54 | 55 | 56 | run_rr(){ 57 | 58 | echo '' 59 | printf " - RexReplace $2 on a %s file: \t" $1 60 | time for i in {1..100}; do 61 | $2 '<.*?>' '' "$1.file" -o > /dev/null 62 | done 63 | echo '' 64 | 65 | } 66 | 67 | 68 | 69 | do_test(){ 70 | 71 | # Do tests 72 | echo '' 73 | echo "## A single $1 file" 74 | echo '' 75 | 76 | echo '_100 rounds of:_' 77 | echo '' 78 | printf " - sed on %s file: \t" $1 79 | time for i in {1..100}; do 80 | cat "$1.file" | sed 's/<.*?>//g' > /dev/null 81 | done 82 | 83 | #run_rr $1 rr_3_m 84 | # run_rr $1 rr_5_m 85 | # run_rr $1 rr_6_m 86 | #run_rr $1 rr_6_b 87 | #run_rr $1 rr_6_b_u 88 | #run_rr $1 rr_6_c 89 | #run_rr $1 rr_6_c_js 90 | #run_rr $1 rr_6 91 | #run_rr $1 rr_6_b_c 92 | # run_rr $1 rr_6_b_c_js 93 | #run_rr $1 rr_6_b_u_c 94 | #run_rr $1 rr_6_b_u_c_js 95 | 96 | 97 | # Total 1,977 98,141 94,509 95,242 96,773 95,887 95,728 97,053 94,747 94,314 95,418 96,743 98 | # Compination sed rr_3_m rr_5_m rr_6_b rr_6_b_u rr_6_c rr_6_c_js rr_6 rr_6_b_c rr_6_b_c_js rr_6_b_u_c rr_6_b_u_c_js 99 | # 1kb 0,633 24,249 23,337 24,131 24,392 24,705 24,553 24,673 23,645 23,322 23,384 25,703 100 | # 5kb 0,498 26,377 23,582 23,448 25,37 23,79 23,734 24,218 23,792 23,895 23,559 23,768 101 | # 10kb 0,401 23,889 23,837 23,909 23,506 23,818 23,961 24,217 23,807 23,434 24,984 23,757 102 | # 100kb 0,445 23,626 23,753 23,754 23,505 23,574 23,48 23,945 23,503 23,663 23,491 23,515 103 | 104 | 105 | # run_rr $1 rr_5_b 106 | # run_rr $1 rr_5_b_c_js 107 | 108 | 109 | run_rr $1 rr 110 | 111 | } 112 | 113 | 114 | create_testdata 115 | 116 | do_test '1Kb' 117 | do_test '5Kb' 118 | do_test '10Kb' 119 | do_test '100Kb' 120 | do_test '500Kb' 121 | do_test '1Mb' 122 | do_test '5Mb' 123 | do_test '10Mb' 124 | do_test '25Mb' 125 | do_test '50Mb' 126 | do_test '100Mb' 127 | 128 | 129 | 130 | 131 | echo '' 132 | echo '----' 133 | echo '' 134 | echo "_All tests completed_" 135 | 136 | remove_testdata 137 | 138 | 139 | -------------------------------------------------------------------------------- /test/speed/speed-code-test-v3: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DATETIME=`date '+%Y-%m-%d %H:%M'` 4 | RR_VERSION="v`rr -v`" 5 | NODE_VERSION=`NODE -v` 6 | DATAPOND="datapond.txt" 7 | echo '' 8 | echo "# RexReplace vs x speed test" 9 | printf "\n\t%s\n\t%s\n\t%s\n\n" "$DATETIME" "RexReplace $RR_VERSION" "Node $NODE_VERSION" 10 | 11 | echo "This test will remove p and div HTML tags from the HTML sorce of George Orwell's 1984." 12 | 13 | echo 'All testresults printed are the sum of 10 rounds given in seconds.' 14 | 15 | TIMEFORMAT=%R 16 | 17 | create_testdata(){ 18 | #return # for debug 19 | 20 | #curl -s 1984.surge.sh > source.file 21 | cat 1984.surge.sh.html > source.file 22 | tail -c $((1*1024)) source.file > 1Kb.file 23 | tail -c $((5*1024)) source.file > 5Kb.file 24 | tail -c $((10*1024)) source.file > 10Kb.file 25 | tail -c $((100*1024)) source.file > 100Kb.file 26 | tail -c $((500*1024)) source.file > 500Kb.file 27 | echo '' > 1Mb.file; for i in {1..2}; do cat 500Kb.file >> 1Mb.file; done 28 | echo '' > 5Mb.file; for i in {1..5}; do cat 1Mb.file >> 5Mb.file; done 29 | echo '' > 10Mb.file; for i in {1..10}; do cat 1Mb.file >> 10Mb.file; done 30 | echo '' > 25Mb.file; for i in {1..25}; do cat 1Mb.file >> 25Mb.file; done 31 | echo '' > 50Mb.file; for i in {1..50}; do cat 1Mb.file >> 50Mb.file; done 32 | echo '' > 100Mb.file; for i in {1..100}; do cat 1Mb.file >> 100Mb.file; done 33 | 34 | 35 | } 36 | 37 | remove_testdata(){ 38 | return # for debug 39 | 40 | rm source.file 41 | rm 1Kb.file 42 | rm 5Kb.file 43 | rm 10Kb.file 44 | rm 100Kb.file 45 | rm 500Kb.file 46 | rm 1Mb.file 47 | rm 5Mb.file 48 | rm 10Mb.file 49 | rm 25Mb.file 50 | rm 50Mb.file 51 | rm 100Mb.file 52 | 53 | 54 | } 55 | 56 | 57 | run_hyperfine(){ 58 | echo '' 59 | printf "## Running test on %s file\n" $1 60 | echo '' 61 | cp "$1.file" "test$1.file" 62 | hyperfine \ 63 | --time-unit second \ 64 | --warmup 5 \ 65 | --min-runs 10 \ 66 | --prepare "cp $1.file test$1.file" \ 67 | "sed -i '' 's:$2:$3:g' test$1.file" \ 68 | "gsed -i -e 's/$2/$3/g' test$1.file" \ 69 | "rr '$2' '$3' test$1.file" \ 70 | "perl -pi -e 's/$2/$3/g' test$1.file" \ 71 | "awk '{gsub(/$2/,\"$3\")}' test$1.file" \ 72 | "replace-in-file '/$2/g' '$3' test$1.file --isRegex" \ 73 | "replace '$2' '$3' test$1.file" \ 74 | "replace-x '$2' '$3' test$1.file" \ 75 | "sd -i '$2' '$3' test$1.file" \ 76 | --export-csv output$1.csv \ 77 | --export-json output$1.json \ 78 | --export-markdown output$1.md \ 79 | # --show-output 80 | echo '' 81 | 82 | echo '----' 83 | } 84 | 85 | 86 | run_hyperfine_specific(){ 87 | echo '' 88 | printf "## Running test on %s file\n" $1 89 | echo '' 90 | cp "$1.file" "test$1.file" 91 | echo hyperfine \ 92 | --time-unit second \ 93 | --warmup 5 \ 94 | --min-runs 10 \ 95 | --prepare "cp $1.file test$1.file" \ 96 | "sed -i '' 's:]*>:$3:g' test$1.file" \ 97 | "gsed -i -e 's:$2:$3:g' test$1.file" \ 98 | "rexreplace '$2' '$3' test$1.file" \ 99 | "perl -pi -e 's:$2:$3:g' test$1.file" \ 100 | "replace-in-file '/<\/*(p|span|div)[^>]*>/g' '$3' test$1.file --isRegex" \ 101 | "replace '$2' '$3' test$1.file" \ 102 | "replace-x '$2' '$3' test$1.file" \ 103 | "sd -i '$2' '$3' test$1.file" \ 104 | --export-csv output$1.csv \ 105 | --export-json output$1.json \ 106 | --export-markdown output$1.md \ 107 | # --show-output 108 | #"awk '{gsub(:$2:,\"$3\")}' test$1.file" \ 109 | echo '' 110 | 111 | echo '----' 112 | 113 | echo '' >> "$DATAPOND" 114 | 115 | echo `stat -f%z "$1.file"` >> "$DATAPOND" 116 | 117 | alasql 'COLUMN OF SELECT mean from csv(?)' "output$1.csv" >> "$DATAPOND" 118 | } 119 | 120 | 121 | 122 | do_test(){ 123 | 124 | #run_hyperfine_specific $1 ']*>' 'foobar' 125 | run_hyperfine $1 'e' 'foobar' 126 | 127 | } 128 | 129 | 130 | create_testdata 131 | 132 | echo '' > "$DATAPOND" 133 | 134 | do_test '1Kb' 135 | do_test '5Kb' 136 | do_test '10Kb' 137 | do_test '100Kb' 138 | do_test '500Kb' 139 | do_test '1Mb' 140 | do_test '5Mb' 141 | do_test '10Mb' 142 | do_test '25Mb' 143 | do_test '50Mb' 144 | do_test '100Mb' 145 | 146 | 147 | 148 | 149 | echo '' 150 | echo "_All tests completed_" 151 | 152 | 153 | alasql 'COLUMN OF SELECT command from csv(?)' output1kb.csv >> "$DATAPOND" 154 | 155 | rr '\[|\]|^\s+"?|[, ].*$' '' "$DATAPOND" -Q 156 | 157 | remove_testdata 158 | 159 | 160 | -------------------------------------------------------------------------------- /test/speed/speed-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DATETIME=`date '+%Y-%m-%d %H:%M'` 4 | RR_VERSION="v`rr -v`" 5 | NODE_VERSION=`NODE -v` 6 | echo '' 7 | echo "# RexReplace vs \`sed\` speed test" 8 | printf "\n\t%s\n\t%s\n\t%s\n\n" "$DATETIME" "RexReplace $RR_VERSION" "Node $NODE_VERSION" 9 | 10 | echo "This test will remove HTML tags from the HTML sorce of George Orwell's 1984 to get the pure text version." 11 | 12 | echo 'All testresults printed are the sum of 10 rounds given in seconds.' 13 | 14 | TIMEFORMAT=%R 15 | 16 | create_testdata(){ 17 | #return # for debug 18 | 19 | curl -s 1984.surge.sh > source.file 20 | head -c $((1*1024)) source.file > 1Kb.file 21 | head -c $((5*1024)) source.file > 5Kb.file 22 | head -c $((10*1024)) source.file > 10Kb.file 23 | head -c $((100*1024)) source.file > 100Kb.file 24 | head -c $((500*1024)) source.file > 500Kb.file 25 | echo '' > 1Mb.file; for i in {1..2}; do cat 500Kb.file >> 1Mb.file; done 26 | echo '' > 5Mb.file; for i in {1..5}; do cat 1Mb.file >> 5Mb.file; done 27 | echo '' > 10Mb.file; for i in {1..10}; do cat 1Mb.file >> 10Mb.file; done 28 | echo '' > 25Mb.file; for i in {1..25}; do cat 1Mb.file >> 25Mb.file; done 29 | echo '' > 50Mb.file; for i in {1..50}; do cat 1Mb.file >> 50Mb.file; done 30 | echo '' > 100Mb.file; for i in {1..100}; do cat 1Mb.file >> 100Mb.file; done 31 | } 32 | 33 | remove_testdata(){ 34 | #return # for debug 35 | 36 | rm source.file 37 | rm 1Kb.file 38 | rm 5Kb.file 39 | rm 10Kb.file 40 | rm 100Kb.file 41 | rm 500Kb.file 42 | rm 1Mb.file 43 | rm 5Mb.file 44 | rm 10Mb.file 45 | rm 25Mb.file 46 | rm 50Mb.file 47 | rm 100Mb.file 48 | 49 | rm A0.txt 50 | rm A1.txt 51 | rm A2.txt 52 | rm A3.txt 53 | rm A4.txt 54 | rm A5.txt 55 | rm A6.txt 56 | rm A7.txt 57 | rm A8.txt 58 | rm A9.txt 59 | 60 | } 61 | 62 | do_test(){ 63 | 64 | # Do tests 65 | echo '' 66 | echo "## A single $1 file" 67 | echo '' 68 | 69 | echo '_10 rounds of:_' 70 | echo '' 71 | printf " - sed on %s file: \t" $1 72 | time for i in {1..10}; do 73 | cat "$1.file" | sed 's/<.*?>//g' > /dev/null 74 | done 75 | 76 | echo '' 77 | printf " - RexReplace on a %s file: \t" $1 78 | time for i in {1..10}; do 79 | rexreplace_ '<.*?>' '' "$1.file" -o > /dev/null 80 | done 81 | echo '' 82 | 83 | } 84 | 85 | 86 | create_testdata 87 | 88 | do_test '1Kb' 89 | do_test '5Kb' 90 | do_test '10Kb' 91 | do_test '100Kb' 92 | do_test '500Kb' 93 | do_test '1Mb' 94 | do_test '5Mb' 95 | do_test '10Mb' 96 | do_test '25Mb' 97 | do_test '50Mb' 98 | do_test '100Mb' 99 | 100 | 101 | 102 | echo '' 103 | echo '' 104 | echo '----' 105 | echo '' 106 | echo '' 107 | echo "## 10 files (10Kb each) - time for 10 rounds" 108 | cat 10Kb.file > A0.txt 109 | cat A0.txt > A1.txt 110 | cat A0.txt > A2.txt 111 | cat A0.txt > A3.txt 112 | cat A0.txt > A4.txt 113 | cat A0.txt > A5.txt 114 | cat A0.txt > A6.txt 115 | cat A0.txt > A7.txt 116 | cat A0.txt > A8.txt 117 | cat A0.txt > A9.txt 118 | 119 | echo '' 120 | printf " - sed on 10 files: \t" 121 | time for i in {1..10}; do 122 | cat A0.txt | sed 's/<.*>//g' > /dev/null 123 | cat A1.txt | sed 's/<.*>//g' > /dev/null 124 | cat A2.txt | sed 's/<.*>//g' > /dev/null 125 | cat A3.txt | sed 's/<.*>//g' > /dev/null 126 | cat A4.txt | sed 's/<.*>//g' > /dev/null 127 | cat A5.txt | sed 's/<.*>//g' > /dev/null 128 | cat A6.txt | sed 's/<.*>//g' > /dev/null 129 | cat A7.txt | sed 's/<.*>//g' > /dev/null 130 | cat A8.txt | sed 's/<.*>//g' > /dev/null 131 | cat A9.txt | sed 's/<.*>//g' > /dev/null 132 | done 133 | 134 | 135 | echo '' 136 | printf " - RexReplace on 10 files: \t" 137 | time for i in {1..10}; do 138 | rexreplace '<.*>' '' -o A0.txt A1.txt A2.txt A3.txt A4.txt A5.txt A6.txt A7.txt A8.txt A9.txt > /dev/null 139 | done 140 | 141 | echo '' 142 | printf " - RexReplace on 10 files given as one glob: \t" 143 | time for i in {1..10}; do 144 | rexreplace '<.*>' '' -o A*.txt > /dev/null 145 | done 146 | 147 | 148 | echo '' 149 | echo '----' 150 | echo '' 151 | echo "_All tests completed_" 152 | 153 | remove_testdata 154 | 155 | 156 | -------------------------------------------------------------------------------- /test/speed/tesopi.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/speed/testlog.speed.md: -------------------------------------------------------------------------------- 1 | # RexReplace vs `sed` speed test 2 | 3 | 2018-07-07 00:10 4 | RexReplace v3.1.0 5 | Node v8.11.3 6 | 7 | This test will remove HTML tags from the HTML sorce of George Orwell's 1984 to get the pure text version. 8 | All testresults printed are the sum of 10 rounds given in seconds. 9 | 10 | ## A single 1Kb file 11 | 12 | _10 rounds of:_ 13 | 14 | - sed on 1Kb file: 0.140 15 | 16 | - RexReplace on a 1Kb file: 5.482 17 | 18 | ## A single 5Kb file 19 | 20 | _10 rounds of:_ 21 | 22 | - sed on 5Kb file: 0.139 23 | 24 | - RexReplace on a 5Kb file: 4.509 25 | 26 | ## A single 10Kb file 27 | 28 | _10 rounds of:_ 29 | 30 | - sed on 10Kb file: 0.101 31 | 32 | - RexReplace on a 10Kb file: 4.213 33 | 34 | ## A single 100Kb file 35 | 36 | _10 rounds of:_ 37 | 38 | - sed on 100Kb file: 0.167 39 | 40 | - RexReplace on a 100Kb file: 3.213 41 | 42 | ## A single 500Kb file 43 | 44 | _10 rounds of:_ 45 | 46 | - sed on 500Kb file: 0.458 47 | 48 | - RexReplace on a 500Kb file: 3.188 49 | 50 | ## A single 1Mb file 51 | 52 | _10 rounds of:_ 53 | 54 | - sed on 1Mb file: 0.913 55 | 56 | - RexReplace on a 1Mb file: 3.570 57 | 58 | ## A single 5Mb file 59 | 60 | _10 rounds of:_ 61 | 62 | - sed on 5Mb file: 4.819 63 | 64 | - RexReplace on a 5Mb file: 4.362 65 | 66 | ## A single 10Mb file 67 | 68 | _10 rounds of:_ 69 | 70 | - sed on 10Mb file: 8.433 71 | 72 | - RexReplace on a 10Mb file: 5.297 73 | 74 | ## A single 25Mb file 75 | 76 | _10 rounds of:_ 77 | 78 | - sed on 25Mb file: 17.726 79 | 80 | - RexReplace on a 25Mb file: 7.144 81 | 82 | ## A single 50Mb file 83 | 84 | _10 rounds of:_ 85 | 86 | - sed on 50Mb file: 44.416 87 | 88 | - RexReplace on a 50Mb file: 13.570 89 | 90 | ## A single 100Mb file 91 | 92 | _10 rounds of:_ 93 | 94 | - sed on 100Mb file: 72.585 95 | 96 | - RexReplace on a 100Mb file: 23.618 97 | 98 | --- 99 | 100 | ## 10 files (10Kb each) - time for 10 rounds 101 | 102 | - sed on 10 files: 0.778 103 | 104 | - RexReplace on 10 files: 3.015 105 | 106 | - RexReplace on 10 files given as one glob: 3.313 107 | 108 | --- 109 | 110 | _All tests completed_ 111 | -------------------------------------------------------------------------------- /test/speed/unicode.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/test.js.stub: -------------------------------------------------------------------------------- 1 | 2 | describe(__filename.replace(/.*\/([^\/]+)\.js$/,'$1')+' - Stub', function() { 3 | 4 | before(function(){ 5 | 6 | }); 7 | 8 | after(function(){ 9 | 10 | }); 11 | 12 | it('rr is awesome', function(){ 13 | rexreplace({ 14 | pattern:'a', 15 | replacement:'b', 16 | files:['myfile'], 17 | }); 18 | assert.equal(1, 1); 19 | }); 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /test/unicode.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/version.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/void-euro.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/void-ignore-case.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/void-multiline.js: -------------------------------------------------------------------------------- 1 | describe(__filename.replace(/.*\/([^\/]+)\.js$/, '$1') + ' - Stub', function () { 2 | before(function () {}); 3 | 4 | after(function () {}); 5 | 6 | it('rr is awesome', function () { 7 | rexreplace({ 8 | pattern: 'a', 9 | replacement: 'b', 10 | files: ['myfile'], 11 | }); 12 | assert.equal(1, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@jridgewell/sourcemap-codec@^1.5.0": 6 | version "1.5.0" 7 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" 8 | integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== 9 | 10 | "@rollup/plugin-replace@6.0.2": 11 | version "6.0.2" 12 | resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-6.0.2.tgz#2f565d312d681e4570ff376c55c5c08eb6f1908d" 13 | integrity sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ== 14 | dependencies: 15 | "@rollup/pluginutils" "^5.0.1" 16 | magic-string "^0.30.3" 17 | 18 | "@rollup/plugin-swc@^0.4.0": 19 | version "0.4.0" 20 | resolved "https://registry.yarnpkg.com/@rollup/plugin-swc/-/plugin-swc-0.4.0.tgz#fb637e505dfd4506bd92258e8fc616d348a212be" 21 | integrity sha512-oAtqXa8rOl7BOK1Rz3rRxI+LIL53S9SqO2KSq2UUUzWgOgXg6492Jh5mL2mv/f9cpit8zFWdwILuVeozZ0C8mg== 22 | dependencies: 23 | "@rollup/pluginutils" "^5.0.1" 24 | smob "^1.4.0" 25 | 26 | "@rollup/pluginutils@^5.0.1": 27 | version "5.1.4" 28 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" 29 | integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== 30 | dependencies: 31 | "@types/estree" "^1.0.0" 32 | estree-walker "^2.0.2" 33 | picomatch "^4.0.2" 34 | 35 | "@rollup/rollup-android-arm-eabi@4.40.2": 36 | version "4.40.2" 37 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz#c228d00a41f0dbd6fb8b7ea819bbfbf1c1157a10" 38 | integrity sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg== 39 | 40 | "@rollup/rollup-android-arm64@4.40.2": 41 | version "4.40.2" 42 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz#e2b38d0c912169fd55d7e38d723aada208d37256" 43 | integrity sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw== 44 | 45 | "@rollup/rollup-darwin-arm64@4.40.2": 46 | version "4.40.2" 47 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz#1fddb3690f2ae33df16d334c613377f05abe4878" 48 | integrity sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w== 49 | 50 | "@rollup/rollup-darwin-x64@4.40.2": 51 | version "4.40.2" 52 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz#818298d11c8109e1112590165142f14be24b396d" 53 | integrity sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ== 54 | 55 | "@rollup/rollup-freebsd-arm64@4.40.2": 56 | version "4.40.2" 57 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz#91a28dc527d5bed7f9ecf0e054297b3012e19618" 58 | integrity sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ== 59 | 60 | "@rollup/rollup-freebsd-x64@4.40.2": 61 | version "4.40.2" 62 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz#28acadefa76b5c7bede1576e065b51d335c62c62" 63 | integrity sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q== 64 | 65 | "@rollup/rollup-linux-arm-gnueabihf@4.40.2": 66 | version "4.40.2" 67 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz#819691464179cbcd9a9f9d3dc7617954840c6186" 68 | integrity sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q== 69 | 70 | "@rollup/rollup-linux-arm-musleabihf@4.40.2": 71 | version "4.40.2" 72 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz#d149207039e4189e267e8724050388effc80d704" 73 | integrity sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg== 74 | 75 | "@rollup/rollup-linux-arm64-gnu@4.40.2": 76 | version "4.40.2" 77 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz#fa72ebddb729c3c6d88973242f1a2153c83e86ec" 78 | integrity sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg== 79 | 80 | "@rollup/rollup-linux-arm64-musl@4.40.2": 81 | version "4.40.2" 82 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz#2054216e34469ab8765588ebf343d531fc3c9228" 83 | integrity sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg== 84 | 85 | "@rollup/rollup-linux-loongarch64-gnu@4.40.2": 86 | version "4.40.2" 87 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz#818de242291841afbfc483a84f11e9c7a11959bc" 88 | integrity sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw== 89 | 90 | "@rollup/rollup-linux-powerpc64le-gnu@4.40.2": 91 | version "4.40.2" 92 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz#0bb4cb8fc4a2c635f68c1208c924b2145eb647cb" 93 | integrity sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q== 94 | 95 | "@rollup/rollup-linux-riscv64-gnu@4.40.2": 96 | version "4.40.2" 97 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz#4b3b8e541b7b13e447ae07774217d98c06f6926d" 98 | integrity sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg== 99 | 100 | "@rollup/rollup-linux-riscv64-musl@4.40.2": 101 | version "4.40.2" 102 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz#e065405e67d8bd64a7d0126c931bd9f03910817f" 103 | integrity sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg== 104 | 105 | "@rollup/rollup-linux-s390x-gnu@4.40.2": 106 | version "4.40.2" 107 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz#dda3265bbbfe16a5d0089168fd07f5ebb2a866fe" 108 | integrity sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ== 109 | 110 | "@rollup/rollup-linux-x64-gnu@4.40.2": 111 | version "4.40.2" 112 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz#90993269b8b995b4067b7b9d72ff1c360ef90a17" 113 | integrity sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng== 114 | 115 | "@rollup/rollup-linux-x64-musl@4.40.2": 116 | version "4.40.2" 117 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz#fdf5b09fd121eb8d977ebb0fda142c7c0167b8de" 118 | integrity sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA== 119 | 120 | "@rollup/rollup-win32-arm64-msvc@4.40.2": 121 | version "4.40.2" 122 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz#6397e1e012db64dfecfed0774cb9fcf89503d716" 123 | integrity sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg== 124 | 125 | "@rollup/rollup-win32-ia32-msvc@4.40.2": 126 | version "4.40.2" 127 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz#df0991464a52a35506103fe18d29913bf8798a0c" 128 | integrity sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA== 129 | 130 | "@rollup/rollup-win32-x64-msvc@4.40.2": 131 | version "4.40.2" 132 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz#8dae04d01a2cbd84d6297d99356674c6b993f0fc" 133 | integrity sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA== 134 | 135 | "@swc/core-darwin-arm64@1.11.24": 136 | version "1.11.24" 137 | resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz#c9fcc9c4bad0511fed26210449556d2b33fb2d9a" 138 | integrity sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA== 139 | 140 | "@swc/core-darwin-x64@1.11.24": 141 | version "1.11.24" 142 | resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz#048ea3ee43281264a62fccb5a944b76d1c56eb24" 143 | integrity sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ== 144 | 145 | "@swc/core-linux-arm-gnueabihf@1.11.24": 146 | version "1.11.24" 147 | resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz#f01ba657a81c67d8fb9f681712e65abf1324cec6" 148 | integrity sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw== 149 | 150 | "@swc/core-linux-arm64-gnu@1.11.24": 151 | version "1.11.24" 152 | resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz#9aefca7f7f87c8312c2fa714c1eb731411d8596c" 153 | integrity sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg== 154 | 155 | "@swc/core-linux-arm64-musl@1.11.24": 156 | version "1.11.24" 157 | resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz#e4805484779bbc59b639eab4f8e45166f3d7a4f7" 158 | integrity sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw== 159 | 160 | "@swc/core-linux-x64-gnu@1.11.24": 161 | version "1.11.24" 162 | resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz#e8d8cc50a49903880944379590b73733e150a5d4" 163 | integrity sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg== 164 | 165 | "@swc/core-linux-x64-musl@1.11.24": 166 | version "1.11.24" 167 | resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz#f3c46212eb8a793f6a42a36b2a9017a9b1462737" 168 | integrity sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw== 169 | 170 | "@swc/core-win32-arm64-msvc@1.11.24": 171 | version "1.11.24" 172 | resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz#b1c3327d81a5f94415ac0b1713e192df1c121fbd" 173 | integrity sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ== 174 | 175 | "@swc/core-win32-ia32-msvc@1.11.24": 176 | version "1.11.24" 177 | resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz#6a944dd6111ec5fae3cf5925b73701e49b109edc" 178 | integrity sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ== 179 | 180 | "@swc/core-win32-x64-msvc@1.11.24": 181 | version "1.11.24" 182 | resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz#eebb5d5ece2710aeb25cc58bd7c5c4c2c046f030" 183 | integrity sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w== 184 | 185 | "@swc/core@1.11.24": 186 | version "1.11.24" 187 | resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.11.24.tgz#340425648296964f815c940b8da00fcdb1ff2abd" 188 | integrity sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg== 189 | dependencies: 190 | "@swc/counter" "^0.1.3" 191 | "@swc/types" "^0.1.21" 192 | optionalDependencies: 193 | "@swc/core-darwin-arm64" "1.11.24" 194 | "@swc/core-darwin-x64" "1.11.24" 195 | "@swc/core-linux-arm-gnueabihf" "1.11.24" 196 | "@swc/core-linux-arm64-gnu" "1.11.24" 197 | "@swc/core-linux-arm64-musl" "1.11.24" 198 | "@swc/core-linux-x64-gnu" "1.11.24" 199 | "@swc/core-linux-x64-musl" "1.11.24" 200 | "@swc/core-win32-arm64-msvc" "1.11.24" 201 | "@swc/core-win32-ia32-msvc" "1.11.24" 202 | "@swc/core-win32-x64-msvc" "1.11.24" 203 | 204 | "@swc/counter@^0.1.3": 205 | version "0.1.3" 206 | resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" 207 | integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== 208 | 209 | "@swc/types@^0.1.21": 210 | version "0.1.21" 211 | resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.21.tgz#6fcadbeca1d8bc89e1ab3de4948cef12344a38c0" 212 | integrity sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ== 213 | dependencies: 214 | "@swc/counter" "^0.1.3" 215 | 216 | "@types/estree@1.0.7": 217 | version "1.0.7" 218 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" 219 | integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== 220 | 221 | "@types/estree@^1.0.0": 222 | version "1.0.6" 223 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" 224 | integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== 225 | 226 | "@types/node@22.15.17": 227 | version "22.15.17" 228 | resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.17.tgz#355ccec95f705b664e4332bb64a7f07db30b7055" 229 | integrity sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw== 230 | dependencies: 231 | undici-types "~6.21.0" 232 | 233 | ansi-regex@^5.0.1: 234 | version "5.0.1" 235 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 236 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 237 | 238 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 239 | version "4.3.0" 240 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 241 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 242 | dependencies: 243 | color-convert "^2.0.1" 244 | 245 | argparse@^2.0.1: 246 | version "2.0.1" 247 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 248 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 249 | 250 | assert@^2.0.0: 251 | version "2.1.0" 252 | resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" 253 | integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== 254 | dependencies: 255 | call-bind "^1.0.2" 256 | is-nan "^1.3.2" 257 | object-is "^1.1.5" 258 | object.assign "^4.1.4" 259 | util "^0.12.5" 260 | 261 | available-typed-arrays@^1.0.7: 262 | version "1.0.7" 263 | resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" 264 | integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== 265 | dependencies: 266 | possible-typed-array-names "^1.0.0" 267 | 268 | balanced-match@^1.0.0: 269 | version "1.0.2" 270 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 271 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 272 | 273 | brace-expansion@^2.0.1: 274 | version "2.0.1" 275 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 276 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 277 | dependencies: 278 | balanced-match "^1.0.0" 279 | 280 | browser-stdout@^1.3.1: 281 | version "1.3.1" 282 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 283 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 284 | 285 | call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.7: 286 | version "1.0.7" 287 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" 288 | integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== 289 | dependencies: 290 | es-define-property "^1.0.0" 291 | es-errors "^1.3.0" 292 | function-bind "^1.1.2" 293 | get-intrinsic "^1.2.4" 294 | set-function-length "^1.2.1" 295 | 296 | camelcase@^6.0.0: 297 | version "6.3.0" 298 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 299 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 300 | 301 | chalk@^4.1.0: 302 | version "4.1.2" 303 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 304 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 305 | dependencies: 306 | ansi-styles "^4.1.0" 307 | supports-color "^7.1.0" 308 | 309 | chokidar@^4.0.1: 310 | version "4.0.3" 311 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" 312 | integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== 313 | dependencies: 314 | readdirp "^4.0.1" 315 | 316 | cliui@^7.0.2: 317 | version "7.0.4" 318 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 319 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 320 | dependencies: 321 | string-width "^4.2.0" 322 | strip-ansi "^6.0.0" 323 | wrap-ansi "^7.0.0" 324 | 325 | cliui@^8.0.1: 326 | version "8.0.1" 327 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 328 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 329 | dependencies: 330 | string-width "^4.2.0" 331 | strip-ansi "^6.0.1" 332 | wrap-ansi "^7.0.0" 333 | 334 | color-convert@^2.0.1: 335 | version "2.0.1" 336 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 337 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 338 | dependencies: 339 | color-name "~1.1.4" 340 | 341 | color-name@~1.1.4: 342 | version "1.1.4" 343 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 344 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 345 | 346 | debug@^4.3.5: 347 | version "4.3.6" 348 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" 349 | integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== 350 | dependencies: 351 | ms "2.1.2" 352 | 353 | decamelize@^4.0.0: 354 | version "4.0.0" 355 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 356 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 357 | 358 | define-data-property@^1.0.1, define-data-property@^1.1.4: 359 | version "1.1.4" 360 | resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" 361 | integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 362 | dependencies: 363 | es-define-property "^1.0.0" 364 | es-errors "^1.3.0" 365 | gopd "^1.0.1" 366 | 367 | define-properties@^1.1.3, define-properties@^1.2.1: 368 | version "1.2.1" 369 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" 370 | integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== 371 | dependencies: 372 | define-data-property "^1.0.1" 373 | has-property-descriptors "^1.0.0" 374 | object-keys "^1.1.1" 375 | 376 | diff@^5.2.0: 377 | version "5.2.0" 378 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" 379 | integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== 380 | 381 | emoji-regex@^8.0.0: 382 | version "8.0.0" 383 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 384 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 385 | 386 | es-define-property@^1.0.0: 387 | version "1.0.0" 388 | resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" 389 | integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== 390 | dependencies: 391 | get-intrinsic "^1.2.4" 392 | 393 | es-errors@^1.3.0: 394 | version "1.3.0" 395 | resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" 396 | integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 397 | 398 | escalade@^3.1.1: 399 | version "3.1.2" 400 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" 401 | integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== 402 | 403 | escape-string-regexp@^4.0.0: 404 | version "4.0.0" 405 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 406 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 407 | 408 | estree-walker@^2.0.2: 409 | version "2.0.2" 410 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" 411 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== 412 | 413 | find-up@^5.0.0: 414 | version "5.0.0" 415 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 416 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 417 | dependencies: 418 | locate-path "^6.0.0" 419 | path-exists "^4.0.0" 420 | 421 | flat@^5.0.2: 422 | version "5.0.2" 423 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 424 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 425 | 426 | for-each@^0.3.3: 427 | version "0.3.3" 428 | resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" 429 | integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== 430 | dependencies: 431 | is-callable "^1.1.3" 432 | 433 | fs.realpath@^1.0.0: 434 | version "1.0.0" 435 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 436 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 437 | 438 | fsevents@~2.3.2: 439 | version "2.3.3" 440 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 441 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 442 | 443 | function-bind@^1.1.2: 444 | version "1.1.2" 445 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 446 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 447 | 448 | get-caller-file@^2.0.5: 449 | version "2.0.5" 450 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 451 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 452 | 453 | get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: 454 | version "1.2.4" 455 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" 456 | integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== 457 | dependencies: 458 | es-errors "^1.3.0" 459 | function-bind "^1.1.2" 460 | has-proto "^1.0.1" 461 | has-symbols "^1.0.3" 462 | hasown "^2.0.0" 463 | 464 | glob@9, glob@^10.4.5, glob@^7.1.1: 465 | version "9.3.5" 466 | resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" 467 | integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== 468 | dependencies: 469 | fs.realpath "^1.0.0" 470 | minimatch "^8.0.2" 471 | minipass "^4.2.4" 472 | path-scurry "^1.6.1" 473 | 474 | globs@0.1.4: 475 | version "0.1.4" 476 | resolved "https://registry.yarnpkg.com/globs/-/globs-0.1.4.tgz#1d13639f6174e4ae73a7f936da7d9a079f657c1c" 477 | integrity sha512-D23dWbOq48vlOraoSigbcQV4tWrnhwk+E/Um2cMuDS3/5dwGmdFeA7L/vAvDhLFlQOTDqHcXh35m/71g2A2WzQ== 478 | dependencies: 479 | glob "^7.1.1" 480 | 481 | gopd@^1.0.1: 482 | version "1.0.1" 483 | resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 484 | integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 485 | dependencies: 486 | get-intrinsic "^1.1.3" 487 | 488 | has-flag@^4.0.0: 489 | version "4.0.0" 490 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 491 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 492 | 493 | has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: 494 | version "1.0.2" 495 | resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" 496 | integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 497 | dependencies: 498 | es-define-property "^1.0.0" 499 | 500 | has-proto@^1.0.1: 501 | version "1.0.3" 502 | resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" 503 | integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== 504 | 505 | has-symbols@^1.0.3: 506 | version "1.0.3" 507 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 508 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 509 | 510 | has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: 511 | version "1.0.2" 512 | resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" 513 | integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== 514 | dependencies: 515 | has-symbols "^1.0.3" 516 | 517 | hasown@^2.0.0: 518 | version "2.0.2" 519 | resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 520 | integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 521 | dependencies: 522 | function-bind "^1.1.2" 523 | 524 | he@^1.2.0: 525 | version "1.2.0" 526 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 527 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 528 | 529 | inherits@^2.0.3: 530 | version "2.0.4" 531 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 532 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 533 | 534 | is-arguments@^1.0.4: 535 | version "1.1.1" 536 | resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" 537 | integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== 538 | dependencies: 539 | call-bind "^1.0.2" 540 | has-tostringtag "^1.0.0" 541 | 542 | is-callable@^1.1.3: 543 | version "1.2.7" 544 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" 545 | integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== 546 | 547 | is-fullwidth-code-point@^3.0.0: 548 | version "3.0.0" 549 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 550 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 551 | 552 | is-generator-function@^1.0.7: 553 | version "1.0.10" 554 | resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" 555 | integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== 556 | dependencies: 557 | has-tostringtag "^1.0.0" 558 | 559 | is-nan@^1.3.2: 560 | version "1.3.2" 561 | resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" 562 | integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== 563 | dependencies: 564 | call-bind "^1.0.0" 565 | define-properties "^1.1.3" 566 | 567 | is-plain-obj@^2.1.0: 568 | version "2.1.0" 569 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 570 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 571 | 572 | is-typed-array@^1.1.3: 573 | version "1.1.13" 574 | resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" 575 | integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== 576 | dependencies: 577 | which-typed-array "^1.1.14" 578 | 579 | is-unicode-supported@^0.1.0: 580 | version "0.1.0" 581 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 582 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 583 | 584 | js-yaml@^4.1.0: 585 | version "4.1.0" 586 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 587 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 588 | dependencies: 589 | argparse "^2.0.1" 590 | 591 | locate-path@^6.0.0: 592 | version "6.0.0" 593 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 594 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 595 | dependencies: 596 | p-locate "^5.0.0" 597 | 598 | log-symbols@^4.1.0: 599 | version "4.1.0" 600 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 601 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 602 | dependencies: 603 | chalk "^4.1.0" 604 | is-unicode-supported "^0.1.0" 605 | 606 | lru-cache@^10.2.0: 607 | version "10.4.3" 608 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" 609 | integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== 610 | 611 | magic-string@^0.30.3: 612 | version "0.30.15" 613 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.15.tgz#d5474a2c4c5f35f041349edaba8a5cb02733ed3c" 614 | integrity sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw== 615 | dependencies: 616 | "@jridgewell/sourcemap-codec" "^1.5.0" 617 | 618 | minimatch@^5.1.6: 619 | version "5.1.6" 620 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" 621 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== 622 | dependencies: 623 | brace-expansion "^2.0.1" 624 | 625 | minimatch@^8.0.2: 626 | version "8.0.4" 627 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" 628 | integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== 629 | dependencies: 630 | brace-expansion "^2.0.1" 631 | 632 | minipass@^4.2.4: 633 | version "4.2.8" 634 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" 635 | integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== 636 | 637 | "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": 638 | version "7.1.2" 639 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" 640 | integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== 641 | 642 | mocha@11.2.2: 643 | version "11.2.2" 644 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.2.2.tgz#2dfefc9652de746389f5286888034239b6486231" 645 | integrity sha512-VlSBxrPYHK4YNOEbFdkCxHQbZMoNzBkoPprqtZRW6311EUF/DlSxoycE2e/2NtRk4WKkIXzyrXDTrlikJMWgbw== 646 | dependencies: 647 | browser-stdout "^1.3.1" 648 | chokidar "^4.0.1" 649 | debug "^4.3.5" 650 | diff "^5.2.0" 651 | escape-string-regexp "^4.0.0" 652 | find-up "^5.0.0" 653 | glob "^10.4.5" 654 | he "^1.2.0" 655 | js-yaml "^4.1.0" 656 | log-symbols "^4.1.0" 657 | minimatch "^5.1.6" 658 | ms "^2.1.3" 659 | picocolors "^1.1.1" 660 | serialize-javascript "^6.0.2" 661 | strip-json-comments "^3.1.1" 662 | supports-color "^8.1.1" 663 | workerpool "^6.5.1" 664 | yargs "^17.7.2" 665 | yargs-parser "^21.1.1" 666 | yargs-unparser "^2.0.0" 667 | 668 | ms@2.1.2: 669 | version "2.1.2" 670 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 671 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 672 | 673 | ms@^2.1.3: 674 | version "2.1.3" 675 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 676 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 677 | 678 | object-is@^1.1.5: 679 | version "1.1.6" 680 | resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" 681 | integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== 682 | dependencies: 683 | call-bind "^1.0.7" 684 | define-properties "^1.2.1" 685 | 686 | object-keys@^1.1.1: 687 | version "1.1.1" 688 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 689 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 690 | 691 | object.assign@^4.1.4: 692 | version "4.1.5" 693 | resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" 694 | integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== 695 | dependencies: 696 | call-bind "^1.0.5" 697 | define-properties "^1.2.1" 698 | has-symbols "^1.0.3" 699 | object-keys "^1.1.1" 700 | 701 | p-limit@^3.0.2: 702 | version "3.1.0" 703 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 704 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 705 | dependencies: 706 | yocto-queue "^0.1.0" 707 | 708 | p-locate@^5.0.0: 709 | version "5.0.0" 710 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 711 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 712 | dependencies: 713 | p-limit "^3.0.2" 714 | 715 | path-exists@^4.0.0: 716 | version "4.0.0" 717 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 718 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 719 | 720 | path-scurry@^1.6.1: 721 | version "1.11.1" 722 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" 723 | integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== 724 | dependencies: 725 | lru-cache "^10.2.0" 726 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 727 | 728 | picocolors@^1.1.1: 729 | version "1.1.1" 730 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" 731 | integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== 732 | 733 | picomatch@^4.0.2: 734 | version "4.0.2" 735 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" 736 | integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== 737 | 738 | possible-typed-array-names@^1.0.0: 739 | version "1.0.0" 740 | resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" 741 | integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== 742 | 743 | prettier@3.5.3: 744 | version "3.5.3" 745 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" 746 | integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== 747 | 748 | randombytes@^2.1.0: 749 | version "2.1.0" 750 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 751 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 752 | dependencies: 753 | safe-buffer "^5.1.0" 754 | 755 | readdirp@^4.0.1: 756 | version "4.1.2" 757 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" 758 | integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== 759 | 760 | require-directory@^2.1.1: 761 | version "2.1.1" 762 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 763 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 764 | 765 | rollup@4.40.2: 766 | version "4.40.2" 767 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.2.tgz#778e88b7a197542682b3e318581f7697f55f0619" 768 | integrity sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg== 769 | dependencies: 770 | "@types/estree" "1.0.7" 771 | optionalDependencies: 772 | "@rollup/rollup-android-arm-eabi" "4.40.2" 773 | "@rollup/rollup-android-arm64" "4.40.2" 774 | "@rollup/rollup-darwin-arm64" "4.40.2" 775 | "@rollup/rollup-darwin-x64" "4.40.2" 776 | "@rollup/rollup-freebsd-arm64" "4.40.2" 777 | "@rollup/rollup-freebsd-x64" "4.40.2" 778 | "@rollup/rollup-linux-arm-gnueabihf" "4.40.2" 779 | "@rollup/rollup-linux-arm-musleabihf" "4.40.2" 780 | "@rollup/rollup-linux-arm64-gnu" "4.40.2" 781 | "@rollup/rollup-linux-arm64-musl" "4.40.2" 782 | "@rollup/rollup-linux-loongarch64-gnu" "4.40.2" 783 | "@rollup/rollup-linux-powerpc64le-gnu" "4.40.2" 784 | "@rollup/rollup-linux-riscv64-gnu" "4.40.2" 785 | "@rollup/rollup-linux-riscv64-musl" "4.40.2" 786 | "@rollup/rollup-linux-s390x-gnu" "4.40.2" 787 | "@rollup/rollup-linux-x64-gnu" "4.40.2" 788 | "@rollup/rollup-linux-x64-musl" "4.40.2" 789 | "@rollup/rollup-win32-arm64-msvc" "4.40.2" 790 | "@rollup/rollup-win32-ia32-msvc" "4.40.2" 791 | "@rollup/rollup-win32-x64-msvc" "4.40.2" 792 | fsevents "~2.3.2" 793 | 794 | safe-buffer@^5.1.0: 795 | version "5.2.1" 796 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 797 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 798 | 799 | serialize-javascript@^6.0.2: 800 | version "6.0.2" 801 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" 802 | integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== 803 | dependencies: 804 | randombytes "^2.1.0" 805 | 806 | set-function-length@^1.2.1: 807 | version "1.2.2" 808 | resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 809 | integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 810 | dependencies: 811 | define-data-property "^1.1.4" 812 | es-errors "^1.3.0" 813 | function-bind "^1.1.2" 814 | get-intrinsic "^1.2.4" 815 | gopd "^1.0.1" 816 | has-property-descriptors "^1.0.2" 817 | 818 | smob@^1.4.0: 819 | version "1.5.0" 820 | resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab" 821 | integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig== 822 | 823 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 824 | version "4.2.3" 825 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 826 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 827 | dependencies: 828 | emoji-regex "^8.0.0" 829 | is-fullwidth-code-point "^3.0.0" 830 | strip-ansi "^6.0.1" 831 | 832 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 833 | version "6.0.1" 834 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 835 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 836 | dependencies: 837 | ansi-regex "^5.0.1" 838 | 839 | strip-json-comments@^3.1.1: 840 | version "3.1.1" 841 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 842 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 843 | 844 | supports-color@^7.1.0: 845 | version "7.2.0" 846 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 847 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 848 | dependencies: 849 | has-flag "^4.0.0" 850 | 851 | supports-color@^8.1.1: 852 | version "8.1.1" 853 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 854 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 855 | dependencies: 856 | has-flag "^4.0.0" 857 | 858 | undici-types@~6.21.0: 859 | version "6.21.0" 860 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" 861 | integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== 862 | 863 | util@^0.12.5: 864 | version "0.12.5" 865 | resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" 866 | integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== 867 | dependencies: 868 | inherits "^2.0.3" 869 | is-arguments "^1.0.4" 870 | is-generator-function "^1.0.7" 871 | is-typed-array "^1.1.3" 872 | which-typed-array "^1.1.2" 873 | 874 | which-typed-array@^1.1.14, which-typed-array@^1.1.2: 875 | version "1.1.15" 876 | resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" 877 | integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== 878 | dependencies: 879 | available-typed-arrays "^1.0.7" 880 | call-bind "^1.0.7" 881 | for-each "^0.3.3" 882 | gopd "^1.0.1" 883 | has-tostringtag "^1.0.2" 884 | 885 | workerpool@^6.5.1: 886 | version "6.5.1" 887 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" 888 | integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== 889 | 890 | wrap-ansi@^7.0.0: 891 | version "7.0.0" 892 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 893 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 894 | dependencies: 895 | ansi-styles "^4.0.0" 896 | string-width "^4.1.0" 897 | strip-ansi "^6.0.0" 898 | 899 | y18n@^5.0.5: 900 | version "5.0.8" 901 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 902 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 903 | 904 | yargs-parser@^20.2.2: 905 | version "20.2.9" 906 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 907 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 908 | 909 | yargs-parser@^21.1.1: 910 | version "21.1.1" 911 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 912 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 913 | 914 | yargs-unparser@^2.0.0: 915 | version "2.0.0" 916 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 917 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 918 | dependencies: 919 | camelcase "^6.0.0" 920 | decamelize "^4.0.0" 921 | flat "^5.0.2" 922 | is-plain-obj "^2.1.0" 923 | 924 | yargs@16: 925 | version "16.2.0" 926 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 927 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 928 | dependencies: 929 | cliui "^7.0.2" 930 | escalade "^3.1.1" 931 | get-caller-file "^2.0.5" 932 | require-directory "^2.1.1" 933 | string-width "^4.2.0" 934 | y18n "^5.0.5" 935 | yargs-parser "^20.2.2" 936 | 937 | yargs@^17.7.2: 938 | version "17.7.2" 939 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" 940 | integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== 941 | dependencies: 942 | cliui "^8.0.1" 943 | escalade "^3.1.1" 944 | get-caller-file "^2.0.5" 945 | require-directory "^2.1.1" 946 | string-width "^4.2.3" 947 | y18n "^5.0.5" 948 | yargs-parser "^21.1.1" 949 | 950 | yarn@1.22.22: 951 | version "1.22.22" 952 | resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.22.tgz#ac34549e6aa8e7ead463a7407e1c7390f61a6610" 953 | integrity sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg== 954 | 955 | yocto-queue@^0.1.0: 956 | version "0.1.0" 957 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 958 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 959 | --------------------------------------------------------------------------------