diff --git a/README.md b/README.md index 61c4bba8a..bfe73fddb 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,13 @@ npm run bench # Run with a custom label npm run bench -- --label my-optimization +# Filter templates by name (regex, case-insensitive) +npm run bench -- --grep "complex|recursive" + +# Run only specific sections (regex, case-insensitive) +npm run bench -- --section precompil +npm run bench -- --section "compilation|precompil" + # Compare results npm run bench:compare diff --git a/bin/handlebars.js b/bin/handlebars.mjs old mode 100755 new mode 100644 similarity index 83% rename from bin/handlebars.js rename to bin/handlebars.mjs index ee1156c85..bfe0c05b5 --- a/bin/handlebars.js +++ b/bin/handlebars.mjs @@ -1,7 +1,15 @@ #!/usr/bin/env node -const yargs = require('yargs') +import { createRequire } from 'node:module'; +import yargs from 'yargs'; + +const require = createRequire(import.meta.url); +const Precompiler = require('../dist/cjs/precompiler'); + +const parser = yargs(process.argv.slice(2)) .usage('Precompile handlebar templates.\nUsage: $0 [template|directory]...') + .help(false) + .version(false) .option('f', { type: 'string', description: 'Output File', @@ -105,19 +113,24 @@ const yargs = require('yargs') }) .wrap(120); -const argv = yargs.argv; +const argv = parser.parseSync(); argv.files = argv._; delete argv._; -const Precompiler = require('../dist/cjs/precompiler'); Precompiler.loadTemplates(argv, function (err, opts) { if (err) { throw err; } if (opts.help || (!opts.templates.length && !opts.version)) { - yargs.showHelp(); + parser.showHelp('log'); } else { - Precompiler.cli(opts); + // cli() is async (returns a Promise), so errors would become unhandled + // rejections. Re-throw via nextTick to surface them as uncaught exceptions. + Promise.resolve(Precompiler.cli(opts)).catch((error) => { + process.nextTick(() => { + throw error; + }); + }); } }); diff --git a/lib/handlebars/compiler/code-gen.js b/lib/handlebars/compiler/code-gen.js index fedfeeeb2..142425ea2 100644 --- a/lib/handlebars/compiler/code-gen.js +++ b/lib/handlebars/compiler/code-gen.js @@ -8,7 +8,12 @@ try { if (typeof define !== 'function' || !define.amd) { // We don't support this in AMD environments. For these environments, we assume that // they are running on the browser and thus have no need for the source-map library. - let SourceMap = require('source-map'); + // The variable indirection prevents bundlers from statically resolving and bundling + // source-map (which requires Node-built-ins). The stub SourceNode below handles + // browser/bundled usage. Bundlers may emit a "Critical dependency" warning — this + // is expected and harmless. + let mod = 'source-map'; + let SourceMap = require(mod); SourceNode = SourceMap.SourceNode; } // oxlint-disable-next-line no-unused-vars -- Babel 5 requires named catch param diff --git a/lib/precompiler.js b/lib/precompiler.js index 78eb3f9d7..92a657986 100644 --- a/lib/precompiler.js +++ b/lib/precompiler.js @@ -152,7 +152,7 @@ function loadFiles(opts, callback) { ); } -module.exports.cli = function (opts) { +module.exports.cli = async function (opts) { if (opts.version) { console.log(Handlebars.VERSION); return; @@ -221,7 +221,7 @@ module.exports.cli = function (opts) { output.add('{};\n'); } - opts.templates.forEach(function (template) { + for (const template of opts.templates) { let options = { knownHelpers: known, knownHelpersOnly: opts.o, @@ -238,11 +238,12 @@ module.exports.cli = function (opts) { // If we are generating a source map, we have to reconstruct the SourceNode object if (opts.map) { - let consumer = new SourceMapConsumer(precompiled.map); + let consumer = await new SourceMapConsumer(precompiled.map); precompiled = SourceNode.fromStringWithSourceMap( precompiled.code, consumer ); + consumer.destroy(); } if (opts.simple) { @@ -264,7 +265,7 @@ module.exports.cli = function (opts) { ');\n', ]); } - }); + } // Output the content if (!opts.simple) { diff --git a/package-lock.json b/package-lock.json index 4675c45e1..db79d4120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "dependencies": { "@handlebars/parser": "^2.1.0", "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "yargs": "^16.2.0" + "source-map": "^0.7.6", + "yargs": "^18.0.0" }, "bin": { "handlebars": "bin/handlebars.js" @@ -27,6 +27,7 @@ "@vitest/browser": "^4.0.18", "@vitest/browser-playwright": "^4.0.18", "@vitest/coverage-v8": "^4.0.18", + "cli-testlab": "^6.0.0", "concurrently": "^5.0.0", "eslint": "^10.0.3", "eslint-plugin-compat": "^7.0.1", @@ -38,7 +39,8 @@ "oxlint": "^1.51.0", "semver": "^5.0.1", "tinybench": "^6.0.0", - "typescript": "^3.4.3", + "tstyche": "^6.2.0", + "typescript": "^5.9.3", "uglify-js": "^3.19.3", "vitest": "^4.0.18" }, @@ -1892,29 +1894,6 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/@eslint/config-array/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1933,22 +1912,6 @@ } } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@eslint/config-helpers": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz", @@ -2063,7 +2026,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -2086,7 +2048,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -3722,6 +3683,7 @@ "integrity": "sha512-kT6yYo8xjKoDfM7iB8N9AmN9DJIlrs7UmQDbpTu1N4zaZocN1/t2fIAWOKjr5+3eJlZQR2twKZhDVHNLbLPjOw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.8", @@ -5355,16 +5317,6 @@ "node": ">=8" } }, - "node_modules/@swc/cli/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, "node_modules/@swc/core": { "version": "1.15.18", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.18.tgz", @@ -5372,6 +5324,7 @@ "dev": true, "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.25" @@ -5709,11 +5662,6 @@ "node": ">=12" } }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -5936,6 +5884,7 @@ "integrity": "sha512-gVQqh7paBz3gC+ZdcCmNSWJMk70IUjDeVqi+5m5vYpEHsIwRgw3Y545jljtajhkekIpIp5Gg8oK7bctgY0E2Ng==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/mocker": "4.0.18", "@vitest/utils": "4.0.18", @@ -6654,6 +6603,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6773,23 +6723,24 @@ } }, "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==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - }, + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -6918,6 +6869,7 @@ "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "peerDependencies": { "bare-abort-controller": "*" }, @@ -7381,6 +7333,29 @@ "dev": true, "license": "MIT" }, + "node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -7401,6 +7376,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7430,8 +7406,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/bundle-name": { "version": "4.1.0", @@ -7648,6 +7623,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-testlab": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cli-testlab/-/cli-testlab-6.0.0.tgz", + "integrity": "sha512-FkV22JAlG5KpxLmqjTdapgS+jcM+42RjsZhy+Q30gMk1d6Gb3yeXGvYrnqcLOf4RGO8KLJJBqYkdViUXdX0Pwg==", + "dev": true, + "dependencies": { + "glob": "^13.0.6", + "rimraf": "^6.1.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/cli-truncate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", @@ -7665,19 +7653,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/cli-truncate/node_modules/string-width": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", @@ -7695,48 +7670,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.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==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", "dependencies": { - "color-name": "~1.1.4" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=20" } }, - "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==" - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -7749,8 +7696,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/compressible": { "version": "2.0.18", @@ -8321,9 +8267,10 @@ "license": "ISC" }, "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==" + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" }, "node_modules/end-of-stream": { "version": "1.4.4", @@ -8468,6 +8415,7 @@ "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", @@ -8663,29 +8611,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/eslint/node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -8801,22 +8726,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/eslint/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -9515,7 +9424,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -9575,6 +9483,24 @@ "node": ">=6" } }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -10022,14 +9948,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "engines": { - "node": ">=8" - } - }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -10288,39 +10206,6 @@ "node": ">=20.0.0" } }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, "node_modules/listr2/node_modules/eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", @@ -10328,58 +10213,6 @@ "dev": true, "license": "MIT" }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -10425,39 +10258,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, "node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", @@ -10491,58 +10291,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -10556,6 +10304,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -11114,7 +10872,8 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/merge-descriptors": { "version": "1.0.3", @@ -11220,6 +10979,32 @@ "dev": true, "license": "ISC" }, + "node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mock-stdin": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/mock-stdin/-/mock-stdin-0.3.1.tgz", @@ -11618,6 +11403,13 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -11680,6 +11472,23 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -11996,6 +11805,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -12109,6 +11919,26 @@ "dev": true, "license": "MIT" }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.59.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", @@ -12243,6 +12073,7 @@ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -12716,19 +12547,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", @@ -12797,11 +12615,12 @@ } }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">= 12" } }, "node_modules/source-map-js": { @@ -13002,27 +12821,35 @@ } }, "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==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "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==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-dirs": { @@ -13139,7 +12966,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -13153,6 +12979,17 @@ "node": ">=10" } }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/terser/node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -13160,7 +12997,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -13250,6 +13086,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13375,6 +13212,30 @@ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", "dev": true }, + "node_modules/tstyche": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tstyche/-/tstyche-6.2.0.tgz", + "integrity": "sha512-WBiB6fGGsmQCFFRGwYaKq528pCLJ0CUUdrIdUm2rnVJ1Ineskbrv9uQADWsD3uHndEV/Hesdx1Gj8PdkBahxlQ==", + "dev": true, + "license": "MIT", + "bin": { + "tstyche": "dist/bin.js" + }, + "engines": { + "node": ">=22.12" + }, + "funding": { + "url": "https://github.com/tstyche/tstyche?sponsor=1" + }, + "peerDependencies": { + "typescript": ">=5.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -13403,16 +13264,18 @@ } }, "node_modules/typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uglify-js": { @@ -13593,6 +13456,7 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -13686,6 +13550,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13699,6 +13564,7 @@ "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", @@ -14001,16 +13867,17 @@ } }, "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==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -14077,28 +13944,29 @@ } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=10" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", "engines": { - "node": ">=10" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs/node_modules/y18n": { @@ -15515,21 +15383,6 @@ "minimatch": "^10.2.4" }, "dependencies": { - "balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true - }, - "brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, - "requires": { - "balanced-match": "^4.0.2" - } - }, "debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -15538,15 +15391,6 @@ "requires": { "ms": "^2.1.3" } - }, - "minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, - "requires": { - "brace-expansion": "^5.0.2" - } } } }, @@ -15623,7 +15467,6 @@ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -15641,7 +15484,6 @@ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -16449,6 +16291,7 @@ "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.7.8.tgz", "integrity": "sha512-kT6yYo8xjKoDfM7iB8N9AmN9DJIlrs7UmQDbpTu1N4zaZocN1/t2fIAWOKjr5+3eJlZQR2twKZhDVHNLbLPjOw==", "dev": true, + "peer": true, "requires": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.8", @@ -17723,12 +17566,6 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true - }, - "source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true } } }, @@ -17737,6 +17574,7 @@ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.18.tgz", "integrity": "sha512-z87aF9GphWp//fnkRsqvtY+inMVPgYW3zSlXH1kJFvRT5H/wiAn+G32qW5l3oEk63KSF1x3Ov0BfHCObAmT8RA==", "dev": true, + "peer": true, "requires": { "@swc/core-darwin-arm64": "1.15.18", "@swc/core-darwin-x64": "1.15.18", @@ -17930,11 +17768,6 @@ } } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, "@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -18135,6 +17968,7 @@ "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.18.tgz", "integrity": "sha512-gVQqh7paBz3gC+ZdcCmNSWJMk70IUjDeVqi+5m5vYpEHsIwRgw3Y545jljtajhkekIpIp5Gg8oK7bctgY0E2Ng==", "dev": true, + "peer": true, "requires": { "@vitest/mocker": "4.0.18", "@vitest/utils": "4.0.18", @@ -18596,7 +18430,8 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -18671,18 +18506,14 @@ "dev": true }, "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" }, "anymatch": { "version": "3.1.3", @@ -18777,6 +18608,7 @@ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "dev": true, + "peer": true, "requires": {} }, "bare-fs": { @@ -19080,11 +18912,29 @@ "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", "dev": true }, + "brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "requires": { + "balanced-match": "^4.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true + } + } + }, "browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, + "peer": true, "requires": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -19104,8 +18954,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "bundle-name": { "version": "4.1.0", @@ -19255,6 +19104,16 @@ "restore-cursor": "^5.0.0" } }, + "cli-testlab": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cli-testlab/-/cli-testlab-6.0.0.tgz", + "integrity": "sha512-FkV22JAlG5KpxLmqjTdapgS+jcM+42RjsZhy+Q30gMk1d6Gb3yeXGvYrnqcLOf4RGO8KLJJBqYkdViUXdX0Pwg==", + "dev": true, + "requires": { + "glob": "^13.0.6", + "rimraf": "^6.1.3" + } + }, "cli-truncate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", @@ -19265,12 +19124,6 @@ "string-width": "^8.2.0" }, "dependencies": { - "ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true - }, "string-width": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", @@ -19280,41 +19133,19 @@ "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } - }, - "strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "requires": { - "ansi-regex": "^6.2.2" - } } } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "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==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "requires": { - "color-name": "~1.1.4" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" } }, - "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==" - }, "colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -19326,8 +19157,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "compressible": { "version": "2.0.18", @@ -19764,9 +19594,9 @@ "dev": true }, "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==" + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" }, "end-of-stream": { "version": "1.4.4", @@ -19875,6 +19705,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", @@ -19908,21 +19739,6 @@ "optionator": "^0.9.3" }, "dependencies": { - "balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true - }, - "brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, - "requires": { - "balanced-match": "^4.0.2" - } - }, "cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -19992,15 +19808,6 @@ "p-locate": "^5.0.0" } }, - "minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, - "requires": { - "brace-expansion": "^5.0.2" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -20551,8 +20358,7 @@ "get-east-asian-width": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", - "dev": true + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==" }, "get-intrinsic": { "version": "1.3.0", @@ -20591,6 +20397,17 @@ "pump": "^3.0.0" } }, + "glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "requires": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + } + }, "gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -20916,11 +20733,6 @@ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true }, - "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==" - }, "is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -21110,60 +20922,11 @@ "wrap-ansi": "^9.0.0" }, "dependencies": { - "ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true - }, - "emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true - }, "eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "dev": true - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "requires": { - "ansi-regex": "^6.2.2" - } - }, - "wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "requires": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - } } } }, @@ -21201,24 +20964,6 @@ "wrap-ansi": "^9.0.0" }, "dependencies": { - "ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true - }, - "emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true - }, "is-fullwidth-code-point": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", @@ -21237,37 +20982,6 @@ "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "requires": { - "ansi-regex": "^6.2.2" - } - }, - "wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "requires": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - } } } }, @@ -21277,6 +20991,12 @@ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", "dev": true }, + "lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true + }, "magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -21569,7 +21289,8 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true + "dev": true, + "peer": true } } }, @@ -21636,6 +21357,21 @@ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, + "minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "requires": { + "brace-expansion": "^5.0.2" + } + }, + "minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true + }, "mock-stdin": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/mock-stdin/-/mock-stdin-0.3.1.tgz", @@ -21902,6 +21638,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -21942,6 +21684,16 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "requires": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + } + }, "path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -22160,7 +21912,8 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-from-string": { "version": "2.0.2", @@ -22236,6 +21989,16 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, + "rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "requires": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + } + }, "rollup": { "version": "4.59.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", @@ -22321,6 +22084,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -22665,12 +22429,6 @@ "is-fullwidth-code-point": "^5.1.0" }, "dependencies": { - "ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true - }, "is-fullwidth-code-point": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", @@ -22723,9 +22481,9 @@ } }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" }, "source-map-js": { "version": "1.2.1", @@ -22890,21 +22648,21 @@ "dev": true }, "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==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" } }, "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "requires": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.2.2" } }, "strip-dirs": { @@ -22986,7 +22744,6 @@ "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "optional": true, - "peer": true, "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -22994,13 +22751,19 @@ "source-map-support": "~0.5.20" }, "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -23062,7 +22825,8 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true + "dev": true, + "peer": true } } }, @@ -23138,6 +22902,13 @@ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", "dev": true }, + "tstyche": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tstyche/-/tstyche-6.2.0.tgz", + "integrity": "sha512-WBiB6fGGsmQCFFRGwYaKq528pCLJ0CUUdrIdUm2rnVJ1Ineskbrv9uQADWsD3uHndEV/Hesdx1Gj8PdkBahxlQ==", + "dev": true, + "requires": {} + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -23158,10 +22929,11 @@ } }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "peer": true }, "uglify-js": { "version": "3.19.3", @@ -23273,6 +23045,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, + "peer": true, "requires": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -23294,7 +23067,8 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true + "dev": true, + "peer": true } } }, @@ -23303,6 +23077,7 @@ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, + "peer": true, "requires": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", @@ -23470,13 +23245,13 @@ "dev": true }, "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==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" } }, "wrappy": { @@ -23518,17 +23293,16 @@ "dev": true }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "requires": { - "cliui": "^7.0.2", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^22.0.0" }, "dependencies": { "y18n": { @@ -23539,9 +23313,9 @@ } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==" }, "yauzl": { "version": "3.2.0", diff --git a/package.json b/package.json index 745921162..856466cb8 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "url": "https://github.com/handlebars-lang/handlebars.js.git" }, "bin": { - "handlebars": "bin/handlebars.js" + "handlebars": "bin/handlebars.mjs" }, "files": [ "bin", @@ -42,7 +42,7 @@ "lint": "npm run lint:oxlint && npm run lint:format && npm run lint:types && npm run lint:compat", "lint:oxlint": "oxlint --max-warnings 0 .", "lint:format": "oxfmt --check .", - "lint:types": "tsc --noEmit --project types", + "lint:types": "tsc --noEmit --project types && tstyche", "lint:compat": "eslint", "test": "npm run build && vitest run --project node --project tasks --project rspack --coverage", "test:browser": "vitest run --project browser", @@ -60,8 +60,8 @@ "dependencies": { "@handlebars/parser": "^2.1.0", "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "yargs": "^16.2.0" + "source-map": "^0.7.6", + "yargs": "^18.0.0" }, "devDependencies": { "@aws-sdk/client-s3": "^3.1011.0", @@ -73,6 +73,7 @@ "@vitest/browser": "^4.0.18", "@vitest/browser-playwright": "^4.0.18", "@vitest/coverage-v8": "^4.0.18", + "cli-testlab": "^6.0.0", "concurrently": "^5.0.0", "eslint": "^10.0.3", "eslint-plugin-compat": "^7.0.1", @@ -84,7 +85,8 @@ "oxlint": "^1.51.0", "semver": "^5.0.1", "tinybench": "^6.0.0", - "typescript": "^3.4.3", + "tstyche": "^6.2.0", + "typescript": "^5.9.3", "uglify-js": "^3.19.3", "vitest": "^4.0.18" }, diff --git a/spec/expected/help.menu.txt b/spec/expected/help.menu.txt index 750aa30cd..824278356 100644 --- a/spec/expected/help.menu.txt +++ b/spec/expected/help.menu.txt @@ -1,10 +1,9 @@ Precompile handlebar templates. -Usage: handlebars.js [template|directory]... +Usage: handlebars.mjs [template|directory]... Options: - --help Outputs this message [boolean] -f, --output Output File [string] - --map Source Map File [string] + --map Source Map File [string] -a, --amd Exports amd style (require.js) [boolean] -c, --commonjs Exports CommonJS style, path to Handlebars module [string] [default: null] -h, --handlebarPath Path to handlebar.js (only valid for amd-style) [string] [default: ""] @@ -22,4 +21,5 @@ Options: -d, --data Include data when compiling [boolean] -e, --extension Template extension. [string] [default: "handlebars"] -b, --bom Removes the BOM (Byte Order Mark) from the beginning of the templates. [boolean] - -v, --version Show version number [boolean] \ No newline at end of file + -v, --version Prints the current compiler version [boolean] + --help Outputs this message [boolean] \ No newline at end of file diff --git a/spec/precompiler.js b/spec/precompiler.js index 0339270e2..ac4a290e1 100644 --- a/spec/precompiler.js +++ b/spec/precompiler.js @@ -33,7 +33,7 @@ describe('precompiler', function () { * @param {Error} loadError the error that should be thrown if uglify is loaded * @param {function} callback a callback-function to run when the mock is active. */ - function mockRequireUglify(loadError, callback) { + async function mockRequireUglify(loadError, callback) { var Module = require('module'); var _resolveFilename = Module._resolveFilename; delete require.cache[require.resolve('uglify-js')]; @@ -45,7 +45,7 @@ describe('precompiler', function () { return _resolveFilename.call(this, request, mod); }; try { - callback(); + await callback(); } finally { Module._resolveFilename = _resolveFilename; delete require.cache[require.resolve('uglify-js')]; @@ -83,72 +83,75 @@ describe('precompiler', function () { console.error = errorLogFunction; }); - it('should output version', function () { - Precompiler.cli({ templates: [], version: true }); + it('should output version', async function () { + await Precompiler.cli({ templates: [], version: true }); expect(log).toBe(Handlebars.VERSION); }); - it('should throw if lacking templates', function () { - expect(function () { - Precompiler.cli({ templates: [] }); - }).toThrow('Must define at least one template or directory.'); + it('should throw if lacking templates', async function () { + await expect(Precompiler.cli({ templates: [] })).rejects.toThrow( + 'Must define at least one template or directory.' + ); }); - it('should handle empty/filtered directories', function () { - Precompiler.cli({ hasDirectory: true, templates: [] }); + it('should handle empty/filtered directories', async function () { + Handlebars.precompile = function () { + return 'simple'; + }; + await Precompiler.cli({ hasDirectory: true, templates: [] }); // Success is not throwing }); - it('should throw when combining simple and minimized', function () { - expect(function () { - Precompiler.cli({ templates: [__dirname], simple: true, min: true }); - }).toThrow('Unable to minimize simple output'); + it('should throw when combining simple and minimized', async function () { + await expect( + Precompiler.cli({ templates: [__dirname], simple: true, min: true }) + ).rejects.toThrow('Unable to minimize simple output'); }); - it('should throw when combining simple and multiple templates', function () { - expect(function () { + it('should throw when combining simple and multiple templates', async function () { + await expect( Precompiler.cli({ templates: [ __dirname + '/artifacts/empty.handlebars', __dirname + '/artifacts/empty.handlebars', ], simple: true, - }); - }).toThrow('Unable to output multiple templates in simple mode'); + }) + ).rejects.toThrow('Unable to output multiple templates in simple mode'); }); - it('should throw when missing name', function () { - expect(function () { - Precompiler.cli({ templates: [{ source: '' }], amd: true }); - }).toThrow('Name missing for template'); + it('should throw when missing name', async function () { + await expect( + Precompiler.cli({ templates: [{ source: '' }], amd: true }) + ).rejects.toThrow('Name missing for template'); }); - it('should throw when combining simple and directories', function () { - expect(function () { - Precompiler.cli({ hasDirectory: true, templates: [1], simple: true }); - }).toThrow('Unable to output multiple templates in simple mode'); + it('should throw when combining simple and directories', async function () { + await expect( + Precompiler.cli({ hasDirectory: true, templates: [1], simple: true }) + ).rejects.toThrow('Unable to output multiple templates in simple mode'); }); - it('should output simple templates', function () { + it('should output simple templates', async function () { Handlebars.precompile = function () { return 'simple'; }; - Precompiler.cli({ templates: [emptyTemplate], simple: true }); + await Precompiler.cli({ templates: [emptyTemplate], simple: true }); expect(log).toBe('simple\n'); }); - it('should default to simple templates', function () { + it('should default to simple templates', async function () { Handlebars.precompile = function () { return 'simple'; }; - Precompiler.cli({ templates: [{ source: '' }] }); + await Precompiler.cli({ templates: [{ source: '' }] }); expect(log).toBe('simple\n'); }); - it('should output amd templates', function () { + it('should output amd templates', async function () { Handlebars.precompile = function () { return 'amd'; }; - Precompiler.cli({ templates: [emptyTemplate], amd: true }); + await Precompiler.cli({ templates: [emptyTemplate], amd: true }); expect(log).toMatch(/template\(amd\)/); }); - it('should output multiple amd', function () { + it('should output multiple amd', async function () { Handlebars.precompile = function () { return 'amd'; }; - Precompiler.cli({ + await Precompiler.cli({ templates: [emptyTemplate, emptyTemplate], amd: true, namespace: 'foo', @@ -157,19 +160,23 @@ describe('precompiler', function () { expect(log).toMatch(/return templates/); expect(log).toMatch(/template\(amd\)/); }); - it('should output amd partials', function () { + it('should output amd partials', async function () { Handlebars.precompile = function () { return 'amd'; }; - Precompiler.cli({ templates: [emptyTemplate], amd: true, partial: true }); + await Precompiler.cli({ + templates: [emptyTemplate], + amd: true, + partial: true, + }); expect(log).toMatch(/return Handlebars\.partials\['empty'\]/); expect(log).toMatch(/template\(amd\)/); }); - it('should output multiple amd partials', function () { + it('should output multiple amd partials', async function () { Handlebars.precompile = function () { return 'amd'; }; - Precompiler.cli({ + await Precompiler.cli({ templates: [emptyTemplate, emptyTemplate], amd: true, partial: true, @@ -177,36 +184,44 @@ describe('precompiler', function () { expect(log).not.toMatch(/return Handlebars\.partials\[/); expect(log).toMatch(/template\(amd\)/); }); - it('should output commonjs templates', function () { + it('should output commonjs templates', async function () { Handlebars.precompile = function () { return 'commonjs'; }; - Precompiler.cli({ templates: [emptyTemplate], commonjs: true }); + await Precompiler.cli({ templates: [emptyTemplate], commonjs: true }); expect(log).toMatch(/template\(commonjs\)/); }); - it('should set data flag', function () { + it('should set data flag', async function () { Handlebars.precompile = function (data, options) { expect(options.data).toBe(true); return 'simple'; }; - Precompiler.cli({ templates: [emptyTemplate], simple: true, data: true }); + await Precompiler.cli({ + templates: [emptyTemplate], + simple: true, + data: true, + }); expect(log).toBe('simple\n'); }); - it('should set known helpers', function () { + it('should set known helpers', async function () { Handlebars.precompile = function (data, options) { expect(options.knownHelpers.foo).toBe(true); return 'simple'; }; - Precompiler.cli({ templates: [emptyTemplate], simple: true, known: 'foo' }); + await Precompiler.cli({ + templates: [emptyTemplate], + simple: true, + known: 'foo', + }); expect(log).toBe('simple\n'); }); - it('should output to file system', function () { + it('should output to file system', async function () { Handlebars.precompile = function () { return 'simple'; }; - Precompiler.cli({ + await Precompiler.cli({ templates: [emptyTemplate], simple: true, output: 'file!', @@ -216,53 +231,53 @@ describe('precompiler', function () { expect(log).toBe(''); }); - it('should output minimized templates', function () { + it('should output minimized templates', async function () { Handlebars.precompile = function () { return 'amd'; }; uglify.minify = function () { return { code: 'min' }; }; - Precompiler.cli({ templates: [emptyTemplate], min: true }); + await Precompiler.cli({ templates: [emptyTemplate], min: true }); expect(log).toBe('min'); }); - it('should omit minimization gracefully, if uglify-js is missing', function () { + it('should omit minimization gracefully, if uglify-js is missing', async function () { var error = new Error("Cannot find module 'uglify-js'"); error.code = 'MODULE_NOT_FOUND'; - mockRequireUglify(error, function () { + await mockRequireUglify(error, async function () { var Precompiler = require('../dist/cjs/precompiler'); Handlebars.precompile = function () { return 'amd'; }; - Precompiler.cli({ templates: [emptyTemplate], min: true }); + await Precompiler.cli({ templates: [emptyTemplate], min: true }); expect(log).toMatch(/template\(amd\)/); expect(log).toMatch(/\n/); expect(errorLog).toMatch(/Code minimization is disabled/); }); }); - it('should fail on errors (other than missing module) while loading uglify-js', function () { - mockRequireUglify(new Error('Mock Error'), function () { - expect(function () { - var Precompiler = require('../dist/cjs/precompiler'); - Handlebars.precompile = function () { - return 'amd'; - }; - Precompiler.cli({ templates: [emptyTemplate], min: true }); - }).toThrow('Mock Error'); + it('should fail on errors (other than missing module) while loading uglify-js', async function () { + await mockRequireUglify(new Error('Mock Error'), async function () { + var Precompiler = require('../dist/cjs/precompiler'); + Handlebars.precompile = function () { + return 'amd'; + }; + await expect( + Precompiler.cli({ templates: [emptyTemplate], min: true }) + ).rejects.toThrow('Mock Error'); }); }); - it('should output map', function () { - Precompiler.cli({ templates: [emptyTemplate], map: 'foo.js.map' }); + it('should output map', async function () { + await Precompiler.cli({ templates: [emptyTemplate], map: 'foo.js.map' }); expect(file).toBe('foo.js.map'); expect(log.match(/sourceMappingURL=/g).length).toBe(1); }); - it('should output map', function () { - Precompiler.cli({ + it('should output map with minification', async function () { + await Precompiler.cli({ templates: [emptyTemplate], min: true, map: 'foo.js.map', diff --git a/spec/source-map.js b/spec/source-map.js index 0a4280695..4565c3f0e 100644 --- a/spec/source-map.js +++ b/spec/source-map.js @@ -25,7 +25,7 @@ describe('source-map', function () { expect(template.map).toBeTruthy(); } }); - it('should map source properly', function () { + it('should map source properly', async function () { var templateSource = ' b{{hello}} \n {{bar}}a {{#block arg hash=(subex 1 subval)}}{{/block}}', template = Handlebars.precompile(templateSource, { @@ -34,7 +34,7 @@ describe('source-map', function () { }); if (template.map) { - var consumer = new SourceMapConsumer(template.map), + var consumer = await new SourceMapConsumer(template.map), lines = template.code.split('\n'), srcLines = templateSource.split('\n'), generated = grepLine('" b"', lines), @@ -43,6 +43,7 @@ describe('source-map', function () { var mapped = consumer.originalPositionFor(generated); expect(mapped.line).toBe(source.line); expect(mapped.column).toBe(source.column); + consumer.destroy(); } }); }); diff --git a/tasks/tests/bin.test.js b/tasks/tests/bin.test.js deleted file mode 100644 index daf21b5e4..000000000 --- a/tasks/tests/bin.test.js +++ /dev/null @@ -1,256 +0,0 @@ -const childProcess = require('child_process'); -const fs = require('fs'); -const os = require('os'); -const path = require('path'); - -const testCases = [ - { - binInputParameters: ['-a', 'spec/artifacts/empty.handlebars'], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.amd.js', - }, - { - binInputParameters: [ - '-a', - '-f', - 'TEST_OUTPUT', - 'spec/artifacts/empty.handlebars', - ], - outputLocation: 'TEST_OUTPUT', - expectedOutputSpec: './spec/expected/empty.amd.js', - }, - { - binInputParameters: [ - '-a', - '-n', - 'CustomNamespace.templates', - 'spec/artifacts/empty.handlebars', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.amd.namespace.js', - }, - { - binInputParameters: [ - '-a', - '--namespace', - 'CustomNamespace.templates', - 'spec/artifacts/empty.handlebars', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.amd.namespace.js', - }, - { - binInputParameters: ['-a', '-s', 'spec/artifacts/empty.handlebars'], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.amd.simple.js', - }, - { - binInputParameters: ['-a', '-m', 'spec/artifacts/empty.handlebars'], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.amd.min.js', - }, - { - binInputParameters: [ - 'spec/artifacts/known.helpers.handlebars', - '-a', - '-k', - 'someHelper', - '-k', - 'anotherHelper', - '-o', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/non.empty.amd.known.helper.js', - }, - { - binInputParameters: ['--help'], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/help.menu.txt', - }, - { - binInputParameters: ['-v'], - outputLocation: 'stdout', - expectedOutput: require('../../package.json').version, - }, - { - binInputParameters: [ - '-a', - '-e', - 'hbs', - './spec/artifacts/non.default.extension.hbs', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/non.default.extension.amd.js', - }, - { - binInputParameters: [ - '-a', - '-p', - './spec/artifacts/partial.template.handlebars', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/partial.template.js', - }, - { - binInputParameters: ['spec/artifacts/empty.handlebars', '-c'], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.common.js', - }, - { - binInputParameters: [ - 'spec/artifacts/empty.handlebars', - 'spec/artifacts/empty.handlebars', - '-a', - '-n', - 'someNameSpace', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/namespace.amd.js', - }, - { - binInputParameters: [ - 'spec/artifacts/empty.handlebars', - '-h', - 'some-path/', - '-a', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/handlebar.path.amd.js', - }, - { - binInputParameters: [ - 'spec/artifacts/partial.template.handlebars', - '-r', - 'spec', - '-a', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.root.amd.js', - }, - { - binInputParameters: [ - '-i', - '
1
', - '-i', - '
2
', - '-N', - 'firstTemplate', - '-N', - 'secondTemplate', - '-a', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.name.amd.js', - }, - { - binInputParameters: [ - '-i', - '
1
', - '-a', - '-m', - '-N', - 'test', - '--map', - './spec/tmp/source.map.amd.txt', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/source.map.amd.js', - }, - { - binInputParameters: ['./spec/artifacts/bom.handlebars', '-b', '-a'], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/bom.amd.js', - }, - // Issue #1673 - { - binInputParameters: [ - '--amd', - '--no-amd', - 'spec/artifacts/empty.handlebars', - ], - outputLocation: 'stdout', - expectedOutputSpec: './spec/expected/empty.common.js', - }, -]; - -expect.extend({ - toEqualWithRelaxedSpace(received, expected) { - const normalize = (str) => - typeof str === 'string' - ? str - .replace(/\r\n/g, '\n') - .split('\n') - .map((line) => line.replace(/\s+/g, ' ').trim()) - .filter((line) => line.length > 0) - .join('\n') - .trim() - : str; - - const normalizedReceived = normalize(received); - const normalizedExpected = normalize(expected); - const pass = normalizedReceived === normalizedExpected; - - return { - pass, - message: () => - `Expected output to match with relaxed whitespace.\n\n` + - `Expected:\n${normalizedExpected}\n\nReceived:\n${normalizedReceived}`, - }; - }, -}); - -describe('bin/handlebars', function () { - testCases.forEach( - ( - { - binInputParameters, - outputLocation, - expectedOutputSpec, - expectedOutput, - }, - index - ) => { - it(`test case ${index}: handlebars ${binInputParameters.join( - ' ' - )}`, function () { - const stdout = executeBinHandlebars(...binInputParameters); - - if (!expectedOutput && expectedOutputSpec) { - expectedOutput = fs.readFileSync(expectedOutputSpec, 'utf-8'); - } - - const useStdout = outputLocation === 'stdout'; - const actualOutput = useStdout - ? stdout - : fs.readFileSync(outputLocation, 'utf-8'); - - if (!useStdout) { - fs.unlinkSync(outputLocation); - } - - expect(actualOutput).toEqualWithRelaxedSpace(expectedOutput); - }); - } - ); -}); - -// helper functions - -function executeBinHandlebars(...args) { - if (os.platform() === 'win32') { - // On Windows, the executable handlebars.js file cannot be run directly - const nodeJs = process.argv[0]; - return execFilesSyncUtf8(nodeJs, ['./bin/handlebars.js'].concat(args)); - } - return execFilesSyncUtf8('./bin/handlebars.js', args); -} - -function execFilesSyncUtf8(command, args) { - const env = process.env; - env.PATH = addPathToNodeJs(env.PATH); - return childProcess.execFileSync(command, args, { encoding: 'utf-8', env }); -} - -function addPathToNodeJs(pathEnvironment) { - return path.dirname(process.argv0) + path.delimiter + pathEnvironment; -} diff --git a/tasks/tests/cli.test.js b/tasks/tests/cli.test.js new file mode 100644 index 000000000..0b7edb5a4 --- /dev/null +++ b/tasks/tests/cli.test.js @@ -0,0 +1,274 @@ +const fs = require('fs'); +const { exec } = require('child_process'); +const { execCommand, FileTestHelper } = require('cli-testlab'); +const Handlebars = require('../../lib'); + +const cli = 'node ./bin/handlebars.mjs'; + +expect.extend({ + toEqualWithRelaxedSpace(received, expected) { + const normalize = (str) => + typeof str === 'string' + ? str + .replace(/\r\n/g, '\n') + .split('\n') + .map((line) => line.replace(/\s+/g, ' ').trim()) + .filter((line) => line.length > 0) + .join('\n') + .trim() + : str; + + const normalizedReceived = normalize(received); + const normalizedExpected = normalize(expected); + const pass = normalizedReceived === normalizedExpected; + + return { + pass, + message: () => + `Expected output to match with relaxed whitespace.\n\n` + + `Expected:\n${normalizedExpected}\n\nReceived:\n${normalizedReceived}`, + }; + }, +}); + +function expectedFile(specPath) { + return fs.readFileSync(specPath, 'utf-8'); +} + +describe('bin/handlebars', function () { + describe('help and version', function () { + it('--help displays help menu', async function () { + const result = await execCommand(`${cli} --help`); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/help.menu.txt') + ); + }); + + it('no arguments displays help menu', async function () { + const result = await execCommand(`${cli}`); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/help.menu.txt') + ); + }); + + it('-v prints the compiler version', async function () { + await execCommand(`${cli} -v`, { + expectedOutput: Handlebars.VERSION, + }); + }); + }); + + describe('AMD output', function () { + it('-a produces AMD output', async function () { + const result = await execCommand( + `${cli} -a spec/artifacts/empty.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.amd.js') + ); + }); + + it('-a -s produces simple AMD output', async function () { + const result = await execCommand( + `${cli} -a -s spec/artifacts/empty.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.amd.simple.js') + ); + }); + + it('-a -m produces minified AMD output', async function () { + const result = await execCommand( + `${cli} -a -m spec/artifacts/empty.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.amd.min.js') + ); + }); + }); + + describe('CommonJS output', function () { + it('-c produces CommonJS output', async function () { + const result = await execCommand( + `${cli} spec/artifacts/empty.handlebars -c` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.common.js') + ); + }); + }); + + describe('namespace', function () { + it('-n sets custom namespace', async function () { + const result = await execCommand( + `${cli} -a -n CustomNamespace.templates spec/artifacts/empty.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.amd.namespace.js') + ); + }); + + it('--namespace sets custom namespace', async function () { + const result = await execCommand( + `${cli} -a --namespace CustomNamespace.templates spec/artifacts/empty.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.amd.namespace.js') + ); + }); + + it('multiple files share a namespace', async function () { + const result = await execCommand( + `${cli} spec/artifacts/empty.handlebars spec/artifacts/empty.handlebars -a -n someNameSpace` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/namespace.amd.js') + ); + }); + }); + + describe('file output', function () { + let files; + + beforeEach(function () { + files = new FileTestHelper({ basePath: '.' }); + files.createDir('tmp'); + }); + + afterEach(function () { + files.cleanup(); + }); + + it('-f writes output to a file', async function () { + const outputFile = 'tmp/cli-test-output.js'; + files.registerForCleanup(outputFile); + + await execCommand( + `${cli} -a -f ${outputFile} spec/artifacts/empty.handlebars` + ); + + expect(files.fileExists(outputFile)).toBe(true); + const content = files.getFileTextContent(outputFile); + expect(content).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.amd.js') + ); + }); + + it('--map writes source map and appends sourceMappingURL', async function () { + const mapFile = 'tmp/cli-test-source.map'; + files.registerForCleanup(mapFile); + + const result = await execCommand( + `${cli} -i "
1
" -a -m -N test --map ${mapFile}` + ); + + expect(result.stdout).toContain('sourceMappingURL='); + expect(files.fileExists(mapFile)).toBe(true); + const parsed = JSON.parse(files.getFileTextContent(mapFile)); + expect(parsed).toHaveProperty('version', 3); + expect(parsed).toHaveProperty('sources'); + expect(parsed).toHaveProperty('mappings'); + }); + }); + + describe('template options', function () { + it('-e sets custom extension', async function () { + const result = await execCommand( + `${cli} -a -e hbs ./spec/artifacts/non.default.extension.hbs` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/non.default.extension.amd.js') + ); + }); + + it('-p compiles as partial', async function () { + const result = await execCommand( + `${cli} -a -p ./spec/artifacts/partial.template.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/partial.template.js') + ); + }); + + it('-r strips root from template names', async function () { + const result = await execCommand( + `${cli} spec/artifacts/partial.template.handlebars -r spec -a` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.root.amd.js') + ); + }); + + it('-b strips BOM', async function () { + const result = await execCommand( + `${cli} ./spec/artifacts/bom.handlebars -b -a` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/bom.amd.js') + ); + }); + + it('-h sets custom handlebar path', async function () { + const result = await execCommand( + `${cli} spec/artifacts/empty.handlebars -h some-path/ -a` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/handlebar.path.amd.js') + ); + }); + + it('-k -o sets known helpers only', async function () { + const result = await execCommand( + `${cli} spec/artifacts/known.helpers.handlebars -a -k someHelper -k anotherHelper -o` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/non.empty.amd.known.helper.js') + ); + }); + }); + + describe('inline templates', function () { + it('-i compiles inline template', async function () { + const result = await execCommand( + `${cli} -i "
hello
" -a -N myTemplate` + ); + expect(result.stdout).toContain("define(['handlebars.runtime']"); + expect(result.stdout).toContain("templates['myTemplate']"); + }); + + it('-i compiles multiple inline templates with -N', async function () { + const result = await execCommand( + `${cli} -i "
1
" -i "
2
" -N firstTemplate -N secondTemplate -a` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.name.amd.js') + ); + }); + }); + + describe('error handling', function () { + it('should not produce unhandled promise rejections on async errors', async function () { + const { stderr } = await new Promise((resolve) => { + exec( + `node --unhandled-rejections=warn ./bin/handlebars.mjs -i "
test
" -N test --map /nonexistent/dir/test.map`, + (error, stdout, stderr) => { + resolve({ exitCode: error ? error.code : 0, stderr }); + } + ); + }); + + expect(stderr).not.toMatch(/unhandled/i); + }); + }); + + describe('negated boolean flags', function () { + it('--no-amd negates --amd (issue #1673)', async function () { + const result = await execCommand( + `${cli} --amd --no-amd spec/artifacts/empty.handlebars` + ); + expect(result.stdout).toEqualWithRelaxedSpace( + expectedFile('./spec/expected/empty.common.js') + ); + }); + }); +}); diff --git a/tests/bench/perf.mjs b/tests/bench/perf.mjs index 62c13d2f1..3c7a31558 100644 --- a/tests/bench/perf.mjs +++ b/tests/bench/perf.mjs @@ -51,6 +51,17 @@ if (grepIdx !== -1 && args[grepIdx + 1]) { } } +const sectionIdx = args.indexOf('--section'); +let sectionPattern = null; +if (sectionIdx !== -1 && args[sectionIdx + 1]) { + try { + sectionPattern = new RegExp(args[sectionIdx + 1], 'i'); + } catch (e) { + console.error(`Invalid --section pattern: ${e.message}`); + process.exit(1); + } +} + // ─── Filter templates ─────────────────────────────────────────────────────── const templates = Object.fromEntries( @@ -92,7 +103,14 @@ function createEnv(def) { return hb; } +function shouldRunSection(title) { + if (!sectionPattern) return true; + return sectionPattern.test(title); +} + async function runSection(title, config, setup) { + if (!shouldRunSection(title)) return null; + printSectionHeader(title); const bench = newBench(config); @@ -120,6 +138,11 @@ async function run() { const allSections = []; + if (sectionPattern) { + console.log(`Filtering sections: /${sectionPattern.source}/i`); + console.log(); + } + // ─── COMPILATION ──────────────────────────────────────────────────────────── allSections.push( @@ -143,40 +166,41 @@ async function run() { const expectedOutputs = {}; - allSections.push( - await runSection( - 'EXECUTION (template rendering)', - EXEC_BENCH_CONFIG, - (bench) => { - for (const [name, def] of Object.entries(templates)) { - const compiled = createEnv(def).compile(def.template); - expectedOutputs[name] = compiled(def.context); - bench.add(`exec: ${name}`, () => { - compiled(def.context); - }); - } + const execResult = await runSection( + 'EXECUTION (template rendering)', + EXEC_BENCH_CONFIG, + (bench) => { + for (const [name, def] of Object.entries(templates)) { + const compiled = createEnv(def).compile(def.template); + expectedOutputs[name] = compiled(def.context); + bench.add(`exec: ${name}`, () => { + compiled(def.context); + }); } - ) + } ); + allSections.push(execResult); // Verify outputs haven't changed during benchmarking - let verifyFails = 0; - for (const [name, def] of Object.entries(templates)) { - const compiled = createEnv(def).compile(def.template); - const actual = compiled(def.context); - if (actual !== expectedOutputs[name]) { - console.warn( - ` WARNING: output mismatch for "${name}"\n expected: ${JSON.stringify(expectedOutputs[name])}\n actual: ${JSON.stringify(actual)}` - ); - verifyFails++; + if (execResult) { + let verifyFails = 0; + for (const [name, def] of Object.entries(templates)) { + const compiled = createEnv(def).compile(def.template); + const actual = compiled(def.context); + if (actual !== expectedOutputs[name]) { + console.warn( + ` WARNING: output mismatch for "${name}"\n expected: ${JSON.stringify(expectedOutputs[name])}\n actual: ${JSON.stringify(actual)}` + ); + verifyFails++; + } } + if (verifyFails === 0) { + console.log('Output verification: all templates OK'); + } else { + console.warn(`Output verification: ${verifyFails} mismatch(es)`); + } + console.log(); } - if (verifyFails === 0) { - console.log('Output verification: all templates OK'); - } else { - console.warn(`Output verification: ${verifyFails} mismatch(es)`); - } - console.log(); // ─── PRECOMPILATION ───────────────────────────────────────────────────────── @@ -249,7 +273,7 @@ async function run() { ) ); - const filepath = saveMarkdownReport(allSections, { + const filepath = saveMarkdownReport(allSections.filter(Boolean), { label, compileConfig: COMPILE_BENCH_CONFIG, execConfig: EXEC_BENCH_CONFIG, diff --git a/tests/integration/multi-nodejs-test/test.sh b/tests/integration/multi-nodejs-test/test.sh index 5dce414ec..a0c43d54b 100755 --- a/tests/integration/multi-nodejs-test/test.sh +++ b/tests/integration/multi-nodejs-test/test.sh @@ -14,7 +14,7 @@ cd "$( dirname "$( readlink -f "$0" )" )" || exit 1 unset npm_config_prefix echo "Handlebars should be able to run in various versions of NodeJS" -for node_version_to_test in 18 20; do +for node_version_to_test in 20 22; do rm -rf target node_modules package-lock.json mkdir target diff --git a/tstyche.config.json b/tstyche.config.json new file mode 100644 index 000000000..c497ad0d4 --- /dev/null +++ b/tstyche.config.json @@ -0,0 +1,4 @@ +{ + "testFileMatch": ["types/__typetests__/**/*.tst.ts"], + "tsconfig": "./types/tsconfig.json" +} diff --git a/types/__typetests__/handlebars.tst.ts b/types/__typetests__/handlebars.tst.ts new file mode 100644 index 000000000..56c299c39 --- /dev/null +++ b/types/__typetests__/handlebars.tst.ts @@ -0,0 +1,575 @@ +import { expect, test, describe } from 'tstyche'; +import Handlebars from 'handlebars'; +import { + HandlebarsTemplatable, + HandlebarsTemplateDelegate, + HandlebarsTemplates, + TemplateSpecification, + KnownHelpers, + BuiltinHelperName, + CustomHelperName, + Logger, + CompilerInfo, + hbs, +} from 'handlebars'; + +// --------------------------------------------------------------------------- +// Handlebars.compile +// --------------------------------------------------------------------------- +describe('Handlebars.compile', () => { + test('returns a HandlebarsTemplateDelegate', () => { + expect(Handlebars.compile('{{name}}')).type.toBe< + HandlebarsTemplateDelegate + >(); + }); + + test('returns a typed delegate when generic is specified', () => { + expect(Handlebars.compile<{ name: string }>('{{name}}')).type.toBe< + HandlebarsTemplateDelegate<{ name: string }> + >(); + }); + + test('compiled template returns string', () => { + const template = Handlebars.compile('{{name}}'); + expect(template({})).type.toBe(); + }); + + test('accepts CompileOptions', () => { + expect( + Handlebars.compile('test', { strict: true, noEscape: true }) + ).type.not.toRaiseError(); + }); + + test('accepts knownHelpers with built-in and custom names', () => { + expect( + Handlebars.compile('test', { + knownHelpers: { each: true, customHelper: true }, + }) + ).type.not.toRaiseError(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.precompile +// --------------------------------------------------------------------------- +describe('Handlebars.precompile', () => { + test('returns TemplateSpecification', () => { + expect( + Handlebars.precompile('{{name}}') + ).type.toBe(); + }); + + test('accepts PrecompileOptions', () => { + expect( + Handlebars.precompile('test', { srcName: 'a.hbs', destName: 'a.js' }) + ).type.not.toRaiseError(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.template +// --------------------------------------------------------------------------- +describe('Handlebars.template', () => { + test('returns HandlebarsTemplateDelegate', () => { + const spec = {} as TemplateSpecification; + expect(Handlebars.template(spec)).type.toBe< + HandlebarsTemplateDelegate + >(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.registerHelper / unregisterHelper +// --------------------------------------------------------------------------- +describe('Handlebars.registerHelper', () => { + test('accepts name and function', () => { + expect( + Handlebars.registerHelper('myHelper', (ctx: any) => 'result') + ).type.toBe(); + }); + + test('accepts a spec object', () => { + expect( + Handlebars.registerHelper({ myHelper: () => 'result' }) + ).type.toBe(); + }); +}); + +describe('Handlebars.unregisterHelper', () => { + test('accepts a name', () => { + expect(Handlebars.unregisterHelper('myHelper')).type.toBe(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.registerPartial / unregisterPartial +// --------------------------------------------------------------------------- +describe('Handlebars.registerPartial', () => { + test('accepts name and string', () => { + expect( + Handlebars.registerPartial('myPartial', '
{{name}}
') + ).type.toBe(); + }); + + test('accepts spec object', () => { + expect( + Handlebars.registerPartial({ myPartial: '
{{name}}
' }) + ).type.toBe(); + }); +}); + +describe('Handlebars.unregisterPartial', () => { + test('accepts a name', () => { + expect(Handlebars.unregisterPartial('myPartial')).type.toBe(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.registerDecorator / unregisterDecorator +// --------------------------------------------------------------------------- +describe('Handlebars.registerDecorator', () => { + test('accepts name and function', () => { + expect( + Handlebars.registerDecorator('myDecorator', () => {}) + ).type.toBe(); + }); +}); + +describe('Handlebars.unregisterDecorator', () => { + test('accepts a name', () => { + expect(Handlebars.unregisterDecorator('myDecorator')).type.toBe(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars utility functions +// --------------------------------------------------------------------------- +describe('Handlebars utility functions', () => { + test('K returns void', () => { + expect(Handlebars.K()).type.toBe(); + }); + + test('createFrame returns any', () => { + expect(Handlebars.createFrame({})).type.toBe(); + }); + + test('blockParams returns any[]', () => { + expect(Handlebars.blockParams([], [])).type.toBe(); + }); + + test('log returns void', () => { + expect(Handlebars.log(1, 'message')).type.toBe(); + }); + + test('noConflict returns typeof Handlebars', () => { + expect(Handlebars.noConflict()).type.toBe(); + }); + + test('escapeExpression is exported at top level', () => { + expect(Handlebars.escapeExpression('test')).type.toBe(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.HelperOptions +// --------------------------------------------------------------------------- +describe('Handlebars.HelperOptions', () => { + test('fn and inverse are callable TemplateDelegates', () => { + const options = {} as Handlebars.HelperOptions; + expect(options.fn({})).type.toBe(); + expect(options.inverse({})).type.toBe(); + }); + + test('hash is a Record', () => { + const options = {} as Handlebars.HelperOptions; + expect(options.hash).type.toBe>(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.SafeString +// --------------------------------------------------------------------------- +describe('Handlebars.SafeString', () => { + test('is constructable with string', () => { + expect( + new Handlebars.SafeString('bold') + ).type.toBe(); + }); + + test('toString returns string', () => { + const safe = new Handlebars.SafeString('test'); + expect(safe.toString()).type.toBe(); + }); + + test('toHTML returns string', () => { + const safe = new Handlebars.SafeString('test'); + expect(safe.toHTML()).type.toBe(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.Exception +// --------------------------------------------------------------------------- +describe('Handlebars.Exception', () => { + test('is constructable with message only', () => { + expect(new Handlebars.Exception('error')).type.toBe(); + }); + + test('is constructable with message and node', () => { + expect( + new Handlebars.Exception('error', { + type: 'MustacheStatement', + loc: { + source: 'source', + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 }, + }, + }) + ).type.not.toRaiseError(); + }); + + test('has all expected fields', () => { + const ex = new Handlebars.Exception('msg'); + expect(ex.message).type.toBe(); + expect(ex.name).type.toBe(); + expect(ex.description).type.toBe(); + expect(ex.fileName).type.toBe(); + expect(ex.number).type.toBe(); + expect(ex.lineNumber).type.toBe(); + expect(ex.endLineNumber).type.toBe(); + expect(ex.column).type.toBe(); + expect(ex.endColumn).type.toBe(); + expect(ex.stack).type.toBe(); + }); +}); + +// --------------------------------------------------------------------------- +// Handlebars.Utils +// --------------------------------------------------------------------------- +describe('Handlebars.Utils', () => { + test('escapeExpression returns string', () => { + expect(Handlebars.Utils.escapeExpression('" -); - -Handlebars.helpers !== undefined; - -const parsedTmpl = Handlebars.parse('

Hello, my name is {{name}}.

', { - srcName: '/foo/bar/baz.hbs', - ignoreStandalone: true, -}); - -const parsedTmplWithoutOptions = Handlebars.parse( - '

Hello, my name is {{name}}.

' -); - -// Custom partial resolution. -const originalResolvePartial = Handlebars.VM.resolvePartial; -Handlebars.VM.resolvePartial = ( - partial: HandlebarsTemplateDelegate | undefined, - context: any, - options: Handlebars.ResolvePartialOptions -): HandlebarsTemplateDelegate => { - const name = options.name.replace(/my/, 'your'); - // transform name. - options.name = name; - return originalResolvePartial(partial, context, options); -}; - -// #1544, allow custom helpers in knownHelpers -Handlebars.compile('test', { - knownHelpers: { - each: true, - customHelper: true, - }, -}); - -Handlebars.compile('test')({}, { allowCallsToHelperMissing: true }); - -Handlebars.compile('test')({}, {}); - -const allthings = {} as - | hbs.AST.MustacheStatement - | hbs.AST.BlockStatement - | hbs.AST.PartialStatement - | hbs.AST.PartialBlockStatement - | hbs.AST.ContentStatement - | hbs.AST.CommentStatement - | hbs.AST.SubExpression - | hbs.AST.PathExpression - | hbs.AST.StringLiteral - | hbs.AST.BooleanLiteral - | hbs.AST.NumberLiteral - | hbs.AST.UndefinedLiteral - | hbs.AST.NullLiteral - | hbs.AST.Hash - | hbs.AST.HashPair; - -switch (allthings.type) { - case 'MustacheStatement': - let mustacheStatement: hbs.AST.MustacheStatement; - mustacheStatement = allthings; - break; - case 'BlockStatement': - let blockStatement: hbs.AST.BlockStatement; - blockStatement = allthings; - break; - case 'PartialStatement': - let partialStatement: hbs.AST.PartialStatement; - partialStatement = allthings; - break; - case 'PartialBlockStatement': - let partialBlockStatement: hbs.AST.PartialBlockStatement; - partialBlockStatement = allthings; - break; - case 'ContentStatement': - let ContentStatement: hbs.AST.ContentStatement; - ContentStatement = allthings; - break; - case 'CommentStatement': - let CommentStatement: hbs.AST.CommentStatement; - CommentStatement = allthings; - break; - case 'SubExpression': - let SubExpression: hbs.AST.SubExpression; - SubExpression = allthings; - break; - case 'PathExpression': - let PathExpression: hbs.AST.PathExpression; - PathExpression = allthings; - break; - case 'StringLiteral': - let StringLiteral: hbs.AST.StringLiteral; - StringLiteral = allthings; - break; - case 'BooleanLiteral': - let BooleanLiteral: hbs.AST.BooleanLiteral; - BooleanLiteral = allthings; - break; - case 'NumberLiteral': - let NumberLiteral: hbs.AST.NumberLiteral; - NumberLiteral = allthings; - break; - case 'UndefinedLiteral': - let UndefinedLiteral: hbs.AST.UndefinedLiteral; - UndefinedLiteral = allthings; - break; - case 'NullLiteral': - let NullLiteral: hbs.AST.NullLiteral; - NullLiteral = allthings; - break; - case 'Hash': - let Hash: hbs.AST.Hash; - Hash = allthings; - break; - case 'HashPair': - let HashPair: hbs.AST.HashPair; - HashPair = allthings; - break; - default: - break; -} - -function testParseWithoutProcessing() { - const parsedTemplate: hbs.AST.Program = Handlebars.parseWithoutProcessing( - '

Hello, my name is {{name}}.

', - { - srcName: '/foo/bar/baz.hbs', - } - ); - - const parsedTemplateWithoutOptions: hbs.AST.Program = - Handlebars.parseWithoutProcessing('

Hello, my name is {{name}}.

'); -} - -function testExceptionTypings() { - // Test exception constructor with a single argument - message. - let exception: Handlebars.Exception = new Handlebars.Exception('message'); - - // Fields - let message: string = exception.message; - let lineNumber: number = exception.lineNumber; - let column: number = exception.column; - let endLineNumber: number = exception.endLineNumber; - let endColumn: number = exception.endColumn; - let description = exception.description; - let name: string = exception.name; - let fileName: string = exception.fileName; - let stack: string | undefined = exception.stack; -} - -function testExceptionWithNodeTypings() { - // Test exception constructor with both arguments. - const exception: Handlebars.Exception = new Handlebars.Exception('message', { - type: 'MustacheStatement', - loc: { - source: 'source', - start: { line: 1, column: 5 }, - end: { line: 10, column: 2 }, - }, - }); - - // Fields - let message: string = exception.message; - let lineNumber: number = exception.lineNumber; - let column: number = exception.column; - let endLineNumber: number = exception.endLineNumber; - let endColumn: number = exception.endColumn; - let description = exception.description; - let name: string = exception.name; - let fileName: string = exception.fileName; - let stack: string | undefined = exception.stack; -} - -function testProtoAccessControlControlOptions() { - Handlebars.compile('test')( - {}, - { - allowedProtoMethods: { allowedMethod: true, forbiddenMethod: false }, - allowedProtoProperties: { - allowedProperty: true, - forbiddenProperty: false, - }, - allowProtoMethodsByDefault: true, - allowProtoPropertiesByDefault: false, - partials: { - link: '{{name}}', - }, - } - ); -} - -function testHandlebarsVersion() { - let version: string = Handlebars.VERSION; -} diff --git a/types/tslint.json b/types/tslint.json deleted file mode 100644 index 19dfb3eb4..000000000 --- a/types/tslint.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "extends": "@definitelytyped/dtslint/dtslint.json", - "rules": { - "adjacent-overload-signatures": false, - "array-type": false, - "arrow-return-shorthand": false, - "ban-types": false, - "callable-types": false, - "comment-format": false, - "dt-header": false, - "eofline": false, - "export-just-namespace": false, - "import-spacing": false, - "interface-name": false, - "interface-over-type-literal": false, - "jsdoc-format": false, - "max-line-length": false, - "member-access": false, - "new-parens": false, - "no-any-union": false, - "no-boolean-literal-compare": false, - "no-conditional-assignment": false, - "no-consecutive-blank-lines": false, - "no-construct": false, - "no-declare-current-package": false, - "no-duplicate-imports": false, - "no-duplicate-variable": false, - "no-empty-interface": false, - "no-for-in-array": false, - "no-inferrable-types": false, - "no-internal-module": false, - "no-irregular-whitespace": false, - "no-mergeable-namespace": false, - "no-misused-new": false, - "no-namespace": false, - "no-object-literal-type-assertion": false, - "no-padding": false, - "no-redundant-jsdoc": false, - "no-redundant-jsdoc-2": false, - "no-redundant-undefined": false, - "no-reference-import": false, - "no-relative-import-in-test": false, - "no-self-import": false, - "no-single-declare-module": false, - "no-string-throw": false, - "no-unnecessary-callback-wrapper": false, - "no-unnecessary-class": false, - "no-unnecessary-generics": false, - "no-unnecessary-qualifier": false, - "no-unnecessary-type-assertion": false, - "no-useless-files": false, - "no-var-keyword": false, - "no-var-requires": false, - "no-void-expression": false, - "no-trailing-whitespace": false, - "object-literal-key-quotes": false, - "object-literal-shorthand": false, - "one-line": false, - "one-variable-per-declaration": false, - "only-arrow-functions": false, - "prefer-conditional-expression": false, - "prefer-const": false, - "prefer-declare-function": false, - "prefer-for-of": false, - "prefer-method-signature": false, - "prefer-template": false, - "radix": false, - "semicolon": false, - "space-before-function-paren": false, - "space-within-parens": false, - "strict-export-declare-modifiers": false, - "trim-file": false, - "triple-equals": false, - "typedef-whitespace": false, - "unified-signatures": false, - "void-return": false, - "whitespace": false - } -} diff --git a/vitest.config.js b/vitest.config.js index 9a86c0c19..b475d4992 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -58,10 +58,10 @@ export default defineConfig({ include: ['dist/cjs/**/*.js'], thresholds: { // Slightly below 100% because SWC injects helper functions - // (e.g. _sliced_to_array, _non_iterable_rest) with branches - // that are unreachable in practice. + // (e.g. _sliced_to_array, _non_iterable_rest, for-of try/catch/finally) + // with branches that are unreachable in practice. statements: 99, - branches: 93, + branches: 92, functions: 100, lines: 100, },