diff --git a/.vscodeignore b/.vscodeignore index 18fa553..cb5abfc 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -31,6 +31,7 @@ src/** .gitignore .yarnrc webpack.config.js +webpack.config.ts vsc-extension-quickstart.md **/tsconfig.json **/.eslintrc.json diff --git a/package.json b/package.json index fa81793..57ed620 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "geode", "displayName": "Geode", "description": "Utilities for the Geode Geometry Dash modding framework", - "version": "1.14.0", + "version": "1.15.0", "engines": { "vscode": "^1.72.0" }, @@ -103,91 +103,135 @@ "textMateRules": [ { "scope": "geode.flalert.ca", - "settings": { "foreground": "#9632ff" } + "settings": { + "foreground": "#9632ff" + } }, { "scope": "geode.flalert.cb", - "settings": { "foreground": "#4a52e1" } + "settings": { + "foreground": "#4a52e1" + } }, { "scope": "geode.flalert.cc", - "settings": { "foreground": "#ffff96" } + "settings": { + "foreground": "#ffff96" + } }, { "scope": "geode.flalert.cd", - "settings": { "foreground": "#ff96ff" } + "settings": { + "foreground": "#ff96ff" + } }, { "scope": "geode.flalert.cf", - "settings": { "foreground": "#96ffff" } + "settings": { + "foreground": "#96ffff" + } }, { "scope": "geode.flalert.cg", - "settings": { "foreground": "#40e348" } + "settings": { + "foreground": "#40e348" + } }, { "scope": "geode.flalert.cj", - "settings": { "foreground": "#32c8ff" } + "settings": { + "foreground": "#32c8ff" + } }, { "scope": "geode.flalert.cl", - "settings": { "foreground": "#60abef" } + "settings": { + "foreground": "#60abef" + } }, { "scope": "geode.flalert.co", - "settings": { "foreground": "#ffa54b" } + "settings": { + "foreground": "#ffa54b" + } }, { "scope": "geode.flalert.cp", - "settings": { "foreground": "#ff00ff" } + "settings": { + "foreground": "#ff00ff" + } }, { "scope": "geode.flalert.cr", - "settings": { "foreground": "#ff5a5a" } + "settings": { + "foreground": "#ff5a5a" + } }, { "scope": "geode.flalert.cs", - "settings": { "foreground": "#ffdc41" } + "settings": { + "foreground": "#ffdc41" + } }, { "scope": "geode.flalert.cy", - "settings": { "foreground": "#ffff00" } + "settings": { + "foreground": "#ffff00" + } }, { "scope": "geode.flalert.blue", - "settings": { "foreground": "#4a52e1" } + "settings": { + "foreground": "#4a52e1" + } }, { "scope": "geode.flalert.green", - "settings": { "foreground": "#40e348" } + "settings": { + "foreground": "#40e348" + } }, { "scope": "geode.flalert.aqua", - "settings": { "foreground": "#60abef" } + "settings": { + "foreground": "#60abef" + } }, { "scope": "geode.flalert.cyan", - "settings": { "foreground": "#32c8ff" } + "settings": { + "foreground": "#32c8ff" + } }, { "scope": "geode.flalert.yellow", - "settings": { "foreground": "#ffff00" } + "settings": { + "foreground": "#ffff00" + } }, { "scope": "geode.flalert.orange", - "settings": { "foreground": "#ffa54b" } + "settings": { + "foreground": "#ffa54b" + } }, { "scope": "geode.flalert.red", - "settings": { "foreground": "#ff5a5a" } + "settings": { + "foreground": "#ff5a5a" + } }, { "scope": "geode.flalert.pink", - "settings": { "foreground": "#ff00ff" } + "settings": { + "foreground": "#ff00ff" + } }, { "scope": "geode.flalert.purple", - "settings": { "foreground": "#9632ff" } + "settings": { + "foreground": "#9632ff" + } } ] } @@ -230,7 +274,7 @@ "jsonValidation": [ { "fileMatch": "mod.json", - "url": "https://raw.githubusercontent.com/geode-sdk/vscode/main/assets/mod-info-validation.json" + "url": "./dist/validation/mod.json" } ] }, @@ -264,8 +308,9 @@ "glob": "^8.0.3", "mocha": "^10.0.0", "prettier": "^3.3.2", - "ts-loader": "^9.3.0", - "typescript": "^4.7.2", + "ts-json-schema-generator": "^2.3.0", + "ts-loader": "^9.5.1", + "typescript": "^4.9.5", "webpack": "^5.72.1", "webpack-cli": "^4.9.2" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4943243..7fa3053 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,12 +81,18 @@ importers: prettier: specifier: ^3.3.2 version: 3.3.2 + ts-json-schema-generator: + specifier: ^2.3.0 + version: 2.3.0 ts-loader: - specifier: ^9.3.0 + specifier: ^9.5.1 version: 9.5.1(typescript@4.9.5)(webpack@5.92.1(webpack-cli@4.10.0)) typescript: - specifier: ^4.7.2 + specifier: ^4.9.5 version: 4.9.5 + typescript-json-schema: + specifier: '0.65' + version: 0.65.1 webpack: specifier: ^5.72.1 version: 5.92.1(webpack-cli@4.10.0) @@ -144,6 +150,10 @@ packages: resolution: {integrity: sha512-8tvi6Cos3m+0KmRbPjgkySXi+UQU/QiuVRFnrxIwt5xZlEEFa69O04RTaNESGgImyBBlYbo2mfE8/U8Bbdk1WQ==} engines: {node: '>=16'} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@discoveryjs/json-ext@0.5.7': resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} @@ -295,6 +305,10 @@ packages: cpu: [x64] os: [win32] + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -316,6 +330,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@microsoft/fast-element@1.13.0': resolution: {integrity: sha512-iFhzKbbD0cFRo9cEzLS3Tdo9BYuatdxmCEKCpZs1Cro/93zNMpZ/Y9/Z7SknmW6fhDZbpBvtO8lLh9TFEcNVAQ==} @@ -342,6 +359,22 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -366,6 +399,9 @@ packages: '@types/node@16.18.101': resolution: {integrity: sha512-AAsx9Rgz2IzG8KJ6tXd6ndNkVcu+GYB6U/SnFAaokSPNx2N7dcIIfnighYUNumvj6YS2q39Dejz5tT0NCV7CWA==} + '@types/node@18.19.50': + resolution: {integrity: sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==} + '@types/object-hash@2.2.1': resolution: {integrity: sha512-i/rtaJFCsPljrZvP/akBqEwUP2y5cZLOmvO+JaYnz01aPknrQ+hB5MRcO7iqCUsFaYfTG8kGfKUyboA07xeDHQ==} @@ -592,6 +628,10 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + acorn@8.12.0: resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} engines: {node: '>=0.4.0'} @@ -629,10 +669,17 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -758,6 +805,10 @@ packages: cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clone-deep@4.0.1: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} @@ -793,6 +844,10 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -810,6 +865,9 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -870,6 +928,10 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + diff@5.0.0: resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} engines: {node: '>=0.3.1'} @@ -910,6 +972,9 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -1054,6 +1119,10 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -1098,6 +1167,10 @@ packages: glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -1273,6 +1346,9 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} @@ -1296,6 +1372,11 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} @@ -1390,10 +1471,16 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + markdown-it@12.3.2: resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} hasBin: true @@ -1444,9 +1531,17 @@ packages: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -1540,6 +1635,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -1556,6 +1654,9 @@ packages: parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + path-equal@1.2.5: + resolution: {integrity: sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1571,6 +1672,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -1696,6 +1801,10 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} @@ -1748,6 +1857,10 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} @@ -1784,6 +1897,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string-width@6.1.0: resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} engines: {node: '>=16'} @@ -1872,6 +1989,11 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + ts-json-schema-generator@2.3.0: + resolution: {integrity: sha512-t4lBQAwZc0sOJq9LJt3NgbznIcslVnm0JeEMFq8qIRklpMRY8jlYD0YmnRWbqBKANxkby91P1XanSSlSOFpUmg==} + engines: {node: '>=18.0.0'} + hasBin: true + ts-loader@9.5.1: resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} engines: {node: '>=12.0.0'} @@ -1879,6 +2001,20 @@ packages: typescript: '*' webpack: ^5.0.0 + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} @@ -1909,17 +2045,29 @@ packages: typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} + typescript-json-schema@0.65.1: + resolution: {integrity: sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==} + hasBin: true + typescript@4.9.5: resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} engines: {node: '>=4.2.0'} hasBin: true + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + uc.micro@1.0.6: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} underscore@1.13.6: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + update-browserslist-db@1.0.16: resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -1939,6 +2087,9 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + watchpack@2.4.1: resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} engines: {node: '>=10.13.0'} @@ -2000,6 +2151,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -2026,6 +2181,10 @@ packages: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} engines: {node: '>=10'} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + yargs-unparser@2.0.0: resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} engines: {node: '>=10'} @@ -2034,12 +2193,20 @@ packages: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} yazl@2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2129,6 +2296,10 @@ snapshots: jsonwebtoken: 9.0.2 uuid: 8.3.2 + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + '@discoveryjs/json-ext@0.5.7': {} '@emnapi/runtime@1.2.0': @@ -2246,6 +2417,15 @@ snapshots: '@img/sharp-win32-x64@0.33.4': optional: true + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -2268,6 +2448,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@microsoft/fast-element@1.13.0': {} '@microsoft/fast-foundation@2.49.6': @@ -2299,6 +2484,17 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@pkgjs/parseargs@0.11.0': + optional: true + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 8.56.10 @@ -2324,6 +2520,10 @@ snapshots: '@types/node@16.18.101': {} + '@types/node@18.19.50': + dependencies: + undici-types: 5.26.5 + '@types/object-hash@2.2.1': {} '@types/plist@3.0.5': @@ -2619,6 +2819,10 @@ snapshots: dependencies: acorn: 8.12.0 + acorn-walk@8.3.4: + dependencies: + acorn: 8.12.0 + acorn@8.12.0: {} agent-base@7.1.1: @@ -2652,11 +2856,15 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.1: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@4.1.3: {} + argparse@2.0.1: {} array-union@2.1.0: {} @@ -2805,6 +3013,12 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clone-deep@4.0.1: dependencies: is-plain-object: 2.0.4 @@ -2841,6 +3055,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 + commander@12.1.0: {} + commander@2.20.3: {} commander@6.2.1: {} @@ -2851,6 +3067,8 @@ snapshots: core-util-is@1.0.3: {} + create-require@1.1.1: {} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -2901,6 +3119,8 @@ snapshots: detect-libc@2.0.3: {} + diff@4.0.2: {} + diff@5.0.0: {} dir-glob@3.0.1: @@ -2941,6 +3161,8 @@ snapshots: emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + end-of-stream@1.4.4: dependencies: once: 1.4.0 @@ -3105,6 +3327,11 @@ snapshots: flatted@3.3.1: {} + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + form-data@4.0.0: dependencies: asynckit: 0.4.0 @@ -3146,6 +3373,15 @@ snapshots: glob-to-regexp@0.4.1: {} + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -3303,6 +3539,12 @@ snapshots: isobject@3.0.1: {} + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jest-worker@27.5.1: dependencies: '@types/node': 16.18.101 @@ -3323,6 +3565,8 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json5@2.2.3: {} + jsonc-parser@3.3.1: {} jsonwebtoken@9.0.2: @@ -3434,10 +3678,14 @@ snapshots: dependencies: js-tokens: 4.0.0 + lru-cache@10.4.3: {} + lru-cache@6.0.0: dependencies: yallist: 4.0.0 + make-error@1.3.6: {} + markdown-it@12.3.2: dependencies: argparse: 2.0.1 @@ -3482,9 +3730,15 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + minimist@1.2.8: optional: true + minipass@7.1.2: {} + mkdirp-classic@0.5.3: optional: true @@ -3599,6 +3853,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.0: {} + pako@1.0.11: {} parent-module@1.0.1: @@ -3618,6 +3874,8 @@ snapshots: dependencies: entities: 4.5.0 + path-equal@1.2.5: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -3626,6 +3884,11 @@ snapshots: path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + path-type@4.0.0: {} pend@1.2.0: {} @@ -3759,6 +4022,8 @@ snapshots: safe-buffer@5.2.1: {} + safe-stable-stringify@2.5.0: {} + sax@1.4.1: {} schema-utils@3.3.0: @@ -3835,6 +4100,8 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + simple-concat@1.0.1: optional: true @@ -3872,6 +4139,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string-width@6.1.0: dependencies: eastasianwidth: 0.2.0 @@ -3958,6 +4231,17 @@ snapshots: dependencies: is-number: 7.0.0 + ts-json-schema-generator@2.3.0: + dependencies: + '@types/json-schema': 7.0.15 + commander: 12.1.0 + glob: 10.4.5 + json5: 2.2.3 + normalize-path: 3.0.0 + safe-stable-stringify: 2.5.0 + tslib: 2.6.3 + typescript: 5.5.4 + ts-loader@9.5.1(typescript@4.9.5)(webpack@5.92.1(webpack-cli@4.10.0)): dependencies: chalk: 4.1.2 @@ -3968,6 +4252,24 @@ snapshots: typescript: 4.9.5 webpack: 5.92.1(webpack-cli@4.10.0) + ts-node@10.9.2(@types/node@18.19.50)(typescript@5.5.4): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.19.50 + acorn: 8.12.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.5.4 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tslib@1.14.1: {} tslib@2.6.3: {} @@ -3996,12 +4298,30 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.6 + typescript-json-schema@0.65.1: + dependencies: + '@types/json-schema': 7.0.15 + '@types/node': 18.19.50 + glob: 7.2.3 + path-equal: 1.2.5 + safe-stable-stringify: 2.5.0 + ts-node: 10.9.2(@types/node@18.19.50)(typescript@5.5.4) + typescript: 5.5.4 + yargs: 17.7.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + typescript@4.9.5: {} + typescript@5.5.4: {} + uc.micro@1.0.6: {} underscore@1.13.6: {} + undici-types@5.26.5: {} + update-browserslist-db@1.0.16(browserslist@4.23.1): dependencies: browserslist: 4.23.1 @@ -4018,6 +4338,8 @@ snapshots: uuid@8.3.2: {} + v8-compile-cache-lib@3.0.1: {} + watchpack@2.4.1: dependencies: glob-to-regexp: 0.4.1 @@ -4096,6 +4418,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} xml2js@0.5.0: @@ -4113,6 +4441,8 @@ snapshots: yargs-parser@20.2.4: {} + yargs-parser@21.1.1: {} + yargs-unparser@2.0.0: dependencies: camelcase: 6.3.0 @@ -4130,6 +4460,16 @@ snapshots: y18n: 5.0.8 yargs-parser: 20.2.4 + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 @@ -4139,4 +4479,6 @@ snapshots: dependencies: buffer-crc32: 0.2.13 + yn@3.1.1: {} + yocto-queue@0.1.0: {} diff --git a/src/project/mod.ts b/src/project/mod.ts index a4383e6..535b0aa 100644 --- a/src/project/mod.ts +++ b/src/project/mod.ts @@ -1,158 +1,614 @@ /* eslint-disable @typescript-eslint/naming-convention */ export interface Font { - path: string; - size: number; - charset: string; - outline: number; + /** + * Path to the font's TTF / OTF file (relative to mod root folder) + */ + path: string, + /** + * Font size in points + * @minimum 0 + */ + size: number, + /** + * List of characters to include in the generated BM font. Default is + * "32-126,8226" + * @pattern [0-9]+(-[0-9]+)?(,([0-9]+(-[0-9]+)?))* + * @default 32-126,8226 + */ + charset: string, + /** + * If specified, will generate a black outline of the provided size around + * the font's characters. Experimental! + * @minimum 0 + */ + outline: number, } export interface Resources { - files?: string[] | null; - sprites?: string[] | null; - fonts?: { [name: string]: Font } | null; - spritesheets?: { [name: string]: string[] } | null; + /** + * Files to include with the mod. Things like sounds, binaries, etc. + */ + files?: string[] | null, + /** + * Sprites to include with the mod. The sprites will automatically have UHD, + * HD and SD versions created of them + */ + sprites?: string[] | null, + /** + * Fonts to include with the mod. Provided format should be TTF / OTF. + * Fonts will be converted automatically into GD-compatible BM fonts by + * Geode CLI before packaging. List the names of the fonts as keys + */ + fonts?: { [name: string]: Font } | null, + /** + * The mod's sprite sheets. Sprite sheets are better optimized than using + * individual image files, so using them for the majority of the sprites in + * your mod is recommended. List the names of the mod's spritesheets as + * keys, and as their values a list of files to include in the sheet + */ + spritesheets?: { [name: string]: string[] } | null, } +export type ShortPlatformIDNoArch = "win" | "mac" | "android" | "ios"; +export type ShortPlatformIDArch = "win" | "mac" | "mac-arm" | "mac-intel" | "android32" | "android64" | "ios"; +export type ShortPlatformID = ShortPlatformIDArch | ShortPlatformIDNoArch; +export type ShortPlatformIDOrGeneric = ShortPlatformID | "desktop" | "mobile"; +export type PlatformID = ShortPlatformID | "windows"; + +/** + * A version meta tag. Geode only supports a limited set of tags + */ +export type VersionTag = "alpha" | "beta" | "prerelease" | "pr"; + +/** + * A version number, as in X.Y.Z. May contain a leading "v", and may contain + * build metadata, such as X.Y.Z-alpha.2 + */ export type Version = | `${number}.${number}.${number}` - | `${number}.${number}.${number}-${string}` - | `${number}.${number}.${number}-${string}${number}` + | `${number}.${number}.${number}-${VersionTag}` + | `${number}.${number}.${number}-${VersionTag}.${number}` | `v${number}.${number}.${number}` - | `v${number}.${number}.${number}-${string}` - | `v${number}.${number}.${number}-${string}${number}`; - -export type SettingType = - | "bool" - | "int" - | "float" - | "string" - | "rgb" - | "color" - | "rgba" - | "path" - | "file" - | "custom"; - -export type Color = + | `v${number}.${number}.${number}-${VersionTag}` + | `v${number}.${number}.${number}-${VersionTag}.${number}`; + +/** + * A Geometry Dash version number, such as 2.206 + */ +export type GDVersion = `${number}.${number}`; + +export type ColorRGB = + /** + * @pattern ^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$ + */ | string | [number, number, number] | { r: number; g: number; b: number }; -export type ColorAlpha = +export type ColorRGBA = + /** + * @pattern ^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$ + */ | string | [number, number, number, number] | { r: number; g: number; b: number; a: number }; -export interface ArrowsControl { - arrows?: boolean; - "arrow-step"?: number; - "big-arrows"?: boolean; - "big-arrow-step"?: number; -} +export type SettingDefaultValue = T | { + win?: T, + mac?: T, + android?: T, + ios?: T, +}; -export interface InputControl { - input?: boolean; +export interface SettingBase { + /** + * Type of the setting. See [the docs](https://docs.geode-sdk.org/mods/settings#setting-types) + * for information on what types are available, and how to use custom types + * @pattern ([a-z]+:)?(a-z0-9\-_)+ + */ + type: string, + /** + * Human-readable name for the setting. Used in the UI. If not present, the + * ID of the setting will be used instead + */ + name?: string, + /** + * Description for what the setting does + */ + description?: string, + /** + * If this setting should only be available on certain platforms, specify + * this property; by default, Geode assumes settings are available on all + * platforms + */ + platforms?: ShortPlatformIDOrGeneric[], } - -export interface SliderControl { - slider?: boolean; - "slider-step"?: number | null; +export interface ValueSetting extends SettingBase { + /** + * The default value for this setting + */ + "default"?: SettingDefaultValue, + /** + * Controls whether this setting should be enabled, based on the values of + * other settings. See [the docs](https://docs.geode-sdk.org/mods/settings#enable-if) + * for the syntax + */ + "enable-if"?: string, + /** + * If the "enable-if" clause is considerably complicated, you can use this + * to specify a human-readable description for what the user should do to + * enable the setting. If not provided, Geode will synthesize one from the + * "enable-if" clause itself. Should be formatted as an order on what to do + * to enable the setting, like "Enable the Catfishing Feature" + */ + "enable-if-description"?: string, + /** + * Whether this setting requires the game to be restarted whenever its value + * is changed + */ + "requires-restart"?: boolean, } - -export interface FileFilter { - description?: string; - files?: string[]; +export interface TitleSetting extends SettingBase { + type: "title", } - -export interface FileControl { - filters?: FileFilter[]; +export interface BoolSetting extends ValueSetting { + type: "bool"; + default: SettingDefaultValue; } - -export interface Setting { - type: SettingType; - name?: string; - description?: string; +export interface IntSetting extends ValueSetting { + type: "int", + /** + * Default value for this setting + */ + default: SettingDefaultValue, + /** + * Default value for this setting + * @asType integer + */ + min?: number, + /** + * Default value for this setting + * @asType integer + */ + max?: number, + /** + * Change the setting's UI + */ + control?: { + /** + * Enable the small (green) arrow controls + */ + "arrows"?: boolean, + /** + * Control how much the small (green) arrows should increment/decrement + * the setting's value when clicked + * @asType integer + */ + "arrow-step"?: number, + /** + * Enable the secondary (pink) arrow controls + */ + "big-arrows"?: boolean, + /** + * Control how much the secondary (pink) arrows should increment/ + * decrement the setting's value when clicked. This should be a larger + * value than the small (green) arrows + * @asType integer + */ + "big-arrow-step"?: number, + /** + * Enable the slider + */ + "slider"?: boolean, + /** + * Control the slider's snap step size + * @asType integer + */ + "slider-step"?: number, + /** + * Enable the text input + */ + "input"?: boolean, + }, } - -export interface IntSetting extends Setting { - type: "int"; - default: number; - min?: number; - max?: number; - "one-of"?: number[]; - control: ArrowsControl & SliderControl & InputControl; +export interface FloatSetting extends ValueSetting { + type: "float", + /** + * Default value for this setting + */ + default: SettingDefaultValue, + /** + * Minimum value for this setting + * @asType number + */ + min?: number, + /** + * Maximum value for this setting + * @asType number + */ + max?: number, + /** + * Change the setting's UI + */ + control?: { + /** + * Enable the small (green) arrow controls + */ + "arrows"?: boolean, + /** + * Control how much the small (green) arrows should increment/decrement + * the setting's value when clicked + * @asType number + */ + "arrow-step"?: number, + /** + * Enable the secondary (pink) arrow controls + */ + "big-arrows"?: boolean, + /** + * Control how much the secondary (pink) arrows should increment/ + * decrement the setting's value when clicked. This should be a larger + * value than the small (green) arrows + * @asType number + */ + "big-arrow-step"?: number, + /** + * Enable the slider + */ + "slider"?: boolean, + /** + * Control the slider's snap step size + * @asType number + */ + "slider-step"?: number, + /** + * Enable the text input + */ + "input"?: boolean, + }, } - -export interface FloatSetting extends Setting { - type: "float"; - default: number; - min?: number; - max?: number; - "one-of"?: number[]; - control: ArrowsControl & SliderControl & InputControl; +export interface StringSetting extends ValueSetting { + type: "string", + default: SettingDefaultValue, + /** + * A regex the string must match + */ + match?: string, + /** + * List of all the allowed characters, similar to `CCTextInputNode` + */ + filter?: string, + /** + * A list of the allowed values for the string. Turns the setting into a + * selection list instead of an input + */ + "one-of"?: string[], } - -export interface StringSetting extends Setting { - type: "string"; - default: string; - match?: string; - "one-of": string[]; +// todo in Geode v4: remove this +export interface PathSetting extends ValueSetting { + /** + * @deprecated Use the "file" or "folder" type instead + */ + type: "path", + default: SettingDefaultValue, + control?: { + /** + * The dialog to show when the user clicks the file selection button in + * the UI + */ + dialog?: "open" | "save", + /** + * Filter options to show in the file pick dialog. The option + * "All files (*.*)" will always be included alongside these by default + */ + filters?: { + /** + * Filter description, like "Level Files" + */ + description?: string; + /** + * File wildcard to match. Can be for example `*.gmd`, `*.gmd2`, or + * `Steve.txt` + */ + files?: string[]; + }[], + }, } - -export interface BoolSetting extends Setting { - type: "bool"; - default: boolean; +export interface FileSetting extends ValueSetting { + type: "file", + default: SettingDefaultValue, + control?: { + /** + * The dialog to show when the user clicks the file selection button in + * the UI + */ + dialog?: "open" | "save", + /** + * Filter options to show in the file pick dialog. The option + * "All files (*.*)" will always be included alongside these by default + */ + filters?: { + /** + * Filter description, like "Level Files" + */ + description?: string; + /** + * File wildcard to match. Can be for example `*.gmd`, `*.gmd2`, or + * `Steve.txt` + */ + files?: string[]; + }[], + }, } - -export interface ColorSetting extends Setting { - type: "color" | "rgb"; - default: Color; +export interface FolderSetting extends ValueSetting { + type: "folder", + default: SettingDefaultValue, } - -export interface ColorAlphaSetting extends Setting { - type: "rgba"; - default: ColorAlpha; +export interface ColorSetting extends ValueSetting { + type: "color" | "rgb", + default: SettingDefaultValue, } - -export interface FileSetting extends Setting { - type: "path" | "file"; - default: string; - control?: FileControl; +export interface ColorAlphaSetting extends ValueSetting { + type: "rgba", + default: SettingDefaultValue, } - -export type Settings = { [id: string]: Setting }; - -export interface Issues { - info: string; - url?: string; +/** + * @additionalProperties true + */ +export interface LegacyCustomSetting extends SettingBase { + /** + * @deprecated Use custom setting types (i.e. `custom:my-type-name`) instead. + * See [our docs](https://docs.geode-sdk.org/mods/settings) for more + */ + type: "custom", + [other: string]: unknown, +} +/** + * @additionalProperties true + */ +export interface CustomTypeSetting extends ValueSetting { + /** + * @pattern custom:[a-z]+ + */ + type: string, + [other: string]: unknown, } +export type Setting = + | TitleSetting + | BoolSetting + | IntSetting + | FloatSetting + | StringSetting + | FileSetting + | PathSetting + | FolderSetting + | ColorSetting + | ColorAlphaSetting + | LegacyCustomSetting + | CustomTypeSetting; export interface Dependency { - id: string; - version: Version; - required?: boolean; + /** + * ID of the dependency + * @pattern [a-z0-9\-_]+\.[a-z0-9\-_]+ + */ + id: string, + /** + * Version of the dependency. Geode assumes the mod follows [semver](https://semver.org); + * this means that versions "1.5.3" and "1.4.0" will be considered valid + * for dependency version "1.4.5" but "2.1.0" would not be valid + */ + version: Version, + /** + * Whether the dependency is required in order to load this mod + * @deprecated Use the "importance" property instead + */ + required?: boolean, + /** + * Whether this dependency is required for the mod to work, or only + * recommended for users + */ + importance: "required" | "recommended" | "suggested", + /** + * If this dependency should only be on certain platforms, specify this + * property; by default, Geode assumes dependencies are used on all + * platforms + */ + platforms?: ShortPlatformIDOrGeneric[], +} +export interface Incompatibility { + /** + * ID of the incompatability + * @pattern [a-z0-9\-_]+\.[a-z0-9\-_]+ + */ + id: string, + /** + * Version of the incompatability. Geode assumes the mod follows [semver](https://semver.org); + * this means that versions "1.5.3" and "1.4.0" will be considered valid + * for incompatability version "1.4.5" but "2.1.0" would not be valid + */ + version: Version, + /** + * How kind of an incompatibility this is + */ + importance: + /** + * This mod does not work with the incompatible mod + */ + "breaking" | + /** + * This mod might work with the incompatible mod, but there will be bugs + */ + "conflicting" | + /** + * This mod is a newer version/alternative for the incompatible mod. + * Geode will present this to the user and allow them to automatically + * migrate from the old mod to this one + */ + "superseded", + /** + * If this incompatibility should only be on certain platforms, specify + * this property; by default, Geode assumes incompatibilities are used on + * all platforms + */ + platforms?: ShortPlatformIDOrGeneric[], } -export interface Api { - include: string[]; +/** + * A tag for a mod. See [the docs](https://docs.geode-sdk.org/mods/configuring#tags) + * for information on what all the tags mean + */ +export type Tag = + "universal" | + "gameplay" | + "editor" | + "offline" | + "online" | + "enhancement" | + "music" | + "interface" | + "bugfix" | + "utility" | + "performance" | + "customization" | + "content" | + "developer" | + "cheats" | + "paid" | + "joke"; + +/** + * Configuration options for a Geode mod. Specifies metadata like the name and + * version, as well as things like settings and resources + */ +interface ModJsonBase { + /** + * The version of Geode this mod targets. Must be the version you currently + * have installed on your machine + */ + geode: Version, + /** + * The version of this mod. Mods should follow [strict semver](https://semver.org); + * this ensures that mods that [use other mods as dependencies](https://docs.geode-sdk.org/mods/dependencies) + * can do so safely + */ + version: Version, + /** + * "What version of Geometry Dash this mod targets. Use \"*\" for any + * version, or specify a version. \"*\" is for mods that only interact with + * Cocos or other libraries, or can handle version checking themselves." + */ + gd: "*" | { + "win"?: GDVersion, + "mac"?: GDVersion, + "android"?: GDVersion, + "ios"?: GDVersion, + }, + /** + * ID of the mod. This is used to uniquely distinguish the mod in places + * like URLs, file names, etc.. Should be formatted as + * \"developer.mod-name\". Note that the ID should never be changed after + * initial release - that's what "name" is for! + * @pattern [a-z0-9\-_]+\.[a-z0-9\-_]+ + */ + id: string, + /** + * Name of the mod. May be anything, but do note that GD usually has limits + * on what characters it can render + */ + name: string, + /** + * Short, free-form description of the mod. Should be less than 45 + * characters long; use `about.md` for a more detailed description! + * @maxLength 45 + */ + description?: string, + /** + * URL of the mod's Git repository, or other equivalent homepage + * @deprecated Use the \"links\" key instead + */ + repository?: string, + /** + * Links to websites and other online content related to the mod + */ + links?: { + /** + * URL of the mod's home website + */ + homepage?: string, + /** + * URL of the mod's Git repository, or wherever the mod's source code is available + */ + source?: string, + /** + * A discussion community for the mod, like a Discord server + */ + community?: string, + }, + /** + * List of mods this mod depends on. See [the docs](https://docs.geode-sdk.org/mods/dependencies) + * for more information + */ + dependencies?: Dependency[] | null, + /** + * List of mods this mod is incompatible with + */ + incompatibilities?: Incompatibility[] | null, + resources?: Resources | null, + /** + * The mod's settings. These are editable by the user in-game through the + * mod's settings page. See [the docs page](https://docs.geode-sdk.org/mods/settings) + * for more information + */ + settings?: { [id: string]: Setting }, + /** + * Info about where and how to report bugs and other issues regarding this + * mod + */ + issues?: { + /** + * Free-form info about where and how to report issues. Supports + * markdown formatting + */ + info: string; + /** + * URL for posting issues. Usually the GitHub issues page + */ + url?: string; + }, + "early-load"?: boolean, + /** + * Tags that describe what this mod is for. A recommended amount is 1-4 tags + */ + tags?: Tag[], + /** + * Define that this mod should be used as a dependency. If this key is + * present, the .lib file is automatically included in the .geode package + */ + api?: { + /** + * Headers to include with the mod. Supports globbing + * @default ["include/*.hpp"] + */ + include: string[]; + }, } -export interface ModJson { - geode: Version; - version: Version; - id: string; - name: string; - developer: string; - description?: string; - repository?: string; - dependencies?: Dependency[] | null; - resources?: Resources | null; - settings?: Settings; - issues?: Issues; - "early-load"?: boolean; - api?: Api; +interface ModJsonWithSingleDevImpl extends ModJsonBase { + /** + * Name of the mod developer. If the mod has multiple developers, use the + * "developers" key, or use a team name like "Geode Team" + */ + developer: string, +} +interface ModJsonWithMultiDevImpl extends ModJsonBase { + /** + * Names of the mod's developers + */ + developers: string[], } +export type ModJson = ModJsonWithSingleDevImpl | ModJsonWithMultiDevImpl; // Mod runtime info, queried through loader IPC @@ -180,7 +636,7 @@ export interface ModRunTimeInfo { "config-dir": string; } -export interface RTModJson extends ModJson { +export interface RTModJson extends ModJsonBase { path: string; binary: string; runtime: ModRunTimeInfo; diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index de8e485..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,48 +0,0 @@ -//@ts-check - -"use strict"; - -const path = require("path"); - -//@ts-check -/** @typedef {import('webpack').Configuration} WebpackConfig **/ - -/** @type WebpackConfig */ -const extensionConfig = { - target: "node", // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ - mode: "none", // this leaves the source code as close as possible to the original (when packaging we set this to 'production') - - entry: "./src/extension.ts", // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ - output: { - // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ - path: path.resolve(__dirname, "dist"), - filename: "extension.js", - libraryTarget: "commonjs2", - }, - externals: { - vscode: "commonjs vscode", - sharp: "sharp", - }, - resolve: { - // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader - extensions: [".ts", ".js"], - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /node_modules/, - use: [ - { - loader: "ts-loader", - }, - ], - }, - ], - }, - devtool: "nosources-source-map", - infrastructureLogging: { - level: "log", // enables logging required for problem matchers - }, -}; -module.exports = [extensionConfig]; diff --git a/webpack.config.ts b/webpack.config.ts new file mode 100644 index 0000000..ef38660 --- /dev/null +++ b/webpack.config.ts @@ -0,0 +1,61 @@ +//@ts-check + +"use strict"; + +import { Configuration, Compiler } from "webpack"; +import { createGenerator } from "ts-json-schema-generator"; +import { mkdirSync, writeFileSync } from "fs"; + +const path = require("path"); + +class JsonValidationGenner { + apply(compiler: Compiler) { + compiler.hooks.watchRun.tap("generate mod.json validation", () => { + const schema = createGenerator({ + path: "./src/project/mod.ts", + tsconfig: "./tsconfig.json", + type: "ModJson", + markdownDescription: true + }).createSchema("ModJson"); + mkdirSync("./dist/validation", { recursive: true }); + writeFileSync("./dist/validation/mod.json", JSON.stringify(schema)); + }); + } +} + +const extensionConfig: Configuration = { + target: "node", + mode: "none", + entry: "./src/extension.ts", + output: { + path: path.resolve(__dirname, "dist"), + filename: "extension.js", + libraryTarget: "commonjs2", + }, + externals: { + vscode: "commonjs vscode", + sharp: "sharp", + }, + resolve: { + extensions: [".ts", ".js"], + }, + module: { + rules: [ + { + test: /\.ts$/, + exclude: /node_modules/, + use: [ + { + loader: "ts-loader", + }, + ], + }, + ], + }, + devtool: "nosources-source-map", + infrastructureLogging: { + level: "log", // enables logging required for problem matchers + }, + plugins: [new JsonValidationGenner()], +}; +module.exports = [extensionConfig];