diff --git a/package-lock.json b/package-lock.json index 9b1cc3ac5e..e850941a98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@eslint/js": "^8.49.0", "@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^6.7.2", - "blockly": "^11.0.0", + "blockly": "^12.0.0-beta.1", "conventional-changelog-conventionalcommits": "^5.0.0", "eslint": "^8.49.0", "eslint-config-google": "^0.14.0", @@ -911,12 +911,12 @@ } }, "node_modules/blockly": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/blockly/-/blockly-11.0.0.tgz", - "integrity": "sha512-6Ie7HuZWZLaETIVKFEP4FPDz267Pubn6+weQNZvXzqnkOYp9sKPSsPue8QIMCV9Qb5F4wYhqivgiDcZJcE1UlQ==", + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/blockly/-/blockly-12.0.0-beta.1.tgz", + "integrity": "sha512-lECwZ4K+YuLXMM0yxWTz1lwkmDl424sst7h/dhtSefuCki8afjI/F87byYK/ZIZsMKBEz2+8wEJ1Wlx5cYWIAg==", "dev": true, "dependencies": { - "jsdom": "23.0.0" + "jsdom": "25.0.1" }, "engines": { "node": ">=18" @@ -1288,15 +1288,15 @@ } }, "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/data-urls": { @@ -2227,9 +2227,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -3057,6 +3057,18 @@ "node": ">= 6" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -3539,38 +3551,38 @@ } }, "node_modules/jsdom": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.0.tgz", - "integrity": "sha512-cbL/UCtohJguhFC7c2/hgW6BeZCNvP7URQGnx9tSJRYKCdnfbfWOrtuLTMfiB2VxKsx5wPHVsh/J0aBy9lIIhQ==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "dependencies": { - "cssstyle": "^3.0.0", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.3", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.14.2", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "canvas": "^3.0.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -3603,9 +3615,9 @@ } }, "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "dependencies": { "agent-base": "^7.0.2", @@ -3615,18 +3627,6 @@ "node": ">= 14" } }, - "node_modules/jsdom/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jsdom/node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -4055,9 +4055,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", - "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true }, "node_modules/object-assign": { @@ -4263,12 +4263,12 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "dev": true, "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -4447,12 +4447,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4497,12 +4491,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4772,9 +4760,9 @@ } }, "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, "node_modules/run-parallel": { @@ -5178,6 +5166,24 @@ "xtend": "~4.0.1" } }, + "node_modules/tldts": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.65.tgz", + "integrity": "sha512-xU9gLTfAGsADQ2PcWee6Hg8RFAv0DnjMGVJmDnUmI8a9+nYmapMQix4afwrdaCtT+AqP4MaxEzu7cCrYmBPbzQ==", + "dev": true, + "dependencies": { + "tldts-core": "^6.1.65" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.65.tgz", + "integrity": "sha512-Uq5t0N0Oj4nQSbU8wFN1YYENvMthvwU13MQrMJRspYCGLSAZjAfoBOJki5IQpnBM/WFskxxC/gIOTwaedmHaSg==", + "dev": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5203,27 +5209,15 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" + "node": ">=16" } }, "node_modules/tr46": { @@ -5369,16 +5363,6 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5525,18 +5509,6 @@ "node": ">=10.13.0" } }, - "node_modules/vinyl-fs/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/vinyl-sourcemap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", @@ -5587,18 +5559,6 @@ "node": ">=12" } }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", @@ -5609,9 +5569,9 @@ } }, "node_modules/whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", "dev": true, "dependencies": { "tr46": "^5.0.0", @@ -6407,12 +6367,12 @@ "dev": true }, "blockly": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/blockly/-/blockly-11.0.0.tgz", - "integrity": "sha512-6Ie7HuZWZLaETIVKFEP4FPDz267Pubn6+weQNZvXzqnkOYp9sKPSsPue8QIMCV9Qb5F4wYhqivgiDcZJcE1UlQ==", + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/blockly/-/blockly-12.0.0-beta.1.tgz", + "integrity": "sha512-lECwZ4K+YuLXMM0yxWTz1lwkmDl424sst7h/dhtSefuCki8afjI/F87byYK/ZIZsMKBEz2+8wEJ1Wlx5cYWIAg==", "dev": true, "requires": { - "jsdom": "23.0.0" + "jsdom": "25.0.1" } }, "brace-expansion": { @@ -6707,12 +6667,12 @@ } }, "cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "requires": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" } }, "data-urls": { @@ -7383,9 +7343,9 @@ } }, "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -8014,6 +7974,15 @@ "debug": "4" } }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -8365,31 +8334,31 @@ "dev": true }, "jsdom": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.0.tgz", - "integrity": "sha512-cbL/UCtohJguhFC7c2/hgW6BeZCNvP7URQGnx9tSJRYKCdnfbfWOrtuLTMfiB2VxKsx5wPHVsh/J0aBy9lIIhQ==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "requires": { - "cssstyle": "^3.0.0", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.3", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.14.2", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "dependencies": { @@ -8412,24 +8381,15 @@ } }, "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "requires": { "agent-base": "^7.0.2", "debug": "4" } }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, "whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -8763,9 +8723,9 @@ } }, "nwsapi": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", - "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true }, "object-assign": { @@ -8919,12 +8879,12 @@ "dev": true }, "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "dev": true, "requires": { - "entities": "^4.4.0" + "entities": "^4.5.0" } }, "path-exists": { @@ -9051,12 +9011,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -9088,12 +9042,6 @@ "side-channel": "^1.0.4" } }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9290,9 +9238,9 @@ } }, "rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, "run-parallel": { @@ -9617,6 +9565,21 @@ "xtend": "~4.0.1" } }, + "tldts": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.65.tgz", + "integrity": "sha512-xU9gLTfAGsADQ2PcWee6Hg8RFAv0DnjMGVJmDnUmI8a9+nYmapMQix4afwrdaCtT+AqP4MaxEzu7cCrYmBPbzQ==", + "dev": true, + "requires": { + "tldts-core": "^6.1.65" + } + }, + "tldts-core": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.65.tgz", + "integrity": "sha512-Uq5t0N0Oj4nQSbU8wFN1YYENvMthvwU13MQrMJRspYCGLSAZjAfoBOJki5IQpnBM/WFskxxC/gIOTwaedmHaSg==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9636,23 +9599,12 @@ } }, "tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "dependencies": { - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - } + "tldts": "^6.1.32" } }, "tr46": { @@ -9765,16 +9717,6 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9889,17 +9831,6 @@ "value-or-function": "^4.0.0", "vinyl": "^3.0.0", "vinyl-sourcemap": "^2.0.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } } }, "vinyl-sourcemap": { @@ -9938,17 +9869,6 @@ "dev": true, "requires": { "iconv-lite": "0.6.3" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } } }, "whatwg-mimetype": { @@ -9958,9 +9878,9 @@ "dev": true }, "whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", "dev": true, "requires": { "tr46": "^5.0.0", diff --git a/package.json b/package.json index 177396cc5d..be5e65263e 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@eslint/js": "^8.49.0", "@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^6.7.2", - "blockly": "^11.0.0", + "blockly": "^12.0.0-beta.1", "conventional-changelog-conventionalcommits": "^5.0.0", "eslint": "^8.49.0", "eslint-config-google": "^0.14.0", diff --git a/plugins/block-shareable-procedures/src/observable_parameter_model.ts b/plugins/block-shareable-procedures/src/observable_parameter_model.ts index 4e14647c55..b253874af9 100644 --- a/plugins/block-shareable-procedures/src/observable_parameter_model.ts +++ b/plugins/block-shareable-procedures/src/observable_parameter_model.ts @@ -13,7 +13,7 @@ export class ObservableParameterModel implements Blockly.procedures.IParameterModel { private id: string; - private variable: Blockly.VariableModel; + private variable: Blockly.IVariableModel; private shouldFireEvents = false; private procedureModel: Blockly.procedures.IProcedureModel | null = null; @@ -44,8 +44,8 @@ export class ObservableParameterModel * @returns This parameter model. */ setName(name: string, id?: string): this { - if (name === this.variable.name) return this; - const oldName = this.variable.name; + if (name === this.variable.getName()) return this; + const oldName = this.variable.getName(); this.variable = this.workspace.getVariable(name) ?? this.workspace.createVariable(name, '', id); @@ -73,7 +73,7 @@ export class ObservableParameterModel protected createBackingVariable( name: string, varId?: string, - ): Blockly.VariableModel { + ): Blockly.IVariableModel { this.variable = this.workspace.getVariable(name) ?? this.workspace.createVariable(name, '', varId); @@ -100,7 +100,7 @@ export class ObservableParameterModel * @returns the name of this parameter. */ getName(): string { - return this.variable.name; + return this.variable.getName(); } /** @@ -123,7 +123,7 @@ export class ObservableParameterModel /** * @returns the variable model associated with the parameter model. */ - getVariableModel(): Blockly.VariableModel { + getVariableModel(): Blockly.IVariableModel { return this.variable; } diff --git a/plugins/block-shareable-procedures/test/procedure_blocks.mocha.js b/plugins/block-shareable-procedures/test/procedure_blocks.mocha.js index 8733ff18c9..8b0694a6eb 100644 --- a/plugins/block-shareable-procedures/test/procedure_blocks.mocha.js +++ b/plugins/block-shareable-procedures/test/procedure_blocks.mocha.js @@ -1237,6 +1237,7 @@ suite('Procedures', function () { 'if a procedure caller block was already disabled before ' + 'its definition was disabled, it is not reenabled', function () { + this.workspace.options.disable = true; const defBlock = createProcDefBlock(this.workspace); const callBlock = createProcCallBlock(this.workspace); globalThis.clock.runAll(); diff --git a/plugins/content-highlight/src/index.ts b/plugins/content-highlight/src/index.ts index 4ec5a2d23f..f8a072b908 100644 --- a/plugins/content-highlight/src/index.ts +++ b/plugins/content-highlight/src/index.ts @@ -13,7 +13,7 @@ import * as Blockly from 'blockly/core'; /** * List of events that cause a change in content area size. */ -const contentChangeEvents = [ +const contentChangeEvents: string[] = [ Blockly.Events.VIEWPORT_CHANGE, Blockly.Events.BLOCK_MOVE, Blockly.Events.BLOCK_DELETE, diff --git a/plugins/continuous-toolbox/README.md b/plugins/continuous-toolbox/README.md index 81504bed6c..dc8cfd3f2b 100644 --- a/plugins/continuous-toolbox/README.md +++ b/plugins/continuous-toolbox/README.md @@ -21,26 +21,26 @@ npm install @blockly/continuous-toolbox --save ## Usage -Include the toolbox, flyout, and metrics manager classes from the plugin in the options struct used when injecting Blockly. This style of flyout works best with a toolbox definition that does not use collapsible categories. +Import and call the `registerContinuousToolbox()` function before injecting +Blockly. This style of flyout works best with a toolbox definition that does +not use collapsible categories. -Note that this plugin uses APIs introduced in the `3.20200924.3` release of Blockly, so you will need to use at least this version or higher. +Note that this plugin uses APIs introduced in the `v12` release of Blockly, so +you will need to use at least this version or higher. ```js import * as Blockly from 'blockly'; -import { - ContinuousToolbox, - ContinuousFlyout, - ContinuousMetrics, -} from '@blockly/continuous-toolbox'; +import {registerContinuousToolbox} from '@blockly/continuous-toolbox'; // Inject Blockly. +registerContinuousToolbox(); const workspace = Blockly.inject('blocklyDiv', { + toolbox: toolboxCategories, plugins: { - toolbox: ContinuousToolbox, - flyoutsVerticalToolbox: ContinuousFlyout, - metricsManager: ContinuousMetrics, + flyoutsVerticalToolbox: 'ContinuousFlyout', + metricsManager: 'ContinuousMetrics', + toolbox: 'ContinuousToolbox', }, - toolbox: toolboxCategories, // ... your other options here ... }); ``` diff --git a/plugins/continuous-toolbox/package-lock.json b/plugins/continuous-toolbox/package-lock.json index 8e5b604102..9ee1aa2009 100644 --- a/plugins/continuous-toolbox/package-lock.json +++ b/plugins/continuous-toolbox/package-lock.json @@ -16,7 +16,7 @@ "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^11.0.0" + "blockly": "^12.0.0-beta.0" } }, "node_modules/@babel/code-frame": { @@ -261,19 +261,6 @@ "node": ">=6.9.0" } }, - "node_modules/@blockly/block-test": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-6.0.6.tgz", - "integrity": "sha512-qxX3nuMRP3pirq8Pwo6TInZWQZnwVNGuRiwIcfKHvpd80eBXEhNGVLvqTPMKu+GU64oTChqm+qSa8QJ0y8j9xg==", - "dev": true, - "license": "Apache 2.0", - "engines": { - "node": ">=8.17.0" - }, - "peerDependencies": { - "blockly": "^11.0.0" - } - }, "node_modules/@blockly/dev-scripts": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@blockly/dev-scripts/-/dev-scripts-4.0.5.tgz", @@ -311,17 +298,16 @@ } }, "node_modules/@blockly/dev-tools": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-8.0.7.tgz", - "integrity": "sha512-/gtLu2tu4ZGaqVCfvivKJ5kWk8lUMQzJh8qtn6Z/U2SJng0nQXcXBEcFVlFAUPt1dE4lNMR7ZYScJw/V+38bgg==", + "version": "8.0.12", + "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-8.0.12.tgz", + "integrity": "sha512-jE0y/Z7ggmM2JS4l0Xf2ic3eecuM+ZDjUZNCcM2k6yy0VDJoxOPN63Cq2soswXQRuKHfzRMHY48rCvoKL3MqPA==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@blockly/block-test": "^6.0.6", - "@blockly/theme-dark": "^7.0.5", - "@blockly/theme-deuteranopia": "^6.0.5", - "@blockly/theme-highcontrast": "^6.0.5", - "@blockly/theme-tritanopia": "^6.0.5", + "@blockly/block-test": "^6.0.11", + "@blockly/theme-dark": "^7.0.10", + "@blockly/theme-deuteranopia": "^6.0.10", + "@blockly/theme-highcontrast": "^6.0.10", + "@blockly/theme-tritanopia": "^6.0.10", "chai": "^4.2.0", "dat.gui": "^0.7.7", "lodash.assign": "^4.2.0", @@ -336,31 +322,23 @@ "blockly": "^11.0.0" } }, - "node_modules/@blockly/eslint-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@blockly/eslint-config/-/eslint-config-4.0.1.tgz", - "integrity": "sha512-yY6aeX6gv0T/+lFwxP35yVbZT2Q6kOgeDfBXTmIsul+S6Qr0ZqMJIkwrCzl1z45YRrB1WBGUJw40rimFwspeyg==", + "node_modules/@blockly/dev-tools/node_modules/@blockly/block-test": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-6.0.11.tgz", + "integrity": "sha512-aIgcxkof1gLJtJXKSvmnug9iSXbv5Qilnov4Sa/QNURiWJRxvMNqWiTZJVu/reuCQK4Qm4jadg9R9l+eu7ujvw==", "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "babel-eslint": "^10.1.0", - "eslint-config-google": "^0.14.0", - "eslint-plugin-jsdoc": "^46.8.0" - }, "engines": { - "node": ">=10.0.0" + "node": ">=8.17.0" }, "peerDependencies": { - "eslint": "7.x" + "blockly": "^11.0.0" } }, - "node_modules/@blockly/theme-dark": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.5.tgz", - "integrity": "sha512-TUS7X+UM5AvTe4Z1mtb371psViAeZSSmTzWuFrdNolX2i9P6XbNA9iKFDF0MObO307pOrtXodmsXpvbtgLeCUw==", + "node_modules/@blockly/dev-tools/node_modules/@blockly/theme-dark": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.10.tgz", + "integrity": "sha512-Wc6n115vt9alxzPkEwYtvBBGoPUV3gaYE00dvSKhqXTNoy1Xioujj9kT9VkGmdMO2mhgnJNczSpvxG8tcd4zLQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=8.17.0" }, @@ -368,12 +346,11 @@ "blockly": "^11.0.0" } }, - "node_modules/@blockly/theme-deuteranopia": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-deuteranopia/-/theme-deuteranopia-6.0.5.tgz", - "integrity": "sha512-z2hcsmRd5yaKf96gNZ1qM7IDqPb2M492FZhomRz6PgFYw/2rFXmQk6WcI84mmcTLrwfOfLkq/HIaPd23Wc3Hcw==", + "node_modules/@blockly/dev-tools/node_modules/@blockly/theme-deuteranopia": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-deuteranopia/-/theme-deuteranopia-6.0.10.tgz", + "integrity": "sha512-im5nIvf/Z0f1vJ9DK5Euu6URfY8G44xeFsat2b7TySF0BfAUWkGsagK3C6D5NatigPxKZqz3exC9zeXEtprAcg==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=8.17.0" }, @@ -381,12 +358,11 @@ "blockly": "^11.0.0" } }, - "node_modules/@blockly/theme-highcontrast": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-highcontrast/-/theme-highcontrast-6.0.5.tgz", - "integrity": "sha512-rLhFM1+M6okikeSGHbZfxqJB7quWFm+RBXCi8ht8bjSkspdh5PCUOs10U4/GbI+YXSuAd2uFdg20xINL+X3KfQ==", + "node_modules/@blockly/dev-tools/node_modules/@blockly/theme-highcontrast": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-highcontrast/-/theme-highcontrast-6.0.10.tgz", + "integrity": "sha512-s1hehl/b50IhebCs20hm2hFWbUTqJ2YSGdR0gnp2NLfNNRWwyZHZk+q4aG3k4L0YBWjNfE3XiRCkDISy83dBIA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=8.17.0" }, @@ -394,12 +370,11 @@ "blockly": "^11.0.0" } }, - "node_modules/@blockly/theme-tritanopia": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-tritanopia/-/theme-tritanopia-6.0.5.tgz", - "integrity": "sha512-FVZmKfTQt1OQGsoZP78ET6V9xw83dd2vlJbTdjL1V6xlh0hixFGnqsze+Pw/FXiSWWLgeNKxTqQ6ImwhTHf5wA==", + "node_modules/@blockly/dev-tools/node_modules/@blockly/theme-tritanopia": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-tritanopia/-/theme-tritanopia-6.0.10.tgz", + "integrity": "sha512-QNIvUHokGMLnCWUzERRZa6sSkD5RIUynWDI+KNurBH21NeWnSNScQiNu0dS/w5MSkZ/Iqqbi79UZoF49SzEayg==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=8.17.0" }, @@ -407,6 +382,25 @@ "blockly": "^11.0.0" } }, + "node_modules/@blockly/eslint-config": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@blockly/eslint-config/-/eslint-config-4.0.1.tgz", + "integrity": "sha512-yY6aeX6gv0T/+lFwxP35yVbZT2Q6kOgeDfBXTmIsul+S6Qr0ZqMJIkwrCzl1z45YRrB1WBGUJw40rimFwspeyg==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "babel-eslint": "^10.1.0", + "eslint-config-google": "^0.14.0", + "eslint-plugin-jsdoc": "^46.8.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "eslint": "7.x" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -475,6 +469,22 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -499,6 +509,12 @@ "node": ">= 4" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@humanwhocodes/config-array": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", @@ -1480,9 +1496,9 @@ } }, "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1509,16 +1525,28 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "peer": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -1542,28 +1570,6 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -1687,6 +1693,12 @@ "node": ">=8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "peer": true + }, "node_modules/babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -1751,6 +1763,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/blockly": { + "version": "12.0.0-beta.0", + "resolved": "https://registry.npmjs.org/blockly/-/blockly-12.0.0-beta.0.tgz", + "integrity": "sha512-Z9cULe95wgQGj87DQZ9RBJRu5oMLQEUTz0beZVcZL/ddVuga6qtZZ9DbaDfCvt4ffVz1O/kyNzPJ+cqvovSjGg==", + "peer": true, + "dependencies": { + "jsdom": "25.0.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -2125,6 +2149,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "peer": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2289,17 +2325,41 @@ "node": ">= 8" } }, + "node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "peer": true, + "dependencies": { + "rrweb-cssom": "^0.7.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/dat.gui": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz", "integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==", "dev": true }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "peer": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -2326,6 +2386,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "peer": true + }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -2427,6 +2493,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2573,6 +2648,18 @@ "node": ">=8.6" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "peer": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/envinfo": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", @@ -2826,6 +2913,22 @@ "@babel/highlight": "^7.10.4" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", @@ -2859,6 +2962,12 @@ "node": ">= 4" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", @@ -2873,6 +2982,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/espree/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", @@ -3330,6 +3451,22 @@ "webpack": "^5.11.0" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -3339,6 +3476,12 @@ "ajv": "^6.9.1" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -3357,6 +3500,20 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3707,6 +3864,18 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "peer": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/html-entities": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", @@ -3770,6 +3939,19 @@ "node": ">=8.0.0" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "peer": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/http-proxy-middleware": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", @@ -3795,6 +3977,19 @@ } } }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "peer": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3819,7 +4014,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -4079,6 +4273,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "peer": true + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4216,6 +4416,46 @@ "node": ">=12.0.0" } }, + "node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "peer": true, + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -4241,9 +4481,9 @@ "dev": true }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { @@ -4511,7 +4751,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4520,7 +4759,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4699,8 +4937,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -4801,6 +5038,12 @@ "node": ">=8" } }, + "node_modules/nwsapi": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", + "peer": true + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -5002,6 +5245,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "peer": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -5230,7 +5485,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -5492,6 +5746,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "peer": true + }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -5551,8 +5811,19 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "peer": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } }, "node_modules/schema-utils": { "version": "4.2.0", @@ -5573,28 +5844,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -5983,6 +6232,22 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/source-map-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/source-map-loader/node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -5992,6 +6257,12 @@ "ajv": "^6.9.1" } }, + "node_modules/source-map-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/source-map-loader/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -6208,6 +6479,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "peer": true + }, "node_modules/table": { "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", @@ -6224,28 +6501,6 @@ "node": ">=10.0.0" } }, - "node_modules/table/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -6307,6 +6562,22 @@ } } }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -6330,6 +6601,12 @@ "node": ">= 10.13.0" } }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -6363,18 +6640,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -6401,6 +6666,24 @@ "dev": true, "license": "MIT" }, + "node_modules/tldts": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.65.tgz", + "integrity": "sha512-xU9gLTfAGsADQ2PcWee6Hg8RFAv0DnjMGVJmDnUmI8a9+nYmapMQix4afwrdaCtT+AqP4MaxEzu7cCrYmBPbzQ==", + "peer": true, + "dependencies": { + "tldts-core": "^6.1.65" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.65.tgz", + "integrity": "sha512-Uq5t0N0Oj4nQSbU8wFN1YYENvMthvwU13MQrMJRspYCGLSAZjAfoBOJki5IQpnBM/WFskxxC/gIOTwaedmHaSg==", + "peer": true + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -6432,6 +6715,30 @@ "node": ">=0.6" } }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "peer": true, + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "peer": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tree-dump": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", @@ -6479,9 +6786,9 @@ } }, "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true }, "node_modules/tsutils": { @@ -6499,6 +6806,12 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6546,6 +6859,20 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -6653,6 +6980,18 @@ "node": ">= 0.8" } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "peer": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", @@ -6676,6 +7015,15 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/webpack": { "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", @@ -6829,13 +7177,6 @@ "url": "https://github.com/sponsors/streamich" } }, - "node_modules/webpack-dev-middleware/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true, - "license": "0BSD" - }, "node_modules/webpack-dev-server": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", @@ -6983,16 +7324,20 @@ "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=0.4.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/webpack/node_modules/ajv-keywords": { @@ -7004,6 +7349,12 @@ "ajv": "^6.9.1" } }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -7047,6 +7398,40 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "peer": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "peer": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7132,7 +7517,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -7150,6 +7534,21 @@ } } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "peer": true + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -7426,12 +7825,6 @@ "to-fast-properties": "^2.0.0" } }, - "@blockly/block-test": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-6.0.6.tgz", - "integrity": "sha512-qxX3nuMRP3pirq8Pwo6TInZWQZnwVNGuRiwIcfKHvpd80eBXEhNGVLvqTPMKu+GU64oTChqm+qSa8QJ0y8j9xg==", - "dev": true - }, "@blockly/dev-scripts": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@blockly/dev-scripts/-/dev-scripts-4.0.5.tgz", @@ -7454,22 +7847,59 @@ } }, "@blockly/dev-tools": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-8.0.7.tgz", - "integrity": "sha512-/gtLu2tu4ZGaqVCfvivKJ5kWk8lUMQzJh8qtn6Z/U2SJng0nQXcXBEcFVlFAUPt1dE4lNMR7ZYScJw/V+38bgg==", + "version": "8.0.12", + "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-8.0.12.tgz", + "integrity": "sha512-jE0y/Z7ggmM2JS4l0Xf2ic3eecuM+ZDjUZNCcM2k6yy0VDJoxOPN63Cq2soswXQRuKHfzRMHY48rCvoKL3MqPA==", "dev": true, "requires": { - "@blockly/block-test": "^6.0.6", - "@blockly/theme-dark": "^7.0.5", - "@blockly/theme-deuteranopia": "^6.0.5", - "@blockly/theme-highcontrast": "^6.0.5", - "@blockly/theme-tritanopia": "^6.0.5", + "@blockly/block-test": "^6.0.11", + "@blockly/theme-dark": "^7.0.10", + "@blockly/theme-deuteranopia": "^6.0.10", + "@blockly/theme-highcontrast": "^6.0.10", + "@blockly/theme-tritanopia": "^6.0.10", "chai": "^4.2.0", "dat.gui": "^0.7.7", "lodash.assign": "^4.2.0", "lodash.merge": "^4.6.2", "monaco-editor": "^0.20.0", "sinon": "^9.0.2" + }, + "dependencies": { + "@blockly/block-test": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-6.0.11.tgz", + "integrity": "sha512-aIgcxkof1gLJtJXKSvmnug9iSXbv5Qilnov4Sa/QNURiWJRxvMNqWiTZJVu/reuCQK4Qm4jadg9R9l+eu7ujvw==", + "dev": true, + "requires": {} + }, + "@blockly/theme-dark": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.10.tgz", + "integrity": "sha512-Wc6n115vt9alxzPkEwYtvBBGoPUV3gaYE00dvSKhqXTNoy1Xioujj9kT9VkGmdMO2mhgnJNczSpvxG8tcd4zLQ==", + "dev": true, + "requires": {} + }, + "@blockly/theme-deuteranopia": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-deuteranopia/-/theme-deuteranopia-6.0.10.tgz", + "integrity": "sha512-im5nIvf/Z0f1vJ9DK5Euu6URfY8G44xeFsat2b7TySF0BfAUWkGsagK3C6D5NatigPxKZqz3exC9zeXEtprAcg==", + "dev": true, + "requires": {} + }, + "@blockly/theme-highcontrast": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-highcontrast/-/theme-highcontrast-6.0.10.tgz", + "integrity": "sha512-s1hehl/b50IhebCs20hm2hFWbUTqJ2YSGdR0gnp2NLfNNRWwyZHZk+q4aG3k4L0YBWjNfE3XiRCkDISy83dBIA==", + "dev": true, + "requires": {} + }, + "@blockly/theme-tritanopia": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-tritanopia/-/theme-tritanopia-6.0.10.tgz", + "integrity": "sha512-QNIvUHokGMLnCWUzERRZa6sSkD5RIUynWDI+KNurBH21NeWnSNScQiNu0dS/w5MSkZ/Iqqbi79UZoF49SzEayg==", + "dev": true, + "requires": {} + } } }, "@blockly/eslint-config": { @@ -7485,30 +7915,6 @@ "eslint-plugin-jsdoc": "^46.8.0" } }, - "@blockly/theme-dark": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.5.tgz", - "integrity": "sha512-TUS7X+UM5AvTe4Z1mtb371psViAeZSSmTzWuFrdNolX2i9P6XbNA9iKFDF0MObO307pOrtXodmsXpvbtgLeCUw==", - "dev": true - }, - "@blockly/theme-deuteranopia": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-deuteranopia/-/theme-deuteranopia-6.0.5.tgz", - "integrity": "sha512-z2hcsmRd5yaKf96gNZ1qM7IDqPb2M492FZhomRz6PgFYw/2rFXmQk6WcI84mmcTLrwfOfLkq/HIaPd23Wc3Hcw==", - "dev": true - }, - "@blockly/theme-highcontrast": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-highcontrast/-/theme-highcontrast-6.0.5.tgz", - "integrity": "sha512-rLhFM1+M6okikeSGHbZfxqJB7quWFm+RBXCi8ht8bjSkspdh5PCUOs10U4/GbI+YXSuAd2uFdg20xINL+X3KfQ==", - "dev": true - }, - "@blockly/theme-tritanopia": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-tritanopia/-/theme-tritanopia-6.0.5.tgz", - "integrity": "sha512-FVZmKfTQt1OQGsoZP78ET6V9xw83dd2vlJbTdjL1V6xlh0hixFGnqsze+Pw/FXiSWWLgeNKxTqQ6ImwhTHf5wA==", - "dev": true - }, "@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -7558,6 +7964,18 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -7572,6 +7990,12 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true } } }, @@ -7710,7 +8134,8 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "dev": true + "dev": true, + "requires": {} }, "@jsonjoy.com/json-pack": { "version": "1.1.0", @@ -7728,7 +8153,8 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", - "dev": true + "dev": true, + "requires": {} }, "@leichtgewicht/ip-codec": { "version": "2.0.5", @@ -8272,19 +8698,22 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", @@ -8315,33 +8744,44 @@ } }, "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true }, "acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true + "dev": true, + "requires": {} }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} + }, + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "peer": true, + "requires": { + "debug": "^4.3.4" + } }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" } }, "ajv-formats": { @@ -8351,26 +8791,6 @@ "dev": true, "requires": { "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } } }, "ajv-keywords": { @@ -8458,6 +8878,12 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "peer": true + }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -8504,6 +8930,15 @@ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true }, + "blockly": { + "version": "12.0.0-beta.0", + "resolved": "https://registry.npmjs.org/blockly/-/blockly-12.0.0-beta.0.tgz", + "integrity": "sha512-Z9cULe95wgQGj87DQZ9RBJRu5oMLQEUTz0beZVcZL/ddVuga6qtZZ9DbaDfCvt4ffVz1O/kyNzPJ+cqvovSjGg==", + "peer": true, + "requires": { + "jsdom": "25.0.1" + } + }, "body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -8760,6 +9195,15 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "peer": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -8888,17 +9332,35 @@ "which": "^2.0.1" } }, + "cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "peer": true, + "requires": { + "rrweb-cssom": "^0.7.1" + } + }, "dat.gui": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz", "integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==", "dev": true }, + "data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "peer": true, + "requires": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + } + }, "debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -8909,6 +9371,12 @@ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "peer": true + }, "deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -8972,6 +9440,12 @@ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "peer": true + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -9079,6 +9553,12 @@ "strip-ansi": "^6.0.1" } }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "peer": true + }, "envinfo": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", @@ -9190,6 +9670,18 @@ "@babel/highlight": "^7.10.4" } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", @@ -9210,6 +9702,12 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true } } }, @@ -9217,7 +9715,8 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-plugin-jsdoc": { "version": "46.10.1", @@ -9293,6 +9792,12 @@ "eslint-visitor-keys": "^1.3.0" }, "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", @@ -9638,10 +10143,29 @@ "tapable": "^2.2.1" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "schema-utils": { @@ -9657,6 +10181,17 @@ } } }, + "form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "peer": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -9910,6 +10445,15 @@ } } }, + "html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "peer": true, + "requires": { + "whatwg-encoding": "^3.1.1" + } + }, "html-entities": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", @@ -9952,6 +10496,16 @@ "requires-port": "^1.0.0" } }, + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "peer": true, + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, "http-proxy-middleware": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", @@ -9965,6 +10519,16 @@ "micromatch": "^4.0.2" } }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "peer": true, + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -9981,7 +10545,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -10142,6 +10705,12 @@ "isobject": "^3.0.1" } }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "peer": true + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -10235,6 +10804,35 @@ "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", "dev": true }, + "jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "peer": true, + "requires": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -10254,9 +10852,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -10461,14 +11059,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -10600,8 +11196,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "7.2.5", @@ -10683,6 +11278,12 @@ "path-key": "^3.0.0" } }, + "nwsapi": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", + "peer": true + }, "object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -10816,6 +11417,15 @@ "lines-and-columns": "^1.1.6" } }, + "parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "peer": true, + "requires": { + "entities": "^4.5.0" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -10976,8 +11586,7 @@ "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "qs": { "version": "6.11.0", @@ -11146,6 +11755,12 @@ "glob": "^7.1.3" } }, + "rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "peer": true + }, "run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -11170,8 +11785,16 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "peer": true, + "requires": { + "xmlchars": "^2.2.0" + } }, "schema-utils": { "version": "4.2.0", @@ -11183,26 +11806,6 @@ "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } } }, "select-hose": { @@ -11500,10 +12103,29 @@ "whatwg-mimetype": "^2.3.0" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "schema-utils": { @@ -11672,6 +12294,12 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "peer": true + }, "table": { "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", @@ -11683,26 +12311,6 @@ "slice-ansi": "^4.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } } }, "tapable": { @@ -11721,14 +12329,6 @@ "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" - }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true - } } }, "terser-webpack-plugin": { @@ -11744,11 +12344,24 @@ "terser": "^5.26.0" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "jest-worker": { "version": "27.5.1", @@ -11761,6 +12374,12 @@ "supports-color": "^8.0.0" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -11793,7 +12412,8 @@ "version": "1.21.0", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", - "dev": true + "dev": true, + "requires": {} }, "thunky": { "version": "1.1.0", @@ -11801,6 +12421,21 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "tldts": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.65.tgz", + "integrity": "sha512-xU9gLTfAGsADQ2PcWee6Hg8RFAv0DnjMGVJmDnUmI8a9+nYmapMQix4afwrdaCtT+AqP4MaxEzu7cCrYmBPbzQ==", + "peer": true, + "requires": { + "tldts-core": "^6.1.65" + } + }, + "tldts-core": { + "version": "6.1.65", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.65.tgz", + "integrity": "sha512-Uq5t0N0Oj4nQSbU8wFN1YYENvMthvwU13MQrMJRspYCGLSAZjAfoBOJki5IQpnBM/WFskxxC/gIOTwaedmHaSg==", + "peer": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -11822,11 +12457,30 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "peer": true, + "requires": { + "tldts": "^6.1.32" + } + }, + "tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "peer": true, + "requires": { + "punycode": "^2.3.1" + } + }, "tree-dump": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", - "dev": true + "dev": true, + "requires": {} }, "ts-loader": { "version": "9.5.1", @@ -11850,9 +12504,9 @@ } }, "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true }, "tsutils": { @@ -11862,6 +12516,14 @@ "dev": true, "requires": { "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } } }, "type-check": { @@ -11895,6 +12557,13 @@ "mime-types": "~2.1.24" } }, + "typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "peer": true + }, "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -11962,6 +12631,15 @@ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true }, + "w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "peer": true, + "requires": { + "xml-name-validator": "^5.0.0" + } + }, "watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", @@ -11981,6 +12659,12 @@ "minimalistic-assert": "^1.0.0" } }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "peer": true + }, "webpack": { "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", @@ -12013,16 +12697,29 @@ "webpack-sources": "^3.2.3" }, "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "schema-utils": { @@ -12092,12 +12789,6 @@ "tree-dump": "^1.0.1", "tslib": "^2.0.0" } - }, - "tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true } } }, @@ -12216,6 +12907,31 @@ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, + "whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "peer": true, + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "peer": true + }, + "whatwg-url": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "peer": true, + "requires": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -12275,7 +12991,19 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true + "requires": {} + }, + "xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "peer": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "peer": true }, "y18n": { "version": "5.0.8", @@ -12337,4 +13065,4 @@ "dev": true } } -} \ No newline at end of file +} diff --git a/plugins/continuous-toolbox/package.json b/plugins/continuous-toolbox/package.json index fea7df2717..cc21c6fe07 100644 --- a/plugins/continuous-toolbox/package.json +++ b/plugins/continuous-toolbox/package.json @@ -43,7 +43,7 @@ "@blockly/dev-tools": "^8.0.10" }, "peerDependencies": { - "blockly": "^11.0.0" + "blockly": "^12.0.0-beta.0" }, "publishConfig": { "access": "public", diff --git a/plugins/continuous-toolbox/src/ContinuousCategory.js b/plugins/continuous-toolbox/src/ContinuousCategory.js deleted file mode 100644 index f0c29fe6f5..0000000000 --- a/plugins/continuous-toolbox/src/ContinuousCategory.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Toolbox category with styling for continuous toolbox. - */ - -import * as Blockly from 'blockly/core'; - -/** Toolbox category for continuous toolbox. */ -export class ContinuousCategory extends Blockly.ToolboxCategory { - /** - * Constructor for ContinuousCategory which is used in ContinuousToolbox. - * @override - */ - constructor(categoryDef, toolbox) { - super(categoryDef, toolbox); - } - - /** @override */ - createLabelDom_(name) { - const label = document.createElement('div'); - label.setAttribute('id', this.getId() + '.label'); - label.textContent = name; - label.classList.add(this.cssConfig_['label']); - return label; - } - - /** @override */ - createIconDom_() { - const icon = document.createElement('div'); - icon.classList.add('categoryBubble'); - icon.style.backgroundColor = this.colour_; - return icon; - } - - /** @override */ - addColourBorder_() { - // No-op - } - - /** @override */ - setSelected(isSelected) { - if (isSelected) { - this.rowDiv_.style.backgroundColor = 'gray'; - Blockly.utils.dom.addClass(this.rowDiv_, this.cssConfig_['selected']); - } else { - this.rowDiv_.style.backgroundColor = ''; - Blockly.utils.dom.removeClass(this.rowDiv_, this.cssConfig_['selected']); - } - Blockly.utils.aria.setState( - /** @type {!Element} */ (this.htmlDiv_), - Blockly.utils.aria.State.SELECTED, - isSelected, - ); - } -} - -Blockly.registry.register( - Blockly.registry.Type.TOOLBOX_ITEM, - Blockly.ToolboxCategory.registrationName, - ContinuousCategory, - true, -); diff --git a/plugins/continuous-toolbox/src/ContinuousCategory.ts b/plugins/continuous-toolbox/src/ContinuousCategory.ts new file mode 100644 index 0000000000..6a5da76c9c --- /dev/null +++ b/plugins/continuous-toolbox/src/ContinuousCategory.ts @@ -0,0 +1,78 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Toolbox category with styling for continuous toolbox. + */ + +import * as Blockly from 'blockly/core'; + +/** Toolbox category for continuous toolbox. */ +export class ContinuousCategory extends Blockly.ToolboxCategory { + /** + * Creates a DOM element to display the category's label. + * + * @param name The name of this category. + * @returns The newly created category label DOM element. + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + override createLabelDom_(name: string): Element { + const label = document.createElement('div'); + label.setAttribute('id', this.getId() + '.label'); + label.textContent = name; + label.classList.add(this.cssConfig_['label'] ?? ''); + return label; + } + + /** + * Creates a DOM element to display the category's icon. This category uses + * color swatches instead of graphical icons. + * + * @returns The newly created category icon DOM element. + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + override createIconDom_(): Element { + const icon = document.createElement('div'); + icon.classList.add('categoryBubble'); + icon.style.backgroundColor = this.colour_; + return icon; + } + + /** + * Adds a color indicator to the toolbox category. Intentionally a no-op. + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + override addColourBorder_() { + // No-op + } + + /** + * Sets whether or not this category is selected in the toolbox. + * + * @param isSelected True if this category is selected, otherwise false. + */ + override setSelected(isSelected: boolean) { + if (!this.rowDiv_ || !this.htmlDiv_) return; + if (isSelected) { + this.rowDiv_.style.backgroundColor = 'gray'; + Blockly.utils.dom.addClass( + this.rowDiv_, + this.cssConfig_['selected'] ?? '', + ); + } else { + this.rowDiv_.style.backgroundColor = ''; + Blockly.utils.dom.removeClass( + this.rowDiv_, + this.cssConfig_['selected'] ?? '', + ); + } + Blockly.utils.aria.setState( + this.htmlDiv_, + Blockly.utils.aria.State.SELECTED, + isSelected, + ); + } +} diff --git a/plugins/continuous-toolbox/src/ContinuousFlyout.js b/plugins/continuous-toolbox/src/ContinuousFlyout.js deleted file mode 100644 index 32b063bb6a..0000000000 --- a/plugins/continuous-toolbox/src/ContinuousFlyout.js +++ /dev/null @@ -1,312 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Flyout that supports always-open continuous scrolling. - */ - -import * as Blockly from 'blockly/core'; -import {ContinuousToolbox} from './ContinuousToolbox'; -import {ContinuousFlyoutMetrics} from './ContinuousMetricsFlyout'; - -/** - * Class for continuous flyout. - */ -export class ContinuousFlyout extends Blockly.VerticalFlyout { - /** @override */ - constructor(workspaceOptions) { - super(workspaceOptions); - - /** - * List of scroll positions for each category. - * @type {!Array<{name: string, position: !Object}>} - */ - this.scrollPositions = []; - - /** - * Target scroll position, used to smoothly scroll to a given category - * location when selected. - * @type {?number} - */ - this.scrollTarget = null; - - /** - * The percentage of the distance to the scrollTarget that should be - * scrolled at a time. Lower values will produce a smoother, slower scroll. - * @type {number} - */ - this.scrollAnimationFraction = 0.3; - - /** - * Whether to recycle blocks when refreshing the flyout. When false, do not - * allow anything to be recycled. The default is to recycle. - * @type {boolean} - * @private - */ - this.recyclingEnabled_ = true; - - this.workspace_.setMetricsManager( - new ContinuousFlyoutMetrics(this.workspace_, this), - ); - - this.workspace_.addChangeListener((e) => { - if (e.type === Blockly.Events.VIEWPORT_CHANGE) { - this.selectCategoryByScrollPosition_(-this.workspace_.scrollY); - } - }); - - this.autoClose = false; - } - - /** - * Gets parent toolbox. - * Since we registered the ContinuousToolbox, we know that's its type. - * @returns {!ContinuousToolbox} Toolbox that owns this flyout. - * @private - */ - getParentToolbox_() { - const toolbox = this.targetWorkspace.getToolbox(); - return /** @type {!ContinuousToolbox} */ (toolbox); - } - - /** - * Records scroll position for each category in the toolbox. - * The scroll position is determined by the coordinates of each category's - * label after the entire flyout has been rendered. - * @package - */ - recordScrollPositions() { - this.scrollPositions = []; - const categoryLabels = this.buttons_.filter( - (button) => - button.isLabel() && - this.getParentToolbox_().getCategoryByName(button.getButtonText()), - ); - for (const [index, button] of categoryLabels.entries()) { - if (button.isLabel()) { - const position = button.getPosition(); - const adjustedPosition = new Blockly.utils.Coordinate( - position.x, - position.y - this.labelGaps[index], - ); - this.scrollPositions.push({ - name: button.getButtonText(), - position: adjustedPosition, - }); - } - } - } - - /** - * Returns the scroll position for the given category name. - * @param {string} name Category name. - * @returns {?Object} Scroll position for given category, or null if not - * found. - * @package - */ - getCategoryScrollPosition(name) { - for (const scrollInfo of this.scrollPositions) { - if (scrollInfo.name === name) { - return scrollInfo.position; - } - } - console.warn(`Scroll position not recorded for category ${name}`); - return null; - } - - /** - * Selects an item in the toolbox based on the scroll position of the flyout. - * @param {number} position Current scroll position of the workspace. - * @private - */ - selectCategoryByScrollPosition_(position) { - // If we are currently auto-scrolling, due to selecting a category by - // clicking on it, do not update the category selection. - if (this.scrollTarget !== null) { - return; - } - const scaledPosition = Math.round(position / this.workspace_.scale); - // Traverse the array of scroll positions in reverse, so we can select the - // furthest category that the scroll position is beyond. - for (let i = this.scrollPositions.length - 1; i >= 0; i--) { - const category = this.scrollPositions[i]; - if (scaledPosition >= category.position.y) { - this.getParentToolbox_().selectCategoryByName(category.name); - return; - } - } - } - - /** - * Scrolls flyout to given position. - * @param {number} position The Y coordinate to scroll to. - */ - scrollTo(position) { - // Set the scroll target to either the scaled position or the lowest - // possible scroll point, whichever is smaller. - const metrics = this.workspace_.getMetrics(); - this.scrollTarget = Math.min( - position * this.workspace_.scale, - metrics.scrollHeight - metrics.viewHeight, - ); - - this.stepScrollAnimation_(); - } - - /** - * Step the scrolling animation by scrolling a fraction of the way to - * a scroll target, and request the next frame if necessary. - * @private - */ - stepScrollAnimation_() { - if (this.scrollTarget === null) { - return; - } - - const currentScrollPos = -this.workspace_.scrollY; - const diff = this.scrollTarget - currentScrollPos; - if (Math.abs(diff) < 1) { - this.workspace_.scrollbar.setY(this.scrollTarget); - this.scrollTarget = null; - return; - } - this.workspace_.scrollbar.setY( - currentScrollPos + diff * this.scrollAnimationFraction, - ); - - requestAnimationFrame(this.stepScrollAnimation_.bind(this)); - } - - /** - * Add additional padding to the bottom of the flyout if needed, - * in order to make it possible to scroll to the top of the last category. - * @param {!Blockly.MetricsManager.ContainerRegion} contentMetrics Content - * metrics for the flyout. - * @param {!Blockly.MetricsManager.ContainerRegion} viewMetrics View metrics - * for the flyout. - * @returns {number} Additional bottom padding. - */ - calculateBottomPadding(contentMetrics, viewMetrics) { - if (this.scrollPositions.length > 0) { - const lastCategory = - this.scrollPositions[this.scrollPositions.length - 1]; - const lastPosition = lastCategory.position.y * this.workspace_.scale; - const lastCategoryHeight = contentMetrics.height - lastPosition; - if (lastCategoryHeight < viewMetrics.height) { - return viewMetrics.height - lastCategoryHeight; - } - } - return 0; - } - - /** @override */ - getX() { - if ( - this.isVisible() && - this.targetWorkspace.toolboxPosition === this.toolboxPosition_ && - this.targetWorkspace.getToolbox() && - this.toolboxPosition_ !== Blockly.utils.toolbox.Position.LEFT - ) { - // This makes it so blocks cannot go under the flyout in RTL mode. - return this.targetWorkspace.getMetricsManager().getViewMetrics().width; - } - - return super.getX(); - } - - /** - * @override - */ - show(flyoutDef) { - super.show(flyoutDef); - this.recordScrollPositions(); - this.workspace_.resizeContents(); - if (!this.getParentToolbox_().getSelectedItem()) { - this.selectCategoryByScrollPosition_(0); - } - } - - /** - * Determine if this block can be recycled in the flyout. Blocks that have no - * variables and are not dynamic shadows can be recycled. - * @param {!Blockly.BlockSvg} block The block to attempt to recycle. - * @returns {boolean} True if the block can be recycled. - * @protected - */ - blockIsRecyclable_(block) { - if (!this.recyclingEnabled_) { - return false; - } - - // If the block needs to parse mutations, never recycle. - if (block.mutationToDom && block.domToMutation) { - return false; - } - - if (!block.isEnabled()) { - return false; - } - - for (const input of block.inputList) { - for (const field of input.fieldRow) { - // No variables. - if (field.referencesVariables()) { - return false; - } - if (field instanceof Blockly.FieldDropdown) { - if (field.isOptionListDynamic()) { - return false; - } - } - } - // Check children. - if (input.connection) { - const targetBlock = - /** @type {Blockly.BlockSvg} */ - (input.connection.targetBlock()); - if (targetBlock && !this.blockIsRecyclable_(targetBlock)) { - return false; - } - } - } - return true; - } - - /** - * Sets the function used to determine whether a block is recyclable. - * @param {function(!Blockly.BlockSvg):boolean} func The function used to - * determine if a block is recyclable. - * @public - */ - setBlockIsRecyclable(func) { - this.blockIsRecyclable_ = func; - } - - /** - * Set whether the flyout can recycle blocks. - * @param {boolean} isEnabled True to allow blocks to be recycled, false - * otherwise. - * @public - */ - setRecyclingEnabled(isEnabled) { - this.recyclingEnabled_ = isEnabled; - } - - /** - * Lay out the blocks in the flyout. - * @param {Array} contents The blocks and buttons to lay out. - * @param {Array} gaps The visible gaps between blocks. - */ - layout_(contents, gaps) { - super.layout_(contents, gaps); - this.labelGaps = []; - for (const [index, item] of contents.entries()) { - if (item.type === 'button' && item.button.isLabel()) { - this.labelGaps.push(gaps[index - 1] ?? this.MARGIN); - } - } - } -} diff --git a/plugins/continuous-toolbox/src/ContinuousFlyout.ts b/plugins/continuous-toolbox/src/ContinuousFlyout.ts new file mode 100644 index 0000000000..9dc3f7d87c --- /dev/null +++ b/plugins/continuous-toolbox/src/ContinuousFlyout.ts @@ -0,0 +1,292 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Flyout that supports always-open continuous scrolling. + */ + +import * as Blockly from 'blockly/core'; +import {ContinuousToolbox} from './ContinuousToolbox'; +import {ContinuousFlyoutMetrics} from './ContinuousFlyoutMetrics'; +import {RecyclableBlockFlyoutInflater} from './RecyclableBlockFlyoutInflater'; + +interface LabelFlyoutItem extends Blockly.FlyoutItem { + getElement(): Blockly.FlyoutButton; +} + +/** + * Class for continuous flyout. + */ +export class ContinuousFlyout extends Blockly.VerticalFlyout { + /** + * Target scroll position, used to smoothly scroll to a given category + * location when selected. + */ + private scrollTarget?: number; + + /** + * Map from category name to its position in the flyout. + */ + private scrollPositions = new Map(); + + /** + * The percentage of the distance to the scrollTarget that should be + * scrolled at a time. Lower values will produce a smoother, slower scroll. + */ + protected scrollAnimationFraction = 0.3; + + /** + * Prevents the flyout from closing automatically when a block is dragged out. + */ + override autoClose = false; + + /** + * Creates a new ContinuousFlyout. + * + * @param workspaceOptions The injection options for the flyout's workspace. + */ + constructor(workspaceOptions: Blockly.Options) { + super(workspaceOptions); + + this.getWorkspace().setMetricsManager( + new ContinuousFlyoutMetrics(this.getWorkspace(), this), + ); + + this.getWorkspace().addChangeListener((e: Blockly.Events.Abstract) => { + if (e.type === Blockly.Events.VIEWPORT_CHANGE) { + this.selectCategoryByScrollPosition(-this.getWorkspace().scrollY); + } + }); + + this.setRecyclingEnabled(true); + } + + /** + * Gets parent toolbox. + * Since we registered the ContinuousToolbox, we know that's its type. + * + * @returns Toolbox that owns this flyout. + */ + private getParentToolbox(): ContinuousToolbox { + return this.targetWorkspace.getToolbox() as ContinuousToolbox; + } + + /** + * Records scroll position for each category in the toolbox. + * The scroll position is determined by the coordinates of each category's + * label after the entire flyout has been rendered. + */ + private recordScrollPositions() { + this.scrollPositions.clear(); + this.getContents() + .filter(this.toolboxItemIsLabel.bind(this)) + .map((item) => item.getElement()) + .forEach((label) => { + this.scrollPositions.set( + label.getButtonText(), + label.getPosition().y - label.height, + ); + }); + } + + /** + * Validates and typechecks that the given toolbox item represents a label. + * + * @param item The toolbox item to check. + * @returns True if the item represents a label in the flyout, and is a + * Blockly.FlyoutButton. + */ + protected toolboxItemIsLabel( + item: Blockly.FlyoutItem, + ): item is LabelFlyoutItem { + const element = item.getElement(); + return !!( + item.getType() === 'label' && + element instanceof Blockly.FlyoutButton && + element.isLabel() && + this.getParentToolbox().getCategoryByName(element.getButtonText()) + ); + } + + /** + * Selects an item in the toolbox based on the scroll position of the flyout. + * + * @param position Current scroll position of the workspace. + */ + private selectCategoryByScrollPosition(position: number) { + // If we are currently auto-scrolling, due to selecting a category by + // clicking on it, do not update the category selection. + if (this.scrollTarget) { + return; + } + const scaledPosition = Math.round(position / this.getWorkspace().scale); + // Traverse the array of scroll positions in reverse, so we can select the + // furthest category that the scroll position is beyond. + for (const [name, position] of [ + ...this.scrollPositions.entries(), + ].reverse()) { + if (scaledPosition >= position) { + this.getParentToolbox().selectCategoryByName(name); + return; + } + } + } + + /** + * Scrolls the flyout to given position. + * + * @param position The Y coordinate to scroll to. + */ + scrollTo(position: number) { + // Set the scroll target to either the scaled position or the lowest + // possible scroll point, whichever is smaller. + const metrics = this.getWorkspace().getMetrics(); + this.scrollTarget = Math.min( + position * this.getWorkspace().scale, + metrics.scrollHeight - metrics.viewHeight, + ); + + this.stepScrollAnimation(); + } + + /** + * Scrolls the flyout to display the given category at the top. + * + * @param category The toolbox category to scroll to in the flyout. + */ + scrollToCategory(category: Blockly.ISelectableToolboxItem) { + const position = this.scrollPositions.get(category.getName()); + if (!position) { + console.warn(`Scroll position not recorded for category ${name}`); + return; + } + this.scrollTo(position); + } + + /** + * Step the scrolling animation by scrolling a fraction of the way to + * a scroll target, and request the next frame if necessary. + */ + private stepScrollAnimation() { + if (!this.scrollTarget) return; + + const currentScrollPos = -this.getWorkspace().scrollY; + const diff = this.scrollTarget - currentScrollPos; + if (Math.abs(diff) < 1) { + this.getWorkspace().scrollbar?.setY(this.scrollTarget); + this.scrollTarget = undefined; + return; + } + this.getWorkspace().scrollbar?.setY( + currentScrollPos + diff * this.scrollAnimationFraction, + ); + + requestAnimationFrame(this.stepScrollAnimation.bind(this)); + } + + /** + * Handles mouse wheel events. + * + * @param e The mouse wheel event to handle. + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + protected override wheel_(e: WheelEvent) { + // Don't scroll in response to mouse wheel events if we're currently + // animating scrolling to a category. + if (!this.scrollTarget) { + super.wheel_(e); + } + } + + /** + * Calculates the additional padding needed at the bottom of the flyout in + * order to make it possible to scroll to the top of the last category. + * + * @param contentMetrics Content metrics for the flyout. + * @param viewMetrics View metrics for the flyout. + * @returns The additional bottom padding needed. + */ + calculateBottomPadding( + contentMetrics: Blockly.MetricsManager.ContainerRegion, + viewMetrics: Blockly.MetricsManager.ContainerRegion, + ): number { + if (this.scrollPositions.size > 0) { + const lastPosition = + ([...this.scrollPositions.values()].pop() ?? 0) * + this.getWorkspace().scale; + const lastCategoryHeight = contentMetrics.height - lastPosition; + if (lastCategoryHeight < viewMetrics.height) { + return viewMetrics.height - lastCategoryHeight; + } + } + return 0; + } + + /** + * Returns the X coordinate for the flyout's position. + */ + override getX(): number { + if ( + this.isVisible() && + this.targetWorkspace.toolboxPosition === this.toolboxPosition_ && + this.targetWorkspace.getToolbox() && + this.toolboxPosition_ !== Blockly.utils.toolbox.Position.LEFT + ) { + // This makes it so blocks cannot go under the flyout in RTL mode. + return this.targetWorkspace.getMetricsManager().getViewMetrics().width; + } + + return super.getX(); + } + + /** + * Displays the given contents in the flyout. + * + * @param flyoutDef A string or JSON object specifying the contents of the + * flyout. + */ + override show(flyoutDef: Blockly.utils.toolbox.FlyoutDefinition | string) { + super.show(flyoutDef); + this.recordScrollPositions(); + this.getWorkspace().resizeContents(); + if (!this.getParentToolbox().getSelectedItem()) { + this.selectCategoryByScrollPosition(0); + } + this.getRecyclableInflater().emptyRecycledBlocks(); + } + + /** + * Sets the function used to determine whether a block is recyclable. + * + * @param func The function used to determine if a block is recyclable. + */ + setBlockIsRecyclable(func: (block: Blockly.Block) => boolean) { + this.getRecyclableInflater().setRecyclingEligibilityChecker(func); + } + + /** + * Set whether the flyout can recycle blocks. + * + * @param isEnabled True to allow blocks to be recycled, false otherwise. + */ + setRecyclingEnabled(isEnabled: boolean) { + this.getRecyclableInflater().setRecyclingEnabled(isEnabled); + } + + /** + * Returns the recyclable block flyout inflater. + * + * @returns The recyclable inflater. + */ + protected getRecyclableInflater(): RecyclableBlockFlyoutInflater { + const inflater = this.getInflaterForType('block'); + if (!(inflater instanceof RecyclableBlockFlyoutInflater)) { + throw new Error('The RecyclableBlockFlyoutInflater is not registered.'); + } + + return inflater; + } +} diff --git a/plugins/continuous-toolbox/src/ContinuousFlyoutMetrics.ts b/plugins/continuous-toolbox/src/ContinuousFlyoutMetrics.ts new file mode 100644 index 0000000000..bd5fea5cdc --- /dev/null +++ b/plugins/continuous-toolbox/src/ContinuousFlyoutMetrics.ts @@ -0,0 +1,47 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as Blockly from 'blockly/core'; +import type {ContinuousFlyout} from './ContinuousFlyout'; + +/** Adds additional padding to the bottom of the flyout if needed. */ +export class ContinuousFlyoutMetrics extends Blockly.FlyoutMetricsManager { + /** + * Returns the metrics for the scroll area of the continuous flyout's + * workspace. Adds additional padding to the bottom of the flyout if needed in + * order to make it possible to scroll to the top of the last category. + * + * @param getWorkspaceCoordinates True to get the scroll metrics in + * workspace coordinates, false to get them in pixel coordinates. + * @param cachedViewMetrics The view metrics if they have been previously + * computed. + * @param cachedContentMetrics The content metrics if they have been + * previously computed. + * @returns The metrics for the scroll container. + */ + override getScrollMetrics( + getWorkspaceCoordinates?: boolean, + cachedViewMetrics?: Blockly.MetricsManager.ContainerRegion, + cachedContentMetrics?: Blockly.MetricsManager.ContainerRegion, + ) { + const scrollMetrics = super.getScrollMetrics( + getWorkspaceCoordinates, + cachedViewMetrics, + cachedContentMetrics, + ); + const contentMetrics = + cachedContentMetrics || this.getContentMetrics(getWorkspaceCoordinates); + const viewMetrics = + cachedViewMetrics || this.getViewMetrics(getWorkspaceCoordinates); + + if (scrollMetrics) { + scrollMetrics.height += ( + this.flyout_ as ContinuousFlyout + ).calculateBottomPadding(contentMetrics, viewMetrics); + } + return scrollMetrics; + } +} diff --git a/plugins/continuous-toolbox/src/ContinuousMetrics.js b/plugins/continuous-toolbox/src/ContinuousMetrics.ts similarity index 75% rename from plugins/continuous-toolbox/src/ContinuousMetrics.js rename to plugins/continuous-toolbox/src/ContinuousMetrics.ts index 97b9a72812..135e16f581 100644 --- a/plugins/continuous-toolbox/src/ContinuousMetrics.js +++ b/plugins/continuous-toolbox/src/ContinuousMetrics.ts @@ -12,16 +12,18 @@ import * as Blockly from 'blockly/core'; /** Computes metrics for a toolbox with an always open flyout. */ export class ContinuousMetrics extends Blockly.MetricsManager { - /** @override */ - constructor(workspace) { - super(workspace); - } /** * Computes the viewport size to not include the toolbox and the flyout. * The default viewport includes the flyout. - * @override + * + * @param getWorkspaceCoordinates True to get the view metrics in workspace + * coordinates, false to get them in pixel coordinates. + * @returns The width, height, top and left of the viewport in either + * workspace coordinates or pixel coordinates. */ - getViewMetrics(getWorkspaceCoordinates = undefined) { + override getViewMetrics( + getWorkspaceCoordinates?: boolean, + ): Blockly.MetricsManager.ContainerRegion { const scale = getWorkspaceCoordinates ? this.workspace_.scale : 1; const svgMetrics = this.getSvgMetrics(); const toolboxMetrics = this.getToolboxMetrics(); @@ -29,7 +31,7 @@ export class ContinuousMetrics extends Blockly.MetricsManager { const toolboxPosition = toolboxMetrics.position; if (this.workspace_.getToolbox()) { - // Note: Not actually supported at this time due to ContinunousToolbox + // Note: Not actually supported at this time due to ContinuousToolbox // only supporting a vertical flyout. But included for completeness. if ( toolboxPosition == Blockly.TOOLBOX_AT_TOP || @@ -52,11 +54,13 @@ export class ContinuousMetrics extends Blockly.MetricsManager { } /** - * Moves the absoluteLeft and absoluteTop so they no longer include the - * flyout. - * @override + * Gets the absolute left and absolute top in pixel coordinates. + * This is where the visible workspace starts in relation to the SVG + * container, shifted to not include the area behind the flyout. + * + * @returns The absolute metrics for the workspace. */ - getAbsoluteMetrics() { + override getAbsoluteMetrics(): Blockly.MetricsManager.AbsoluteMetrics { const toolboxMetrics = this.getToolboxMetrics(); const flyoutMetrics = this.getFlyoutMetrics(false); const toolboxPosition = toolboxMetrics.position; @@ -81,9 +85,3 @@ export class ContinuousMetrics extends Blockly.MetricsManager { }; } } - -Blockly.registry.register( - Blockly.registry.Type.METRICS_MANAGER, - 'CustomMetricsManager', - ContinuousMetrics, -); diff --git a/plugins/continuous-toolbox/src/ContinuousMetricsFlyout.js b/plugins/continuous-toolbox/src/ContinuousMetricsFlyout.js deleted file mode 100644 index 90b84a872e..0000000000 --- a/plugins/continuous-toolbox/src/ContinuousMetricsFlyout.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as Blockly from 'blockly/core'; - -/** Adds additional padding to the bottom of the flyout if needed. */ -export class ContinuousFlyoutMetrics extends Blockly.FlyoutMetricsManager { - /** @override */ - constructor(workspace, flyout) { - super(workspace, flyout); - } - /** - * Adds additional padding to the bottom of the flyout if needed, - * in order to make it possible to scroll to the top of the last category. - * @override - */ - getScrollMetrics( - getWorkspaceCoordinates = undefined, - cachedViewMetrics = undefined, - cachedContentMetrics = undefined, - ) { - const scrollMetrics = super.getScrollMetrics( - getWorkspaceCoordinates, - cachedViewMetrics, - cachedContentMetrics, - ); - const contentMetrics = - cachedContentMetrics || this.getContentMetrics(getWorkspaceCoordinates); - const viewMetrics = - cachedViewMetrics || this.getViewMetrics(getWorkspaceCoordinates); - - if (scrollMetrics) { - scrollMetrics.height += this.flyout_.calculateBottomPadding( - contentMetrics, - viewMetrics, - ); - } - return scrollMetrics; - } -} diff --git a/plugins/continuous-toolbox/src/ContinuousToolbox.js b/plugins/continuous-toolbox/src/ContinuousToolbox.js deleted file mode 100644 index 634f9a2033..0000000000 --- a/plugins/continuous-toolbox/src/ContinuousToolbox.js +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Toolbox that uses a continuous scrolling flyout. - */ - -import * as Blockly from 'blockly/core'; -import {ContinuousFlyout} from './ContinuousFlyout'; - -/** - * Class for continuous toolbox. - */ -export class ContinuousToolbox extends Blockly.Toolbox { - /** @override */ - constructor(workspace) { - super(workspace); - } - - /** @override */ - init() { - super.init(); - - // Populate the flyout with all blocks and show it immediately. - const flyout = this.getFlyout(); - flyout.show(this.getInitialFlyoutContents_()); - flyout.recordScrollPositions(); - - this.workspace_.addChangeListener((e) => { - if ( - e.type === Blockly.Events.BLOCK_CREATE || - e.type === Blockly.Events.BLOCK_DELETE - ) { - this.refreshSelection(); - } - }); - } - - /** @override */ - getFlyout() { - return /** @type {ContinuousFlyout} */ (super.getFlyout()); - } - - /** - * Gets the contents that should be shown in the flyout immediately. - * This includes all blocks and labels for each category of block. - * @returns {!Blockly.utils.toolbox.FlyoutItemInfoArray} Flyout contents. - * @private - */ - getInitialFlyoutContents_() { - /** @type {!Blockly.utils.toolbox.FlyoutItemInfoArray} */ - let contents = []; - for (const toolboxItem of this.contents_) { - if (toolboxItem instanceof Blockly.ToolboxCategory) { - // Create a label node to go at the top of the category - contents.push({kind: 'LABEL', text: toolboxItem.getName()}); - /** - * @type {string|Blockly.utils.toolbox.FlyoutItemInfoArray| - * Blockly.utils.toolbox.FlyoutItemInfo} - */ - let itemContents = toolboxItem.getContents(); - - // Handle custom categories (e.g. variables and functions) - if (typeof itemContents === 'string') { - itemContents = - /** @type {!Blockly.utils.toolbox.DynamicCategoryInfo} */ ({ - custom: itemContents, - kind: 'CATEGORY', - }); - } - contents = contents.concat(itemContents); - } - } - return contents; - } - - /** @override */ - refreshSelection() { - this.getFlyout().show(this.getInitialFlyoutContents_()); - } - - /** @override */ - updateFlyout_(_oldItem, newItem) { - if (newItem) { - const target = this.getFlyout().getCategoryScrollPosition( - newItem.name_, - ).y; - this.getFlyout().scrollTo(target); - } - } - - /** @override */ - shouldDeselectItem_(oldItem, newItem) { - // Should not deselect if the same category is clicked again. - return oldItem && oldItem !== newItem; - } - - /** - * Gets a category by name. - * @param {string} name Name of category to get. - * @returns {?Blockly.ToolboxCategory} Category, or null if not - * found. - * @package - */ - getCategoryByName(name) { - const category = this.contents_.find( - (item) => - item instanceof Blockly.ToolboxCategory && - item.isSelectable() && - name === item.getName(), - ); - if (category) { - return /** @type {!Blockly.ToolboxCategory} */ (category); - } - return null; - } - - /** - * Selects the category with the given name. - * Similar to setSelectedItem, but importantly, does not call updateFlyout - * because this is called while the flyout is being scrolled. - * @param {string} name Name of category to select. - * @package - */ - selectCategoryByName(name) { - const newItem = this.getCategoryByName(name); - if (!newItem) { - return; - } - const oldItem = this.selectedItem_; - - if (this.shouldDeselectItem_(oldItem, newItem)) { - this.deselectItem_(oldItem); - } - - if (this.shouldSelectItem_(oldItem, newItem)) { - this.selectItem_(oldItem, newItem); - } - } - - /** @override */ - getClientRect() { - // If the flyout never closes, it should be the deletable area. - const flyout = this.getFlyout(); - if (flyout && !flyout.autoClose) { - return flyout.getClientRect(); - } - return super.getClientRect(); - } -} - -Blockly.Css.register(` -.categoryBubble { - margin: 0 auto 0.125rem; - border-radius: 100%; - border: 1px solid; - width: 1.25rem; - height: 1.25rem; -} -.blocklyTreeRow { - height: initial; - padding: 3px 0; -} -.blocklyTreeRowContentContainer { - display: flex; - flex-direction: column; -} -.blocklyTreeLabel { - margin: auto; -} -`); diff --git a/plugins/continuous-toolbox/src/ContinuousToolbox.ts b/plugins/continuous-toolbox/src/ContinuousToolbox.ts new file mode 100644 index 0000000000..5f77dd94c2 --- /dev/null +++ b/plugins/continuous-toolbox/src/ContinuousToolbox.ts @@ -0,0 +1,203 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Toolbox that uses a continuous scrolling flyout. + */ + +import * as Blockly from 'blockly/core'; +import {ContinuousFlyout} from './ContinuousFlyout'; + +/** + * Class for continuous toolbox. + */ +export class ContinuousToolbox extends Blockly.Toolbox { + /** + * Timeout ID used to prevent refreshing the flyout during extensive block + * changes. + */ + private refreshDebouncer?: ReturnType; + + /** + * Initializes the continuous toolbox. + */ + override init() { + super.init(); + + // Populate the flyout with all blocks and show it immediately. + const flyout = this.getFlyout(); + flyout.show(this.getInitialFlyoutContents()); + + this.getWorkspace().addChangeListener((e: Blockly.Events.Abstract) => { + if ( + e.type === Blockly.Events.BLOCK_CREATE || + e.type === Blockly.Events.BLOCK_DELETE || + e.type === Blockly.Events.BLOCK_CHANGE + ) { + this.refreshSelection(); + } + }); + } + + /** + * Returns the continuous toolbox's flyout. + * + * @returns The toolbox's flyout. + */ + override getFlyout(): ContinuousFlyout { + return super.getFlyout() as ContinuousFlyout; + } + + /** + * Gets the contents that should be shown in the flyout immediately. + * This includes all blocks and labels for each category of block. + * + * @returns Flyout contents. + */ + private getInitialFlyoutContents(): Blockly.utils.toolbox.FlyoutItemInfoArray { + return this.getToolboxItems().flatMap(this.convertToolboxItemToFlyoutItems); + } + + /** + * Converts a given toolbox item to an array of flyout items, generally a + * label followed by the category's blocks. + * + * @param toolboxItem The toolbox item/category to convert. + * @returns An array of flyout items contained in the given toolbox item. + */ + protected convertToolboxItemToFlyoutItems( + toolboxItem: Blockly.IToolboxItem, + ): Blockly.utils.toolbox.FlyoutItemInfoArray { + let contents: Blockly.utils.toolbox.FlyoutItemInfoArray = []; + if (toolboxItem instanceof Blockly.ToolboxCategory) { + // Create a label node to go at the top of the category + contents.push({kind: 'LABEL', text: toolboxItem.getName()}); + let itemContents = toolboxItem.getContents(); + + // Handle custom categories (e.g. variables and functions) + if (typeof itemContents === 'string') { + itemContents = [ + { + custom: itemContents, + kind: 'CATEGORY', + }, + ]; + } + contents = contents.concat(itemContents); + } + return contents; + } + + /** + * Updates the flyout's contents if it is visible. + */ + override refreshSelection() { + if (this.getFlyout().isVisible()) { + if (this.refreshDebouncer) { + clearTimeout(this.refreshDebouncer); + } + this.refreshDebouncer = setTimeout(() => { + this.getFlyout().show(this.getInitialFlyoutContents()); + }, 100); + } + } + + /** + * Scrolls the flyout to display the newly selected category's contents. + * + * @param oldItem The previously selected toolbox category. + * @param newItem The newly selected toolbox category. + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + override updateFlyout_( + oldItem: Blockly.ISelectableToolboxItem | null, + newItem: Blockly.ISelectableToolboxItem | null, + ) { + if (newItem) { + this.getFlyout().scrollToCategory(newItem); + if (!this.getFlyout().isVisible()) { + this.getFlyout().show(this.getInitialFlyoutContents()); + } + } else if (this.getFlyout().autoClose) { + this.getFlyout().hide(); + } + } + + /** + * Returns whether or not the toolbox should deselect the old category. + * + * @param oldItem The previously selected toolbox category. + * @param newItem The newly selected toolbox category. + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + override shouldDeselectItem_( + oldItem: Blockly.ISelectableToolboxItem | null, + newItem: Blockly.ISelectableToolboxItem | null, + ): boolean { + // Should not deselect if the same category is clicked again. + return !!(oldItem && oldItem !== newItem); + } + + /** + * Gets a category by name. + * + * @param name Name of category to get. + * @returns Category, or null if not found. + * @internal + */ + getCategoryByName(name: string): Blockly.ISelectableToolboxItem | null { + const category = this.getToolboxItems().find( + (item) => + item instanceof Blockly.ToolboxCategory && + item.isSelectable() && + name === item.getName(), + ); + if (category) { + return category as Blockly.ISelectableToolboxItem; + } + return null; + } + + /** + * Selects the category with the given name. + * Similar to setSelectedItem, but importantly, does not call updateFlyout + * because this is called while the flyout is being scrolled. + * + * @param name Name of category to select. + * @internal + */ + selectCategoryByName(name: string) { + const newItem = this.getCategoryByName(name); + if (!newItem) { + return; + } + const oldItem = this.selectedItem_; + + if (oldItem && this.shouldDeselectItem_(oldItem, newItem)) { + this.deselectItem_(oldItem); + } + + if (this.shouldSelectItem_(oldItem, newItem)) { + this.selectItem_(oldItem, newItem); + } + } + + /** + * Returns the bounding rectangle of the drag target/deletion area in pixels + * relative to the viewport. + * + * @returns The toolbox's bounding box. Null if drag target area should be + * ignored. + */ + override getClientRect(): Blockly.utils.Rect | null { + // If the flyout never closes, it should be the deletable area. + const flyout = this.getFlyout(); + if (flyout && !flyout.autoClose) { + return flyout.getClientRect(); + } + return super.getClientRect(); + } +} diff --git a/plugins/continuous-toolbox/src/RecyclableBlockFlyoutInflater.ts b/plugins/continuous-toolbox/src/RecyclableBlockFlyoutInflater.ts new file mode 100644 index 0000000000..6a6feb7d43 --- /dev/null +++ b/plugins/continuous-toolbox/src/RecyclableBlockFlyoutInflater.ts @@ -0,0 +1,193 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as Blockly from 'blockly/core'; + +/** + * A block inflater that caches and reuses blocks to improve performance. + */ +export class RecyclableBlockFlyoutInflater extends Blockly.BlockFlyoutInflater { + /** + * Whether or not block recycling is enabled. + */ + private recyclingEnabled = false; + + /** + * Map from block type to block instance. + */ + private recycledBlocks = new Map(); + + /** + * Custom function to use for checking whether or not blocks can be recycled. + */ + private recycleEligibilityChecker?: (block: Blockly.Block) => boolean; + + /** + * Toggles whether or not recycling is enabled. + * + * @param enabled True if recycling should be enabled. + */ + setRecyclingEnabled(enabled: boolean) { + this.recyclingEnabled = enabled; + } + + /** + * Sets a function to use to determine a block's ability to be recycled. + * + * @param checker The eligibility check function to use, or undefined to + * revert to the built-in default. + */ + setRecyclingEligibilityChecker(checker?: (block: Blockly.Block) => boolean) { + this.recycleEligibilityChecker = checker; + } + + /** + * Creates a new block from the given block definition. + * + * @param blockDefinition The definition to create a block from. + * @param workspace The workspace to create the block on. + * @returns The newly created block. + */ + override createBlock( + blockDefinition: Blockly.utils.toolbox.BlockInfo, + workspace: Blockly.WorkspaceSvg, + ): Blockly.BlockSvg { + const blockType = this.getTypeFromDefinition(blockDefinition); + return ( + this.getRecycledBlock(blockType) ?? + super.createBlock(blockDefinition, workspace) + ); + } + + /** + * Returns the type of a block from an XML or JSON block definition. + * + * @param blockDefinition The block definition to parse. + * @returns The block type. + */ + private getTypeFromDefinition( + blockDefinition: Blockly.utils.toolbox.BlockInfo, + ): string { + let type: string | null | undefined; + if (blockDefinition['blockxml']) { + const xml = + typeof blockDefinition['blockxml'] === 'string' + ? Blockly.utils.xml.textToDom(blockDefinition['blockxml']) + : (blockDefinition['blockxml'] as Element); + type = xml.getAttribute('type'); + } else { + type = blockDefinition['type']; + } + + if (!type) { + throw new Error( + `Block type is not specified in block definition: ${JSON.stringify( + blockDefinition, + )}`, + ); + } + return type; + } + + /** + * Puts a previously created block into the recycle bin and moves it to the + * top of the workspace. Used during large workspace swaps to limit the number + * of new DOM elements we need to create. + * + * @param block The block to recycle. + */ + private recycleBlock(block: Blockly.BlockSvg) { + const xy = block.getRelativeToSurfaceXY(); + block.moveBy(-xy.x, -xy.y); + this.recycledBlocks.set(block.type, block); + } + + /** + * Returns a block from the cache of recycled blocks with the given type, or + * undefined if one cannot be found. + * + * @param blockType The type of the block to try to recycle. + * @returns The recycled block, or undefined if one could not be recycled. + */ + private getRecycledBlock(blockType: string): Blockly.BlockSvg | undefined { + const block = this.recycledBlocks.get(blockType); + this.recycledBlocks.delete(blockType); + return block; + } + + /** + * Returns whether the given block can be recycled or not. + * + * @param block The block to check for recyclability. + * @returns True if the block can be recycled. False otherwise. + */ + protected blockIsRecyclable(block: Blockly.Block): boolean { + if (!this.recyclingEnabled) { + return false; + } + + if (this.recycleEligibilityChecker) { + return this.recycleEligibilityChecker(block); + } + + // If the block needs to parse mutations, never recycle. + if (block.mutationToDom && block.domToMutation) { + return false; + } + + if (!block.isEnabled()) { + return false; + } + + for (const input of block.inputList) { + for (const field of input.fieldRow) { + // No variables. + if (field.referencesVariables()) { + return false; + } + if (field instanceof Blockly.FieldDropdown) { + if (field.isOptionListDynamic()) { + return false; + } + } + } + // Check children. + if (input.connection) { + const targetBlock = input.connection.targetBlock(); + if (targetBlock && !this.blockIsRecyclable(targetBlock)) { + return false; + } + } + } + return true; + } + + /** + * Disposes of the provided block. + * + * @param item The block to dispose of. + */ + override disposeItem(item: Blockly.FlyoutItem) { + const element = item.getElement(); + if ( + element instanceof Blockly.BlockSvg && + this.blockIsRecyclable(element) + ) { + this.removeListeners(element.id); + this.recycleBlock(element); + } else { + super.disposeItem(item); + } + } + + /** + * Clears the cache of recycled blocks. + */ + emptyRecycledBlocks() { + this.recycledBlocks.forEach((block) => block.dispose(false, false)); + this.recycledBlocks.clear(); + } +} diff --git a/plugins/continuous-toolbox/src/index.js b/plugins/continuous-toolbox/src/index.js deleted file mode 100644 index 6197eca06c..0000000000 --- a/plugins/continuous-toolbox/src/index.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Continuous-scroll toolbox and flyout that is always open. - */ - -export * from './ContinuousCategory'; -export * from './ContinuousFlyout'; -export * from './ContinuousMetrics'; -export * from './ContinuousToolbox'; diff --git a/plugins/continuous-toolbox/src/index.ts b/plugins/continuous-toolbox/src/index.ts new file mode 100644 index 0000000000..6319793295 --- /dev/null +++ b/plugins/continuous-toolbox/src/index.ts @@ -0,0 +1,90 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Continuous-scroll toolbox and flyout that is always open. + */ + +import * as Blockly from 'blockly/core'; + +import {ContinuousCategory} from './ContinuousCategory'; +import {ContinuousFlyout} from './ContinuousFlyout'; +import {ContinuousMetrics} from './ContinuousMetrics'; +import {ContinuousToolbox} from './ContinuousToolbox'; +import {RecyclableBlockFlyoutInflater} from './RecyclableBlockFlyoutInflater'; + +export { + ContinuousCategory, + ContinuousFlyout, + ContinuousMetrics, + ContinuousToolbox, + RecyclableBlockFlyoutInflater, +}; + +/** + * Registers the components of the continuous toolbox, replacing Blockly's + * built-in defaults. + */ +export function registerContinuousToolbox() { + Blockly.registry.register( + Blockly.registry.Type.TOOLBOX_ITEM, + Blockly.ToolboxCategory.registrationName, + ContinuousCategory, + true, + ); + + Blockly.registry.register( + Blockly.registry.Type.METRICS_MANAGER, + 'ContinuousMetrics', + ContinuousMetrics, + true, + ); + + Blockly.registry.register( + Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX, + 'ContinuousFlyout', + ContinuousFlyout, + true, + ); + + Blockly.registry.register( + Blockly.registry.Type.TOOLBOX, + 'ContinuousToolbox', + ContinuousToolbox, + true, + ); + + Blockly.registry.register( + Blockly.registry.Type.FLYOUT_INFLATER, + 'block', + RecyclableBlockFlyoutInflater, + true, + ); + + Blockly.Css.register(` + .categoryBubble { + margin: 0 auto 0.125rem; + border-radius: 100%; + border: 1px solid; + width: 1.25rem; + height: 1.25rem; + } + .blocklyToolboxCategory { + height: initial; + padding: 3px 0; + } + .blocklyTreeRowContentContainer { + display: flex; + flex-direction: column; + } + .blocklyTreeLabel { + margin: auto; + } + .blocklyToolboxCategoryLabel { + text-align: center; + } + `); +} diff --git a/plugins/continuous-toolbox/test/index.js b/plugins/continuous-toolbox/test/index.js index 57b17ef701..f78f44a60c 100644 --- a/plugins/continuous-toolbox/test/index.js +++ b/plugins/continuous-toolbox/test/index.js @@ -9,12 +9,8 @@ */ import * as Blockly from 'blockly'; -import {toolboxCategories, createPlayground} from '@blockly/dev-tools'; -import { - ContinuousToolbox, - ContinuousFlyout, - ContinuousMetrics, -} from '../src/index'; +import {createPlayground} from '@blockly/dev-tools'; +import {registerContinuousToolbox} from '../src/index'; /** * Create a workspace. @@ -23,23 +19,16 @@ import { * @returns {!Blockly.WorkspaceSvg} The created workspace. */ function createWorkspace(blocklyDiv, options) { - const workspace = Blockly.inject(blocklyDiv, options); - - return workspace; + return Blockly.inject(blocklyDiv, options); } document.addEventListener('DOMContentLoaded', function () { - const defaultOptions = { - toolbox: toolboxCategories, + registerContinuousToolbox(); + createPlayground(document.getElementById('root'), createWorkspace, { plugins: { - toolbox: ContinuousToolbox, - flyoutsVerticalToolbox: ContinuousFlyout, - metricsManager: ContinuousMetrics, + flyoutsVerticalToolbox: 'ContinuousFlyout', + metricsManager: 'ContinuousMetrics', + toolbox: 'ContinuousToolbox', }, - }; - createPlayground( - document.getElementById('root'), - createWorkspace, - defaultOptions, - ); + }); }); diff --git a/plugins/continuous-toolbox/tsconfig.json b/plugins/continuous-toolbox/tsconfig.json new file mode 100644 index 0000000000..b849232f2b --- /dev/null +++ b/plugins/continuous-toolbox/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "outDir": "dist", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "module": "es2015", + "moduleResolution": "bundler", + "target": "es6", + "strict": true + }, + // NOTE: `test/**/*` is automatically included in `blockly-scripts start`. + // Only src matters for production builds. + "include": ["src"] +} diff --git a/plugins/field-bitmap/src/field-bitmap.ts b/plugins/field-bitmap/src/field-bitmap.ts index 70b4fea421..8cf361160f 100644 --- a/plugins/field-bitmap/src/field-bitmap.ts +++ b/plugins/field-bitmap/src/field-bitmap.ts @@ -59,7 +59,6 @@ export class FieldBitmap extends Blockly.Field { super(value, validator, config); this.SERIALIZABLE = true; - this.CURSOR = 'default'; this.buttonOptions = {...DEFAULT_BUTTONS, ...config?.buttons}; this.pixelColours = {...DEFAULT_PIXEL_COLOURS, ...config?.colours}; diff --git a/plugins/field-colour/src/field_colour.ts b/plugins/field-colour/src/field_colour.ts index dc5c88dfe4..4d125853d2 100644 --- a/plugins/field-colour/src/field_colour.ts +++ b/plugins/field-colour/src/field_colour.ts @@ -33,9 +33,6 @@ export class FieldColour extends Blockly.Field { */ override SERIALIZABLE = true; - /** Mouse cursor style when over the hotspot that initiates the editor. */ - override CURSOR = 'default'; - /** * Used to tell if the field needs to be rendered the next time the block is * rendered. Colour fields are statically sized, and only need to be diff --git a/plugins/field-date/src/field_date.ts b/plugins/field-date/src/field_date.ts index 9b2a9ff8b8..0ec7c4846a 100644 --- a/plugins/field-date/src/field_date.ts +++ b/plugins/field-date/src/field_date.ts @@ -20,11 +20,6 @@ export class FieldDate extends Blockly.FieldTextInput { */ SERIALIZABLE = true; - /** - * Mouse cursor style when over the hotspot that initiates the editor. - */ - CURSOR = 'text'; - /** * Class for a date input field. Derived from the Closure library date * picker. diff --git a/plugins/keyboard-navigation/src/navigation.js b/plugins/keyboard-navigation/src/navigation.js index 9fc285ba8d..e78edb897f 100644 --- a/plugins/keyboard-navigation/src/navigation.js +++ b/plugins/keyboard-navigation/src/navigation.js @@ -503,13 +503,15 @@ export class Navigation { const flyoutContents = flyout.getContents(); const firstFlyoutItem = flyoutContents[0]; if (!firstFlyoutItem) return; - if (firstFlyoutItem.button) { + if (firstFlyoutItem.element instanceof Blockly.FlyoutButton) { const astNode = Blockly.ASTNode.createButtonNode( - firstFlyoutItem.button, + firstFlyoutItem.element, ); this.getFlyoutCursor(workspace).setCurNode(astNode); - } else if (firstFlyoutItem.block) { - const astNode = Blockly.ASTNode.createStackNode(firstFlyoutItem.block); + } else if (firstFlyoutItem.element instanceof Blockly.BlockSvg) { + const astNode = Blockly.ASTNode.createStackNode( + firstFlyoutItem.element, + ); this.getFlyoutCursor(workspace).setCurNode(astNode); } } diff --git a/plugins/keyboard-navigation/src/navigation_controller.js b/plugins/keyboard-navigation/src/navigation_controller.js index 8f3820a906..d3eaa4c1c1 100644 --- a/plugins/keyboard-navigation/src/navigation_controller.js +++ b/plugins/keyboard-navigation/src/navigation_controller.js @@ -126,13 +126,13 @@ export class NavigationController { } switch (shortcut.name) { case Constants.SHORTCUT_NAMES.PREVIOUS: - return this.selectPrevious_(); + return this.selectPrevious(); case Constants.SHORTCUT_NAMES.OUT: - return this.selectParent_(); + return this.selectParent(); case Constants.SHORTCUT_NAMES.NEXT: - return this.selectNext_(); + return this.selectNext(); case Constants.SHORTCUT_NAMES.IN: - return this.selectChild_(); + return this.selectChild(); default: return false; } diff --git a/plugins/keyboard-navigation/test/navigation_test.mocha.js b/plugins/keyboard-navigation/test/navigation_test.mocha.js index ed5c67e989..81705b850d 100644 --- a/plugins/keyboard-navigation/test/navigation_test.mocha.js +++ b/plugins/keyboard-navigation/test/navigation_test.mocha.js @@ -83,22 +83,22 @@ suite('Navigation', function () { [ 'Calls toolbox selectNext', createKeyDownEvent(Blockly.utils.KeyCodes.S, 'NotAField'), - 'selectNext_', + 'selectNext', ], [ 'Calls toolbox selectPrevious', createKeyDownEvent(Blockly.utils.KeyCodes.W, 'NotAField'), - 'selectPrevious_', + 'selectPrevious', ], [ 'Calls toolbox selectParent', createKeyDownEvent(Blockly.utils.KeyCodes.D, 'NotAField'), - 'selectChild_', + 'selectChild', ], [ 'Calls toolbox selectChild', createKeyDownEvent(Blockly.utils.KeyCodes.A, 'NotAField'), - 'selectParent_', + 'selectParent', ], ]; @@ -109,7 +109,7 @@ suite('Navigation', function () { test(testCaseName, function () { const toolbox = this.workspace.getToolbox(); const selectStub = sinon.stub(toolbox, stubName); - toolbox.selectedItem_ = toolbox.contents_[0]; + toolbox.selectedItem_ = toolbox.contents.values().next().value; Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); sinon.assert.called(selectStub); }); @@ -554,7 +554,10 @@ suite('Navigation', function () { Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, tEvent); - const firstCategory = this.workspace.getToolbox().contents_[0]; + const firstCategory = this.workspace + .getToolbox() + .contents.values() + .next().value; chai.assert.isTrue(keyDownSpy.returned(true)); chai.assert.equal( this.workspace.getToolbox().getSelectedItem(), diff --git a/plugins/workspace-minimap/src/focus_region.ts b/plugins/workspace-minimap/src/focus_region.ts index bb71f07918..70b5b6fba7 100644 --- a/plugins/workspace-minimap/src/focus_region.ts +++ b/plugins/workspace-minimap/src/focus_region.ts @@ -12,7 +12,7 @@ import * as Blockly from 'blockly/core'; -const blockEvents = new Set([ +const blockEvents = new Set([ Blockly.Events.VIEWPORT_CHANGE, Blockly.Events.BLOCK_CHANGE, Blockly.Events.BLOCK_CREATE, diff --git a/plugins/workspace-minimap/src/minimap.ts b/plugins/workspace-minimap/src/minimap.ts index f61b7a4d8f..041701d418 100644 --- a/plugins/workspace-minimap/src/minimap.ts +++ b/plugins/workspace-minimap/src/minimap.ts @@ -15,7 +15,7 @@ import * as Blockly from 'blockly/core'; import {FocusRegion} from './focus_region'; // Events that should be send over to the minimap from the primary workspace -const blockEvents = new Set([ +const blockEvents = new Set([ Blockly.Events.BLOCK_CHANGE, Blockly.Events.BLOCK_CREATE, Blockly.Events.BLOCK_DELETE,