diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 11d9025..0d6724a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 registry-url: https://registry.npmjs.org/ scope: netatwork - run: npm ci diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d0bbba4..f3058a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,8 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 registry-url: https://registry.npmjs.org/ - run: npm ci + - run: npm run build - run: npm test diff --git a/.gitignore b/.gitignore index 5207587..708ccf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -/node_modules /dist +/node_modules /test_out diff --git a/.npmignore b/.npmignore index 864e071..33f29a4 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,7 @@ +/.editorconfig /.github +/node_modules +/src /test /test_out -/node_modules -/ava.* /tsconfig* -/src diff --git a/CHANGELOG.md b/CHANGELOG.md index fa82059..bb6b36b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ +# 5.0 ++ **Breaking Change**: Drop support for nodejs 19 or lower. + # 4.1 + Add `--no-externals` command line option. diff --git a/README.md b/README.md index f575d26..7261c79 100644 --- a/README.md +++ b/README.md @@ -162,3 +162,6 @@ Show verbose information like the effective configuration options. ### `--no-externals` If specified, external locales are not included in the output. + +### `--no-color` +Disable colored command line output. diff --git a/ava.config.mjs b/ava.config.mjs deleted file mode 100644 index 17778c0..0000000 --- a/ava.config.mjs +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; - -export default { - verbose: true, - files: [ - "test_out/test/**/*.js", - "!**/_*" - ] -} diff --git a/package-lock.json b/package-lock.json index 53a461f..3eded85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,279 +1,84 @@ { "name": "@netatwork/aurelia-i18n-tools", - "version": "4.1.1", + "version": "5.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@netatwork/aurelia-i18n-tools", - "version": "4.1.1", + "version": "5.0.0", "license": "Apache-2.0", "dependencies": { "ansi-colors": "^4.1.3", "chokidar": "^3.6.0", "decamelize": "^6.0.0", - "parse5": "^7.1.2", - "picomatch": "^4.0.1", + "parse5": "^7.2.1", + "picomatch": "^4.0.2", "yargs-parser": "^21.1.1" }, "bin": { "naw-aurelia-i18n": "dist/cli.js" }, "devDependencies": { - "@types/node": "^20.11.29", - "@types/parse5": "^7.0.0", + "@mxjp/parallel": "^1.0.2", + "@netatwork/aurelia-i18n-tools": "file:.", + "@types/node": "^22.10.2", "@types/picomatch": "^2.3.3", "@types/yargs-parser": "^21.0.3", - "ava": "^6.1.2", - "concurrently": "^8.2.2", - "typescript": "^5.4.2" - } - }, - "node_modules/@babel/runtime": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", - "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" + "typescript": "^5.7.2" } }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "node_modules/@mxjp/parallel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mxjp/parallel/-/parallel-1.0.2.tgz", + "integrity": "sha512-f9A0WBJTLHtASCerZ4eiQvKhsGMYXhhza9g3j/cuwaX2LBSBQoMlJ++00zgqRbl6Fjgp1y7ydEmkXG41gHJfuw==", "dev": true, - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "mx-parallel": "main.js" } }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@netatwork/aurelia-i18n-tools": { + "resolved": "", + "link": true }, "node_modules/@types/node": { - "version": "20.11.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.29.tgz", - "integrity": "sha512-P99thMkD/1YkCvAtOd6/zGedKNA0p2fj4ZpjCzcNiSCBWgm3cNRTBfa/qjFnsKkkojxu4vVLtWpesnZ9+ap+gA==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/parse5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-f2SeAxumolBmhuR62vNGTsSAvdz/Oj0k682xNrcKJ4dmRnTPODB74j6CPoNPzBPTHsu7Y7W7u93Mgp8Ovo8vWw==", - "deprecated": "This is a stub types definition. parse5 provides its own type definitions, so you do not need this installed.", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, + "license": "MIT", "dependencies": { - "parse5": "*" + "undici-types": "~6.20.0" } }, "node_modules/@types/picomatch": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.3.tgz", - "integrity": "sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg==", - "dev": true + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.4.tgz", + "integrity": "sha512-0so8lU8O5zatZS/2Fi4zrwks+vZv7e0dygrgEZXljODXBig97l4cPQD+9LabXfGJOWwoRkTVz6Q4edZvD12UOA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs-parser": { "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "node_modules/@vercel/nft": { - "version": "0.26.4", - "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz", - "integrity": "sha512-j4jCOOXke2t8cHZCIxu1dzKLHLcFmYzC3yqAK6MfZznOL1QIJKd0xcFsXK3zcqzU7ScsE2zWkiMMNHGMHgp+FA==", - "dev": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.5", - "@rollup/pluginutils": "^4.0.0", - "acorn": "^8.6.0", - "acorn-import-attributes": "^1.9.2", - "async-sema": "^3.1.1", - "bindings": "^1.4.0", - "estree-walker": "2.0.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.2", - "node-gyp-build": "^4.2.2", - "resolve-from": "^5.0.0" - }, - "bin": { - "nft": "out/cli.js" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.2.tgz", - "integrity": "sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } + "license": "MIT" }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -286,6 +91,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -293,154 +99,11 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arrgv": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", - "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/arrify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", - "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/async-sema": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", - "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", - "dev": true - }, - "node_modules/ava": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/ava/-/ava-6.1.2.tgz", - "integrity": "sha512-WcpxJ8yZ7mk9ABTinD0IAjcemovSeVGjuuwZx0JS9johREWFeLTl8UP6wd7l6nmnrWqkKZdwaD71a/ocH4qPKw==", - "dev": true, - "dependencies": { - "@vercel/nft": "^0.26.2", - "acorn": "^8.11.3", - "acorn-walk": "^8.3.2", - "ansi-styles": "^6.2.1", - "arrgv": "^1.0.2", - "arrify": "^3.0.0", - "callsites": "^4.1.0", - "cbor": "^9.0.1", - "chalk": "^5.3.0", - "chunkd": "^2.0.1", - "ci-info": "^4.0.0", - "ci-parallel-vars": "^1.0.1", - "cli-truncate": "^4.0.0", - "code-excerpt": "^4.0.0", - "common-path-prefix": "^3.0.0", - "concordance": "^5.0.4", - "currently-unhandled": "^0.4.1", - "debug": "^4.3.4", - "emittery": "^1.0.1", - "figures": "^6.0.1", - "globby": "^14.0.0", - "ignore-by-default": "^2.1.0", - "indent-string": "^5.0.0", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "matcher": "^5.0.0", - "memoize": "^10.0.0", - "ms": "^2.1.3", - "p-map": "^7.0.1", - "package-config": "^5.0.0", - "picomatch": "^3.0.1", - "plur": "^5.1.0", - "pretty-ms": "^9.0.0", - "resolve-cwd": "^3.0.0", - "stack-utils": "^2.0.6", - "strip-ansi": "^7.1.0", - "supertap": "^3.0.1", - "temp-dir": "^3.0.0", - "write-file-atomic": "^5.0.1", - "yargs": "^17.7.2" - }, - "bin": { - "ava": "entrypoints/cli.mjs" - }, - "engines": { - "node": "^18.18 || ^20.8 || ^21" - }, - "peerDependencies": { - "@ava/typescript": "*" - }, - "peerDependenciesMeta": { - "@ava/typescript": { - "optional": true - } - } - }, - "node_modules/ava/node_modules/picomatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", - "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -448,82 +111,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/blueimp-md5": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, - "node_modules/callsites": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.1.0.tgz", - "integrity": "sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cbor": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", - "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", - "dev": true, - "dependencies": { - "nofilter": "^3.1.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -543,1704 +147,172 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chunkd": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true - }, - "node_modules/ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ci-parallel-vars": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", - "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", - "dev": true - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "to-regex-range": "^5.0.1" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/code-excerpt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", - "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", - "dev": true, - "dependencies": { - "convert-to-spaces": "^2.0.1" - }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=0.10.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concordance": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", - "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", - "dev": true, - "dependencies": { - "date-time": "^3.1.0", - "esutils": "^2.0.3", - "fast-diff": "^1.2.0", - "js-string-escape": "^1.0.1", - "lodash": "^4.17.15", - "md5-hex": "^3.0.1", - "semver": "^7.3.2", - "well-known-symbols": "^2.0.0" - }, - "engines": { - "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" - } - }, - "node_modules/concurrently": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", - "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.2", - "date-fns": "^2.30.0", - "lodash": "^4.17.21", - "rxjs": "^7.8.1", - "shell-quote": "^1.8.1", - "spawn-command": "0.0.2", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^14.13.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "node_modules/convert-to-spaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", - "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", - "dev": true, - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/date-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", - "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", - "dev": true, - "dependencies": { - "time-zone": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/emittery": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.0.3.tgz", - "integrity": "sha512-tJdCJitoy2lrC2ldJcqN4vkqJ00lT+tOWNT1hBJjO/3FDMJa5TTIiYGCKGkn/WfCyOzUMObeohbVTj00fhiLiA==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dev": true, - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up-simple": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", - "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", - "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", - "dev": true, - "engines": { - "node": ">=10 <11 || >=12 <13 || >=14" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/irregular-plurals": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", - "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", - "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/matcher": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", - "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/md5-hex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", - "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", - "dev": true, - "dependencies": { - "blueimp-md5": "^2.10.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/memoize": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.0.0.tgz", - "integrity": "sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==", - "dev": true, - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/memoize?sponsor=1" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", - "dev": true, - "engines": { - "node": ">=12.19" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-config": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/package-config/-/package-config-5.0.0.tgz", - "integrity": "sha512-GYTTew2slBcYdvRHqjhwaaydVMvn/qrGC323+nKclYioNSLTDUM/lGgtGTgyHVtYcozb+XkE8CNhwcraOmZ9Mg==", - "dev": true, - "dependencies": { - "find-up-simple": "^1.0.0", - "load-json-file": "^7.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/picomatch": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", - "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/plur": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", - "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", - "dev": true, - "dependencies": { - "irregular-plurals": "^3.3.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-ms": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", - "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", - "dev": true, - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/spawn-command": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", - "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.12.0" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" + "node": ">=0.10.0" } }, - "node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "dev": true, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" + "entities": "^4.5.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/supertap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", - "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", - "dev": true, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { - "indent-string": "^5.0.0", - "js-yaml": "^3.14.1", - "serialize-error": "^7.0.1", - "strip-ansi": "^7.0.1" + "picomatch": "^2.2.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8.10.0" } }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/time-zone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", - "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", - "dev": true, - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -2248,44 +320,12 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2295,316 +335,20 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/well-known-symbols": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", - "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } + "license": "MIT" }, "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { "node": ">=12" } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } } } } diff --git a/package.json b/package.json index 97df1e6..c65d068 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@netatwork/aurelia-i18n-tools", - "version": "4.1.1", + "version": "5.0.0", "description": "A toolchain to help with localization in aurelia projects.", "repository": { "type": "git", @@ -8,32 +8,38 @@ }, "type": "module", "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, "bin": { "naw-aurelia-i18n": "./dist/cli.js" }, "scripts": { - "build": "tsc -p tsconfig-build.json", - "build:watch": "tsc -p tsconfig-build.json -w", - "test": "tsc -p tsconfig-test.json && ava", - "start": "tsc -p tsconfig-test.json && concurrently \"tsc -p tsconfig-test.json -w\" \"ava -w\"", - "prepack": "npm test && npm run build" + "start": "mx-parallel npm:start:*", + "start:build": "tsc -p tsconfig-build.json -w --preserveWatchOutput", + "start:test": "tsc -p tsconfig-test.json -w --preserveWatchOutput", + "build": "tsc -p tsconfig-build.json && tsc -p tsconfig-test.json", + "test": "node --enable-source-maps --test \"./test_out/**/*.test.js\"", + "prepack": "npm run build && npm test" }, "dependencies": { "ansi-colors": "^4.1.3", "chokidar": "^3.6.0", "decamelize": "^6.0.0", - "parse5": "^7.1.2", - "picomatch": "^4.0.1", + "parse5": "^7.2.1", + "picomatch": "^4.0.2", "yargs-parser": "^21.1.1" }, "devDependencies": { - "@types/node": "^20.11.29", - "@types/parse5": "^7.0.0", + "@mxjp/parallel": "^1.0.2", + "@types/node": "^22.10.2", "@types/picomatch": "^2.3.3", "@types/yargs-parser": "^21.0.3", - "ava": "^6.1.2", - "concurrently": "^8.2.2", - "typescript": "^5.4.2" + "typescript": "^5.7.2", + "@netatwork/aurelia-i18n-tools": "file:." }, "author": "Net at Work GmbH", "license": "Apache-2.0" diff --git a/src/aurelia-i18n-attribute.ts b/src/aurelia-i18n-attribute.ts index 7c0b9a4..43095f5 100644 --- a/src/aurelia-i18n-attribute.ts +++ b/src/aurelia-i18n-attribute.ts @@ -6,40 +6,40 @@ const NAME_DELIMITER = /,/g; * Representation of the "t" i18n attribute from aurelia-i18n. */ export class AureliaI18nAttribute implements Iterable<[string, string]> { - private readonly _nameToKey = new Map(); + #nameToKey = new Map(); - public get isEmpty() { - return this._nameToKey.size === 0; + get isEmpty() { + return this.#nameToKey.size === 0; } - public [Symbol.iterator]() { - return this._nameToKey[Symbol.iterator](); + [Symbol.iterator]() { + return this.#nameToKey[Symbol.iterator](); } - public has(name: string) { - return this._nameToKey.has(name); + has(name: string) { + return this.#nameToKey.has(name); } - public set(name: string, key: string) { - this._nameToKey.set(name, key); + set(name: string, key: string) { + this.#nameToKey.set(name, key); if (name === "text") { - this._nameToKey.delete("html"); + this.#nameToKey.delete("html"); } else if (name === "html") { - this._nameToKey.delete("text"); + this.#nameToKey.delete("text"); } } - public get(name: string) { - return this._nameToKey.get(name); + get(name: string) { + return this.#nameToKey.get(name); } - public keys() { - return this._nameToKey.values(); + keys() { + return this.#nameToKey.values(); } - public mapKeysToNames() { + mapKeysToNames() { const keyToNames = new Map(); - for (const [name, key] of this._nameToKey) { + for (const [name, key] of this.#nameToKey) { const names = keyToNames.get(key); if (names) { names.push(name); @@ -50,13 +50,13 @@ export class AureliaI18nAttribute implements Iterable<[string, string]> { return keyToNames; } - public toString() { + toString() { return Array.from(this.mapKeysToNames()) .map(([key, names]) => (names.length === 1 && names[0] === "text") ? key : `[${names.join(",")}]${key}`) .join(";"); } - public static parse(value: string) { + static parse(value: string) { const attribute = new AureliaI18nAttribute(); NAMES_KEY_PAIR.lastIndex = 0; while (NAMES_KEY_PAIR.lastIndex < value.length) { diff --git a/src/aurelia-template-file.ts b/src/aurelia-template-file.ts index 7187051..65b35be 100644 --- a/src/aurelia-template-file.ts +++ b/src/aurelia-template-file.ts @@ -1,42 +1,46 @@ import { parseFragment } from "parse5"; -import { traverseElements, getAttributeValue, analyzeElementContent, treeDiagnostics, DocumentFragment, Element } from "./utility/parse5-tree.js"; -import { Config, ElementContentLocalizationType } from "./config.js"; import { AureliaI18nAttribute } from "./aurelia-i18n-attribute.js"; -import { Source, SourceJustifyKeysOptions, SourceJustifyKeysResult } from "./source.js"; +import { Config, ElementContentLocalizationType } from "./config.js"; import { Diagnostic } from "./diagnostics.js"; +import { Source, SourceJustifyKeysOptions, SourceJustifyKeysResult } from "./source.js"; +import { analyzeElementContent, DocumentFragment, Element, getAttributeValue, traverseElements, treeDiagnostics } from "./utility/parse5-tree.js"; /** * Represents a localized aurelia template file. */ export class AureliaTemplateFile implements Source { - private constructor( - private readonly _filename: string, - private _source: string, - private _root: DocumentFragment - ) {} + #filename: string; + #source: string; + #root: DocumentFragment; + + constructor(filename: string, source: string, root: DocumentFragment) { + this.#filename = filename; + this.#source = source; + this.#root = root; + } - private static parseHtml(source: string) { + static #parseHtml(source: string) { return parseFragment(source, { scriptingEnabled: false, sourceCodeLocationInfo: true }); } - public static parse(filename: string, source: string) { - return new AureliaTemplateFile(filename, source, AureliaTemplateFile.parseHtml(source)); + static parse(filename: string, source: string) { + return new AureliaTemplateFile(filename, source, AureliaTemplateFile.#parseHtml(source)); } - public get filename() { - return this._filename; + get filename() { + return this.#filename; } - public get source() { - return this._source; + get source() { + return this.#source; } - public extractKeys(config: Config) { + extractKeys(config: Config) { const keys = new Map(); - for (const element of traverseElements(this._root, config.ignoreElement)) { + for (const element of traverseElements(this.#root, config.ignoreElement)) { const elementWhitespaceHandling = config.getElementWhitespaceHandling(element.tagName); const attributeValue = getAttributeValue(element, "t"); @@ -76,11 +80,11 @@ export class AureliaTemplateFile implements Source { return keys; } - public justifyKeys(config: Config, { prefix, diagnostics, diagnosticsOnly, isReserved }: SourceJustifyKeysOptions): SourceJustifyKeysResult { + justifyKeys(config: Config, { prefix, diagnostics, diagnosticsOnly, isReserved }: SourceJustifyKeysOptions): SourceJustifyKeysResult { const knownKeys = new Set(); const candidates: JustificationCandidate[] = []; - for (const element of traverseElements(this._root, config.ignoreElement)) { + for (const element of traverseElements(this.#root, config.ignoreElement)) { const elementConfig = config.getLocalizedElement(element.tagName); const { hasText, hasElements } = analyzeElementContent(element, config.ignoreTextContent); const originalAttributeValue = getAttributeValue(element, "t"); @@ -89,7 +93,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.MixedContent, details: {}, - filename: this._filename, + filename: this.filename, source: this.source, ...treeDiagnostics.content(element) }); @@ -106,7 +110,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.InvalidTAttribute, details: { error }, - filename: this._filename, + filename: this.filename, source: this.source, ...treeDiagnostics.attribute(element, "t") }); @@ -119,7 +123,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.UnlocalizedText, details: {}, - filename: this._filename, + filename: this.filename, source: this.source, ...treeDiagnostics.content(element) }); @@ -128,7 +132,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.DisallowedTAttribute, details: {}, - filename: this._filename, + filename: this.filename, source: this.source, ...treeDiagnostics.startTag(element) }); @@ -183,7 +187,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.DisallowedContent, details: {}, - filename: this._filename, + filename: this.filename, source: this.source, ...treeDiagnostics.content }); @@ -204,7 +208,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.DisallowedLocalizedAttribute, details: { key, name }, - filename: this._filename, + filename: this.filename, source: this.source, ...treeDiagnostics.startTag(element) }); @@ -217,10 +221,10 @@ export class AureliaTemplateFile implements Source { const attributeLocation = element.sourceCodeLocation!.attrs!.t; start = attributeLocation.startOffset; end = attributeLocation.endOffset; - while (/\s/.test(this._source.charAt(start - 1))) { + while (/\s/.test(this.source.charAt(start - 1))) { start--; } - space = this._source.slice(start, attributeLocation.startOffset); + space = this.source.slice(start, attributeLocation.startOffset); } else { const tagLocation = location.startTag!; start = end = tagLocation.endOffset - 1; @@ -239,7 +243,7 @@ export class AureliaTemplateFile implements Source { diagnostics.report({ type: Diagnostic.Type.WrongPrefix, details: { key, expectedPrefix: prefix }, - filename: this._filename + filename: this.filename }); } } @@ -249,16 +253,16 @@ export class AureliaTemplateFile implements Source { let updatedSource = ""; let sourcePos = 0; for (const commit of commits) { - updatedSource += this._source.slice(sourcePos, commit.start); + updatedSource += this.source.slice(sourcePos, commit.start); updatedSource += commit.replacement; sourcePos = commit.end; } - updatedSource += this._source.slice(sourcePos); + updatedSource += this.source.slice(sourcePos); - const modified = this._source !== updatedSource; + const modified = this.source !== updatedSource; if (!diagnosticsOnly) { - this._source = updatedSource; - this._root = AureliaTemplateFile.parseHtml(updatedSource); + this.#source = updatedSource; + this.#root = AureliaTemplateFile.#parseHtml(updatedSource); } return { modified, replacedKeys }; } diff --git a/src/cli.ts b/src/cli.ts index 0624b60..7b978e0 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,13 +1,10 @@ #!/usr/bin/env node - -import { pathToFileURL } from "node:url"; import { readFile } from "node:fs/promises"; import { dirname, extname, relative, resolve } from "node:path"; - +import { pathToFileURL } from "node:url"; import parse from "yargs-parser"; - -import { Project } from "./project.js"; import { ConfigOptions, createConfig } from "./config.js"; +import { Project } from "./project.js"; (async () => { const args = parse(process.argv.slice(2), { @@ -16,6 +13,7 @@ import { ConfigOptions, createConfig } from "./config.js"; "watch", "verbose", "externals", + "color", ], string: ["config"], alias: { @@ -30,6 +28,7 @@ import { ConfigOptions, createConfig } from "./config.js"; const watch = Boolean(args.watch ?? development); const verbose = Boolean(args.verbose ?? false); const externals = Boolean(args.externals ?? true); + const color = Boolean(args.color ?? true); const configFilename = resolve(args.config ?? "i18n-config.mjs"); if (verbose) { @@ -57,6 +56,7 @@ import { ConfigOptions, createConfig } from "./config.js"; const config = createConfig(dirname(configFilename), options); const project = new Project({ config, development }); + project.diagnosticFormatter.color = color; project.reportDiagnosticsToConsole(); await project.run({ watch, externals }); })().catch(error => { diff --git a/src/config.ts b/src/config.ts index 76c275f..e51fc36 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,4 @@ import { resolve } from "node:path"; - import { Diagnostic } from "./diagnostics.js"; export interface ConfigOptions { @@ -81,7 +80,7 @@ export interface ConfigOptions { */ attributes?: Record; /** - * + * Whitespace handling for node text content. */ content?: Config.WhitespaceHandling; } | Config.WhitespaceHandling>; diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 0160427..8950ddd 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -1,8 +1,7 @@ -import { EventEmitter } from "node:events"; -import { inspect } from "node:util"; - import colors from "ansi-colors"; +import { EventEmitter } from "node:events"; import { relative } from "node:path"; +import { inspect } from "node:util"; export interface Diagnostic extends DiagnosticLocationPair { readonly type: T; @@ -87,54 +86,61 @@ export declare interface Diagnostics { } export class Diagnostics extends EventEmitter { - public report(diagnostic: Diagnostic) { + report(diagnostic: Diagnostic) { this.emit("report", diagnostic); } } export class DiagnosticFormatter { - public constructor(options: DiagnosticFormatterOptions = {}) { - this.color = options.color === undefined ? true : options.color; + constructor(options: DiagnosticFormatterOptions = {}) { + this.color = options.color ?? true; this.context = options.context; } - public color: boolean; - public context?: string; + /** + * See {@link DiagnosticFormatterOptions.color} + */ + color: boolean; - private formatPropertyPath(path: string[]) { + /** + * See {@link DiagnosticFormatterOptions.context} + */ + context?: string; + + #formatPropertyPath(path: string[]) { return colors.green(path.join("/")); } - private formatError(error: any) { + #formatError(error: any) { return inspect(error, false, undefined, this.color); } - private formatName(name: string) { + #formatName(name: string) { return `"${colors.green(name)}"`; } - private readonly messages: { + #messages: { [T in Diagnostic.Type]: (details: Diagnostic.Details) => string } = { - [Diagnostic.Type.InvalidJsonData]: d => `Invalid json data at ${this.formatPropertyPath(d.path)}. Only objects and strings are allowed.`, - [Diagnostic.Type.InvalidJsonPartName]: d => `Invalid json property name at ${this.formatPropertyPath(d.path)}. Property names should not contain dots.`, + [Diagnostic.Type.InvalidJsonData]: d => `Invalid json data at ${this.#formatPropertyPath(d.path)}. Only objects and strings are allowed.`, + [Diagnostic.Type.InvalidJsonPartName]: d => `Invalid json property name at ${this.#formatPropertyPath(d.path)}. Property names should not contain dots.`, [Diagnostic.Type.MixedContent]: d => `Element contains both text content and elements.`, - [Diagnostic.Type.InvalidTAttribute]: d => `Malformed t-attribute value: ${this.formatError(d.error)}`, + [Diagnostic.Type.InvalidTAttribute]: d => `Malformed t-attribute value: ${this.#formatError(d.error)}`, [Diagnostic.Type.UnlocalizedText]: d => `Element contains unlocalized text content.`, [Diagnostic.Type.DisallowedTAttribute]: d => `Unconfigured element has a t-attribute.`, [Diagnostic.Type.DisallowedContent]: d => `Unconfigured element contains text or html content.`, - [Diagnostic.Type.DisallowedLocalizedAttribute]: d => `Unconfigured attribute ${this.formatName(d.name)} is localized with key ${this.formatName(d.key)}.`, - [Diagnostic.Type.WrongPrefix]: d => `Key ${this.formatName(d.key)} is expected to start with the prefix ${this.formatName(d.expectedPrefix)}.`, - [Diagnostic.Type.DuplicateKeyOrPath]: d => `Duplicate localization key or path: ${this.formatPropertyPath(d.path)}`, - [Diagnostic.Type.DuplicateKey]: d => `Duplicate localization key: ${this.formatName(d.key)}`, - [Diagnostic.Type.OutdatedTranslation]: d => `Translation of ${this.formatName(d.key)} for locale ${this.formatName(d.localeId)} is outdated.`, - [Diagnostic.Type.MissingTranslation]: d => `Translation of ${this.formatName(d.key)} for locale ${this.formatName(d.localeId)} is missing.`, - [Diagnostic.Type.ModifiedSource]: d => `Changes to the source should have been committed.`, - [Diagnostic.Type.ModifiedTranslation]: d => `Changes to translation data should have been committed.`, - [Diagnostic.Type.UnknownLocale]: d => `Key ${this.formatName(d.key)} has translations for ${this.formatName(d.localeId)}, but this locale is not configured.`, + [Diagnostic.Type.DisallowedLocalizedAttribute]: d => `Unconfigured attribute ${this.#formatName(d.name)} is localized with key ${this.#formatName(d.key)}.`, + [Diagnostic.Type.WrongPrefix]: d => `Key ${this.#formatName(d.key)} is expected to start with the prefix ${this.#formatName(d.expectedPrefix)}.`, + [Diagnostic.Type.DuplicateKeyOrPath]: d => `Duplicate localization key or path: ${this.#formatPropertyPath(d.path)}`, + [Diagnostic.Type.DuplicateKey]: d => `Duplicate localization key: ${this.#formatName(d.key)}`, + [Diagnostic.Type.OutdatedTranslation]: d => `Translation of ${this.#formatName(d.key)} for locale ${this.#formatName(d.localeId)} is outdated.`, + [Diagnostic.Type.MissingTranslation]: d => `Translation of ${this.#formatName(d.key)} for locale ${this.#formatName(d.localeId)} is missing.`, + [Diagnostic.Type.ModifiedSource]: d => `Source file is not in sync with translation data. Run i18n tools in development mode once and check for i18n related changes.`, + [Diagnostic.Type.ModifiedTranslation]: d => `Translation data is not in sync with source files. Run i18n tools in development mode once and check for i18n related changes.`, + [Diagnostic.Type.UnknownLocale]: d => `Key ${this.#formatName(d.key)} has translations for ${this.#formatName(d.localeId)}, but this locale is not configured.`, }; - public format(diagnostic: Diagnostic) { + format(diagnostic: Diagnostic) { let fileInfo = ""; if (diagnostic.filename) { const filename = (this.context ? relative(this.context, diagnostic.filename) : diagnostic.filename); @@ -143,15 +149,23 @@ export class DiagnosticFormatter { fileInfo += `:${colors.yellowBright(String(diagnostic.start.line))}:${colors.yellowBright(String(diagnostic.start.col))}`; } } - - const message = this.messages[diagnostic.type](> diagnostic.details); - - return `[${colors.red("aurelia-i18n")}]${fileInfo} ${message}`; + const message = this.#messages[diagnostic.type](> diagnostic.details); + let raw = `[${colors.red("aurelia-i18n")}]${fileInfo} ${message}`; + if (!this.color) { + raw = colors.strip(raw); + } + return raw; } } export interface DiagnosticFormatterOptions { - prefix?: string; + /** + * If true (default), formatted output is colored. + */ color?: boolean; + + /** + * Optional absolute path to omit from formatted file paths. + */ context?: string; } diff --git a/src/json-resource-file.ts b/src/json-resource-file.ts index 4ff5831..75cfce6 100644 --- a/src/json-resource-file.ts +++ b/src/json-resource-file.ts @@ -1,35 +1,39 @@ import { Config } from "./config.js"; -import { Source, SourceExtractKeysOptions } from "./source.js"; -import { LocaleData } from "./locale-data.js"; import { Diagnostic } from "./diagnostics.js"; +import { LocaleData } from "./locale-data.js"; +import { Source, SourceExtractKeysOptions } from "./source.js"; export class JsonResourceFile implements Source { - public constructor( - private readonly _filename: string, - private readonly _source: string, - private readonly _data: LocaleData - ) {} + #filename: string; + #source: string; + #data: LocaleData; + + constructor(filename: string, source: string, data: LocaleData) { + this.#filename = filename; + this.#source = source; + this.#data = data; + } - public get filename() { - return this._filename; + get filename() { + return this.#filename; } - public get source() { - return this._source; + get source() { + return this.#source; } - public static parse(filename: string, source: string) { + static parse(filename: string, source: string) { return new JsonResourceFile(filename, source, JSON.parse(source)); } - public extractKeys(config: Config, { prefix, diagnostics }: SourceExtractKeysOptions) { + extractKeys(config: Config, { prefix, diagnostics }: SourceExtractKeysOptions) { const keys = new Map(); (function traverse(this: JsonResourceFile, data: LocaleData, path: string[]) { if (data === null || typeof data !== "object" || Array.isArray(data)) { diagnostics.report({ type: Diagnostic.Type.InvalidJsonData, details: { path }, - filename: this._filename, + filename: this.#filename, source: this.source }); } else { @@ -38,7 +42,7 @@ export class JsonResourceFile implements Source { diagnostics.report({ type: Diagnostic.Type.InvalidJsonPartName, details: { path }, - filename: this._filename + filename: this.#filename }); } const childPath = path.concat(part); @@ -50,7 +54,7 @@ export class JsonResourceFile implements Source { } } } - }).call(this, this._data, []); + }).call(this, this.#data, []); return keys; } } diff --git a/src/locale-data.ts b/src/locale-data.ts index b88b075..cffaa39 100644 --- a/src/locale-data.ts +++ b/src/locale-data.ts @@ -1,4 +1,4 @@ -import { Diagnostics, Diagnostic } from "./diagnostics.js"; +import { Diagnostic, Diagnostics } from "./diagnostics.js"; export interface LocaleData { [part: string]: LocaleData | string; diff --git a/src/project.ts b/src/project.ts index 8d0e651..8bdaa66 100644 --- a/src/project.ts +++ b/src/project.ts @@ -1,55 +1,70 @@ +import { mkdir, readFile, writeFile } from "node:fs/promises"; import { basename, dirname, extname, relative } from "node:path"; - +import { AureliaTemplateFile } from "./aurelia-template-file.js"; import { Config } from "./config.js"; +import { Diagnostic, DiagnosticFormatter, Diagnostics } from "./diagnostics.js"; +import { JsonResourceFile } from "./json-resource-file.js"; +import { LocaleData } from "./locale-data.js"; import { Source } from "./source.js"; -import { Diagnostics, Diagnostic, DiagnosticFormatter } from "./diagnostics.js"; -import { PairSet } from "./utility/pair-set.js"; import { TranslationData } from "./translation-data.js"; -import { LocaleData } from "./locale-data.js"; import { deduplicateModuleFilenames, findFiles, joinPattern, watchFiles } from "./utility/file-system.js"; -import { AureliaTemplateFile } from "./aurelia-template-file.js"; -import { mkdir, readFile, writeFile } from "node:fs/promises"; -import { JsonResourceFile } from "./json-resource-file.js"; +import { PairSet } from "./utility/pair-set.js"; export class Project { - public readonly config: Config; - public readonly diagnostics = new Diagnostics(); - public readonly diagnosticFormatter = new DiagnosticFormatter(); - public readonly development: boolean; + #config: Config; + #development: boolean; + #diagnostics = new Diagnostics(); + #diagnosticFormatter = new DiagnosticFormatter(); /** A map of filenames to sources. */ - private readonly _sources = new Map(); + #sources = new Map(); /** A pair set of filename/key pairs. */ - private readonly _knownKeys = new PairSet(); + #knownKeys = new PairSet(); /** A set of filenames of sources that have not been justified yet. */ - private readonly _unprocessedSources = new Set(); + #unprocessedSources = new Set(); /** A set of filenames of sources that have been modified in memory. */ - private readonly _modifiedSources = new Set(); + #modifiedSources = new Set(); /** Map from locales to filenames to external locale data. */ - private readonly _externalLocales = new Map>(); + #externalLocales = new Map>(); + + #translationData = new TranslationData(); + #translationDataModified = false; - private _translationData = new TranslationData(); - private _translationDataModified = false; + constructor(options: ProjectOptions) { + this.#config = options.config; + this.#development = Boolean(options.development); + } + + get config() { + return this.#config; + } + + get diagnostics() { + return this.#diagnostics; + } + + get diagnosticFormatter() { + return this.#diagnosticFormatter; + } - public constructor(options: ProjectOptions) { - this.config = options.config; - this.development = Boolean(options.development); + get development() { + return this.#development; } /** * Get or set translation data. * A task runner should set this property before processing sources if translation data exists on disk. */ - public get translationData() { - return this._translationData; + get translationData() { + return this.#translationData; } - public set translationData(data: TranslationData) { - this._translationData = data; - this._translationDataModified = data.parsedVersion != 2; + set translationData(data: TranslationData) { + this.#translationData = data; + this.#translationDataModified = data.parsedVersion != 2; } - public getPrefix(filename: string) { + getPrefix(filename: string) { if (/^\.\.($|[\\\/])/.test(relative(this.config.src, filename))) { throw new Error(`Filename is outside of the project source directory: ${filename}`); } @@ -75,51 +90,51 @@ export class Project { return `${this.config.prefix}${sanitizeName(name)}.`; } - protected extractKeys(source: Source, prefix = this.getPrefix(source.filename)) { + #extractKeys(source: Source, prefix = this.getPrefix(source.filename)) { const keys = source.extractKeys(this.config, { prefix, diagnostics: this.diagnostics }); - this._knownKeys.deleteKey(source.filename); + this.#knownKeys.deleteKey(source.filename); for (const key of keys.keys()) { - this._knownKeys.add(source.filename, key); + this.#knownKeys.add(source.filename, key); } - if (this._translationData.updateKeys(source.filename, keys)) { - this._translationDataModified = true; + if (this.#translationData.updateKeys(source.filename, keys)) { + this.#translationDataModified = true; } } /** * Should be called by a task runner to update or add a source file. */ - public updateSource(source: Source) { - const oldSource = this._sources.get(source.filename); - this._sources.set(source.filename, source); + updateSource(source: Source) { + const oldSource = this.#sources.get(source.filename); + this.#sources.set(source.filename, source); if (!oldSource || oldSource.source !== source.source) { - this._unprocessedSources.add(source.filename); - this.extractKeys(source); + this.#unprocessedSources.add(source.filename); + this.#extractKeys(source); } } /** * Can be called by a task runner to delete a source. */ - public deleteSource(filename: string) { - this._sources.delete(filename); - this._unprocessedSources.delete(filename); - this._knownKeys.deleteKey(filename); - this._modifiedSources.delete(filename); + deleteSource(filename: string) { + this.#sources.delete(filename); + this.#unprocessedSources.delete(filename); + this.#knownKeys.deleteKey(filename); + this.#modifiedSources.delete(filename); } /** * Should be called by a task runner to process updated sources. */ - public processSources() { - for (const [filename, file] of this._translationData.files) { + processSources() { + for (const [filename, file] of this.#translationData.files) { for (const key of file.content.keys()) { - this._knownKeys.add(filename, key); + this.#knownKeys.add(filename, key); } } - for (const filename of this._unprocessedSources) { - this._unprocessedSources.delete(filename); - const source = this._sources.get(filename)!; + for (const filename of this.#unprocessedSources) { + this.#unprocessedSources.delete(filename); + const source = this.#sources.get(filename)!; if (source.justifyKeys) { const prefix = this.getPrefix(filename); const result = source.justifyKeys(this.config, { @@ -127,7 +142,7 @@ export class Project { diagnostics: this.diagnostics, diagnosticsOnly: !this.development, isReserved: key => { - const filenames = this._knownKeys.getKeys(key); + const filenames = this.#knownKeys.getKeys(key); if (filenames) { return filenames.size > (filenames.has(filename) ? 1 : 0); } @@ -137,21 +152,21 @@ export class Project { if (result.modified) { for (const [oldKey, newKeys] of result.replacedKeys) { for (const newKey of newKeys) { - const hintFilenames = this._knownKeys.getKeys(oldKey); - if (this._translationData.copyTranslations(filename, oldKey, newKey, hintFilenames)) { - this._translationDataModified = true; + const hintFilenames = this.#knownKeys.getKeys(oldKey); + if (this.#translationData.copyTranslations(filename, oldKey, newKey, hintFilenames)) { + this.#translationDataModified = true; } } } - this.extractKeys(source, prefix); - this._modifiedSources.add(filename); + this.#extractKeys(source, prefix); + this.#modifiedSources.add(filename); } } } - for (const [filename, file] of this._translationData.files) { - if (!this._sources.has(filename) || file.content.size === 0) { - this._translationData.deleteFile(filename); - this._translationDataModified = true; + for (const [filename, file] of this.#translationData.files) { + if (!this.#sources.has(filename) || file.content.size === 0) { + this.#translationData.deleteFile(filename); + this.#translationDataModified = true; } } } @@ -164,34 +179,34 @@ export class Project { * In prorudction, no hooks will be invoked and diagnostics * are reported if anything has been modified. */ - public async handleModified(hooks: ProjectHandleModifiedHooks) { + async handleModified(hooks: ProjectHandleModifiedHooks) { if (this.development) { const writeTasks: (void | Promise)[] = []; - for (const filename of this._modifiedSources) { - this._modifiedSources.delete(filename); + for (const filename of this.#modifiedSources) { + this.#modifiedSources.delete(filename); if (hooks.writeSource) { - writeTasks.push(hooks.writeSource(this._sources.get(filename)!)); + writeTasks.push(hooks.writeSource(this.#sources.get(filename)!)); } } - if (this._translationDataModified) { - this._translationDataModified = false; + if (this.#translationDataModified) { + this.#translationDataModified = false; if (hooks.writeTranslationData) { - writeTasks.push(hooks.writeTranslationData(this._translationData)); + writeTasks.push(hooks.writeTranslationData(this.#translationData)); } } await Promise.all(writeTasks); } else { - for (const filename of this._modifiedSources) { + for (const filename of this.#modifiedSources) { this.diagnostics.report({ type: Diagnostic.Type.ModifiedSource, details: {}, filename }); } - if (this._translationDataModified) { + if (this.#translationDataModified) { this.diagnostics.report({ type: Diagnostic.Type.ModifiedTranslation, details: {} @@ -203,12 +218,12 @@ export class Project { /** * Add external locale data. */ - public addExternalLocale(localeId: string, filename: string, data: LocaleData) { - const entries = this._externalLocales.get(localeId); + addExternalLocale(localeId: string, filename: string, data: LocaleData) { + const entries = this.#externalLocales.get(localeId); if (entries) { entries.set(filename, data); } else { - this._externalLocales.set(localeId, new Map([[filename, data]])); + this.#externalLocales.set(localeId, new Map([[filename, data]])); } } @@ -216,9 +231,9 @@ export class Project { * Compile translation data and external locales. * @returns A map of locale ids to compiled locale data. */ - public compileLocales() { - const locales = this._translationData.compile(this.config, this.diagnostics); - for (const [localeId, files] of this._externalLocales) { + compileLocales() { + const locales = this.#translationData.compile(this.config, this.diagnostics); + for (const [localeId, files] of this.#externalLocales) { for (const data of files.values()) { const target = locales.get(localeId); if (target) { @@ -236,7 +251,7 @@ export class Project { * * This will also set the process exit code to 1 if any errors are reported. */ - public reportDiagnosticsToConsole() { + reportDiagnosticsToConsole() { this.diagnostics.on("report", diagnostic => { const handling = this.config.getDiagnosticHandling(diagnostic.type); if (handling === Config.DiagnosticHandling.Error) { @@ -251,7 +266,7 @@ export class Project { /** * Run the standard production or development workflow for this project. */ - public async run(options?: ProjectRunOptions) { + async run(options?: ProjectRunOptions) { const sourcePatterns = [ "**/*.html", "**/*.r.json", diff --git a/src/translation-data.ts b/src/translation-data.ts index a134f12..a838897 100644 --- a/src/translation-data.ts +++ b/src/translation-data.ts @@ -1,23 +1,22 @@ import { isAbsolute, join, relative } from "node:path"; - -import { LocaleData } from "./locale-data.js"; import { Config } from "./config.js"; -import { Diagnostics, Diagnostic } from "./diagnostics.js"; +import { Diagnostic, Diagnostics } from "./diagnostics.js"; +import { LocaleData } from "./locale-data.js"; /** * A container for translation data that is used as an * interface between this library and external tools. */ export class TranslationData { - public constructor( + constructor( /** A map of absolute filenames to file information */ - public readonly files = new Map(), + readonly files = new Map(), /** An array of obsolete translations */ - public readonly obsolete: TranslationData.ObsoleteTranslation[] = [], + readonly obsolete: TranslationData.ObsoleteTranslation[] = [], /** The version of the file that was loaded */ - public readonly parsedVersion: 1 | 2 = 2 + readonly parsedVersion: 1 | 2 = 2 ) {} /** @@ -26,7 +25,7 @@ export class TranslationData { * @param keys A map of i18n keys to english translations. * @returns true if anything has been modified. */ - public updateKeys(filename: string, keys: Map) { + updateKeys(filename: string, keys: Map) { let modified = false; let file = this.files.get(filename); if (!file) { @@ -57,7 +56,7 @@ export class TranslationData { } for (const [key, translationSet] of file.content) { if (!keys.has(key)) { - this.pushObsoleteSet(translationSet); + this.#pushObsoleteSet(translationSet); file.content.delete(key); modified = true; } @@ -70,7 +69,7 @@ export class TranslationData { * @param config The project configuration. * @returns A map of locale ids to compiled locale data. */ - public compile(config: Config, diagnostics: Diagnostics) { + compile(config: Config, diagnostics: Diagnostics) { const locales = new Map(config.locales.map(locale => { return [locale, LocaleData.createNew()]; })); @@ -130,7 +129,7 @@ export class TranslationData { * @param hintFilenames A hint to other files where translations for the old key could be found. * @returns true if anything has been copied. */ - public copyTranslations(filename: string, oldKey: string, newKey: string, hintFilenames?: Iterable) { + copyTranslations(filename: string, oldKey: string, newKey: string, hintFilenames?: Iterable) { const file = this.files.get(filename); if (file) { const translation = file.content.get(oldKey); @@ -153,7 +152,7 @@ export class TranslationData { return false; } - private pushObsoleteSet(translationSet: TranslationData.TranslationSet) { + #pushObsoleteSet(translationSet: TranslationData.TranslationSet) { if (translationSet.translations.size > 0) { this.obsolete.push({ content: translationSet.source.content, @@ -164,12 +163,12 @@ export class TranslationData { } } - public deleteFile(filename: string) { + deleteFile(filename: string) { var file = this.files.get(filename); if (file) { this.files.delete(filename); for (var translationSet of file.content.values()) { - this.pushObsoleteSet(translationSet); + this.#pushObsoleteSet(translationSet); } } } @@ -179,7 +178,7 @@ export class TranslationData { * @param value The set to clone. * @param markAsOutdated If true, the clone will be marked as outdated. Default is `true` */ - public static cloneTranslationSet(value: TranslationData.TranslationSet, markAsOutdated = true): TranslationData.TranslationSet { + static cloneTranslationSet(value: TranslationData.TranslationSet, markAsOutdated = true): TranslationData.TranslationSet { const translations = new Map(); for (const [localeId, translation] of value.translations) { translations.set(localeId, TranslationData.cloneTranslation(translation)); @@ -194,7 +193,7 @@ export class TranslationData { /** * Deep clone a translation object. */ - public static cloneTranslation(value: TranslationData.Translation): TranslationData.Translation { + static cloneTranslation(value: TranslationData.Translation): TranslationData.Translation { return { content: value.content, lastModified: value.lastModified, @@ -207,7 +206,7 @@ export class TranslationData { * @param json The json data. * @param basePath The base path for resolving filenames. */ - public static parse(json: string, basePath: string) { + static parse(json: string, basePath: string) { const data: TranslationData.JsonV1 | TranslationData.JsonV2 = JSON.parse(json); if (!isObject(data)) { throw new TypeError(`data must be an object.`); @@ -314,7 +313,7 @@ export class TranslationData { * Format this translation data as json. * @param basePath The base path for creating relative filenames. */ - public formatJson(basePath: string) { + formatJson(basePath: string) { const json: TranslationData.JsonV2 = Object.create(null) json.version = 2; diff --git a/src/utility/file-system.ts b/src/utility/file-system.ts index 56ee3cc..d5d01ae 100644 --- a/src/utility/file-system.ts +++ b/src/utility/file-system.ts @@ -1,9 +1,8 @@ -import * as posixPath from "node:path/posix"; -import { readdir } from "node:fs/promises"; - import { watch } from "chokidar"; -import picomatch from "picomatch"; +import { readdir } from "node:fs/promises"; import { join, normalize } from "node:path"; +import * as posixPath from "node:path/posix"; +import picomatch from "picomatch"; export interface WatchFileUpdates { initial: boolean; diff --git a/src/utility/pair-set.ts b/src/utility/pair-set.ts index 9fe6af0..bd249e5 100644 --- a/src/utility/pair-set.ts +++ b/src/utility/pair-set.ts @@ -4,31 +4,31 @@ * fast queries for both keys and values. */ export class PairSet { - private readonly _keys = new Map>(); - private readonly _values = new Map>(); + #keys = new Map>(); + #vals = new Map>(); - public add(key: K, value: V) { - add(this._keys, key, value); - add(this._values, value, key); + add(key: K, value: V) { + add(this.#keys, key, value); + add(this.#vals, value, key); } - public delete(key: K, value: V) { - del(this._keys, key, value); - del(this._values, value, key); + delete(key: K, value: V) { + del(this.#keys, key, value); + del(this.#vals, value, key); } - public deleteKey(key: K) { - const values = this._keys.get(key); + deleteKey(key: K) { + const values = this.#keys.get(key); if (values) { - this._keys.delete(key); + this.#keys.delete(key); for (const value of values) { - del(this._values, value, key); + del(this.#vals, value, key); } } } - public getKeys(value: V): ReadonlySet | undefined { - return this._values.get(value); + getKeys(value: V): ReadonlySet | undefined { + return this.#vals.get(value); } } diff --git a/src/utility/parse5-tree.ts b/src/utility/parse5-tree.ts index 856a1d6..077fe2e 100644 --- a/src/utility/parse5-tree.ts +++ b/src/utility/parse5-tree.ts @@ -1,10 +1,9 @@ import { defaultTreeAdapter as adapter } from "parse5"; import type { DocumentFragment, Element, Node, ParentNode, Template } from "../../node_modules/parse5/dist/tree-adapters/default.js"; +import { DiagnosticLocationPair } from "../diagnostics.js"; export type { DocumentFragment, Element }; -import { DiagnosticLocationPair } from "../diagnostics.js"; - const IGNORED_NODE_NAMES = new Set(["#comment", "#documentType", "#text"]); export function * traverseElements(node: Node, ignoreTagNames: (tagName: string) => boolean): Generator { diff --git a/test/aurelia-template-file.test.ts b/test/aurelia-template-file.test.ts new file mode 100644 index 0000000..3e7205e --- /dev/null +++ b/test/aurelia-template-file.test.ts @@ -0,0 +1,225 @@ +import { AureliaTemplateFile, Config, ConfigOptions, createConfig, Diagnostic, ElementContentLocalizationType } from "@netatwork/aurelia-i18n-tools"; +import { deepStrictEqual, strictEqual } from "node:assert"; +import { join } from "node:path"; +import test, { suite } from "node:test"; +import { captureDiagnostics, code, expectNoDiagnostics, testDir } from "./utility.js"; + +await suite("aurelia-template-file", async () => { + const filename = join(testDir, "template.html"); + const config = createConfig(testDir, { + src: ".", + localize: { + div: { + content: ElementContentLocalizationType.Text, + attributes: ["foo", "bar"] + } + } + }); + + await test("allocate new keys", () => { + const source = AureliaTemplateFile.parse(filename, code(` +
content
+
+ `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: expectNoDiagnostics(), + }); + strictEqual(result.modified, true); + strictEqual(result.replacedKeys.size, 0); + strictEqual(source.source, code(` +
content
+
+ `)); + }); + + await test("reuse existing keys", () => { + const source = AureliaTemplateFile.parse(filename, code(` +
content
+ `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: expectNoDiagnostics() + }); + strictEqual(result.modified, true); + strictEqual(result.replacedKeys.size, 0); + strictEqual(source.source, code(` +
content
+ `)); + }); + + await test("replace duplicate keys", () => { + const source = AureliaTemplateFile.parse(filename, code(` +
content
+
content
+ `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: expectNoDiagnostics() + }); + strictEqual(result.modified, true); + strictEqual(result.replacedKeys.size, 0); + strictEqual(source.source, code(` +
content
+
content
+ `)); + }); + + await test("replace reserved keys", () => { + const source = AureliaTemplateFile.parse(filename, code(` +
content
+ `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: expectNoDiagnostics(), + isReserved: k => k === "test.t7" + }); + strictEqual(result.modified, true); + strictEqual(result.replacedKeys.size, 1); + deepStrictEqual(result.replacedKeys.get("test.t7"), new Set(["test.t0"])); + strictEqual(source.source, code(` +
content
+ `)); + }); + + await test("replace keys with wrong prefixes", () => { + const source = AureliaTemplateFile.parse(filename, code(` +
content
+ `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: expectNoDiagnostics(), + }); + strictEqual(result.modified, true); + strictEqual(result.replacedKeys.size, 1); + deepStrictEqual(result.replacedKeys.get("foo.t7"), new Set(["test.t0"])); + strictEqual(source.source, code(` +
content
+ `)); + }); + + await test("report unlocalized text content", () => { + const diagnostics = captureDiagnostics(); + const source = AureliaTemplateFile.parse(filename, code(` + content + `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: diagnostics.host + }); + strictEqual(result.modified, false); + strictEqual(source.source, code(` + content + `)); + deepStrictEqual(diagnostics.all.map(d => d.type), [Diagnostic.Type.UnlocalizedText]); + }); + + await test("keep linebreaks when replacing keys", () => { + const source = AureliaTemplateFile.parse(filename, code(` +
content
+ `)); + const result = source.justifyKeys(config, { + prefix: "test.", + diagnostics: expectNoDiagnostics() + }); + strictEqual(result.modified, true); + strictEqual(result.replacedKeys.size, 0); + strictEqual(source.source, code(` +
content
+ `)); + }); + + function assertWhitespaceHandling(whitespace: ConfigOptions["whitespace"], markup: string, expectedValues: string[]) { + const config = createConfig(testDir, { src: ".", whitespace }); + const source = AureliaTemplateFile.parse(filename, code(markup)); + deepStrictEqual(Array.from(source.extractKeys(config).values()), expectedValues); + } + + await test("preserves whitespace by default", () => { + assertWhitespaceHandling( + undefined, + ` +
foo 1
+
+ `, + [" foo 1 ", " bar 2 "] + ); + }); + + await test("applies whitespace handling to specific attributes", () => { + assertWhitespaceHandling( + { + "*": { + attributes: { + "*": Config.WhitespaceHandling.Trim, + bar: Config.WhitespaceHandling.Collapse + } + } + }, + ` +
+
+ `, + ["1", " 2 "] + ); + }); + + await test("applies whitespace handling to specific elements", () => { + assertWhitespaceHandling( + { + "*": Config.WhitespaceHandling.Trim, + span: Config.WhitespaceHandling.Collapse + }, + ` +
1
+
+ 3 + + `, + ["1", "2", " 3 ", " 4 "] + ); + }); + + await test("correctly trims whitespace", () => { + assertWhitespaceHandling( + { + "*": Config.WhitespaceHandling.Trim + }, + ` +
foo 1
+
bar2
+ `, + ["foo 1", "bar2"] + ); + }); + + await test("correctly collapses whitespace", () => { + assertWhitespaceHandling( + { + "*": Config.WhitespaceHandling.Collapse + }, + ` +
foo 1
+
bar 2
+ `, + [" foo 1 ", "bar 2"] + ); + }); + + await test("correctly trims and collapses whitespace", () => { + assertWhitespaceHandling( + { + "*": Config.WhitespaceHandling.TrimCollapse + }, + ` +
foo 1
+
bar 2
+ `, + ["foo 1", "bar 2"] + ); + }); +}); diff --git a/test/aurelia-template-file.ts b/test/aurelia-template-file.ts deleted file mode 100644 index 43eb912..0000000 --- a/test/aurelia-template-file.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { join } from "node:path"; - -import test, { ExecutionContext } from "ava"; - -import { expectNoDiagnostics, code, captureDiagnostics, testDir } from "./_utility.js"; -import { AureliaTemplateFile, createConfig, ElementContentLocalizationType, Diagnostic, Config, ConfigOptions } from "../src/index.js"; - -const filename = join(testDir, "template.html"); -const config = createConfig(testDir, { - src: ".", - localize: { - div: { - content: ElementContentLocalizationType.Text, - attributes: ["foo", "bar"] - } - } -}); - -test("allocate new keys", t => { - const source = AureliaTemplateFile.parse(filename, code(` -
content
-
- `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: expectNoDiagnostics(t) - }); - t.true(result.modified); - t.is(result.replacedKeys.size, 0); - t.is(source.source, code(` -
content
-
- `)); -}); - -test("reuse existing keys", t => { - const source = AureliaTemplateFile.parse(filename, code(` -
content
- `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: expectNoDiagnostics(t) - }); - t.true(result.modified); - t.is(result.replacedKeys.size, 0); - t.is(source.source, code(` -
content
- `)); -}); - -test("replace duplicate keys", t => { - const source = AureliaTemplateFile.parse(filename, code(` -
content
-
content
- `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: expectNoDiagnostics(t) - }); - t.true(result.modified); - t.is(result.replacedKeys.size, 0); - t.is(source.source, code(` -
content
-
content
- `)); -}); - -test("replace reserved keys", t => { - const source = AureliaTemplateFile.parse(filename, code(` -
content
- `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: expectNoDiagnostics(t), - isReserved: k => k === "test.t7" - }); - t.true(result.modified); - t.is(result.replacedKeys.size, 1); - t.deepEqual(result.replacedKeys.get("test.t7"), new Set(["test.t0"])); - t.is(source.source, code(` -
content
- `)); -}); - -test("replace keys with wrong prefixes", t => { - const source = AureliaTemplateFile.parse(filename, code(` -
content
- `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: expectNoDiagnostics(t), - }); - t.true(result.modified); - t.is(result.replacedKeys.size, 1); - t.deepEqual(result.replacedKeys.get("foo.t7"), new Set(["test.t0"])); - t.is(source.source, code(` -
content
- `)); -}); - -test("report unlocalized text content", t => { - const diagnostics = captureDiagnostics(); - const source = AureliaTemplateFile.parse(filename, code(` - content - `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: diagnostics.host - }); - t.false(result.modified); - t.is(source.source, code(` - content - `)); - t.deepEqual(diagnostics.all.map(d => d.type), [Diagnostic.Type.UnlocalizedText]); -}); - -test("keep linebreaks when replacing keys", t => { - const source = AureliaTemplateFile.parse(filename, code(` -
content
- `)); - const result = source.justifyKeys(config, { - prefix: "test.", - diagnostics: expectNoDiagnostics(t) - }); - t.true(result.modified); - t.is(result.replacedKeys.size, 0); - t.is(source.source, code(` -
content
- `)); -}); - -function whitespaceHandling(t: ExecutionContext, whitespace: ConfigOptions["whitespace"], markup: string, expectedValues: string[]) { - const config = createConfig(testDir, { src: ".", whitespace }); - const source = AureliaTemplateFile.parse(filename, code(markup)); - t.deepEqual(Array.from(source.extractKeys(config).values()), expectedValues); -} - -test("preserves whitespace by default", whitespaceHandling, undefined, ` -
foo 1
-
-`, [" foo 1 ", " bar 2 "]); - -test("applies whitespace handling to specific attributes", whitespaceHandling, { - "*": { - attributes: { - "*": Config.WhitespaceHandling.Trim, - bar: Config.WhitespaceHandling.Collapse - } - } -}, ` -
-
-`, ["1", " 2 "]); - -test("applies whitespace handling to specific elements", whitespaceHandling, { - "*": Config.WhitespaceHandling.Trim, - span: Config.WhitespaceHandling.Collapse -}, ` -
1
-
- 3 - -`, ["1", "2", " 3 ", " 4 "]); - -test("correctly trims whitespace", whitespaceHandling, { - "*": Config.WhitespaceHandling.Trim -}, ` -
foo 1
-
bar2
-`, ["foo 1", "bar2"]); - -test("correctly collapses whitespace", whitespaceHandling, { - "*": Config.WhitespaceHandling.Collapse -}, ` -
foo 1
-
bar 2
-`, [" foo 1 ", "bar 2"]); - -test("correctly trims and collapses whitespace", whitespaceHandling, { - "*": Config.WhitespaceHandling.TrimCollapse -}, ` -
foo 1
-
bar 2
-`, ["foo 1", "bar 2"]); diff --git a/test/file-system.test.ts b/test/file-system.test.ts new file mode 100644 index 0000000..4abf5ca --- /dev/null +++ b/test/file-system.test.ts @@ -0,0 +1,22 @@ +import { deepStrictEqual } from "assert"; +import { suite, test } from "node:test"; +import { deduplicateModuleFilenames } from "../dist/utility/file-system.js"; + +await suite("file-system", async () => { + await test("deduplicateModuleFilenames", () => { + const filenames = deduplicateModuleFilenames([ + "/foo/bar", + "/foo/node_modules/test/a", + "/foo/bar/node_modules/test/a", + "/bar/node_modules/test/b", + "/bar/foo/node_modules/test/b", + ]); + filenames.sort(); + deepStrictEqual(filenames, [ + "/bar/foo/node_modules/test/b", + "/foo/bar", + "/foo/bar/node_modules/test/a", + ]); + }); +}); + diff --git a/test/file-system.ts b/test/file-system.ts deleted file mode 100644 index 484d9fa..0000000 --- a/test/file-system.ts +++ /dev/null @@ -1,18 +0,0 @@ -import test from "ava"; -import { deduplicateModuleFilenames } from "../src/utility/file-system.js"; - -test("deduplicateModuleFilenames", t => { - const filenames = deduplicateModuleFilenames([ - "/foo/bar", - "/foo/node_modules/test/a", - "/foo/bar/node_modules/test/a", - "/bar/node_modules/test/b", - "/bar/foo/node_modules/test/b", - ]); - filenames.sort(); - t.deepEqual(filenames, [ - "/bar/foo/node_modules/test/b", - "/foo/bar", - "/foo/bar/node_modules/test/a", - ]); -}); diff --git a/test/project.test.ts b/test/project.test.ts new file mode 100644 index 0000000..872cb49 --- /dev/null +++ b/test/project.test.ts @@ -0,0 +1,304 @@ +import { AureliaTemplateFile, createConfig, ElementContentLocalizationType, Project } from "@netatwork/aurelia-i18n-tools"; +import { strictEqual } from "node:assert"; +import { join } from "node:path"; +import test, { suite } from "node:test"; +import { code, handleModified, testDir } from "./utility.js"; + +await suite("project", async () => { + await test("justify sources and update translation data", async () => { + const config = createConfig(testDir, { + src: ".", + prefix: "app.", + localize: { + div: { content: ElementContentLocalizationType.Text } + } + }); + + const project = new Project({ + config, + development: true + }); + + const filename = join(testDir, "test.html"); + project.updateSource(AureliaTemplateFile.parse(filename, code(` + + `))); + + project.processSources(); + + const { sources, translationData } = await handleModified(project); + + strictEqual(sources.size, 1); + strictEqual(sources.get(filename), code(` + + `)); + + strictEqual(translationData!.files.get(filename)!.content.get("app.test.t0")!.source.content, "test"); + }); + + await test("use fallback for unknown elements", async () => { + const config = createConfig(testDir, { + src: ".", + prefix: "app.", + localize: { + "*": { content: ElementContentLocalizationType.Text }, + "div": { }, + "input": { attributes: ["placeholder"] }, + } + }); + + const project = new Project({ + config, + development: true + }); + + const filename = join(testDir, "test.html"); + project.updateSource(AureliaTemplateFile.parse(filename, code(` + + `))); + + project.processSources(); + + const { sources } = await handleModified(project); + + strictEqual(sources.size, 1); + strictEqual(sources.get(filename), code(` + + `)); + }); + + await test("skip adding removed translations to obsolete items if no translations exist", async () => { + const config = createConfig(testDir, { + src: ".", + prefix: "app.", + localize: { + div: { content: ElementContentLocalizationType.Text } + } + }); + const project = new Project({ config, development: true }); + + const filename1 = join(testDir, "test1.html"); + project.updateSource(AureliaTemplateFile.parse(filename1, code(` + + `))); + + const filename2 = join(testDir, "test2.html"); + project.updateSource(AureliaTemplateFile.parse(filename2, code(` + + `))); + + project.processSources(); + await handleModified(project); + + project.deleteSource(filename1); + project.updateSource(AureliaTemplateFile.parse(filename2, code(` + + `))); + + project.processSources(); + + const { translationData } = await handleModified(project); + strictEqual(translationData!.obsolete.length, 0); + }); + + await test("add removed translations to obsolete items if translations exist", async () => { + const config = createConfig(testDir, { + src: ".", + prefix: "app.", + localize: { + div: { content: ElementContentLocalizationType.Text } + } + }); + const project = new Project({ config, development: true }); + + const filename1 = join(testDir, "test1.html"); + project.updateSource(AureliaTemplateFile.parse(filename1, code(` + + `))); + + const filename2 = join(testDir, "test2.html"); + project.updateSource(AureliaTemplateFile.parse(filename2, code(` + + `))); + + project.processSources(); + await handleModified(project); + + project.translationData.files.get(filename1)!.content.get("app.test1.t0")!.translations.set("de", { + content: "Foo", + ignoreSpelling: [], + lastModified: Date.now() + }); + + project.translationData.files.get(filename2)!.content.get("app.test2.t0")!.translations.set("de", { + content: "Bar", + ignoreSpelling: [], + lastModified: Date.now() + }); + + project.deleteSource(filename1); + project.updateSource(AureliaTemplateFile.parse(filename2, code(` + + `))); + + project.processSources(); + + const { translationData } = await handleModified(project); + strictEqual(translationData!.obsolete.length, 2); + strictEqual(translationData!.obsolete[0].content, "bar"); + strictEqual(translationData!.obsolete[1].content, "foo"); + }); + + await test("use existing translations for reserved keys", async () => { + const config = createConfig(testDir, { + src: ".", + prefix: "app.", + localize: { + div: { content: ElementContentLocalizationType.Text } + } + }); + + const project = new Project({ + config, + development: true + }); + + const filename1 = join(testDir, "foo/test.html"); + project.updateSource(AureliaTemplateFile.parse(filename1, code(` + + `))); + + const filename2 = join(testDir, "bar/test.html"); + project.updateSource(AureliaTemplateFile.parse(filename2, code(` + + `))); + + project.translationData.files.set(filename2, { + content: new Map([ + ["app.test.t0", { + source: { + content: "test", + lastModified: Date.now(), + ignoreSpelling: [] + }, + translations: new Map([ + ["de", { + content: "translation", + lastModified: Date.now(), + ignoreSpelling: [] + }] + ]) + }] + ]) + }); + + project.processSources(); + + const { sources, translationData } = await handleModified(project); + + strictEqual(sources.size, 1); + strictEqual(sources.get(filename1), code(` + + `)); + + strictEqual(translationData!.files.get(filename1)!.content.get("app.test.t1")!.translations.has("de"), true); + }); + + await test("use existing translations for replaced prefixes", async () => { + const config = createConfig(testDir, { + src: ".", + prefix: "app.", + localize: { + div: { content: ElementContentLocalizationType.Text } + } + }); + + const project = new Project({ + config, + development: true + }); + + const filename1 = join(testDir, "test.html"); + project.updateSource(AureliaTemplateFile.parse(filename1, code(` + + `))); + + project.translationData.files.set(join(testDir, "foo.html"), { + content: new Map([ + ["app.foo.t0", { + source: { + content: "test", + lastModified: Date.now(), + ignoreSpelling: [] + }, + translations: new Map([ + ["de", { + content: "translation", + lastModified: Date.now(), + ignoreSpelling: [] + }] + ]) + }] + ]) + }); + + project.processSources(); + + const { sources, translationData } = await handleModified(project); + + strictEqual(sources.size, 1); + strictEqual(sources.get(filename1), code(` + + `)); + + strictEqual(translationData!.files.get(filename1)!.content.get("app.test.t0")!.translations.has("de"), true); + }); + + await test("prefixes", () => { + const config = createConfig(testDir, { src: "src", prefix: "app." }); + const project = new Project({ config }); + + function getPrefix(name: string) { + return project.getPrefix(join(testDir, name)); + } + + strictEqual(getPrefix("src/test.html"), "app.test."); + strictEqual(getPrefix("src/test/index.html"), "app.test."); + strictEqual(getPrefix("src/Test/index.html"), "app.test."); + strictEqual(getPrefix("src/foo-bar.html"), "app.foo-bar."); + strictEqual(getPrefix("src/fooBar.html"), "app.foo-bar."); + strictEqual(getPrefix("src/fooBarBaz.html"), "app.foo-bar-baz."); + strictEqual(getPrefix("src/fooBAR.html"), "app.foo-bar."); + strictEqual(getPrefix("src/foo.bar.html"), "app.foo.bar."); + }); +}); diff --git a/test/project.ts b/test/project.ts deleted file mode 100644 index c239f80..0000000 --- a/test/project.ts +++ /dev/null @@ -1,303 +0,0 @@ -import { join } from "node:path"; - -import test from "ava"; - -import { code, testDir, handleModified } from "./_utility.js"; -import { Project, createConfig, AureliaTemplateFile, ElementContentLocalizationType, TranslationData } from "../src/index.js"; - -test("justify sources and update translation data", async t => { - const config = createConfig(testDir, { - src: ".", - prefix: "app.", - localize: { - div: { content: ElementContentLocalizationType.Text } - } - }); - - const project = new Project({ - config, - development: true - }); - - const filename = join(testDir, "test.html"); - project.updateSource(AureliaTemplateFile.parse(filename, code(` - - `))); - - project.processSources(); - - const { sources, translationData } = await handleModified(project); - - t.is(sources.size, 1); - t.is(sources.get(filename), code(` - - `)); - - t.is(translationData!.files.get(filename)!.content.get("app.test.t0")!.source.content, "test"); -}); - -test("use fallback for unknown elements", async t => { - const config = createConfig(testDir, { - src: ".", - prefix: "app.", - localize: { - "*": { content: ElementContentLocalizationType.Text }, - "div": { }, - "input": { attributes: ["placeholder"] }, - } - }); - - const project = new Project({ - config, - development: true - }); - - const filename = join(testDir, "test.html"); - project.updateSource(AureliaTemplateFile.parse(filename, code(` - - `))); - - project.processSources(); - - const { sources } = await handleModified(project); - - t.is(sources.size, 1); - t.is(sources.get(filename), code(` - - `)); -}); - -test("skip adding removed translations to obsolete items if no translations exist", async t => { - const config = createConfig(testDir, { - src: ".", - prefix: "app.", - localize: { - div: { content: ElementContentLocalizationType.Text } - } - }); - const project = new Project({ config, development: true }); - - const filename1 = join(testDir, "test1.html"); - project.updateSource(AureliaTemplateFile.parse(filename1, code(` - - `))); - - const filename2 = join(testDir, "test2.html"); - project.updateSource(AureliaTemplateFile.parse(filename2, code(` - - `))); - - project.processSources(); - await handleModified(project); - - project.deleteSource(filename1); - project.updateSource(AureliaTemplateFile.parse(filename2, code(` - - `))); - - project.processSources(); - - const { translationData } = await handleModified(project); - t.is(translationData!.obsolete.length, 0); -}); - -test("add removed translations to obsolete items if translations exist", async t => { - const config = createConfig(testDir, { - src: ".", - prefix: "app.", - localize: { - div: { content: ElementContentLocalizationType.Text } - } - }); - const project = new Project({ config, development: true }); - - const filename1 = join(testDir, "test1.html"); - project.updateSource(AureliaTemplateFile.parse(filename1, code(` - - `))); - - const filename2 = join(testDir, "test2.html"); - project.updateSource(AureliaTemplateFile.parse(filename2, code(` - - `))); - - project.processSources(); - await handleModified(project); - - project.translationData.files.get(filename1)!.content.get("app.test1.t0")!.translations.set("de", { - content: "Foo", - ignoreSpelling: [], - lastModified: Date.now() - }); - - project.translationData.files.get(filename2)!.content.get("app.test2.t0")!.translations.set("de", { - content: "Bar", - ignoreSpelling: [], - lastModified: Date.now() - }); - - project.deleteSource(filename1); - project.updateSource(AureliaTemplateFile.parse(filename2, code(` - - `))); - - project.processSources(); - - const { translationData } = await handleModified(project); - t.is(translationData!.obsolete.length, 2); - t.is(translationData!.obsolete[0].content, "bar"); - t.is(translationData!.obsolete[1].content, "foo"); -}); - -test("use existing translations for reserved keys", async t => { - const config = createConfig(testDir, { - src: ".", - prefix: "app.", - localize: { - div: { content: ElementContentLocalizationType.Text } - } - }); - - const project = new Project({ - config, - development: true - }); - - const filename1 = join(testDir, "foo/test.html"); - project.updateSource(AureliaTemplateFile.parse(filename1, code(` - - `))); - - const filename2 = join(testDir, "bar/test.html"); - project.updateSource(AureliaTemplateFile.parse(filename2, code(` - - `))); - - project.translationData.files.set(filename2, { - content: new Map([ - ["app.test.t0", { - source: { - content: "test", - lastModified: Date.now(), - ignoreSpelling: [] - }, - translations: new Map([ - ["de", { - content: "translation", - lastModified: Date.now(), - ignoreSpelling: [] - }] - ]) - }] - ]) - }); - - project.processSources(); - - const { sources, translationData } = await handleModified(project); - - t.is(sources.size, 1); - t.is(sources.get(filename1), code(` - - `)); - - t.true(translationData!.files.get(filename1)!.content.get("app.test.t1")!.translations.has("de")); -}); - -test("use existing translations for replaced prefixes", async t => { - const config = createConfig(testDir, { - src: ".", - prefix: "app.", - localize: { - div: { content: ElementContentLocalizationType.Text } - } - }); - - const project = new Project({ - config, - development: true - }); - - const filename1 = join(testDir, "test.html"); - project.updateSource(AureliaTemplateFile.parse(filename1, code(` - - `))); - - project.translationData.files.set(join(testDir, "foo.html"), { - content: new Map([ - ["app.foo.t0", { - source: { - content: "test", - lastModified: Date.now(), - ignoreSpelling: [] - }, - translations: new Map([ - ["de", { - content: "translation", - lastModified: Date.now(), - ignoreSpelling: [] - }] - ]) - }] - ]) - }); - - project.processSources(); - - const { sources, translationData } = await handleModified(project); - - t.is(sources.size, 1); - t.is(sources.get(filename1), code(` - - `)); - - t.true(translationData!.files.get(filename1)!.content.get("app.test.t0")!.translations.has("de")); -}); - -test("prefixes", t => { - const config = createConfig(testDir, { src: "src", prefix: "app." }); - const project = new Project({ config }); - - function getPrefix(name: string) { - return project.getPrefix(join(testDir, name)); - } - - t.is(getPrefix("src/test.html"), "app.test."); - t.is(getPrefix("src/test/index.html"), "app.test."); - t.is(getPrefix("src/Test/index.html"), "app.test."); - t.is(getPrefix("src/foo-bar.html"), "app.foo-bar."); - t.is(getPrefix("src/fooBar.html"), "app.foo-bar."); - t.is(getPrefix("src/fooBarBaz.html"), "app.foo-bar-baz."); - t.is(getPrefix("src/fooBAR.html"), "app.foo-bar."); - t.is(getPrefix("src/foo.bar.html"), "app.foo.bar."); -}); diff --git a/test/translation-data.test.ts b/test/translation-data.test.ts new file mode 100644 index 0000000..5232581 --- /dev/null +++ b/test/translation-data.test.ts @@ -0,0 +1,123 @@ +import { TranslationData } from "@netatwork/aurelia-i18n-tools"; +import { strictEqual } from "node:assert"; +import { join } from "node:path"; +import test, { suite } from "node:test"; +import { testDir } from "./utility.js"; + +await suite("translation-data", async () => { + await test("parse v1", () => { + var data = TranslationData.parse(JSON.stringify( { + "src/test.html": { + content: { + "test.t0": { + content: "foo", + ignoreSpelling: [], + lastModified: "2020-06-17T08:04:10.519Z", + translations: {} + } + } + } + }), testDir); + + + strictEqual(data.parsedVersion, 1); + + const file = data.files.get(join(testDir, "src/test.html"))!; + strictEqual(file.content.has("test.t0"), true); + }); + + await test("parse v2", () => { + var data = TranslationData.parse(JSON.stringify( { + version: 2, + files: { + "src/test.html": { + content: { + "test.t0": { + content: "foo", + ignoreSpelling: [], + lastModified: "2020-06-17T08:04:10.519Z", + translations: { + "de": { + content: "bar", + ignoreSpelling: [], + lastModified: "2020-06-17T08:04:10.519Z" + } + } + } + } + } + }, + obsolete: [ + { + content: "bar", + translations: { + "de": "baz" + } + } + ] + }), testDir); + + strictEqual(data.parsedVersion, 2); + + const file = data.files.get(join(testDir, "src/test.html"))!; + strictEqual(file.content.get("test.t0")!.source.content, "foo"); + strictEqual(file.content.get("test.t0")!.translations.get("de")!.content, "bar"); + + strictEqual(data.obsolete.length, 1); + strictEqual(data.obsolete[0].content, "bar"); + strictEqual(data.obsolete[0].translations.get("de"), "baz"); + }); + + await test("stringify", () => { + var data = new TranslationData(new Map([ + [join(testDir, "src/test.html"), { + content: new Map([ + ["test.t0", { + source: { + content: "foo", + lastModified: Date.now(), + ignoreSpelling: [] + }, + translations: new Map([ + ["de", { + content: "bar", + lastModified: Date.now(), + ignoreSpelling: [] + }] + ]) + }] + ]) + }] + ]), [ + { + content: "bar", + translations: new Map([ + ["de", "baz"] + ]) + }, + { + content: "bar", + translations: new Map([ + ["de", "baz"] + ]) + }, + { + content: "bar", + translations: new Map([ + ["de", "foo"] + ]) + } + ]); + + const json: TranslationData.JsonV2 = JSON.parse(data.formatJson(testDir)); + strictEqual(json.version, 2); + strictEqual(json.files["src/test.html"].content["test.t0"].content, "foo"); + strictEqual(json.files["src/test.html"].content["test.t0"].translations["de"].content, "bar"); + + strictEqual(json.obsolete.length, 2); + strictEqual(json.obsolete[0].content, "bar"); + strictEqual(json.obsolete[0].translations["de"], "baz"); + strictEqual(json.obsolete[1].content, "bar"); + strictEqual(json.obsolete[1].translations["de"], "foo"); + }); +}); diff --git a/test/translation-data.ts b/test/translation-data.ts deleted file mode 100644 index 8610675..0000000 --- a/test/translation-data.ts +++ /dev/null @@ -1,119 +0,0 @@ -import test from "ava"; -import { join } from "path"; -import { TranslationData } from "../src/index.js"; -import { testDir } from "./_utility.js"; - -test("parse v1", t => { - var data = TranslationData.parse(JSON.stringify( { - "src/test.html": { - content: { - "test.t0": { - content: "foo", - ignoreSpelling: [], - lastModified: "2020-06-17T08:04:10.519Z", - translations: {} - } - } - } - }), testDir); - - t.is(data.parsedVersion, 1); - - const file = data.files.get(join(testDir, "src/test.html"))!; - t.true(file.content.has("test.t0")); -}); - -test("parse v2", t => { - var data = TranslationData.parse(JSON.stringify( { - version: 2, - files: { - "src/test.html": { - content: { - "test.t0": { - content: "foo", - ignoreSpelling: [], - lastModified: "2020-06-17T08:04:10.519Z", - translations: { - "de": { - content: "bar", - ignoreSpelling: [], - lastModified: "2020-06-17T08:04:10.519Z" - } - } - } - } - } - }, - obsolete: [ - { - content: "bar", - translations: { - "de": "baz" - } - } - ] - }), testDir); - - t.is(data.parsedVersion, 2); - - const file = data.files.get(join(testDir, "src/test.html"))!; - t.is(file.content.get("test.t0")!.source.content, "foo"); - t.is(file.content.get("test.t0")!.translations.get("de")!.content, "bar"); - - t.is(data.obsolete.length, 1); - t.is(data.obsolete[0].content, "bar"); - t.is(data.obsolete[0].translations.get("de"), "baz"); -}); - -test("stringify", t => { - var data = new TranslationData(new Map([ - [join(testDir, "src/test.html"), { - content: new Map([ - ["test.t0", { - source: { - content: "foo", - lastModified: Date.now(), - ignoreSpelling: [] - }, - translations: new Map([ - ["de", { - content: "bar", - lastModified: Date.now(), - ignoreSpelling: [] - }] - ]) - }] - ]) - }] - ]), [ - { - content: "bar", - translations: new Map([ - ["de", "baz"] - ]) - }, - { - content: "bar", - translations: new Map([ - ["de", "baz"] - ]) - }, - { - content: "bar", - translations: new Map([ - ["de", "foo"] - ]) - } - ]); - - const json: TranslationData.JsonV2 = JSON.parse(data.formatJson(testDir)); - t.is(json.version, 2); - t.is(json.files["src/test.html"].content["test.t0"].content, "foo"); - t.is(json.files["src/test.html"].content["test.t0"].translations["de"].content, "bar"); - - t.is(json.obsolete.length, 2); - t.is(json.obsolete[0].content, "bar"); - t.is(json.obsolete[0].translations["de"], "baz"); - t.is(json.obsolete[1].content, "bar"); - t.is(json.obsolete[1].translations["de"], "foo"); -}); diff --git a/test/_utility.ts b/test/utility.ts similarity index 82% rename from test/_utility.ts rename to test/utility.ts index 9f7f286..d7fae3a 100644 --- a/test/_utility.ts +++ b/test/utility.ts @@ -1,14 +1,11 @@ +import { Diagnostic, Diagnostics, Project, TranslationData } from "@netatwork/aurelia-i18n-tools"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; -import { ExecutionContext } from "ava"; - -import { Diagnostics, Diagnostic, Project, TranslationData } from "../src/index.js"; - -export function expectNoDiagnostics(t: ExecutionContext) { +export function expectNoDiagnostics() { const host = new Diagnostics(); host.on("report", diagnostic => { - t.fail(`Unexpected diagnostic: ${diagnostic.type}`); + throw new Error(`Unexpected diagnostic: ${diagnostic.type}`); }); return host; } diff --git a/tsconfig-test.json b/tsconfig-test.json index 59c4655..0a8f0e3 100644 --- a/tsconfig-test.json +++ b/tsconfig-test.json @@ -1,11 +1,11 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "rootDir": ".", - "outDir": "test_out" + "rootDir": "test", + "outDir": "test_out", + "sourceMap": true }, "include": [ - "src", "test" ] }