From 179e487a6fdf0d39c018c06f1430f799650e8ead Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Sun, 16 Oct 2022 11:13:33 +0300 Subject: [PATCH 1/3] chore: upgrade things --- .editorconfig | 10 + .eslintignore | 1 + .eslintrc.yml | 6 +- .github/workflows/ci.yml | 6 +- .github/workflows/publish-npm.yml | 6 +- package-lock.json | 473 ++++++++++++++++-------------- package.json | 7 +- rollup.config.js | 3 +- src/context.js | 4 +- src/fixture.js | 48 ++- src/index.js | 8 +- src/matchers.js | 88 +++--- src/utils.js | 56 ++-- 13 files changed, 377 insertions(+), 339 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintignore diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a56f2d2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# https://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..a261f29 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +dist/* diff --git a/.eslintrc.yml b/.eslintrc.yml index bec9519..822de5e 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,6 +1,6 @@ extends: - chartjs - - plugin:es/no-new-in-es2019 + - plugin:es/restrict-to-es2018 env: es6: true @@ -18,7 +18,7 @@ globals: waitForResize: true parserOptions: - ecmaVersion: 2018 + ecmaVersion: 2022 sourceType: module ecmaFeatures: impliedStrict: true @@ -33,6 +33,8 @@ rules: max-statements: ["warn", 30] no-empty-function: "off" no-use-before-define: ["error", { "functions": false }] + no-var: "error" + prefer-const: "error" # disable everything, except Rest/Spread Properties in ES2018 es/no-async-iteration: "error" es/no-malformed-template-literals: "error" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a43d83e..572b4ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,10 +12,10 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - name: Setup and build run: | npm ci diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index d2f8c0e..90885be 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -8,10 +8,10 @@ jobs: publish-npm: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 registry-url: https://registry.npmjs.org/ - name: Setup and build run: | diff --git a/package-lock.json b/package-lock.json index b7250b2..ac49323 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,14 +12,14 @@ "pixelmatch": "^5.3.0" }, "devDependencies": { - "@rollup/plugin-commonjs": "^22.0.2", - "@rollup/plugin-node-resolve": "^14.1.0", + "@rollup/plugin-commonjs": "^23.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", "eslint": "^8.21.0", "eslint-config-chartjs": "^0.3.0", "eslint-plugin-es": "^4.1.0", "esm": "^3.2.25", "mocha": "^10.0.0", - "rollup": "^2.77.2" + "rollup": "^3.2.1" }, "peerDependencies": { "jasmine": ">=3.0.0", @@ -37,9 +37,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -60,9 +60,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", - "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -73,16 +73,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -138,69 +128,108 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "22.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", - "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", + "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^3.1.0", + "@rollup/pluginutils": "^4.2.1", "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.26.4" }, "engines": { - "node": ">= 12.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.68.0" + "rollup": "^2.68.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz", - "integrity": "sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.0.tgz", + "integrity": "sha512-iwJbzfTzlzDDQcGmkS7EkCKwe2kSkdBrjX87Fy/KrNjr6UNnLpod0t6X66e502LRe5JJCA4FFqrEscWPnZAkig==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", + "@rollup/pluginutils": "^4.2.1", + "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", - "is-builtin-module": "^3.1.0", + "is-builtin-module": "^3.2.0", "is-module": "^1.0.0", - "resolve": "^1.19.0" + "resolve": "^1.22.1" }, "engines": { - "node": ">= 10.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.78.0" + "rollup": "^2.78.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dev": true, "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", + "estree-walker": "^2.0.1", "picomatch": "^2.2.2" }, "engines": { "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" } }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -226,23 +255,15 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.7.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.19.tgz", - "integrity": "sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==" + "version": "18.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz", + "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==", + "peer": true }, "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, "node_modules/accepts": { @@ -376,9 +397,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "peer": true, "dependencies": { "bytes": "3.1.2", @@ -389,7 +410,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -667,9 +688,9 @@ "peer": true }, "node_modules/date-format": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.13.tgz", - "integrity": "sha512-bnYCwf8Emc3pTD8pXnre+wfnjGtfi5ncMDKy7+cWZXbmRAsdWkOQHrfC1yz/KiwP5thDp2kCHWYWKBX4HP1hoQ==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "peer": true, "engines": { "node": ">=4.0" @@ -871,14 +892,13 @@ } }, "node_modules/eslint": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", - "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", + "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.2", + "@eslint/eslintrc": "^1.3.3", "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -1720,9 +1740,9 @@ "peer": true }, "node_modules/js-sdsl": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", - "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "dev": true }, "node_modules/js-yaml": { @@ -1868,28 +1888,31 @@ } }, "node_modules/log4js": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.6.1.tgz", - "integrity": "sha512-J8VYFH2UQq/xucdNu71io4Fo+purYYudyErgBbswWKO0MC6QVOERRomt5su/z6d3RJSmLyTGmXl3Q/XjKCf+/A==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.7.0.tgz", + "integrity": "sha512-KA0W9ffgNBLDj6fZCq/lRbgR6ABAodRIDHrZnS48vOtfKa4PzWImb0Md1lmGCdO3n3sbCm/n1/WmrNlZ8kCI3Q==", "peer": true, "dependencies": { - "date-format": "^4.0.13", + "date-format": "^4.0.14", "debug": "^4.3.4", - "flatted": "^3.2.6", + "flatted": "^3.2.7", "rfdc": "^1.3.0", - "streamroller": "^3.1.2" + "streamroller": "^3.1.3" }, "engines": { "node": ">=8.0" } }, "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", "dev": true, "dependencies": { "sourcemap-codec": "^1.4.8" + }, + "engines": { + "node": ">=12" } }, "node_modules/media-typer": { @@ -1968,10 +1991,13 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "peer": true + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/mkdirp": { "version": "0.5.6", @@ -1986,12 +2012,11 @@ } }, "node_modules/mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "dependencies": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -2345,9 +2370,9 @@ } }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "peer": true, "dependencies": { "side-channel": "^1.0.4" @@ -2506,15 +2531,16 @@ } }, "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.2.1.tgz", + "integrity": "sha512-Y9lBWYY7pOiWhJbwMEnLicDuTu9IqjJb5jJM88L8O5rdreJrX1j9WhriMHQSOwVYPFg1xkLoXQyDfQ2U6Ejzyg==", "dev": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.18.0", + "npm": ">=8.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -2629,9 +2655,9 @@ } }, "node_modules/socket.io": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.2.tgz", - "integrity": "sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz", + "integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==", "peer": true, "dependencies": { "accepts": "~1.3.4", @@ -2689,12 +2715,12 @@ } }, "node_modules/streamroller": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.2.tgz", - "integrity": "sha512-wZswqzbgGGsXYIrBYhOE0yP+nQ6XRk7xDcYwuQAGTYXdyAUmvgVFE0YU1g5pvQT0m7GBaQfYcSnlHbapuK0H0A==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", + "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", "peer": true, "dependencies": { - "date-format": "^4.0.13", + "date-format": "^4.0.14", "debug": "^4.3.4", "fs-extra": "^8.1.0" }, @@ -2838,9 +2864,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "version": "0.7.32", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz", + "integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==", "funding": [ { "type": "opencollective", @@ -3051,9 +3077,9 @@ "peer": true }, "@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -3068,9 +3094,9 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", - "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -3078,12 +3104,6 @@ "minimatch": "^3.0.4" } }, - "@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true - }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -3123,51 +3143,74 @@ } }, "@rollup/plugin-commonjs": { - "version": "22.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", - "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", + "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", "dev": true, "requires": { - "@rollup/pluginutils": "^3.1.0", + "@rollup/pluginutils": "^4.2.1", "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.26.4" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "@rollup/plugin-node-resolve": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz", - "integrity": "sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.0.tgz", + "integrity": "sha512-iwJbzfTzlzDDQcGmkS7EkCKwe2kSkdBrjX87Fy/KrNjr6UNnLpod0t6X66e502LRe5JJCA4FFqrEscWPnZAkig==", "dev": true, "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", + "@rollup/pluginutils": "^4.2.1", + "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", - "is-builtin-module": "^3.1.0", + "is-builtin-module": "^3.2.0", "is-module": "^1.0.0", - "resolve": "^1.19.0" + "resolve": "^1.22.1" } }, "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dev": true, "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", + "estree-walker": "^2.0.1", "picomatch": "^2.2.2" - }, - "dependencies": { - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - } } }, "@socket.io/component-emitter": { @@ -3195,23 +3238,15 @@ "dev": true }, "@types/node": { - "version": "18.7.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.19.tgz", - "integrity": "sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==" + "version": "18.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz", + "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==", + "peer": true }, "@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, "accepts": { @@ -3306,9 +3341,9 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "peer": true, "requires": { "bytes": "3.1.2", @@ -3319,7 +3354,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -3537,9 +3572,9 @@ "peer": true }, "date-format": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.13.tgz", - "integrity": "sha512-bnYCwf8Emc3pTD8pXnre+wfnjGtfi5ncMDKy7+cWZXbmRAsdWkOQHrfC1yz/KiwP5thDp2kCHWYWKBX4HP1hoQ==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "peer": true }, "debug": { @@ -3687,14 +3722,13 @@ "dev": true }, "eslint": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", - "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", + "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.2", + "@eslint/eslintrc": "^1.3.3", "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -4318,9 +4352,9 @@ "peer": true }, "js-sdsl": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", - "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "dev": true }, "js-yaml": { @@ -4436,22 +4470,22 @@ } }, "log4js": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.6.1.tgz", - "integrity": "sha512-J8VYFH2UQq/xucdNu71io4Fo+purYYudyErgBbswWKO0MC6QVOERRomt5su/z6d3RJSmLyTGmXl3Q/XjKCf+/A==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.7.0.tgz", + "integrity": "sha512-KA0W9ffgNBLDj6fZCq/lRbgR6ABAodRIDHrZnS48vOtfKa4PzWImb0Md1lmGCdO3n3sbCm/n1/WmrNlZ8kCI3Q==", "peer": true, "requires": { - "date-format": "^4.0.13", + "date-format": "^4.0.14", "debug": "^4.3.4", - "flatted": "^3.2.6", + "flatted": "^3.2.7", "rfdc": "^1.3.0", - "streamroller": "^3.1.2" + "streamroller": "^3.1.3" } }, "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", "dev": true, "requires": { "sourcemap-codec": "^1.4.8" @@ -4509,9 +4543,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "peer": true }, "mkdirp": { @@ -4524,12 +4558,11 @@ } }, "mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "requires": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -4785,9 +4818,9 @@ "peer": true }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "peer": true, "requires": { "side-channel": "^1.0.4" @@ -4889,9 +4922,9 @@ } }, "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.2.1.tgz", + "integrity": "sha512-Y9lBWYY7pOiWhJbwMEnLicDuTu9IqjJb5jJM88L8O5rdreJrX1j9WhriMHQSOwVYPFg1xkLoXQyDfQ2U6Ejzyg==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -4966,9 +4999,9 @@ "dev": true }, "socket.io": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.2.tgz", - "integrity": "sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz", + "integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==", "peer": true, "requires": { "accepts": "~1.3.4", @@ -5014,12 +5047,12 @@ "peer": true }, "streamroller": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.2.tgz", - "integrity": "sha512-wZswqzbgGGsXYIrBYhOE0yP+nQ6XRk7xDcYwuQAGTYXdyAUmvgVFE0YU1g5pvQT0m7GBaQfYcSnlHbapuK0H0A==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", + "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", "peer": true, "requires": { - "date-format": "^4.0.13", + "date-format": "^4.0.14", "debug": "^4.3.4", "fs-extra": "^8.1.0" } @@ -5118,9 +5151,9 @@ } }, "ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "version": "0.7.32", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz", + "integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==", "peer": true }, "universalify": { diff --git a/package.json b/package.json index 55df81d..ced5db2 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "main": "dist/chartjs-test-utils.js", "module": "dist/chartjs-test-utils.js", "scripts": { + "autobuild": "rollup -c -w", "build": "rollup -c", "lint": "eslint src/**/*.js", "test": "npm run lint && npx mocha -r esm" @@ -31,14 +32,14 @@ }, "homepage": "https://github.com/chartjs/chartjs-test-utils#readme", "devDependencies": { - "@rollup/plugin-commonjs": "^22.0.2", - "@rollup/plugin-node-resolve": "^14.1.0", + "@rollup/plugin-commonjs": "^23.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", "eslint": "^8.21.0", "eslint-config-chartjs": "^0.3.0", "eslint-plugin-es": "^4.1.0", "esm": "^3.2.25", "mocha": "^10.0.0", - "rollup": "^2.77.2" + "rollup": "^3.2.1" }, "dependencies": { "pixelmatch": "^5.3.0" diff --git a/rollup.config.js b/rollup.config.js index b926e08..6502eb6 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,7 @@ +import {readFileSync} from 'fs'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; -import {name, version, homepage, main} from './package.json'; +const {name, version, homepage, main} = JSON.parse(readFileSync('./package.json')); const banner = `/*! * ${name} v${version} diff --git a/src/context.js b/src/context.js index 30c05d4..73de4de 100644 --- a/src/context.js +++ b/src/context.js @@ -102,8 +102,8 @@ export default class Context { _initMethods() { // define methods to test here // no way to introspect so we have to do some extra work :( - var me = this; - var methods = { + const me = this; + const methods = { arc: function() { }, arcTo: function() { }, beginPath: function() { }, diff --git a/src/fixture.js b/src/fixture.js index 5dfc960..60b0bab 100644 --- a/src/fixture.js +++ b/src/fixture.js @@ -1,7 +1,7 @@ import {readImageData, _acquireChart, _releaseChart} from './utils'; function readFile(url, callback) { - var request = new XMLHttpRequest(); + const request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState === 4) { return callback(request.responseText); @@ -12,42 +12,34 @@ function readFile(url, callback) { request.send(null); } -function loadConfig(url, callback) { - var regex = /\.(json|js)$/i; - var matches = url.match(regex); - var type = matches ? matches[1] : 'json'; - var cfg = null; +function createJsConfig(content) { + return new Function(` +"use strict"; +var module = {}; +${content}; +return module.exports || fixture;'` + )(); +} - readFile(url, function(content) { - switch (type) { - case 'js': - cfg = new Function('"use strict"; var module = {};' + content + '; return module.exports || fixture;')(); - break; - case 'json': - cfg = JSON.parse(content); - break; - default: - } +function loadConfig(url, callback) { + const parser = url.endsWith('.js') ? createJsConfig : JSON.parse; - callback(cfg); - }); + readFile(url, (content) => callback(parser(content))); } function specFromFixture(description, inputs) { - var input = inputs.js || inputs.json; + const input = inputs.js || inputs.json; it(input, function(done) { loadConfig(input, function(json) { - var descr = json.description || (json.description = description); - - var config = json.config; - var options = config.options || (config.options = {}); + const {description: descr = description, config} = json; + const options = config.options || (config.options = {}); // plugins are disabled by default, except if the path contains 'plugin' or there are instance plugins if (input.indexOf('plugin') === -1 && config.plugins === undefined) { options.plugins = options.plugins || false; } - var chart = _acquireChart(config, json.options); + const chart = _acquireChart(config, json.options); const _done = () => { if (!inputs.png) { fail(descr + '\r\nMissing PNG comparison file for ' + input); @@ -71,13 +63,11 @@ function specFromFixture(description, inputs) { } export function specsFromFixtures(path) { - var regex = new RegExp('(^/base/test/fixtures/' + path + '.+)\\.(png|json|js)'); - var inputs = {}; + const regex = new RegExp('(^/base/test/fixtures/' + path + '.+)\\.(png|json|js)'); + const inputs = {}; Object.keys(__karma__.files || {}).forEach(function(file) { - var matches = file.match(regex); - var name = matches && matches[1]; - var type = matches && matches[2]; + const [, name, type] = file.match(regex); if (name && type) { inputs[name] = inputs[name] || {}; diff --git a/src/index.js b/src/index.js index d3f8ae8..54e52ab 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,11 @@ import Context from './context'; import matchers from './matchers'; import {_acquireChart, _releaseChart, injectCSS} from './utils'; -export * from './fixture'; +export {specsFromFixtures} from './fixture'; export {afterEvent, waitForResize, triggerMouseEvent} from './utils'; // Keep track of all acquired charts to automatically release them after each specs -var charts = {}; +const charts = {}; /** * Injects a new canvas (and div wrapper) and creates the associated Chart instance @@ -20,7 +20,7 @@ var charts = {}; * @param {boolean} [options.persistent] - If true, the chart will not be released after the spec. */ export function acquireChart(config, options) { - var chart = _acquireChart(config, options); + const chart = _acquireChart(config, options); charts[chart.id] = chart; return chart; } @@ -53,7 +53,7 @@ export function addMatchers() { export function releaseCharts() { Object.keys(charts).forEach(function(id) { - var chart = charts[id]; + const chart = charts[id]; if (!(chart.$test || {}).persistent) { _releaseChart(chart); } diff --git a/src/matchers.js b/src/matchers.js index c398408..cfaa24d 100644 --- a/src/matchers.js +++ b/src/matchers.js @@ -1,7 +1,5 @@ -'use strict'; - import pixelmatch from 'pixelmatch'; -import {createCanvas} from './utils'; +import {createCanvas, getCtx} from './utils'; import {toEqualOptions} from './matchers.options'; function toPercent(value) { @@ -9,21 +7,21 @@ function toPercent(value) { } function createImageData(w, h) { - var canvas = createCanvas(w, h); - var context = canvas.getContext('2d'); + const canvas = createCanvas(w, h); + const context = canvas.getContext('2d'); return context.getImageData(0, 0, w, h); } function canvasFromImageData(data) { - var canvas = createCanvas(data.width, data.height); - var context = canvas.getContext('2d'); + const canvas = createCanvas(data.width, data.height); + const context = canvas.getContext('2d'); context.putImageData(data, 0, 0); return canvas; } function buildPixelMatchPreview(actual, expected, diff, threshold, tolerance, count, description) { - var ratio = count / (actual.width * actual.height); - var wrapper = document.createElement('div'); + const ratio = count / (actual.width * actual.height); + const wrapper = document.createElement('div'); wrapper.appendChild(document.createTextNode(description)); wrapper.style.cssText = 'display: flex; overflow-y: auto'; @@ -38,10 +36,10 @@ function buildPixelMatchPreview(actual, expected, diff, threshold, tolerance, co 'tol: ' + toPercent(tolerance) + '%' } ].forEach(function(values) { - var item = document.createElement('div'); + const item = document.createElement('div'); item.style.cssText = 'text-align: center; font: 12px monospace; line-height: 1.4; margin: 8px'; item.innerHTML = '
' + values.label + '
'; - var canvas = canvasFromImageData(values.data); + const canvas = canvasFromImageData(values.data); canvas.style.cssText = 'border: 1px dashed red'; item.appendChild(canvas); wrapper.appendChild(item); @@ -58,13 +56,13 @@ function buildPixelMatchPreview(actual, expected, diff, threshold, tolerance, co function toBeCloseToPixel() { return { compare: function(actual, expected) { - var result = false; + let result = false; if (!isNaN(actual) && !isNaN(expected)) { - var diff = Math.abs(actual - expected); - var A = Math.abs(actual); - var B = Math.abs(expected); - var percentDiff = 0.005; // 0.5% diff + const diff = Math.abs(actual - expected); + const A = Math.abs(actual); + const B = Math.abs(expected); + const percentDiff = 0.005; // 0.5% diff result = (diff <= (A > B ? A : B) * percentDiff) || diff < 2; // 2 pixels is fine } @@ -89,8 +87,8 @@ function toBeCloseToPoint() { function toEqualOneOf() { return { compare: function(actual, expecteds) { - var result = false; - for (var i = 0, l = expecteds.length; i < l; i++) { + let result = false; + for (let i = 0, l = expecteds.length; i < l; i++) { if (actual === expecteds[i]) { result = true; break; @@ -106,7 +104,7 @@ function toEqualOneOf() { function toBeValidChart() { return { compare: function(actual) { - var message = null; + let message = null; if (!(actual instanceof Chart)) { message = 'Expected ' + actual + ' to be an instance of Chart'; @@ -131,21 +129,21 @@ function toBeValidChart() { function toBeChartOfSize() { return { compare: function(actual, expected) { - var res = toBeValidChart().compare(actual); + const res = toBeValidChart().compare(actual); if (!res.pass) { return res; } - var message = null; - var canvas = actual.ctx.canvas; - var style = getComputedStyle(canvas); - var pixelRatio = actual.options.devicePixelRatio || window.devicePixelRatio; - var dh = parseInt(style.height, 10) || 0; - var dw = parseInt(style.width, 10) || 0; - var rh = canvas.height; - var rw = canvas.width; - var orh = rh / pixelRatio; - var orw = rw / pixelRatio; + let message = null; + const canvas = actual.ctx.canvas; + const style = getComputedStyle(canvas); + const pixelRatio = actual.options.devicePixelRatio || window.devicePixelRatio; + const dh = parseInt(style.height, 10) || 0; + const dw = parseInt(style.width, 10) || 0; + const rh = canvas.height; + const rw = canvas.width; + const orh = rh / pixelRatio; + const orw = rw / pixelRatio; // sanity checks if (actual.height !== orh) { @@ -176,33 +174,23 @@ function toBeChartOfSize() { function toEqualImageData() { return { compare: function(actual, expected, opts) { - var message = null; - var debug = opts.debug || false; - var tolerance = opts.tolerance === undefined ? 0.001 : opts.tolerance; - var threshold = opts.threshold === undefined ? 0.1 : opts.threshold; - var ctx, idata, ddata, w, h, aw, ah, count, ratio; - - if (actual instanceof Chart) { - ctx = actual.ctx; - } else if (actual instanceof HTMLCanvasElement) { - ctx = actual.getContext('2d'); - } else if (actual instanceof CanvasRenderingContext2D) { - ctx = actual; - } + const ctx = getCtx(actual); + const {debug = false, tolerance = 0.001, threshold = 0.1} = opts; + let message = null; + let count; if (ctx) { - h = expected.height; - w = expected.width; - aw = ctx.canvas.width; - ah = ctx.canvas.height; - idata = ctx.getImageData(0, 0, aw, ah); - ddata = createImageData(w, h); + const {height: h, width: w} = expected; + const {canvas: {width: aw, height: ah}} = ctx; + const idata = ctx.getImageData(0, 0, aw, ah); + const ddata = createImageData(w, h); + if (aw === w && ah === h) { count = pixelmatch(idata.data, expected.data, ddata.data, w, h, {threshold: threshold}); } else { count = Math.abs(aw * ah - w * h); } - ratio = count / (w * h); + const ratio = count / (w * h); if ((ratio > tolerance) || debug) { message = buildPixelMatchPreview(idata, expected, ddata, threshold, tolerance, count, opts.description); diff --git a/src/utils.js b/src/utils.js index 5453607..c42990a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,20 +1,20 @@ import {spritingOn, spritingOff} from './spriting'; export function createCanvas(w, h) { - var canvas = document.createElement('canvas'); + const canvas = document.createElement('canvas'); canvas.width = w; canvas.height = h; return canvas; } export function readImageData(url, callback) { - var image = new Image(); + const image = new Image(); image.onload = function() { - var h = image.height; - var w = image.width; - var canvas = createCanvas(w, h); - var ctx = canvas.getContext('2d'); + const h = image.height; + const w = image.width; + const canvas = createCanvas(w, h); + const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0, w, h); callback(ctx.getImageData(0, 0, w, h)); }; @@ -34,9 +34,9 @@ export function readImageData(url, callback) { * @param {boolean} [options.persistent] - If true, the chart will not be released after the spec. */ export function _acquireChart(config, options) { - var wrapper = document.createElement('div'); - var canvas = document.createElement('canvas'); - var chart, key; + const wrapper = document.createElement('div'); + const canvas = document.createElement('canvas'); + let chart, key; config = config || {}; options = options || {}; @@ -73,7 +73,7 @@ export function _acquireChart(config, options) { window.document.body.appendChild(wrapper); try { - var ctx; + let ctx; if (options.useOffscreenCanvas) { if (!canvas.transferControlToOffscreen) { // If this browser does not support offscreen canvas, mark the test as 'pending', which will skip the @@ -82,7 +82,7 @@ export function _acquireChart(config, options) { // remove if all browsers implement `transferControlToOffscreen` return pending(); } - var offscreenCanvas = canvas.transferControlToOffscreen(); + const offscreenCanvas = canvas.transferControlToOffscreen(); ctx = offscreenCanvas.getContext('2d'); } else { ctx = canvas.getContext('2d'); @@ -108,7 +108,7 @@ export function _releaseChart(chart) { spritingOff(chart.ctx); chart.destroy(); - var wrapper = (chart.$test || {}).wrapper; + const wrapper = (chart.$test || {}).wrapper; if (wrapper && wrapper.parentNode) { wrapper.parentNode.removeChild(wrapper); } @@ -116,8 +116,8 @@ export function _releaseChart(chart) { export function injectCSS(css) { // https://stackoverflow.com/q/3922139 - var head = document.getElementsByTagName('head')[0]; - var style = document.createElement('style'); + const head = document.getElementsByTagName('head')[0]; + const style = document.createElement('style'); style.setAttribute('type', 'text/css'); if (style.styleSheet) { // IE style.styleSheet.cssText = css; @@ -128,7 +128,7 @@ export function injectCSS(css) { } export function waitForResize(chart, callback) { - var override = chart.resize; + const override = chart.resize; chart.resize = function() { chart.resize = override; override.apply(this, arguments); @@ -137,7 +137,7 @@ export function waitForResize(chart, callback) { } export function afterEvent(chart, type, callback) { - var override = chart._eventHandler; + const override = chart._eventHandler; chart._eventHandler = function(event) { override.call(this, event); if (event.type === type || (event.native && event.native.type === type)) { @@ -149,7 +149,7 @@ export function afterEvent(chart, type, callback) { } function _resolveElementPoint(el) { - var point = {x: 0, y: 0}; + let point = {x: 0, y: 0}; if (el) { if (typeof el.getCenterPoint === 'function') { point = el.getCenterPoint(); @@ -161,10 +161,10 @@ function _resolveElementPoint(el) { } export async function triggerMouseEvent(chart, type, el) { - var node = chart.canvas; - var rect = node.getBoundingClientRect(); - var point = _resolveElementPoint(el); - var event = new MouseEvent(type, { + const node = chart.canvas; + const rect = node.getBoundingClientRect(); + const point = _resolveElementPoint(el); + const event = new MouseEvent(type, { clientX: rect.left + point.x, clientY: rect.top + point.y, cancelable: true, @@ -172,7 +172,7 @@ export async function triggerMouseEvent(chart, type, el) { view: window }); - var promise = new Promise((resolve) => { + const promise = new Promise((resolve) => { afterEvent(chart, type, resolve); }); @@ -182,3 +182,15 @@ export async function triggerMouseEvent(chart, type, el) { return event; } + +export function getCtx(chart) { + let ctx; + if (chart instanceof Chart) { + ctx = chart.ctx; + } else if (chart instanceof HTMLCanvasElement) { + ctx = chart.getContext('2d'); + } else if (chart instanceof CanvasRenderingContext2D) { + ctx = chart; + } + return ctx; +} From b71f4d73ae4ba617cb504b92e62c8c6486461985 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Sun, 16 Oct 2022 12:08:49 +0300 Subject: [PATCH 2/3] refactor: move things to helpers --- src/events.js | 55 ++++++++++ src/fixture.js | 29 +---- src/helpers/chart.js | 75 +++++++++++++ src/helpers/defaults.js | 13 +++ src/helpers/dom.js | 45 ++++++++ src/helpers/fixture.js | 43 ++++++++ src/helpers/index.js | 5 + src/{ => helpers}/spriting.js | 0 src/index.js | 24 +++-- src/matchers.js | 2 +- src/utils.js | 196 ---------------------------------- 11 files changed, 251 insertions(+), 236 deletions(-) create mode 100644 src/events.js create mode 100644 src/helpers/chart.js create mode 100644 src/helpers/defaults.js create mode 100644 src/helpers/dom.js create mode 100644 src/helpers/fixture.js create mode 100644 src/helpers/index.js rename src/{ => helpers}/spriting.js (100%) delete mode 100644 src/utils.js diff --git a/src/events.js b/src/events.js new file mode 100644 index 0000000..a816707 --- /dev/null +++ b/src/events.js @@ -0,0 +1,55 @@ +export function waitForResize(chart, callback) { + const override = chart.resize; + chart.resize = function() { + chart.resize = override; + override.apply(this, arguments); + callback(); + }; +} + +export function afterEvent(chart, type, callback) { + const override = chart._eventHandler; + chart._eventHandler = function(event) { + override.call(this, event); + if (event.type === type || (event.native && event.native.type === type)) { + chart._eventHandler = override; + // eslint-disable-next-line callback-return + callback(); + } + }; +} + +function _resolveElementPoint(el) { + let point = {x: 0, y: 0}; + if (el) { + if (typeof el.getCenterPoint === 'function') { + point = el.getCenterPoint(); + } else if (el.x !== undefined && el.y !== undefined) { + point = el; + } + } + return point; +} + +export async function triggerMouseEvent(chart, type, el) { + const node = chart.canvas; + const rect = node.getBoundingClientRect(); + const point = _resolveElementPoint(el); + const event = new MouseEvent(type, { + clientX: rect.left + point.x, + clientY: rect.top + point.y, + cancelable: true, + bubbles: true, + view: window + }); + + const promise = new Promise((resolve) => { + afterEvent(chart, type, resolve); + }); + + node.dispatchEvent(event); + + await promise; + + return event; +} diff --git a/src/fixture.js b/src/fixture.js index 60b0bab..a1e441f 100644 --- a/src/fixture.js +++ b/src/fixture.js @@ -1,31 +1,4 @@ -import {readImageData, _acquireChart, _releaseChart} from './utils'; - -function readFile(url, callback) { - const request = new XMLHttpRequest(); - request.onreadystatechange = function() { - if (request.readyState === 4) { - return callback(request.responseText); - } - }; - - request.open('GET', url, false); - request.send(null); -} - -function createJsConfig(content) { - return new Function(` -"use strict"; -var module = {}; -${content}; -return module.exports || fixture;'` - )(); -} - -function loadConfig(url, callback) { - const parser = url.endsWith('.js') ? createJsConfig : JSON.parse; - - readFile(url, (content) => callback(parser(content))); -} +import {_acquireChart, _releaseChart, loadConfig, readImageData} from './helpers/index'; function specFromFixture(description, inputs) { const input = inputs.js || inputs.json; diff --git a/src/helpers/chart.js b/src/helpers/chart.js new file mode 100644 index 0000000..33139c2 --- /dev/null +++ b/src/helpers/chart.js @@ -0,0 +1,75 @@ +import {applyDefaultChartConfig, applyDefaultFixtureOptions} from './defaults'; +import {createWrapperAndCanvas} from './dom'; +import {spritingOn, spritingOff} from './spriting'; + +/** + * Injects a new canvas (and div wrapper) and creates the associated Chart instance + * using the given config. Additional options allow tweaking elements generation. + * @param {object} [config] - Chart config. + * @param {object} [options] - Chart acquisition options. + * @param {object} [options.canvas] - Canvas attributes. + * @param {object} [options.wrapper] - Canvas wrapper attributes. + * @param {boolean} [options.useOffscreenCanvas] - use an OffscreenCanvas instead of the normal HTMLCanvasElement. + * @param {boolean} [options.useShadowDOM] - use shadowDom + * @param {boolean} [options.persistent] - If true, the chart will not be released after the spec. + */ +export function _acquireChart(config = {}, options = {}) { + applyDefaultChartConfig(config); + applyDefaultFixtureOptions(options); + + const {wrapper, canvas} = createWrapperAndCanvas(config, options); + let chart; + + try { + let ctx; + if (options.useOffscreenCanvas) { + if (!canvas.transferControlToOffscreen) { + // If this browser does not support offscreen canvas, mark the test as 'pending', which will skip the + // test. + // TODO: switch to skip() once it's implemented (https://github.com/jasmine/jasmine/issues/1709), or + // remove if all browsers implement `transferControlToOffscreen` + return pending(); + } + const offscreenCanvas = canvas.transferControlToOffscreen(); + ctx = offscreenCanvas.getContext('2d'); + } else { + ctx = canvas.getContext('2d'); + } + if (options.spriteText) { + spritingOn(ctx); + } + chart = new Chart(ctx, config); + } catch (e) { + window.document.body.removeChild(wrapper); + throw e; + } + + chart.$test = { + persistent: options.persistent, + wrapper: wrapper + }; + + return chart; +} + +export function _releaseChart(chart) { + spritingOff(chart.ctx); + chart.destroy(); + + const wrapper = (chart.$test || {}).wrapper; + if (wrapper && wrapper.parentNode) { + wrapper.parentNode.removeChild(wrapper); + } +} + +export function getCtx(chart) { + let ctx; + if (chart instanceof Chart) { + ctx = chart.ctx; + } else if (chart instanceof HTMLCanvasElement) { + ctx = chart.getContext('2d'); + } else if (chart instanceof CanvasRenderingContext2D) { + ctx = chart; + } + return ctx; +} diff --git a/src/helpers/defaults.js b/src/helpers/defaults.js new file mode 100644 index 0000000..3cfc86b --- /dev/null +++ b/src/helpers/defaults.js @@ -0,0 +1,13 @@ +export function applyDefaultChartConfig(config) { + config.platform = config.platform || Chart.platforms.BasicPlatform; + + const options = config.options = config.options || {}; + options.animation = options.animation === undefined ? false : options.animation; + options.responsive = options.responsive === undefined ? false : options.responsive; + options.locale = options.locale || 'en-US'; +} + +export function applyDefaultFixtureOptions(options) { + options.canvas = options.canvas || {height: 512, width: 512}; + options.wrapper = options.wrapper || {class: 'chartjs-wrapper'}; +} diff --git a/src/helpers/dom.js b/src/helpers/dom.js new file mode 100644 index 0000000..a778ee6 --- /dev/null +++ b/src/helpers/dom.js @@ -0,0 +1,45 @@ +export function createCanvas(w, h) { + const canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + return canvas; +} + +export function createWrapperAndCanvas(config, options) { + const wrapper = document.createElement('div'); + const canvas = document.createElement('canvas'); + + for (const key in options.canvas) { + if (Object.prototype.hasOwnProperty.call(options.canvas, key)) { + canvas.setAttribute(key, options.canvas[key]); + } + } + + for (const key in options.wrapper) { + if (Object.prototype.hasOwnProperty.call(options.wrapper, key)) { + wrapper.setAttribute(key, options.wrapper[key]); + } + } + + if (options.useShadowDOM) { + if (!wrapper.attachShadow) { + // If shadowDOM is not supported by the browsers, mark test as 'pending'. + return pending(); + } + wrapper.attachShadow({mode: 'open'}).appendChild(canvas); + } else { + wrapper.appendChild(canvas); + } + window.document.body.appendChild(wrapper); + + return {wrapper, canvas}; +} + +export function injectCSS(css) { + // https://stackoverflow.com/q/3922139 + const head = document.getElementsByTagName('head')[0]; + const style = document.createElement('style'); + style.setAttribute('type', 'text/css'); + style.appendChild(document.createTextNode(css)); + head.appendChild(style); +} diff --git a/src/helpers/fixture.js b/src/helpers/fixture.js new file mode 100644 index 0000000..eb0bd87 --- /dev/null +++ b/src/helpers/fixture.js @@ -0,0 +1,43 @@ +import {createCanvas} from './dom'; + +function readFile(url, callback) { + const request = new XMLHttpRequest(); + request.onreadystatechange = function() { + if (request.readyState === 4) { + return callback(request.responseText); + } + }; + + request.open('GET', url, false); + request.send(null); +} + +function createJsConfig(content) { + return new Function(` +"use strict"; +var module = {}; +${content}; +return module.exports || fixture;` + )(); +} + +export function loadConfig(url, callback) { + const parser = url.endsWith('.js') ? createJsConfig : JSON.parse; + + readFile(url, (content) => callback(parser(content))); +} + +export function readImageData(url, callback) { + const image = new Image(); + + image.onload = function() { + const h = image.height; + const w = image.width; + const canvas = createCanvas(w, h); + const ctx = canvas.getContext('2d'); + ctx.drawImage(image, 0, 0, w, h); + callback(ctx.getImageData(0, 0, w, h)); + }; + + image.src = url; +} diff --git a/src/helpers/index.js b/src/helpers/index.js new file mode 100644 index 0000000..ae20215 --- /dev/null +++ b/src/helpers/index.js @@ -0,0 +1,5 @@ +export * from './chart'; +export * from './defaults'; +export * from './dom'; +export * from './fixture'; +export * from './spriting'; diff --git a/src/spriting.js b/src/helpers/spriting.js similarity index 100% rename from src/spriting.js rename to src/helpers/spriting.js diff --git a/src/index.js b/src/index.js index 54e52ab..8f34c5b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,10 @@ import Context from './context'; import matchers from './matchers'; -import {_acquireChart, _releaseChart, injectCSS} from './utils'; +import {injectCSS} from './helpers/dom'; +import {_acquireChart, _releaseChart} from './helpers/index'; export {specsFromFixtures} from './fixture'; -export {afterEvent, waitForResize, triggerMouseEvent} from './utils'; +export {afterEvent, waitForResize, triggerMouseEvent} from './events'; // Keep track of all acquired charts to automatically release them after each specs const charts = {}; @@ -36,15 +37,16 @@ export function createMockContext() { export function injectWrapperCSS() { // some style initialization to limit differences between browsers across different platforms. - injectCSS( - '.chartjs-wrapper, .chartjs-wrapper canvas {' + - 'border: 0;' + - 'margin: 0;' + - 'padding: 0;' + - '}' + - '.chartjs-wrapper {' + - 'position: absolute' + - '}'); + injectCSS(` + .chartjs-wrapper, .chartjs-wrapper canvas { + border: 0; + margin: 0; + padding: 0; + } + .chartjs-wrapper: { + position: absolute; + } + `); } export function addMatchers() { diff --git a/src/matchers.js b/src/matchers.js index cfaa24d..3b19210 100644 --- a/src/matchers.js +++ b/src/matchers.js @@ -1,5 +1,5 @@ import pixelmatch from 'pixelmatch'; -import {createCanvas, getCtx} from './utils'; +import {createCanvas, getCtx} from './helpers/index'; import {toEqualOptions} from './matchers.options'; function toPercent(value) { diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index c42990a..0000000 --- a/src/utils.js +++ /dev/null @@ -1,196 +0,0 @@ -import {spritingOn, spritingOff} from './spriting'; - -export function createCanvas(w, h) { - const canvas = document.createElement('canvas'); - canvas.width = w; - canvas.height = h; - return canvas; -} - -export function readImageData(url, callback) { - const image = new Image(); - - image.onload = function() { - const h = image.height; - const w = image.width; - const canvas = createCanvas(w, h); - const ctx = canvas.getContext('2d'); - ctx.drawImage(image, 0, 0, w, h); - callback(ctx.getImageData(0, 0, w, h)); - }; - - image.src = url; -} - -/** - * Injects a new canvas (and div wrapper) and creates the associated Chart instance - * using the given config. Additional options allow tweaking elements generation. - * @param {object} [config] - Chart config. - * @param {object} [options] - Chart acquisition options. - * @param {object} [options.canvas] - Canvas attributes. - * @param {object} [options.wrapper] - Canvas wrapper attributes. - * @param {boolean} [options.useOffscreenCanvas] - use an OffscreenCanvas instead of the normal HTMLCanvasElement. - * @param {boolean} [options.useShadowDOM] - use shadowDom - * @param {boolean} [options.persistent] - If true, the chart will not be released after the spec. - */ -export function _acquireChart(config, options) { - const wrapper = document.createElement('div'); - const canvas = document.createElement('canvas'); - let chart, key; - - config = config || {}; - options = options || {}; - options.canvas = options.canvas || {height: 512, width: 512}; - options.wrapper = options.wrapper || {class: 'chartjs-wrapper'}; - - for (key in options.canvas) { - if (Object.prototype.hasOwnProperty.call(options.canvas, key)) { - canvas.setAttribute(key, options.canvas[key]); - } - } - - for (key in options.wrapper) { - if (Object.prototype.hasOwnProperty.call(options.wrapper, key)) { - wrapper.setAttribute(key, options.wrapper[key]); - } - } - - // by default, remove chart animation and auto resize - config.options = config.options || {}; - config.options.animation = config.options.animation === undefined ? false : config.options.animation; - config.options.responsive = config.options.responsive === undefined ? false : config.options.responsive; - config.options.locale = config.options.locale || 'en-US'; - - if (options.useShadowDOM) { - if (!wrapper.attachShadow) { - // If shadowDOM is not supported by the browsers, mark test as 'pending'. - return pending(); - } - wrapper.attachShadow({mode: 'open'}).appendChild(canvas); - } else { - wrapper.appendChild(canvas); - } - window.document.body.appendChild(wrapper); - - try { - let ctx; - if (options.useOffscreenCanvas) { - if (!canvas.transferControlToOffscreen) { - // If this browser does not support offscreen canvas, mark the test as 'pending', which will skip the - // test. - // TODO: switch to skip() once it's implemented (https://github.com/jasmine/jasmine/issues/1709), or - // remove if all browsers implement `transferControlToOffscreen` - return pending(); - } - const offscreenCanvas = canvas.transferControlToOffscreen(); - ctx = offscreenCanvas.getContext('2d'); - } else { - ctx = canvas.getContext('2d'); - } - if (options.spriteText) { - spritingOn(ctx); - } - chart = new Chart(ctx, config); - } catch (e) { - window.document.body.removeChild(wrapper); - throw e; - } - - chart.$test = { - persistent: options.persistent, - wrapper: wrapper - }; - - return chart; -} - -export function _releaseChart(chart) { - spritingOff(chart.ctx); - chart.destroy(); - - const wrapper = (chart.$test || {}).wrapper; - if (wrapper && wrapper.parentNode) { - wrapper.parentNode.removeChild(wrapper); - } -} - -export function injectCSS(css) { - // https://stackoverflow.com/q/3922139 - const head = document.getElementsByTagName('head')[0]; - const style = document.createElement('style'); - style.setAttribute('type', 'text/css'); - if (style.styleSheet) { // IE - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } - head.appendChild(style); -} - -export function waitForResize(chart, callback) { - const override = chart.resize; - chart.resize = function() { - chart.resize = override; - override.apply(this, arguments); - callback(); - }; -} - -export function afterEvent(chart, type, callback) { - const override = chart._eventHandler; - chart._eventHandler = function(event) { - override.call(this, event); - if (event.type === type || (event.native && event.native.type === type)) { - chart._eventHandler = override; - // eslint-disable-next-line callback-return - callback(); - } - }; -} - -function _resolveElementPoint(el) { - let point = {x: 0, y: 0}; - if (el) { - if (typeof el.getCenterPoint === 'function') { - point = el.getCenterPoint(); - } else if (el.x !== undefined && el.y !== undefined) { - point = el; - } - } - return point; -} - -export async function triggerMouseEvent(chart, type, el) { - const node = chart.canvas; - const rect = node.getBoundingClientRect(); - const point = _resolveElementPoint(el); - const event = new MouseEvent(type, { - clientX: rect.left + point.x, - clientY: rect.top + point.y, - cancelable: true, - bubbles: true, - view: window - }); - - const promise = new Promise((resolve) => { - afterEvent(chart, type, resolve); - }); - - node.dispatchEvent(event); - - await promise; - - return event; -} - -export function getCtx(chart) { - let ctx; - if (chart instanceof Chart) { - ctx = chart.ctx; - } else if (chart instanceof HTMLCanvasElement) { - ctx = chart.getContext('2d'); - } else if (chart instanceof CanvasRenderingContext2D) { - ctx = chart; - } - return ctx; -} From b51e5c0e90ed78fa61e2832703b637dd6f698e06 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Sun, 16 Oct 2022 14:12:07 +0300 Subject: [PATCH 3/3] export defaults --- src/{helpers => }/defaults.js | 0 src/helpers/chart.js | 4 ++-- src/helpers/dom.js | 2 +- src/helpers/index.js | 1 - src/index.js | 1 + 5 files changed, 4 insertions(+), 4 deletions(-) rename src/{helpers => }/defaults.js (100%) diff --git a/src/helpers/defaults.js b/src/defaults.js similarity index 100% rename from src/helpers/defaults.js rename to src/defaults.js diff --git a/src/helpers/chart.js b/src/helpers/chart.js index 33139c2..bde46c5 100644 --- a/src/helpers/chart.js +++ b/src/helpers/chart.js @@ -1,4 +1,4 @@ -import {applyDefaultChartConfig, applyDefaultFixtureOptions} from './defaults'; +import {applyDefaultChartConfig, applyDefaultFixtureOptions} from '../defaults'; import {createWrapperAndCanvas} from './dom'; import {spritingOn, spritingOff} from './spriting'; @@ -17,7 +17,7 @@ export function _acquireChart(config = {}, options = {}) { applyDefaultChartConfig(config); applyDefaultFixtureOptions(options); - const {wrapper, canvas} = createWrapperAndCanvas(config, options); + const {wrapper, canvas} = createWrapperAndCanvas(options); let chart; try { diff --git a/src/helpers/dom.js b/src/helpers/dom.js index a778ee6..b5aebbb 100644 --- a/src/helpers/dom.js +++ b/src/helpers/dom.js @@ -5,7 +5,7 @@ export function createCanvas(w, h) { return canvas; } -export function createWrapperAndCanvas(config, options) { +export function createWrapperAndCanvas(options) { const wrapper = document.createElement('div'); const canvas = document.createElement('canvas'); diff --git a/src/helpers/index.js b/src/helpers/index.js index ae20215..ad8008f 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -1,5 +1,4 @@ export * from './chart'; -export * from './defaults'; export * from './dom'; export * from './fixture'; export * from './spriting'; diff --git a/src/index.js b/src/index.js index 8f34c5b..1341b2f 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ import {_acquireChart, _releaseChart} from './helpers/index'; export {specsFromFixtures} from './fixture'; export {afterEvent, waitForResize, triggerMouseEvent} from './events'; +export {applyDefaultChartConfig, applyDefaultFixtureOptions} from './defaults'; // Keep track of all acquired charts to automatically release them after each specs const charts = {};