From 37bcdc8bfdeb91df9ebc874aa23d550bf164f8ea Mon Sep 17 00:00:00 2001 From: FurryR Date: Sun, 3 Mar 2024 21:43:01 +0800 Subject: [PATCH] :sparkles: l10n & more --- README.md | 24 +- README_zh-CN.md | 100 +++++ package-lock.json | 928 +-------------------------------------- package.json | 8 +- scratch-vm | 2 +- src/compiler/renderer.ts | 60 +++ src/compiler/runtime.ts | 327 +++++++++----- src/compiler/target.ts | 10 +- src/index.ts | 104 ++++- src/l10n/index.ts | 101 +++++ src/log/index.ts | 1 + tsconfig.json | 5 +- tsup.config.ts | 3 +- 13 files changed, 584 insertions(+), 1089 deletions(-) create mode 100644 README_zh-CN.md create mode 100644 src/l10n/index.ts diff --git a/README.md b/README.md index d14dfe2..d81792f 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,19 @@ # 👾 Hyren -> A tampermonkey script to use Turbowarp compiler anywhere. +> A tampermonkey script to use Turbowarp features anywhere. [![Visitors](https://hits.dwyl.com/FurryR/hyren.svg?style=flat-square)](http://github.com/FurryR/hyren) [![🛠️ Build](https://github.com/FurryR/hyren/actions/workflows/ci.yaml/badge.svg)](https://github.com/FurryR/hyren/actions/workflows/ci.yaml) +[🇺🇸](./README.md) | [🇨🇳](./README-zh_CN.md) + ## 🐱 Features -- ✅ Turbowarp compiler anywhere. -- ⭐ Always keep updated with Turbowarp compiler. +- ✅ Turbowarp features anywhere. +- ⭐ Always keep updated with Turbowarp. - 🤖 Requires no extra configuration. - 🛠️ Perfect compatibility with [`Eureka`](https://github.com/EurekaScratch/eureka-loader). @@ -58,7 +60,7 @@ Usually you can use hyren to boost most projects, but there are always some exce **⚠️ WARNING:** make sure you have read [**Compatibility**](#🛠️-compatibility) section before you installed. -## 📄 Reference +## 📄 Documentation - `Hyren.Compiler.set(flag?: boolean)` Enable/Disable compiler. If flag is not specified, returns current status. Defaults to `true`. @@ -71,11 +73,15 @@ Usually you can use hyren to boost most projects, but there are always some exce - `Hyren.Options.fps(num?: number)` Set framerate to `num`. The allowed framerate range is `[0,250]`. `0` is a special value which means **"matching device screen refresh rate"**. If num is not specified, returns current specified framerate. Defaults to `30`. - `Hyren.Options.maxClones(num?: number)` - Set max clone limit to `num`. If num is not specified, returns current specified counter. Defaults to `300`. + Set max clone limit to `num`. If num is not specified, returns current specified limit. Defaults to `300`. - `Hyren.Options.fencing(flag?: boolean)` - Set whether to enable fencing check. If flag is not specified, returns current status. Defaults to `true`. + Enable/Disable fencing check. If flag is not specified, returns current status. Defaults to `true`. - `Hyren.Options.miscLimit(flag?: boolean)` - Set whether to enable miscellaneous limits presented by original Scratch. If flag is not specified, returns current status. Defaults to `true`. + Enable/Disable miscellaneous limits presented by original Scratch. If flag is not specified, returns current status. Defaults to `true`. +- `Hyren.Options.size(width?: number, height?: number)` + Set stage size. If both width and height are not specified, returns current status. Otherwise, set stage width/height while keeping the unspecified one. +- `Hyren.save()` + Save settings to the project. Compatible with Turbowarp. ## ⚡ Performance @@ -89,4 +95,6 @@ Testing on: 12th Gen Intel(R) Core(TM) i7-12700F + Nvidia RTX 4060 (32 GiB RAM, | Scratch | 28592 | 4054 | 411 | 3544 | | ClipCC | 27929 | 4094 | 447 | 3640 | -Tips: Hyren does not provide renderer optimizations. +~~Tips: Hyren does not provide renderer optimizations.~~ + +Note: This section is outdated. My graphics card is not working, someone plz help me test it diff --git a/README_zh-CN.md b/README_zh-CN.md new file mode 100644 index 0000000..6c633fa --- /dev/null +++ b/README_zh-CN.md @@ -0,0 +1,100 @@ +
+ +# 👾 Hyren + +> 在任何地方使用 Turbowarp 特性。 + +[![Visitors](https://hits.dwyl.com/FurryR/hyren.svg?style=flat-square)](http://github.com/FurryR/hyren) +[![🛠️ Build](https://github.com/FurryR/hyren/actions/workflows/ci.yaml/badge.svg)](https://github.com/FurryR/hyren/actions/workflows/ci.yaml) + +[🇺🇸](./README.md) | [🇨🇳](./README-zh_CN.md) + +
+ +## 🐱 功能 + +- ✅ 在任何地方使用 Turbowarp 特性。 +- ⭐ 永远和 Turbowarp 保持更新。 +- 🤖 无需任何额外配置。 +- 🛠️ 和 [`Eureka`](https://github.com/EurekaScratch/eureka-loader) 有着完美的兼容性。 + +## 🔥 支持的平台 + +- [x] Scratch +- [x] Codingclip +- [x] Aerfaying (阿儿法营) +- [x] Xiaomawang (小码王) +- [x] CodeLab +- [x] Xueersi (学而思) +- [x] Creaticode + +❓ 虽然这些平台有自己的原生编译器,我们仍然支持它们但这可能导致一些问题。 + +- [x] Cocrea +- [x] Co-Create World (共创世界) +- [x] Adacraft +- [x] 40code +- [x] Turbowarp +- [x] PenguinMod + +## 🛠️ 兼容性 + +> 如果出了个 bug,它是 Hyren 导致的。如果关了 Hyren 还有这个 bug,那它就是 Turbowarp 导致的。 -- @garbomuffin,Turbowarp 主要开发者 + +通常你可以使用 Hyren 来加速大多数作品,但凡事都有例外。 + +1. 在用 Gandi IDE 时,我看到一些随机的错误但作品跑得好好的。 + > 请无视这些错误,你的作品一切正常。Hyren 将在编译失败时自动转为使用解释,所以它可能会影响性能。 +2. 我在用 Microsoft Edge。我用了 Hyren 但是我不感觉快了多少。 + > 请关闭 Edge 的增强安全性保护。这玩意会禁用浏览器的 JIT 所以特别慢。 +3. 其它错误。 + > 好吧,Hyren 只是一个实验性的项目。虽然禁用 Hyren 可能有效,但你就不能再享受编译器了。 + +## 🤔 如何使用 + +1. 🔽 从 [`Github Actions`](https://github.com/FurryR/hyren/actions/workflows/ci.yaml) 下载 Hyren 的每日构建 (**需要登录**)。请永远下载最后一个提交的构建。你可以下载 `hyren-debug` 或者 `hyren-release` 二者之一。解压构建产物(就是刚刚下载的)到一个文件夹里。 + +2. 🐺 在浏览器中打开构建产物(就是压缩包里面的内容),你的 `Tampermonkey` / `ViolentMonkey` 将会自动检测它为一个用户脚本。点击 `安装`。 + +3. 🎉 完成! + +**⚠️ 警告:** 在安装前请确保你已经读了 [**兼容性**](#🛠️-兼容性) 这一段。 + +## 📄 文档 + +- `Hyren.Compiler.set(flag?: boolean)` + 启用/禁用编译器。如果 flag 未被指定,返回当前的状态。默认为 `true`。 +- `Hyren.Compiler.warp(flag?: boolean)` + 启用/禁用编译器的循环检测器。如果 flag 未被指定,返回当前的状态。如果你在使用编辑器,它将默认设定为 `true`,否则它将设定为 `false`。 +- `Hyren.Interpolation.set(flag?: boolean)` + 启用/禁用补帧。如果 flag 未被指定,返回当前的状态。默认为 `false`。 +- `Hyren.Options.hires(flag?: boolean)` + 启用/禁用高质量渲染器 (又称 `HQPen` 或高清画笔). 如果 flag 未被指定,返回当前的状态。默认为 `false`。 +- `Hyren.Options.fps(num?: number)` + 设置帧率为 `num`。允许的帧率区间为 `[0,250]`。`0` 是一个特殊值,意味着帧率将匹配设备刷新率。如果 num 未被指定,返回当前的帧率。默认为 `30`. +- `Hyren.Options.maxClones(num?: number)` + 设置最大克隆体限制为 `num`。如果 num 未被指定,返回当前的最大限制。默认为 `300`. +- `Hyren.Options.fencing(flag?: boolean)` + 启用/禁用角色边缘检测。如果 flag 未被指定,返回当前的状态。默认为 `true`。 +- `Hyren.Options.miscLimit(flag?: boolean)` + 启用/禁用原版 Scratch 的其它限制。如果 flag 未被指定,返回当前的状态。默认为 `true`。 +- `Hyren.Options.size(width?: number, height?: number)` + 设置舞台大小。如果 width 和 height 都未被指定,返回当前状态。否则,将设置舞台的宽/高并对未指定的那部分保持原来的值。 +- `Hyren.save()` + 保存设置到项目。兼容 Turbowarp。 + +## ⚡ 性能 + +⚡ 性能测试使用的作品:https://scratch.mit.edu/projects/441947766/ + +设备:12th Gen Intel(R) Core(TM) i7-12700F + Nvidia RTX 4060 (32 GiB RAM, 8 GiB VRAM) + +| 设备 | 计算性能 | 数据处理性能 | 画笔性能 | 总分 | +| --------- | -------- | ------------ | -------- | ---- | +| Turbowarp | 27929 | 4120 | 1711 | 6234 | +| Scratch | 28592 | 4054 | 411 | 3544 | +| ClipCC | 27929 | 4094 | 447 | 3640 | + +~~提示:Hyren 不提供渲染器优化。~~ + +注意:这段的内容已经过时了。我的显卡寄了,有人吗帮忙测试一下子 diff --git a/package-lock.json b/package-lock.json index e8ec888..158e07f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,15 +8,14 @@ "name": "hyren", "version": "1.1.0", "license": "AGPL-3.0-only", + "dependencies": { + "@turbowarp/json": "^0.1.2" + }, "devDependencies": { "@turbowarp/types": "^0.0.12", - "@types/node": "^20.11.20", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", - "blockly": "^10.3.0", "eslint": "^8.56.0", - "format-message": "^6.2.4", - "http-server": "^14.1.1", "pre-commit": "^1.2.2", "prettier": "^3.2.1", "tsup": "^8.0.1", @@ -839,14 +838,10 @@ "win32" ] }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } + "node_modules/@turbowarp/json": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@turbowarp/json/-/json-0.1.2.tgz", + "integrity": "sha512-9nWywp+0SH7ROVzQPQQO9gMWBikahsqyMWp1Ku8VV0q+q6bnx6dS0aNPTjqTtF2GHAY55hcREsqKzaoUdWBSwg==" }, "node_modules/@turbowarp/types": { "version": "0.0.12", @@ -866,15 +861,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/node": { - "version": "20.11.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", - "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/@types/semver": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", @@ -1077,13 +1063,6 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true - }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -1105,18 +1084,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1191,39 +1158,12 @@ "node": ">=8" } }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1233,15 +1173,6 @@ "node": ">=8" } }, - "node_modules/blockly": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/blockly/-/blockly-10.4.1.tgz", - "integrity": "sha512-FcAnMU4/uJkOiY3p3OISDfko8iXFlEIF52L2l1EclShkLuC+igW670Q2I+RXhjIyWRA9Lv08BCQLWuGXlsAlKw==", - "dev": true, - "dependencies": { - "jsdom": "22.1.0" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1293,25 +1224,6 @@ "node": ">=8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1391,18 +1303,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "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==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1439,15 +1339,6 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, - "node_modules/corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1462,32 +1353,6 @@ "node": ">= 8" } }, - "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", - "dev": true, - "dependencies": { - "rrweb-cssom": "^0.6.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1505,44 +1370,12 @@ } } }, - "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==", - "dev": true - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1567,19 +1400,6 @@ "node": ">=6.0.0" } }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1592,39 +1412,6 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/esbuild": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", @@ -1839,12 +1626,6 @@ "node": ">=0.10.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -1983,26 +1764,6 @@ "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -2031,54 +1792,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "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==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/format-message": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/format-message/-/format-message-6.2.4.tgz", - "integrity": "sha512-/24zYeSRy2ZlEO2OIctm7jOHvMpoWf+uhqFCaqqyZKi1C229zAAy2E5vF4lSSaMH0a2kewPrOzq6xN4Yy7cQrw==", - "dev": true, - "dependencies": { - "format-message-formats": "^6.2.4", - "format-message-interpret": "^6.2.4", - "format-message-parse": "^6.2.4", - "lookup-closest-locale": "^6.2.0" - } - }, - "node_modules/format-message-formats": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/format-message-formats/-/format-message-formats-6.2.4.tgz", - "integrity": "sha512-smT/fAqBLqusWfWCKRAx6QBDAAbmYznWsIyTyk66COmvwt2Byiqd7SJe2ma9a5oV0kwRaOJpN/F4lr4YK/n6qQ==", - "dev": true - }, - "node_modules/format-message-interpret": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/format-message-interpret/-/format-message-interpret-6.2.4.tgz", - "integrity": "sha512-dRvz9mXhITApyOtfuFEb/XqvCe1u6RMkQW49UJHXS8w2S8cAHCqq5LNDFK+QK6XVzcofROycLb/k1uybTAKt2w==", - "dev": true, - "dependencies": { - "format-message-formats": "^6.2.4", - "lookup-closest-locale": "^6.2.0" - } - }, - "node_modules/format-message-parse": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/format-message-parse/-/format-message-parse-6.2.4.tgz", - "integrity": "sha512-k7WqXkEzgXkW4wkHdS6Cv2Ou0rIFtiDelZjgoe1saW4p7FT7zS8OeAUpAekhormqzpeecR97e4vBft1zMsfFOQ==", - "dev": true - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2099,34 +1812,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -2228,18 +1913,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2255,143 +1928,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-server": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", - "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", - "dev": true, - "dependencies": { - "basic-auth": "^2.0.1", - "chalk": "^4.1.2", - "corser": "^2.0.1", - "he": "^1.2.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy": "^1.18.1", - "mime": "^1.6.0", - "minimist": "^1.2.6", - "opener": "^1.5.1", - "portfinder": "^1.0.28", - "secure-compare": "3.0.1", - "union": "~0.5.0", - "url-join": "^4.0.1" - }, - "bin": { - "http-server": "bin/http-server" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -2401,18 +1937,6 @@ "node": ">=10.17.0" } }, - "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/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -2523,12 +2047,6 @@ "node": ">=8" } }, - "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==", - "dev": true - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2592,48 +2110,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", - "decimal.js": "^10.4.3", - "domexception": "^4.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2716,12 +2192,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2734,12 +2204,6 @@ "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", "dev": true }, - "node_modules/lookup-closest-locale": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", - "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", - "dev": true - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2780,39 +2244,6 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/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, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/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, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -2837,15 +2268,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", @@ -2855,18 +2277,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2911,12 +2321,6 @@ "node": ">=8" } }, - "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2926,15 +2330,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2959,15 +2354,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -3036,18 +2422,6 @@ "node": ">=6" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3130,29 +2504,6 @@ "node": ">= 6" } }, - "node_modules/portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "dev": true, - "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/postcss-load-config": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", @@ -3296,12 +2647,6 @@ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "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/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3311,27 +2656,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "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", @@ -3379,12 +2703,6 @@ "node": ">=8.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3451,12 +2769,6 @@ "fsevents": "~2.3.2" } }, - "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==", - "dev": true - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3486,30 +2798,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "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 - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/secure-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", - "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", - "dev": true - }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -3525,23 +2813,6 @@ "node": ">=10" } }, - "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3563,24 +2834,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -3821,12 +3074,6 @@ "node": ">=8" } }, - "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==", - "dev": true - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3866,33 +3113,6 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", - "dev": true, - "dependencies": { - "punycode": "^2.3.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -4021,33 +3241,6 @@ "node": ">=14.17" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", - "dev": true, - "dependencies": { - "qs": "^6.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4057,83 +3250,12 @@ "punycode": "^2.1.0" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "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", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", - "dev": true, - "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4249,42 +3371,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index d14fb79..658394b 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "lint:type": "tsc --noEmit -p ./tsconfig.json", "fix": "eslint ./src --fix", "build": "cd scratch-render && npm run build && cd .. && tsup --minify", - "start": "cd scratch-render && npm run build && cd .. && tsup && http-server ./dist -p 8080 --cors", "dev": "cd scratch-render && npm run build && cd .. && tsup", "format": "prettier ./src *.md -c -w", "lint:format": "prettier ./src *.md -c" @@ -31,16 +30,15 @@ "homepage": "https://github.com/FurryR/lpp-scratch#readme", "devDependencies": { "@turbowarp/types": "^0.0.12", - "@types/node": "^20.11.20", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", - "blockly": "^10.3.0", "eslint": "^8.56.0", - "format-message": "^6.2.4", - "http-server": "^14.1.1", "pre-commit": "^1.2.2", "prettier": "^3.2.1", "tsup": "^8.0.1", "typescript": "^5.3.3" + }, + "dependencies": { + "@turbowarp/json": "^0.1.2" } } diff --git a/scratch-vm b/scratch-vm index 9a4afe2..b6c4208 160000 --- a/scratch-vm +++ b/scratch-vm @@ -1 +1 @@ -Subproject commit 9a4afe2864bfbb8fe727d1b0a49423c97feb3300 +Subproject commit b6c42081b077dabb20f4a8b2c829324e14320738 diff --git a/src/compiler/renderer.ts b/src/compiler/renderer.ts index 2345828..e70b126 100644 --- a/src/compiler/renderer.ts +++ b/src/compiler/renderer.ts @@ -29,6 +29,16 @@ export default function patchRenderer(vm: VM) { value: 'INTERPOLATION_CHANGED', writable: false }) + if (!(vm.runtime.constructor as any).MONITORS_UPDATE) + Object.defineProperty(vm.runtime.constructor, 'MONITORS_UPDATE', { + value: 'MONITORS_UPDATE', + writable: false + }) + if (!(vm.runtime.constructor as any).STAGE_SIZE_CHANGED) + Object.defineProperty(vm.runtime.constructor, 'STAGE_SIZE_CHANGED', { + value: 'STAGE_SIZE_CHANGED', + writable: false + }) ;(vm.runtime as any).frameLoop = new FrameLoop(vm.runtime) ;(vm.runtime as any).interpolationEnabled = false const _attachRenderer = vm.runtime.constructor.prototype.attachRenderer @@ -206,6 +216,48 @@ export default function patchRenderer(vm: VM) { this.frameLoop.start() this.emit((vm.runtime.constructor as any).RUNTIME_STARTED) } + vm.runtime.constructor.prototype.setStageSize = function ( + width: number, + height: number + ) { + width = Math.round(Math.max(1, width)) + height = Math.round(Math.max(1, height)) + if (this.stageWidth !== width || this.stageHeight !== height) { + const deltaX = width - this.stageWidth + const deltaY = height - this.stageHeight + // Preserve monitor location relative to the center of the stage + if (this._monitorState.size > 0) { + const offsetX = deltaX / 2 + const offsetY = deltaY / 2 + for (const monitor of this._monitorState.valueSeq()) { + const newMonitor = monitor + .set('x', monitor.get('x') + offsetX) + .set('y', monitor.get('y') + offsetY) + this.requestUpdateMonitor(newMonitor) + } + this.emit( + (vm.runtime.constructor as any).MONITORS_UPDATE, + this._monitorState + ) + } + + this.stageWidth = width + this.stageHeight = height + if (this.renderer) { + this.renderer.setStageSize( + -width / 2, + width / 2, + -height / 2, + height / 2 + ) + } + } + this.emit( + (vm.runtime.constructor as any).STAGE_SIZE_CHANGED, + width, + height + ) + } const renderer = vm.runtime.renderer if ((renderer as any)._gandiShaderManager) { // you won gandi, i will keep your shader manager. @@ -218,6 +270,14 @@ export default function patchRenderer(vm: VM) { renderer._yBottom, renderer._yTop ) + const nativeSize = newRenderer.getNativeSize() + ;(vm.runtime as any).stageWidth = nativeSize[0] + ;(vm.runtime as any).stageHeight = nativeSize[1] + ;(newRenderer as any)._events = Object.assign( + {}, + (renderer as any)._events, + (newRenderer as any)._events + ) renderer.resize = newRenderer.resize.bind(newRenderer) vm.runtime.attachRenderer(newRenderer) } diff --git a/src/compiler/runtime.ts b/src/compiler/runtime.ts index 9373994..e25394e 100644 --- a/src/compiler/runtime.ts +++ b/src/compiler/runtime.ts @@ -1,4 +1,7 @@ import { ExtendedRuntime, ExtendedThread } from '../typing' +import * as ExtendedJSON from '@turbowarp/json' +import { formatMessage } from 'src/l10n' +import { MainLog, VMLog } from 'src/log' import compilerExecute = require('../../scratch-vm/src/compiler/jsexecute') import patchThread from './thread' import patchRenderer from './renderer' @@ -7,9 +10,10 @@ import patchTarget from './target' import Compatibility from '../compatibility' import { IRGenerator, ScriptTreeGenerator } from 'scratch-vm/src/compiler/irgen' import JSGenerator = require('scratch-vm/src/compiler/jsgen') +import uid = require('scratch-vm/src//util/uid') export default function patchRuntime(vm: VM) { - class HyrenError extends Error { + class HyrenInterrupt extends Error { constructor() { super('Interrupted by Hyren') } @@ -30,12 +34,22 @@ export default function patchRuntime(vm: VM) { value: 'COMPILER_OPTIONS_CHANGED', writable: false }) + if (!(vm.runtime.constructor as any).TURBO_MODE_ON) + Object.defineProperty(vm.runtime.constructor, 'TURBO_MODE_ON', { + value: 'TURBO_MODE_ON', + writable: false + }) + if (!(vm.runtime.constructor as any).TURBO_MODE_OFF) + Object.defineProperty(vm.runtime.constructor, 'TURBO_MODE_OFF', { + value: 'TURBO_MODE_OFF', + writable: false + }) vm.runtime.constructor.prototype.setRuntimeOptions = function ( runtimeOptions: any ) { this.runtimeOptions = Object.assign({}, this.runtimeOptions, runtimeOptions) this.emit( - (vm.runtime.constructor as any).COMPILER_OPTIONS_CHANGED, + (vm.runtime.constructor as any).RUNTIME_OPTIONS_CHANGED, this.runtimeOptions ) if (this.renderer) { @@ -70,11 +84,11 @@ export default function patchRuntime(vm: VM) { let isPromiseWaitOrYieldTick = false const proxy = new Proxy(thread, { get(target, p, receiver) { - if (p === 'isCompiled') return false // Force to run in interpreter. - if (p === 'peekStack') { + if (p === 'isCompiled') + return false // Force to run in interpreter. + else if (p === 'peekStack') { return () => currentStack - } - if (p === 'peekStackFrame') { + } else if (p === 'peekStackFrame') { const _peekStackFrame = Reflect.get(target, p, receiver) return function (this: VM.Thread) { const result = _peekStackFrame.call(this) @@ -86,10 +100,9 @@ export default function patchRuntime(vm: VM) { } }) } - } - if (p === 'goToNextBlock') { + } else if (p === 'goToNextBlock') { return () => { - throw new HyrenError() + throw new HyrenInterrupt() } } return Reflect.get(target, p, receiver) @@ -104,14 +117,14 @@ export default function patchRuntime(vm: VM) { } else if (newValue !== (threadConstructor as any).STATUS_YIELD) { isPromiseWaitOrYieldTick = true } - } + } else if (p === 'blockGlowInFrame') return true // hyren: preventing set blockGlowInFrame (by stepThread()) return Reflect.set(target, p, newValue, receiver) } }) try { seq.stepThread(proxy) } catch (e) { - if (!(e instanceof HyrenError)) throw e + if (!(e instanceof HyrenInterrupt)) throw e } finally { if (seq.activeThread) seq.activeThread = thread } @@ -153,14 +166,14 @@ export default function patchRuntime(vm: VM) { Object.prototype.hasOwnProperty = function () { // eslint-disable-next-line @typescript-eslint/no-this-alias defaultBlockPackages = this - throw new HyrenError() + throw new HyrenInterrupt() } try { _registerBlockPackages.call(this) Object.prototype.hasOwnProperty = _hasOwnProperty } catch (e) { Object.prototype.hasOwnProperty = _hasOwnProperty - if (!(e instanceof HyrenError)) throw e + if (!(e instanceof HyrenInterrupt)) throw e // Object.assign(defaultBlockPackages, twBlocks) for (const packageName in defaultBlockPackages) { if ( @@ -278,97 +291,6 @@ export default function patchRuntime(vm: VM) { } } } - // runtime.constructor.prototype.startHats = function ( - // requestedHatOpcode: string, - // optMatchFields?: Record, - // optTarget?: VM.Target - // ) { - // if (!Object.prototype.hasOwnProperty.call(this._hats, requestedHatOpcode)) { - // // No known hat with this opcode. - // return - // } - // const instance = this - // const newThreads: VM.Thread[] = [] - // // Look up metadata for the relevant hat. - // const hatMeta = instance._hats[requestedHatOpcode] - - // for (const opts in optMatchFields) { - // if (!Object.prototype.hasOwnProperty.call(optMatchFields, opts)) continue - // optMatchFields[opts] = optMatchFields[opts].toUpperCase() - // } - - // // tw: By assuming that all new threads will not interfere with eachother, we can optimize the loops - // // inside the allScriptsByOpcodeDo callback below. - // const startingThreadListLength = this.threads.length - - // // Consider all scripts, looking for hats with opcode `requestedHatOpcode`. - // this.allScriptsByOpcodeDo( - // requestedHatOpcode, - // (script: any, target: VM.Target) => { - // const { blockId: topBlockId, fieldsOfInputs: hatFields } = script - - // // Match any requested fields. - // // For example: ensures that broadcasts match. - // // This needs to happen before the block is evaluated - // // (i.e., before the predicate can be run) because "broadcast and wait" - // // needs to have a precise collection of started threads. - // for (const matchField in optMatchFields) { - // if (hatFields[matchField].value !== optMatchFields[matchField]) { - // // Field mismatch. - // return - // } - // } - - // if (hatMeta.restartExistingThreads) { - // // If `restartExistingThreads` is true, we should stop - // // any existing threads starting with the top block. - // // hyren: use `this.threads` instead of `this.threadMap` as non-Turbowarp Scratch does not have it. - // const existingThread = this.threads.find( - // (v: any) => v.target === target && v.topBlock === topBlockId - // ) - // if (existingThread) { - // newThreads.push(this._restartThread(existingThread)) - // return - // } - // } else { - // // If `restartExistingThreads` is false, we should - // // give up if any threads with the top block are running. - // for (let j = 0; j < startingThreadListLength; j++) { - // if ( - // this.threads[j].target === target && - // this.threads[j].topBlock === topBlockId && - // // stack click threads and hat threads can coexist - // !this.threads[j].stackClick && - // this.threads[j].status !== (threadConstructor as any).STATUS_DONE - // ) { - // // Some thread is already running. - // return - // } - // } - // } - // // Start the thread with this top block. - // newThreads.push(this._pushThread(topBlockId, target)) - // }, - // optTarget - // ) - // // For compatibility with Scratch 2, edge triggered hats need to be processed before - // // threads are stepped. See ScratchRuntime.as for original implementation - // newThreads.forEach((thread: any) => { - // if (thread.isCompiled) { - // if (thread.executableHat) { - // // It is quite likely that we are currently executing a block, so make sure - // // that we leave the compiler's state intact at the end. - // compilerExecute.saveGlobalState() - // compilerExecute(thread) - // compilerExecute.restoreGlobalState() - // } - // } else { - // execute(this.sequencer, thread) - // thread.goToNextBlock() - // } - // }) - // return newThreads - // } const _resetCache = runtime.flyoutBlocks.constructor.prototype.resetCache runtime.flyoutBlocks.constructor.prototype.resetCache = function () { _resetCache.call(this) @@ -400,35 +322,196 @@ export default function patchRuntime(vm: VM) { runtime.constructor.prototype.setCompilerOptions = function ( compilerOptions: object ) { - if ( - typeof runtime.compilerOptions === 'object' && - runtime.compilerOptions !== null + this.compilerOptions = Object.assign( + {}, + this.compilerOptions, + compilerOptions ) - Object.assign(this.compilerOptions, compilerOptions) - else - this.compilerOptions = Object.assign( - {}, - this.compilerOptions, - compilerOptions - ) this.resetAllCaches() this.emit( (runtime as any).constructor.COMPILER_OPTIONS_CHANGED, - compilerOptions + this.compilerOptions ) } ;(vm as any).setCompilerOptions = function (compilerOptions: object) { ;(this.runtime as any).setCompilerOptions(compilerOptions) } + ;(runtime as any).setCompilerOptions({ + enabled: true, + warpTimer: !!(vm as any)._events.workspaceUpdate + }) + if (!vm.runtime.constructor.prototype.parseProjectOptions) { + const COMMENT_CONFIG_MAGIC = ' // _twconfig_' + const _installTargets = vm.constructor.prototype.installTargets + vm.constructor.prototype.installTargets = function ( + targets: object[], + extensions: object, + wholeProject: boolean + ) { + return _installTargets + .call(this, targets, extensions, wholeProject) + .then(() => { + if (wholeProject) { + this.runtime.parseProjectOptions() + } + }) + } + vm.runtime.constructor.prototype.findProjectOptionsComment = function () { + const target = this.getTargetForStage() + const comments: any[] = target.comments + for (const comment of Object.values(comments)) { + if (comment.text.includes(COMMENT_CONFIG_MAGIC)) { + return comment + } + } + return null + } + vm.runtime.constructor.prototype.parseProjectOptions = function () { + const comment = this.findProjectOptionsComment() + if (!comment) return + const lineWithMagic = comment.text + .split('\n') + .find((i: string) => i.endsWith(COMMENT_CONFIG_MAGIC)) + if (!lineWithMagic) { + VMLog.warn('Config comment does not contain valid line') + return + } + + const jsonText = lineWithMagic.substr( + 0, + lineWithMagic.length - COMMENT_CONFIG_MAGIC.length + ) + let parsed: any + try { + parsed = ExtendedJSON.parse(jsonText) + if (!parsed || typeof parsed !== 'object') { + throw new Error('Invalid object') + } + } catch (e) { + VMLog.warn('Config comment has invalid JSON', e) + return + } + + if (typeof parsed.framerate === 'number') { + if (parsed.framerate === 0) { + MainLog.log(formatMessage('hyren.fps.sync')) + } else { + MainLog.log( + formatMessage('hyren.fps').replace('%o', String(parsed.framerate)) + ) + } + this.setFramerate(parsed.framerate) + } + if (parsed.turbo) { + this.turboMode = true + this.emit((vm.runtime.constructor as any).TURBO_MODE_ON) + } + if (parsed.interpolation) { + this.setInterpolation(true) + MainLog.log(formatMessage('hyren.interpolation.enabled')) + } + if (parsed.runtimeOptions) { + if (parsed.runtimeOptions?.miscLimits === false) + MainLog.log(formatMessage('hyren.miscLimits.disabled')) + if (parsed.runtimeOptions?.fencing === false) + MainLog.log(formatMessage('hyren.fencing.disabled')) + if (typeof parsed.runtimeOptions?.maxClones !== 'undefined') + MainLog.log( + formatMessage('hyren.maxClones').replace( + '%o', + String(parsed.runtimeOptions.maxClones) + ) + ) + this.setRuntimeOptions(parsed.runtimeOptions) + } + if (parsed.hq && this.renderer) { + MainLog.log(formatMessage('hyren.hires.enabled')) + this.renderer.setUseHighQualityRender(true) + } + const storedWidth = +parsed.width || this.stageWidth + const storedHeight = +parsed.height || this.stageHeight + if ( + storedWidth !== this.stageWidth || + storedHeight !== this.stageHeight + ) { + MainLog.log( + formatMessage('hyren.size') + .replace('%o', String(storedWidth)) + .replace('%2o', String(storedHeight)) + ) + this.setStageSize(storedWidth, storedHeight) + } + } + vm.runtime.constructor.prototype.storeProjectOptions = function () { + const options = this.generateDifferingProjectOptions() + // TODO: translate + const text = `Configuration for https://turbowarp.org/\nYou can move, resize, and minimize this comment, but don't edit it by hand. This comment can be deleted to remove the stored settings.\n${ExtendedJSON.stringify(options)}${COMMENT_CONFIG_MAGIC}` + const existingComment = this.findProjectOptionsComment() + if (existingComment) { + existingComment.text = text + } else { + const target = this.getTargetForStage() + // TODO: smarter position logic + target.createComment(uid(), null, text, 50, 50, 350, 170, false) + } + this.emitProjectChanged() + } + vm.runtime.constructor.prototype.generateDifferingProjectOptions = + function () { + const difference = (oldObject: any, newObject: any) => { + const result: any = {} + for (const key of Object.keys(newObject)) { + const newValue = newObject[key] + const oldValue = oldObject[key] + if (typeof newValue === 'object' && newValue) { + const valueDiffering = difference(oldValue, newValue) + if (Object.keys(valueDiffering).length > 0) { + result[key] = valueDiffering + } + } else if (newValue !== oldValue) { + result[key] = newValue + } + } + return result + } + return difference( + this._defaultStoredSettings, + this._generateAllProjectOptions() + ) + } + vm.runtime.constructor.prototype._generateAllProjectOptions = function () { + return { + framerate: this.frameLoop?.framerate ?? 30, + runtimeOptions: this.runtimeOptions, + interpolation: this.interpolationEnabled ?? false, + turbo: this.turboMode, + hq: this.renderer ? this.renderer.useHighQualityRender ?? false : false, + width: this.stageWidth ?? (vm.runtime.constructor as any).STAGE_WIDTH, + height: this.stageHeight ?? (vm.runtime.constructor as any).STAGE_HEIGHT + } + } + vm.constructor.prototype.storeProjectOptions = function () { + this.runtime.storeProjectOptions() + if (this.editingTarget.isStage) { + this.emitWorkspaceUpdate() + } + } + ;(vm.runtime as any)._defaultStoredSettings = ( + vm.runtime as any + )._generateAllProjectOptions() + } + if ( + !(vm.runtime as any)._events[(vm.runtime.constructor as any).TURBO_MODE_ON] + ) { + vm.runtime.on((vm.runtime.constructor as any).TURBO_MODE_ON, () => { + vm.emit((vm.runtime.constructor as any).TURBO_MODE_ON) + }) + } if ( - typeof runtime.compilerOptions !== 'object' || - runtime.compilerOptions === null || - typeof runtime.compilerOptions.enabled !== 'boolean' || - typeof runtime.compilerOptions.warpTimer !== 'boolean' + !(vm.runtime as any)._events[(vm.runtime.constructor as any).TURBO_MODE_OFF] ) { - ;(runtime as any).setCompilerOptions({ - enabled: true, - warpTimer: !!(vm as any)._events.workspaceUpdate + vm.runtime.on((vm.runtime.constructor as any).TURBO_MODE_OFF, () => { + vm.emit((vm.runtime.constructor as any).TURBO_MODE_OFF) }) } } diff --git a/src/compiler/target.ts b/src/compiler/target.ts index 1ca70f1..3414006 100644 --- a/src/compiler/target.ts +++ b/src/compiler/target.ts @@ -29,14 +29,8 @@ export default function patchTarget(vm: VM) { : 0 const maxScale = fencing ? Math.min( - (1.5 * - (this.runtime.stageWidth ?? - (vm.runtime.constructor as any).STAGE_WIDTH)) / - origW, - (1.5 * - (this.runtime.stageHeight ?? - (vm.runtime.constructor as any).STAGE_HEIGHT)) / - origH + (1.5 * this.runtime.stageWidth) / origW, + (1.5 * this.runtime.stageHeight) / origH ) : Infinity this.size = MathUtil.clamp(size / 100, minScale, maxScale) * 100 diff --git a/src/index.ts b/src/index.ts index 4add1ca..67fab75 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import { MainLog } from './log' import * as VM from 'scratch-vm' +import { locale, formatMessage } from './l10n' import { version } from '../package.json' import patchRuntime from './compiler/runtime' @@ -18,15 +19,6 @@ export function trap(callback: (vm: VM) => void) { Object.prototype.hasOwnProperty.call(self, 'editingTarget') && Object.prototype.hasOwnProperty.call(self, 'runtime') ) { - MainLog.groupCollapsed(`🐺 Hyren v${version}`) - console.log( - 'Copyright (c) 2024 FurryR. Visit my profile at https://github.com/FurryR' - ) - console.log( - 'Hyren is based on Turbowarp compiler. Check https://turbowarp.org/editor for more details.' - ) - console.log('GitHub Repository: https://github.com/FurryR/hyren') - MainLog.groupEnd() Function.prototype.bind = oldBind callback(self as VM) return oldBind.call(this, self, ...args) @@ -39,6 +31,18 @@ function vmInstanceAssert(): never { throw new Error('Accessed Hyren APIs before VM instance initialization') } trap(vm => { + vm.on('LOCALE_CHANGED' as any, () => { + locale.value = (vm as any).getLocale() + }) + vm.once('targetsUpdate', () => { + locale.value = (vm as any).getLocale() + MainLog.groupCollapsed(`🐺 Hyren v${version}`) + console.log(formatMessage('hyren.aboutme')) + console.log(formatMessage('hyren.abouttw')) + console.log(formatMessage('hyren.ghrepo')) + console.log(formatMessage('hyren.help')) + MainLog.groupEnd() + }) patchRuntime(vm) vmInstance = vm ;(window as any).Hyren = { @@ -47,7 +51,10 @@ trap(vm => { if (!vmInstance) vmInstanceAssert() if (flag === undefined) return (vmInstance.runtime as any).interpolationEnabled - ;(vmInstance.runtime as any).setInterpolation(!!flag) + const enabled = !!flag + if (enabled) MainLog.log(formatMessage('hyren.interpolation.enabled')) + else MainLog.log(formatMessage('hyren.interpolation.disabled')) + ;(vmInstance.runtime as any).setInterpolation(enabled) } }, Compiler: { @@ -55,61 +62,120 @@ trap(vm => { if (!vmInstance) vmInstanceAssert() if (flag === undefined) return (vmInstance.runtime as any).compilerOptions?.enabled + const enabled = !!flag + if (enabled) MainLog.log(formatMessage('hyren.compiler.enabled')) + else MainLog.log(formatMessage('hyren.compiler.disabled')) ;(vmInstance.runtime as any).setCompilerOptions({ - enabled: !!flag + enabled }) }, warp(flag: unknown) { if (!vmInstance) vmInstanceAssert() if (flag === undefined) return (vmInstance.runtime as any).compilerOptions?.warpTimer + const enabled = !!flag + if (enabled) MainLog.log(formatMessage('hyren.warp.enabled')) + else MainLog.log(formatMessage('hyren.warp.disabled')) ;(vmInstance.runtime as any).setCompilerOptions({ - warpTimer: !!flag + warpTimer: enabled }) } }, Options: { + size(width: unknown, height: unknown) { + if (!vmInstance) vmInstanceAssert() + const nativeSize = vm.runtime.renderer.getNativeSize() + if (width === undefined && height == undefined) return nativeSize + width = width ?? nativeSize[0] + height = height ?? nativeSize[1] + const v = Number(width) + const v2 = Number(height) + const x = isNaN(v) ? nativeSize[0] : width + const y = isNaN(v2) ? nativeSize[1] : height + MainLog.log( + formatMessage('hyren.size') + .replace('%o', String(x)) + .replace('%2o', String(y)) + ) + ;(vmInstance.runtime as any).setStageSize(x, y) + return [x, y] + }, hires(flag: unknown) { if (!vmInstance) vmInstanceAssert() if (flag === undefined) return (vmInstance.runtime as any).renderer?.useHighQualityRender - ;(vmInstance.runtime as any).renderer?.setUseHighQualityRender(!!flag) + const enabled = !!flag + if (enabled) MainLog.log(formatMessage('hyren.hires.enabled')) + else MainLog.log(formatMessage('hyren.hires.disabled')) + ;(vmInstance.runtime as any).renderer?.setUseHighQualityRender(enabled) + return enabled }, fps(num: unknown) { if (!vmInstance) vmInstanceAssert() if (num === undefined) return (vmInstance.runtime as any).frameLoop?.framerate const v = Number(num) - ;(vmInstance.runtime as any).setFramerate(isNaN(v) ? 30 : v) + const fps = isNaN(v) ? 30 : v + if (fps === 0) { + MainLog.log(formatMessage('hyren.fps.sync')) + } else { + MainLog.log(formatMessage('hyren.fps').replace('%o', String(fps))) + } + ;(vmInstance.runtime as any).setFramerate(fps) + return fps }, maxClones(num: unknown) { if (!vmInstance) vmInstanceAssert() if (num === undefined) return (vmInstance.runtime as any).runtimeOptions?.maxClones const v = Number(num) + const maxClones = isNaN(v) + ? (vmInstance.runtime.constructor as any).MAX_CLONES + : v + if (maxClones === (vmInstance.runtime.constructor as any).MAX_CLONES) { + MainLog.log( + formatMessage('hyren.maxClones.default').replace( + '%o', + String(maxClones) + ) + ) + } else { + MainLog.log( + formatMessage('hyren.maxClones').replace('%o', String(maxClones)) + ) + } ;(vmInstance.runtime as any).setRuntimeOptions({ - maxClones: isNaN(v) - ? (vmInstance.runtime.constructor as any).MAX_CLONES - : v + maxClones }) }, miscLimits(flag: unknown) { if (!vmInstance) vmInstanceAssert() if (flag === undefined) return (vmInstance.runtime as any).runtimeOptions?.miscLimits + const enabled = !!flag + if (enabled) MainLog.log(formatMessage('hyren.miscLimits.enabled')) + else MainLog.log(formatMessage('hyren.miscLimits.disabled')) ;(vmInstance.runtime as any).setRuntimeOptions({ - miscLimits: !!flag + miscLimits: enabled }) }, fencing(flag: unknown) { if (!vmInstance) vmInstanceAssert() if (flag === undefined) return (vmInstance.runtime as any).runtimeOptions?.fencing + const enabled = !!flag + if (enabled) MainLog.log(formatMessage('hyren.fencing.enabled')) + else MainLog.log(formatMessage('hyren.fencing.disabled')) ;(vmInstance.runtime as any).setRuntimeOptions({ - fencing: !!flag + fencing: enabled }) } }, + save() { + if (!vmInstance) vmInstanceAssert() + MainLog.log(formatMessage('hyren.save')) + ;(vmInstance as any).storeProjectOptions() + }, version } }) diff --git a/src/l10n/index.ts b/src/l10n/index.ts new file mode 100644 index 0000000..ad97e77 --- /dev/null +++ b/src/l10n/index.ts @@ -0,0 +1,101 @@ +const l10n: Record> = { + en: { + 'hyren.aboutme': + 'Copyright (c) 2024 FurryR. Visit my profile at https://github.com/FurryR', + 'hyren.abouttw': + 'Hyren is based on Turbowarp. Check https://turbowarp.org/editor for more details.', + 'hyren.ghrepo': + 'GitHub Repository: https://github.com/FurryR/hyren. Hyren is licensed under the AGPL-3.0 license.', + 'hyren.help': + 'You can use global object `Hyren` to adjust Hyren settings. For more information, please check https://github.com/FurryR/hyren/blob/main/README.md#-documentation.', + 'hyren.compiler.enabled': 'The compiler is enabled.', + 'hyren.compiler.disabled': 'The compiler is disabled.', + 'hyren.warp.enabled': + 'The warp timer is enabled. (⚠️ Performance might be affected)', + 'hyren.warp.disabled': 'The warp timer is disabled.', + 'hyren.hires.enabled': + 'High resolution (HQPen) optimization is enabled. (⚠️ Performance might be affected)', + 'hyren.hires.disabled': 'High resolution (HQPen) optimization is disabled.', + 'hyren.interpolation.enabled': 'Interpolation is enabled.', + 'hyren.interpolation.disabled': 'Interpolation is disabled.', + 'hyren.fps': 'The framerate is set to %o.', + 'hyren.fps.sync': + 'The framerate is set to matching device screen refresh rate.', + 'hyren.size': 'The stage size is set to %ox%2o.', + 'hyren.maxClones': 'The max clone count is set to %o.', + 'hyren.maxClones.default': 'The max clone count is set to %o by default.', + 'hyren.miscLimits.enabled': 'The miscellaneous limits are enabled.', + 'hyren.miscLimits.disabled': 'The miscellaneous limits are disabled.', + 'hyren.fencing.enabled': 'Sprite fencing check is enabled.', + 'hyren.fencing.disabled': 'Sprite fencing check is disabled.', + 'hyren.save': 'Options are saved into project.' + }, + ja: { + 'hyren.aboutme': + 'Copyright (c) 2024 FurryR. https://github.com/FurryR は私のプロファイルです。', + 'hyren.abouttw': + 'Hyren は Turbowarp をもとにして作られたのです。詳しくは https://turbowarp.org/editor をご覧ください。', + 'hyren.ghrepo': + 'GitHub レポジトリー: https://github.com/FurryR/hyren。Hyren は AGPL-3.0 でライセンスされています。', + 'hyren.help': + 'グローバルオブジェクト `Hyren` で Hyren の色々な設定を調整できます。詳しくは https://github.com/FurryR/hyren/blob/main/README.md#-documentation をご覧ください。', + 'hyren.compiler.enabled': 'コンパイラーが有効になりました。', + 'hyren.compiler.disabled': 'コンパイラーが無効になりました。', + 'hyren.warp.enabled': + 'Warp タイマーが有効になりました。(⚠️ パフォーマンスに影響する可能性があります)', + 'hyren.warp.disabled': 'Warp タイマーが無効になりました。', + 'hyren.hires.enabled': + '高解像度(ペンできれいに描画する)の最適化が有効になりました。(⚠️ パフォーマンスに影響する可能性があります)', + 'hyren.hires.disabled': + '高解像度(ペンできれいに描画する)の最適化が無効になりました。', + 'hyren.interpolation.enabled': '補完機能が有効になりました。', + 'hyren.interpolation.disabled': '補完機能が無効になりました。', + 'hyren.fps': 'フレームレートが %o に設定されました。', + 'hyren.fps.sync': + 'フレームレートがお使いのデバイスのリフレッシュレートに設定されました。', + 'hyren.size': 'ステージの大きさが %ox%2o に設定されました。', + 'hyren.maxClones': '最大クローン制限が %o に設定されました。', + 'hyren.maxClones.default': + '最大クローン制限がデフォルトの %o に設定されました。', + 'hyren.miscLimits.enabled': 'その他の制限が有効になりました。', + 'hyren.miscLimits.disabled': 'その他の制限が無効になりました。', + 'hyren.fencing.enabled': '動く範囲と大きさの制限が有効になりました。', + 'hyren.fencing.disabled': '動く範囲と大きさの制限が無効になりました。', + 'hyren.save': '設定がプロジェクトに保存されました。' + }, + 'zh-cn': { + 'hyren.aboutme': + '版权所有 (c) 2024 FurryR。我的个人主页是 https://github.com/FurryR 。', + 'hyren.abouttw': + 'Hyren 基于 Turbowarp。请访问 https://turbowarp.org/editor 以获得更多信息。', + 'hyren.ghrepo': + 'GitHub 仓库: https://github.com/FurryR/hyren。Hyren 以 AGPL-3.0 开源协议授权。', + 'hyren.help': + '您可以使用全局对象 `Hyren` 来调整 Hyren 的各种设定。欲知更多,请访问 https://github.com/FurryR/hyren/blob/main/README_zh-CN.md#-documentation。', + 'hyren.compiler.enabled': '已启用编译器。', + 'hyren.compiler.disabled': '已禁用编译器。', + 'hyren.warp.enabled': '已启用循环计时器。(⚠️ 可能会影响性能)', + 'hyren.warp.disabled': '已禁用循环计时器。', + 'hyren.hires.enabled': + '已启用高清渲染(高清画笔)优化。(⚠️ 可能会影响性能)', + 'hyren.hires.disabled': '已禁用高清渲染(高清画笔)优化。', + 'hyren.interpolation.enabled': '已启用补帧。', + 'hyren.interpolation.disabled': '已禁用补帧。', + 'hyren.fps': '帧率已被设置为 %o。', + 'hyren.fps.sync': '帧率已被设置为和设备屏幕刷新率同步。', + 'hyren.size': '舞台大小已被设置为 %ox%2o。', + 'hyren.maxClones': '最大克隆体数已被设置为 %o。', + 'hyren.maxClones.default': '最大克隆体数已被设置为默认的 %o。', + 'hyren.miscLimits.enabled': '已启用其它限制。', + 'hyren.miscLimits.disabled': '已禁用其它限制。', + 'hyren.fencing.enabled': '已启用角色边缘检测。', + 'hyren.fencing.disabled': '已禁用角色边缘检测。', + 'hyren.save': '已在作品中保存设置。' + } +} +export let locale = { + value: 'en' +} +export const formatMessage = (id: string) => { + return l10n[locale.value]?.[id] ?? l10n['en']?.[id] ?? id +} diff --git a/src/log/index.ts b/src/log/index.ts index adf8af9..7286c4b 100644 --- a/src/log/index.ts +++ b/src/log/index.ts @@ -1,3 +1,4 @@ import nanolog = require('@turbowarp/nanolog') nanolog.enable() export const MainLog = nanolog() +export const VMLog = nanolog('vm') diff --git a/tsconfig.json b/tsconfig.json index d0868de..34cf690 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,11 +24,10 @@ /* Module Resolution Options */ "resolveJsonModule": true, "allowJs": true, - "checkJs": false, // "moduleResolution": "", // "esModuleInterop": true, // "allowSyntheticDefaultImports": true, - "types": ["node"], + "types": [], "baseUrl": ".", "paths": { // "~/*": [ @@ -40,13 +39,11 @@ }, "lib": ["ESNext", "DOM"], "target": "ESNext", - "moduleResolution": "Node", "outDir": "dist", "declaration": true }, "include": [ "src/**/*", - "scratch-vm/src/**/*", "tsup.config.ts", "package.json" ] diff --git a/tsup.config.ts b/tsup.config.ts index e61c357..4589e37 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,4 +1,5 @@ import { defineConfig } from 'tsup' +import { version } from './package.json' export default defineConfig({ name: 'hyren', @@ -10,7 +11,7 @@ export default defineConfig({ js: `// ==UserScript== // @name Hyren // @description Run compiler anywhere. -// @version 1 +// @version ${version} // @author FurryR // @match https://scratch.mit.edu/projects/* // @match https://aerfaying.com/Projects/*