From 5819ebd1b0463d144912f0e66209198124559a9c Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Tue, 30 Dec 2025 14:58:53 +0000 Subject: [PATCH 1/7] feat: check imports using ast --- package.json | 4 +- pnpm-lock.yaml | 371 +++++++++++++++++++++++----------- scripts/i18n-import-check.ts | 379 +++++++++++++++++++++++++++++++++++ 3 files changed, 631 insertions(+), 123 deletions(-) create mode 100644 scripts/i18n-import-check.ts diff --git a/package.json b/package.json index 02cde59cd3..97dff04979 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,13 @@ "prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config", "prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend", "prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend", - "icons:add": "pnpm --filter @modrinth/assets icons:add", + "icons:add": "pnpm --filter @modrinth/assets icons:add", "scripts": "node scripts/run.mjs" }, "devDependencies": { "@modrinth/tooling-config": "workspace:*", + "@vue/compiler-sfc": "^3.5.26", + "chalk": "^5.6.2", "if-ci": "^3.0.0", "prettier": "^3.3.2", "turbo": "^2.5.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2248d5c2ff..abc6cf396c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,12 @@ importers: '@modrinth/tooling-config': specifier: workspace:* version: link:packages/tooling-config + '@vue/compiler-sfc': + specifier: ^3.5.26 + version: 3.5.26 + chalk: + specifier: ^5.6.2 + version: 5.6.2 if-ci: specifier: ^3.0.0 version: 3.0.0 @@ -140,7 +146,7 @@ importers: version: 1.2.1(eslint@9.13.0(jiti@2.6.1)) '@formatjs/cli': specifier: ^6.2.12 - version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) + version: 6.2.12(@vue/compiler-core@3.5.26)(vue@3.5.13(typescript@5.5.4)) '@modrinth/tooling-config': specifier: workspace:* version: link:../../packages/tooling-config @@ -347,7 +353,7 @@ importers: devDependencies: '@formatjs/cli': specifier: ^6.2.12 - version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) + version: 6.2.12(@vue/compiler-core@3.5.26)(vue@3.5.13(typescript@5.5.4)) '@nuxt/devtools': specifier: ^1.3.3 version: 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.44.1))(vue@3.5.13(typescript@5.5.4)) @@ -497,7 +503,7 @@ importers: devDependencies: '@formatjs/cli': specifier: ^6.2.12 - version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.8.3)) + version: 6.2.12(@vue/compiler-core@3.5.26)(vue@3.5.13(typescript@5.8.3)) '@modrinth/tooling-config': specifier: workspace:* version: link:../tooling-config @@ -649,7 +655,7 @@ importers: devDependencies: '@formatjs/cli': specifier: ^6.2.12 - version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) + version: 6.2.12(@vue/compiler-core@3.5.26)(vue@3.5.13(typescript@5.5.4)) '@modrinth/tooling-config': specifier: workspace:* version: link:../tooling-config @@ -865,10 +871,18 @@ packages: resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} @@ -882,6 +896,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-proposal-decorators@7.24.7': resolution: {integrity: sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==} engines: {node: '>=6.9.0'} @@ -943,6 +962,10 @@ packages: resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + '@cloudflare/kv-asset-handler@0.3.4': resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} @@ -3096,15 +3119,27 @@ packages: '@vue/compiler-core@3.5.13': resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + '@vue/compiler-core@3.5.26': + resolution: {integrity: sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==} + '@vue/compiler-dom@3.5.13': resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + '@vue/compiler-dom@3.5.26': + resolution: {integrity: sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==} + '@vue/compiler-sfc@3.5.13': resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + '@vue/compiler-sfc@3.5.26': + resolution: {integrity: sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==} + '@vue/compiler-ssr@3.5.13': resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + '@vue/compiler-ssr@3.5.26': + resolution: {integrity: sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==} + '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} @@ -3147,6 +3182,9 @@ packages: '@vue/shared@3.5.13': resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + '@vue/shared@3.5.26': + resolution: {integrity: sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==} + '@vue/tsconfig@0.7.0': resolution: {integrity: sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==} peerDependencies: @@ -3509,6 +3547,10 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} @@ -4084,6 +4126,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@7.0.0: + resolution: {integrity: sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==} + engines: {node: '>=0.12'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -5629,6 +5675,11 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -6264,6 +6315,10 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + posthog-js@1.158.2: resolution: {integrity: sha512-ovb7GHHRNDf6vmuL+8lbDukewzDzQlLZXg3d475hrfHSBgidYeTxtLGtoBcUz4x6558BLDFjnSip+f3m4rV9LA==} @@ -8394,8 +8449,12 @@ snapshots: '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-option@7.25.9': {} '@babel/helpers@7.26.0': @@ -8407,6 +8466,10 @@ snapshots: dependencies: '@babel/types': 7.26.3 + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + '@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -8481,6 +8544,11 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@cloudflare/kv-asset-handler@0.3.4': dependencies: mime: 3.0.0 @@ -8936,8 +9004,8 @@ snapshots: hast-util-to-html: 9.0.5 hast-util-to-text: 4.0.2 hastscript: 9.0.0 - postcss: 8.4.49 - postcss-nested: 6.0.1(postcss@8.4.49) + postcss: 8.5.3 + postcss-nested: 6.0.1(postcss@8.5.3) unist-util-visit: 5.0.0 unist-util-visit-parents: 6.0.1 @@ -8964,14 +9032,14 @@ snapshots: '@floating-ui/utils@0.2.4': {} - '@formatjs/cli@6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4))': + '@formatjs/cli@6.2.12(@vue/compiler-core@3.5.26)(vue@3.5.13(typescript@5.5.4))': optionalDependencies: - '@vue/compiler-core': 3.5.13 + '@vue/compiler-core': 3.5.26 vue: 3.5.13(typescript@5.5.4) - '@formatjs/cli@6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.8.3))': + '@formatjs/cli@6.2.12(@vue/compiler-core@3.5.26)(vue@3.5.13(typescript@5.8.3))': optionalDependencies: - '@vue/compiler-core': 3.5.13 + '@vue/compiler-core': 3.5.26 vue: 3.5.13(typescript@5.8.3) '@formatjs/ecma402-abstract@2.3.6': @@ -9221,7 +9289,7 @@ snapshots: '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping@0.3.31': dependencies: @@ -9557,10 +9625,10 @@ snapshots: '@rollup/plugin-replace': 6.0.1(rollup@4.28.1) '@vitejs/plugin-vue': 5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.44.1))(vue@3.5.13(typescript@5.5.4)) '@vitejs/plugin-vue-jsx': 4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.44.1))(vue@3.5.13(typescript@5.5.4)) - autoprefixer: 10.4.20(postcss@8.4.49) + autoprefixer: 10.4.20(postcss@8.5.3) clear: 0.1.0 consola: 3.2.3 - cssnano: 7.0.6(postcss@8.4.49) + cssnano: 7.0.6(postcss@8.5.3) defu: 6.1.4 esbuild: 0.24.0 escape-string-regexp: 5.0.0 @@ -9570,13 +9638,13 @@ snapshots: h3: 1.13.0 jiti: 2.4.2 knitwork: 1.1.0 - magic-string: 0.30.14 + magic-string: 0.30.21 mlly: 1.7.3 ohash: 1.1.4 pathe: 1.1.2 perfect-debounce: 1.0.0 pkg-types: 1.2.1 - postcss: 8.4.49 + postcss: 8.5.3 rollup-plugin-visualizer: 5.12.0(rollup@4.28.1) std-env: 3.8.0 strip-literal: 2.1.1 @@ -9817,7 +9885,7 @@ snapshots: estree-walker: 2.0.2 fdir: 6.4.2(picomatch@4.0.2) is-reference: 1.2.1 - magic-string: 0.30.14 + magic-string: 0.30.21 picomatch: 4.0.2 optionalDependencies: rollup: 4.28.1 @@ -9826,7 +9894,7 @@ snapshots: dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.28.1) estree-walker: 2.0.2 - magic-string: 0.30.14 + magic-string: 0.30.21 optionalDependencies: rollup: 4.28.1 @@ -9849,7 +9917,7 @@ snapshots: '@rollup/plugin-replace@6.0.1(rollup@4.28.1)': dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.28.1) - magic-string: 0.30.14 + magic-string: 0.30.21 optionalDependencies: rollup: 4.28.1 @@ -10856,11 +10924,24 @@ snapshots: estree-walker: 2.0.2 source-map-js: 1.2.1 + '@vue/compiler-core@3.5.26': + dependencies: + '@babel/parser': 7.28.5 + '@vue/shared': 3.5.26 + entities: 7.0.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + '@vue/compiler-dom@3.5.13': dependencies: '@vue/compiler-core': 3.5.13 '@vue/shared': 3.5.13 + '@vue/compiler-dom@3.5.26': + dependencies: + '@vue/compiler-core': 3.5.26 + '@vue/shared': 3.5.26 + '@vue/compiler-sfc@3.5.13': dependencies: '@babel/parser': 7.26.3 @@ -10873,11 +10954,28 @@ snapshots: postcss: 8.4.49 source-map-js: 1.2.1 + '@vue/compiler-sfc@3.5.26': + dependencies: + '@babel/parser': 7.28.5 + '@vue/compiler-core': 3.5.26 + '@vue/compiler-dom': 3.5.26 + '@vue/compiler-ssr': 3.5.26 + '@vue/shared': 3.5.26 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.6 + source-map-js: 1.2.1 + '@vue/compiler-ssr@3.5.13': dependencies: '@vue/compiler-dom': 3.5.13 '@vue/shared': 3.5.13 + '@vue/compiler-ssr@3.5.26': + dependencies: + '@vue/compiler-dom': 3.5.26 + '@vue/shared': 3.5.26 + '@vue/compiler-vue2@2.7.16': dependencies: de-indent: 1.0.2 @@ -10954,6 +11052,8 @@ snapshots: '@vue/shared@3.5.13': {} + '@vue/shared@3.5.26': {} + '@vue/tsconfig@0.7.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))': optionalDependencies: typescript: 5.8.3 @@ -11284,6 +11384,16 @@ snapshots: postcss: 8.4.49 postcss-value-parser: 4.2.0 + autoprefixer@10.4.20(postcss@8.5.3): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001687 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + axobject-query@4.1.0: {} b4a@1.6.6: {} @@ -11444,6 +11554,8 @@ snapshots: chalk@5.3.0: {} + chalk@5.6.2: {} + change-case@5.4.4: {} character-entities-html4@2.1.0: {} @@ -11650,9 +11762,9 @@ snapshots: dependencies: uncrypto: 0.1.3 - css-declaration-sorter@7.2.0(postcss@8.4.49): + css-declaration-sorter@7.2.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 css-select@5.1.0: dependencies: @@ -11680,49 +11792,49 @@ snapshots: cssfilter@0.0.10: {} - cssnano-preset-default@7.0.6(postcss@8.4.49): + cssnano-preset-default@7.0.6(postcss@8.5.3): dependencies: browserslist: 4.24.2 - css-declaration-sorter: 7.2.0(postcss@8.4.49) - cssnano-utils: 5.0.0(postcss@8.4.49) - postcss: 8.4.49 - postcss-calc: 10.0.2(postcss@8.4.49) - postcss-colormin: 7.0.2(postcss@8.4.49) - postcss-convert-values: 7.0.4(postcss@8.4.49) - postcss-discard-comments: 7.0.3(postcss@8.4.49) - postcss-discard-duplicates: 7.0.1(postcss@8.4.49) - postcss-discard-empty: 7.0.0(postcss@8.4.49) - postcss-discard-overridden: 7.0.0(postcss@8.4.49) - postcss-merge-longhand: 7.0.4(postcss@8.4.49) - postcss-merge-rules: 7.0.4(postcss@8.4.49) - postcss-minify-font-values: 7.0.0(postcss@8.4.49) - postcss-minify-gradients: 7.0.0(postcss@8.4.49) - postcss-minify-params: 7.0.2(postcss@8.4.49) - postcss-minify-selectors: 7.0.4(postcss@8.4.49) - postcss-normalize-charset: 7.0.0(postcss@8.4.49) - postcss-normalize-display-values: 7.0.0(postcss@8.4.49) - postcss-normalize-positions: 7.0.0(postcss@8.4.49) - postcss-normalize-repeat-style: 7.0.0(postcss@8.4.49) - postcss-normalize-string: 7.0.0(postcss@8.4.49) - postcss-normalize-timing-functions: 7.0.0(postcss@8.4.49) - postcss-normalize-unicode: 7.0.2(postcss@8.4.49) - postcss-normalize-url: 7.0.0(postcss@8.4.49) - postcss-normalize-whitespace: 7.0.0(postcss@8.4.49) - postcss-ordered-values: 7.0.1(postcss@8.4.49) - postcss-reduce-initial: 7.0.2(postcss@8.4.49) - postcss-reduce-transforms: 7.0.0(postcss@8.4.49) - postcss-svgo: 7.0.1(postcss@8.4.49) - postcss-unique-selectors: 7.0.3(postcss@8.4.49) - - cssnano-utils@5.0.0(postcss@8.4.49): + css-declaration-sorter: 7.2.0(postcss@8.5.3) + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-calc: 10.0.2(postcss@8.5.3) + postcss-colormin: 7.0.2(postcss@8.5.3) + postcss-convert-values: 7.0.4(postcss@8.5.3) + postcss-discard-comments: 7.0.3(postcss@8.5.3) + postcss-discard-duplicates: 7.0.1(postcss@8.5.3) + postcss-discard-empty: 7.0.0(postcss@8.5.3) + postcss-discard-overridden: 7.0.0(postcss@8.5.3) + postcss-merge-longhand: 7.0.4(postcss@8.5.3) + postcss-merge-rules: 7.0.4(postcss@8.5.3) + postcss-minify-font-values: 7.0.0(postcss@8.5.3) + postcss-minify-gradients: 7.0.0(postcss@8.5.3) + postcss-minify-params: 7.0.2(postcss@8.5.3) + postcss-minify-selectors: 7.0.4(postcss@8.5.3) + postcss-normalize-charset: 7.0.0(postcss@8.5.3) + postcss-normalize-display-values: 7.0.0(postcss@8.5.3) + postcss-normalize-positions: 7.0.0(postcss@8.5.3) + postcss-normalize-repeat-style: 7.0.0(postcss@8.5.3) + postcss-normalize-string: 7.0.0(postcss@8.5.3) + postcss-normalize-timing-functions: 7.0.0(postcss@8.5.3) + postcss-normalize-unicode: 7.0.2(postcss@8.5.3) + postcss-normalize-url: 7.0.0(postcss@8.5.3) + postcss-normalize-whitespace: 7.0.0(postcss@8.5.3) + postcss-ordered-values: 7.0.1(postcss@8.5.3) + postcss-reduce-initial: 7.0.2(postcss@8.5.3) + postcss-reduce-transforms: 7.0.0(postcss@8.5.3) + postcss-svgo: 7.0.1(postcss@8.5.3) + postcss-unique-selectors: 7.0.3(postcss@8.5.3) + + cssnano-utils@5.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 - cssnano@7.0.6(postcss@8.4.49): + cssnano@7.0.6(postcss@8.5.3): dependencies: - cssnano-preset-default: 7.0.6(postcss@8.4.49) + cssnano-preset-default: 7.0.6(postcss@8.5.3) lilconfig: 3.1.2 - postcss: 8.4.49 + postcss: 8.5.3 csso@5.0.5: dependencies: @@ -11914,6 +12026,8 @@ snapshots: entities@4.5.0: {} + entities@7.0.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -14090,6 +14204,8 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 + nanoid@3.3.11: {} + nanoid@3.3.7: {} nanoid@3.3.8: {} @@ -14146,7 +14262,7 @@ snapshots: klona: 2.0.6 knitwork: 1.1.0 listhen: 1.9.0 - magic-string: 0.30.14 + magic-string: 0.30.21 magicast: 0.3.5 mime: 4.0.4 mlly: 1.7.3 @@ -14690,42 +14806,42 @@ snapshots: pluralize@8.0.0: {} - postcss-calc@10.0.2(postcss@8.4.49): + postcss-calc@10.0.2(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - postcss-colormin@7.0.2(postcss@8.4.49): + postcss-colormin@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 caniuse-api: 3.0.0 colord: 2.9.3 - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-convert-values@7.0.4(postcss@8.4.49): + postcss-convert-values@7.0.4(postcss@8.5.3): dependencies: browserslist: 4.24.2 - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-discard-comments@7.0.3(postcss@8.4.49): + postcss-discard-comments@7.0.3(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 - postcss-discard-duplicates@7.0.1(postcss@8.4.49): + postcss-discard-duplicates@7.0.1(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 - postcss-discard-empty@7.0.0(postcss@8.4.49): + postcss-discard-empty@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 - postcss-discard-overridden@7.0.0(postcss@8.4.49): + postcss-discard-overridden@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-import@15.1.0(postcss@8.4.49): dependencies: @@ -14746,43 +14862,43 @@ snapshots: optionalDependencies: postcss: 8.4.49 - postcss-merge-longhand@7.0.4(postcss@8.4.49): + postcss-merge-longhand@7.0.4(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - stylehacks: 7.0.4(postcss@8.4.49) + stylehacks: 7.0.4(postcss@8.5.3) - postcss-merge-rules@7.0.4(postcss@8.4.49): + postcss-merge-rules@7.0.4(postcss@8.5.3): dependencies: browserslist: 4.24.2 caniuse-api: 3.0.0 - cssnano-utils: 5.0.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-selector-parser: 6.1.2 - postcss-minify-font-values@7.0.0(postcss@8.4.49): + postcss-minify-font-values@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-minify-gradients@7.0.0(postcss@8.4.49): + postcss-minify-gradients@7.0.0(postcss@8.5.3): dependencies: colord: 2.9.3 - cssnano-utils: 5.0.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-minify-params@7.0.2(postcss@8.4.49): + postcss-minify-params@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 - cssnano-utils: 5.0.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-minify-selectors@7.0.4(postcss@8.4.49): + postcss-minify-selectors@7.0.4(postcss@8.5.3): dependencies: cssesc: 3.0.0 - postcss: 8.4.49 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-nested@6.0.1(postcss@8.4.49): @@ -14790,66 +14906,71 @@ snapshots: postcss: 8.4.49 postcss-selector-parser: 6.1.2 - postcss-normalize-charset@7.0.0(postcss@8.4.49): + postcss-nested@6.0.1(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 - postcss-normalize-display-values@7.0.0(postcss@8.4.49): + postcss-normalize-charset@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 + + postcss-normalize-display-values@7.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-positions@7.0.0(postcss@8.4.49): + postcss-normalize-positions@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-repeat-style@7.0.0(postcss@8.4.49): + postcss-normalize-repeat-style@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-string@7.0.0(postcss@8.4.49): + postcss-normalize-string@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-timing-functions@7.0.0(postcss@8.4.49): + postcss-normalize-timing-functions@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-unicode@7.0.2(postcss@8.4.49): + postcss-normalize-unicode@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-url@7.0.0(postcss@8.4.49): + postcss-normalize-url@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-normalize-whitespace@7.0.0(postcss@8.4.49): + postcss-normalize-whitespace@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-ordered-values@7.0.1(postcss@8.4.49): + postcss-ordered-values@7.0.1(postcss@8.5.3): dependencies: - cssnano-utils: 5.0.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-reduce-initial@7.0.2(postcss@8.4.49): + postcss-reduce-initial@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 caniuse-api: 3.0.0 - postcss: 8.4.49 + postcss: 8.5.3 - postcss-reduce-transforms@7.0.0(postcss@8.4.49): + postcss-reduce-transforms@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-selector-parser@6.1.2: @@ -14857,15 +14978,15 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-svgo@7.0.1(postcss@8.4.49): + postcss-svgo@7.0.1(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-value-parser: 4.2.0 svgo: 3.3.2 - postcss-unique-selectors@7.0.3(postcss@8.4.49): + postcss-unique-selectors@7.0.3(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-value-parser@4.2.0: {} @@ -14882,6 +15003,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + posthog-js@1.158.2: dependencies: fflate: 0.4.8 @@ -15731,10 +15858,10 @@ snapshots: dependencies: inline-style-parser: 0.2.3 - stylehacks@7.0.4(postcss@8.4.49): + stylehacks@7.0.4(postcss@8.5.3): dependencies: browserslist: 4.24.2 - postcss: 8.4.49 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 sucrase@3.35.0: @@ -16050,7 +16177,7 @@ snapshots: dependencies: acorn: 8.14.0 estree-walker: 3.0.3 - magic-string: 0.30.17 + magic-string: 0.30.21 unplugin: 1.16.0 unctx@2.4.1: @@ -16191,7 +16318,7 @@ snapshots: fast-glob: 3.3.2 json5: 2.2.3 local-pkg: 0.5.1 - magic-string: 0.30.14 + magic-string: 0.30.21 mlly: 1.7.3 pathe: 1.1.2 scule: 1.3.0 @@ -16277,7 +16404,7 @@ snapshots: unwasm@0.3.9: dependencies: knitwork: 1.1.0 - magic-string: 0.30.14 + magic-string: 0.30.21 mlly: 1.7.3 pathe: 1.1.2 pkg-types: 1.2.1 diff --git a/scripts/i18n-import-check.ts b/scripts/i18n-import-check.ts new file mode 100644 index 0000000000..4e29eb5a5a --- /dev/null +++ b/scripts/i18n-import-check.ts @@ -0,0 +1,379 @@ +import { parse as parseVue } from '@vue/compiler-sfc' +import { parse as parseTs, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree' +import type { TSESTree } from '@typescript-eslint/typescript-estree' +import chalk from 'chalk' +import * as fs from 'fs' +import * as path from 'path' + +// i18n symbols that should be imported from @modrinth/ui +const I18N_SYMBOLS = ['useVIntl', 'defineMessage', 'defineMessages', 'IntlFormatted'] as const +type I18nSymbol = (typeof I18N_SYMBOLS)[number] + +// formatMessage is special - it's destructured from useVIntl(), not directly imported +const FORMAT_MESSAGE = 'formatMessage' + +// Valid import sources for i18n symbols +const VALID_IMPORT_SOURCES = ['@modrinth/ui'] + +// Directories to exclude from scanning +const EXCLUDED_DIRS = new Set(['node_modules', '.output', '.nuxt', 'dist', '.git', '.turbo']) + +interface FileIssue { + file: string + symbol: string + line: number +} + +interface ImportInfo { + symbol: string + source: string +} + +interface Usage { + symbol: string + line: number +} + +const theme = { + warning: chalk.yellow, + error: chalk.red, + success: chalk.green, + muted: chalk.gray, + highlight: chalk.white.bold, + file: chalk.cyan, +} + +/** + * Recursively find all .vue and .ts files in directories + */ +function findFiles(dirs: string[]): string[] { + const files: string[] = [] + + function walk(dir: string) { + if (!fs.existsSync(dir)) return + + const entries = fs.readdirSync(dir, { withFileTypes: true }) + for (const entry of entries) { + const fullPath = path.join(dir, entry.name) + + if (entry.isDirectory()) { + // Skip excluded directories and hidden directories + if (!EXCLUDED_DIRS.has(entry.name) && !entry.name.startsWith('.')) { + walk(fullPath) + } + } else if (entry.isFile()) { + if (entry.name.endsWith('.vue') || entry.name.endsWith('.ts')) { + // Skip .d.ts files + if (!entry.name.endsWith('.d.ts')) { + files.push(fullPath) + } + } + } + } + } + + for (const dir of dirs) { + walk(dir) + } + + return files +} + +/** + * Parse TypeScript/JavaScript content into AST + */ +function parseTsContent(content: string, isJsx: boolean = false): TSESTree.Program | null { + try { + return parseTs(content, { + jsx: isJsx, + loc: true, + range: true, + }) + } catch { + return null + } +} + +/** + * Extract script content from Vue SFC + */ +function extractVueScript(content: string): { script: string; isTs: boolean } | null { + try { + const { descriptor } = parseVue(content) + const scriptContent = descriptor.scriptSetup?.content || descriptor.script?.content + if (!scriptContent) return null + + const lang = descriptor.scriptSetup?.lang || descriptor.script?.lang + const isTs = lang === 'ts' || lang === 'tsx' + + return { script: scriptContent, isTs } + } catch { + return null + } +} + +/** + * Walk AST and call visitor for each node + */ +function walkAst(node: TSESTree.Node, visitor: (node: TSESTree.Node) => void) { + visitor(node) + + for (const key of Object.keys(node)) { + const child = (node as Record)[key] + if (child && typeof child === 'object') { + if (Array.isArray(child)) { + for (const item of child) { + if (item && typeof item === 'object' && 'type' in item) { + walkAst(item as TSESTree.Node, visitor) + } + } + } else if ('type' in child) { + walkAst(child as TSESTree.Node, visitor) + } + } + } +} + +/** + * Extract import information from AST + */ +function extractImports(ast: TSESTree.Program): ImportInfo[] { + const imports: ImportInfo[] = [] + + for (const node of ast.body) { + if (node.type === AST_NODE_TYPES.ImportDeclaration) { + const source = node.source.value as string + for (const specifier of node.specifiers) { + if (specifier.type === AST_NODE_TYPES.ImportSpecifier) { + imports.push({ + symbol: specifier.imported.type === AST_NODE_TYPES.Identifier + ? specifier.imported.name + : String(specifier.imported.value), + source, + }) + } else if (specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier) { + imports.push({ + symbol: specifier.local.name, + source, + }) + } + } + } + } + + return imports +} + +/** + * Find usages of i18n symbols in AST + */ +function findUsages(ast: TSESTree.Program): Usage[] { + const usages: Usage[] = [] + const localVariables = new Set() + + // First pass: collect locally declared variables to avoid false positives + walkAst(ast, (node) => { + if (node.type === AST_NODE_TYPES.VariableDeclarator && node.id.type === AST_NODE_TYPES.Identifier) { + localVariables.add(node.id.name) + } + if (node.type === AST_NODE_TYPES.FunctionDeclaration && node.id) { + localVariables.add(node.id.name) + } + }) + + // Second pass: find usages + walkAst(ast, (node) => { + // Check for call expressions: useVIntl(), defineMessage(), defineMessages(), formatMessage() + if (node.type === AST_NODE_TYPES.CallExpression) { + const callee = node.callee + if (callee.type === AST_NODE_TYPES.Identifier) { + const name = callee.name + if (I18N_SYMBOLS.includes(name as I18nSymbol) || name === FORMAT_MESSAGE) { + usages.push({ + symbol: name, + line: callee.loc.start.line, + }) + } + } + } + + // Check for JSX elements: + if (node.type === AST_NODE_TYPES.JSXOpeningElement) { + const name = node.name + if (name.type === AST_NODE_TYPES.JSXIdentifier && name.name === 'IntlFormatted') { + usages.push({ + symbol: 'IntlFormatted', + line: name.loc.start.line, + }) + } + } + + // Check for component references in Vue (e.g., components: { IntlFormatted }) + if (node.type === AST_NODE_TYPES.Property) { + if (node.key.type === AST_NODE_TYPES.Identifier && node.key.name === 'IntlFormatted') { + // This is defining IntlFormatted as a component, check if it's imported + usages.push({ + symbol: 'IntlFormatted', + line: node.key.loc.start.line, + }) + } + } + }) + + return usages +} + +/** + * Check if import source is valid for i18n symbols + */ +function isValidImportSource(source: string, filePath: string): boolean { + // Direct import from @modrinth/ui + if (VALID_IMPORT_SOURCES.includes(source)) { + return true + } + + // Relative imports within packages/ui are valid + if (filePath.includes('packages/ui/') || filePath.includes('packages\\ui\\')) { + if (source.startsWith('./') || source.startsWith('../')) { + return true + } + } + + return false +} + +/** + * Analyze a single file for missing i18n imports + */ +function analyzeFile(filePath: string): FileIssue[] { + const issues: FileIssue[] = [] + + try { + const content = fs.readFileSync(filePath, 'utf-8') + let ast: TSESTree.Program | null = null + + if (filePath.endsWith('.vue')) { + const scriptInfo = extractVueScript(content) + if (!scriptInfo) return [] + ast = parseTsContent(scriptInfo.script, true) + } else { + ast = parseTsContent(content, filePath.endsWith('.tsx')) + } + + if (!ast) return [] + + const imports = extractImports(ast) + const usages = findUsages(ast) + + // Build a map of imported symbols from valid sources + const validImports = new Map() + for (const imp of imports) { + if (isValidImportSource(imp.source, filePath)) { + validImports.set(imp.symbol, imp.source) + } + } + + // Check if useVIntl is imported (for formatMessage validation) + const hasUseVIntl = validImports.has('useVIntl') + + // Check each usage + for (const usage of usages) { + const symbol = usage.symbol + + if (symbol === FORMAT_MESSAGE) { + // formatMessage is valid if useVIntl is imported + if (!hasUseVIntl) { + issues.push({ + file: filePath, + symbol: `${symbol} (useVIntl not imported)`, + line: usage.line, + }) + } + } else if (!validImports.has(symbol)) { + issues.push({ + file: filePath, + symbol, + line: usage.line, + }) + } + } + } catch { + // Silent fail for unparseable files + } + + return issues +} + +/** + * Main function + */ +function main() { + const args = process.argv.slice(2) + const verbose = args.includes('--verbose') || args.includes('-v') + + const rootDir = path.resolve(__dirname, '..') + + const dirsToScan = [ + path.join(rootDir, 'apps/frontend/src'), + path.join(rootDir, 'apps/app-frontend/src'), + path.join(rootDir, 'packages'), + ] + + console.log() + process.stdout.write(theme.muted(' Scanning for i18n import issues... ')) + + const files = findFiles(dirsToScan) + console.log(theme.success(`found ${files.length} files`)) + + const allIssues: FileIssue[] = [] + + for (const file of files) { + const issues = analyzeFile(file) + allIssues.push(...issues) + } + + console.log() + + if (allIssues.length === 0) { + console.log(theme.success(' No missing i18n imports found!')) + console.log() + process.exit(0) + } + + // Group issues by file + const issuesByFile = new Map() + for (const issue of allIssues) { + const existing = issuesByFile.get(issue.file) || [] + existing.push(issue) + issuesByFile.set(issue.file, existing) + } + + // Print issues + for (const [file, issues] of issuesByFile) { + const relativePath = path.relative(rootDir, file) + console.log(theme.warning(` ${relativePath}`)) + + for (const issue of issues) { + console.log(theme.muted(` Line ${issue.line}: `) + theme.highlight(issue.symbol) + theme.muted(' is used but not imported')) + } + console.log() + } + + // Summary + console.log(theme.muted(' ─'.repeat(30))) + console.log( + theme.warning(` Summary: ${issuesByFile.size} file(s) with ${allIssues.length} missing i18n import(s)`) + ) + console.log() + + if (verbose) { + console.log(theme.muted(' Tip: Import these symbols from @modrinth/ui')) + console.log(theme.muted(' Example: import { useVIntl, defineMessages } from \'@modrinth/ui\'')) + console.log() + } + + // Exit with 0 (warn only, don't block CI) + process.exit(0) +} + +main() From 44226a37f3c82fb31f22429df55e6722f9f066e8 Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Tue, 30 Dec 2025 16:50:34 +0000 Subject: [PATCH 2/7] fix: lint --- .../components/ui/InstanceCreationModal.vue | 4 ++-- .../src/components/ui/ProjectCard.vue | 2 +- .../src/components/ui/SplashScreen.vue | 3 +-- .../src/components/ui/world/WorldItem.vue | 4 +--- packages/api-client/src/features/auth.ts | 2 +- .../src/features/circuit-breaker.ts | 2 +- packages/api-client/src/features/retry.ts | 2 +- packages/api-client/src/platform/nuxt.ts | 2 +- packages/api-client/src/platform/tauri.ts | 2 +- packages/assets/styles/classes.scss | 14 +++++------ packages/assets/styles/defaults.scss | 5 ++-- packages/assets/styles/variables.scss | 9 +++---- .../moderation/src/data/nags/description.ts | 24 +++++++++---------- packages/moderation/src/data/stages/links.ts | 8 +++---- .../billing/ServersUpgradeModalWrapper.vue | 4 ++-- .../ui/src/components/skin/SkinButton.vue | 3 +-- .../components/skin/SkinLikeTextButton.vue | 3 +-- .../components/skin/SkinPreviewRenderer.vue | 7 ++++-- 18 files changed, 47 insertions(+), 53 deletions(-) diff --git a/apps/app-frontend/src/components/ui/InstanceCreationModal.vue b/apps/app-frontend/src/components/ui/InstanceCreationModal.vue index a8158f07c7..83dee767f1 100644 --- a/apps/app-frontend/src/components/ui/InstanceCreationModal.vue +++ b/apps/app-frontend/src/components/ui/InstanceCreationModal.vue @@ -341,7 +341,7 @@ const create_instance = async () => { creating.value = true const loader_version_value = loader_version.value === 'other' ? specified_loader_version.value : loader_version.value - const loaderVersion = loader.value === 'vanilla' ? null : (loader_version_value ?? 'stable') + const loaderVersion = loader.value === 'vanilla' ? null : loader_version_value ?? 'stable' hide() creating.value = false @@ -350,7 +350,7 @@ const create_instance = async () => { profile_name.value, game_version.value, loader.value, - loader.value === 'vanilla' ? null : (loader_version_value ?? 'stable'), + loader.value === 'vanilla' ? null : loader_version_value ?? 'stable', icon.value, ).catch(handleError) diff --git a/apps/app-frontend/src/components/ui/ProjectCard.vue b/apps/app-frontend/src/components/ui/ProjectCard.vue index 43e9a10dfd..2d23f3ae39 100644 --- a/apps/app-frontend/src/components/ui/ProjectCard.vue +++ b/apps/app-frontend/src/components/ui/ProjectCard.vue @@ -63,7 +63,7 @@ const toTransparent = computed(() => {
diff --git a/packages/api-client/src/features/auth.ts b/packages/api-client/src/features/auth.ts index 81745b3c4d..b7e67a2eae 100644 --- a/packages/api-client/src/features/auth.ts +++ b/packages/api-client/src/features/auth.ts @@ -45,7 +45,7 @@ export interface AuthConfig extends FeatureConfig { * ``` */ export class AuthFeature extends AbstractFeature { - declare protected config: AuthConfig + protected declare config: AuthConfig async execute(next: () => Promise, context: RequestContext): Promise { const token = await this.getToken() diff --git a/packages/api-client/src/features/circuit-breaker.ts b/packages/api-client/src/features/circuit-breaker.ts index cd846a3810..2f850ff0ec 100644 --- a/packages/api-client/src/features/circuit-breaker.ts +++ b/packages/api-client/src/features/circuit-breaker.ts @@ -111,7 +111,7 @@ export class InMemoryCircuitBreakerStorage implements CircuitBreakerStorage { * ``` */ export class CircuitBreakerFeature extends AbstractFeature { - declare protected config: Required + protected declare config: Required private storage: CircuitBreakerStorage constructor(config?: CircuitBreakerConfig) { diff --git a/packages/api-client/src/features/retry.ts b/packages/api-client/src/features/retry.ts index 002f87da98..223d01d9f1 100644 --- a/packages/api-client/src/features/retry.ts +++ b/packages/api-client/src/features/retry.ts @@ -70,7 +70,7 @@ export interface RetryConfig extends FeatureConfig { * ``` */ export class RetryFeature extends AbstractFeature { - declare protected config: Required + protected declare config: Required constructor(config?: RetryConfig) { super(config) diff --git a/packages/api-client/src/platform/nuxt.ts b/packages/api-client/src/platform/nuxt.ts index 3230751c56..5f57977a5f 100644 --- a/packages/api-client/src/platform/nuxt.ts +++ b/packages/api-client/src/platform/nuxt.ts @@ -71,7 +71,7 @@ export interface NuxtClientConfig extends ClientConfig { * ``` */ export class NuxtModrinthClient extends AbstractModrinthClient { - declare protected config: NuxtClientConfig + protected declare config: NuxtClientConfig constructor(config: NuxtClientConfig) { super(config) diff --git a/packages/api-client/src/platform/tauri.ts b/packages/api-client/src/platform/tauri.ts index 015c3b0c07..05bfb9fb99 100644 --- a/packages/api-client/src/platform/tauri.ts +++ b/packages/api-client/src/platform/tauri.ts @@ -37,7 +37,7 @@ interface HttpError extends Error { * ``` */ export class TauriModrinthClient extends AbstractModrinthClient { - declare protected config: TauriClientConfig + protected declare config: TauriClientConfig constructor(config: TauriClientConfig) { super(config) diff --git a/packages/assets/styles/classes.scss b/packages/assets/styles/classes.scss index d4d6a72c0a..e6adcce613 100644 --- a/packages/assets/styles/classes.scss +++ b/packages/assets/styles/classes.scss @@ -46,13 +46,13 @@ } > :where( - input + *, - .input-group + *, - .textarea-wrapper + *, - .chips + *, - .resizable-textarea-wrapper + *, - .input-div + * - ) { + input + *, + .input-group + *, + .textarea-wrapper + *, + .chips + *, + .resizable-textarea-wrapper + *, + .input-div + * + ) { margin-block-start: var(--gap-md); } diff --git a/packages/assets/styles/defaults.scss b/packages/assets/styles/defaults.scss index e0490a1d61..eee83e8fca 100644 --- a/packages/assets/styles/defaults.scss +++ b/packages/assets/styles/defaults.scss @@ -7,9 +7,8 @@ body { // Defaults background-color: var(--color-bg); color: var(--color-base); - --font-standard: - Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell, - Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --font-standard: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, + Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; --mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; font-family: var(--font-standard); font-size: 16px; diff --git a/packages/assets/styles/variables.scss b/packages/assets/styles/variables.scss index 69b4cd781a..f1045b6a76 100644 --- a/packages/assets/styles/variables.scss +++ b/packages/assets/styles/variables.scss @@ -127,12 +127,10 @@ --shadow-inset-sm: inset 0px -1px 2px hsla(221, 39%, 91%, 0.15); --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2); - --shadow-raised: - 0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15), + --shadow-raised: 0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15), 1px 2px 2.2px -1.7px hsl(var(--shadow-color) / 0.12), 4.4px 8.8px 9.7px -3.4px hsl(var(--shadow-color) / 0.09); - --shadow-floating: - hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, + --shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px; --shadow-card: rgba(50, 50, 100, 0.1) 0px 2px 4px 0px; @@ -350,8 +348,7 @@ html { --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2); --shadow-raised: 0px -2px 4px hsla(221, 39%, 11%, 0.1); - --shadow-floating: - hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, + --shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px; --shadow-card: rgba(0, 0, 0, 0.25) 0px 2px 4px 0px; diff --git a/packages/moderation/src/data/nags/description.ts b/packages/moderation/src/data/nags/description.ts index 90d866230f..177aa547df 100644 --- a/packages/moderation/src/data/nags/description.ts +++ b/packages/moderation/src/data/nags/description.ts @@ -235,18 +235,18 @@ export const descriptionNags: Nag[] = [ const summary = context.project.description?.trim() || '' return Boolean( summary.match(/https:\/\//g) || - summary.match(/http:\/\//g) || - summary.match(/# .*/g) || - summary.match(/---/g) || - summary.match(/\n/g) || - summary.match(/\[.*\]\(.*\)/g) || - summary.match(/!\[.*\]/g) || - summary.match(/`.*`/g) || - summary.match(/\*.*\*/g) || - summary.match(/_.*_/g) || - summary.match(/~~.*~~/g) || - summary.match(/```/g) || - summary.match(/> /g), + summary.match(/http:\/\//g) || + summary.match(/# .*/g) || + summary.match(/---/g) || + summary.match(/\n/g) || + summary.match(/\[.*\]\(.*\)/g) || + summary.match(/!\[.*\]/g) || + summary.match(/`.*`/g) || + summary.match(/\*.*\*/g) || + summary.match(/_.*_/g) || + summary.match(/~~.*~~/g) || + summary.match(/```/g) || + summary.match(/> /g), ) }, link: { diff --git a/packages/moderation/src/data/stages/links.ts b/packages/moderation/src/data/stages/links.ts index 7e6004d9c1..9675a5c171 100644 --- a/packages/moderation/src/data/stages/links.ts +++ b/packages/moderation/src/data/stages/links.ts @@ -12,10 +12,10 @@ const links: Stage = { shouldShow: (project) => Boolean( project.issues_url || - project.source_url || - project.wiki_url || - project.discord_url || - project.donation_urls.length > 0, + project.source_url || + project.wiki_url || + project.discord_url || + project.donation_urls.length > 0, ), text: async (project) => { let text = (await import('../messages/checklist-text/links/base.md?raw')).default diff --git a/packages/ui/src/components/billing/ServersUpgradeModalWrapper.vue b/packages/ui/src/components/billing/ServersUpgradeModalWrapper.vue index e07f4ab74d..be7839ff63 100644 --- a/packages/ui/src/components/billing/ServersUpgradeModalWrapper.vue +++ b/packages/ui/src/components/billing/ServersUpgradeModalWrapper.vue @@ -181,9 +181,9 @@ const dryRunResponse = ref<{ const pendingDowngradeBody = ref(null) const currentPlanFromSubscription = computed(() => { return subscription.value - ? (pyroProducts.find((p) => + ? pyroProducts.find((p) => p.prices.some((price) => price.id === subscription.value?.price_id), - ) ?? undefined) + ) ?? undefined : undefined }) diff --git a/packages/ui/src/components/skin/SkinButton.vue b/packages/ui/src/components/skin/SkinButton.vue index 14fb06ae09..510376c3ea 100644 --- a/packages/ui/src/components/skin/SkinButton.vue +++ b/packages/ui/src/components/skin/SkinButton.vue @@ -110,8 +110,7 @@ function onImageLoad(type: 'forward' | 'backward') { } .skin-btn-bg.selected { - background: - linear-gradient( + background: linear-gradient( 157.61deg, var(--color-brand) -76.68%, rgba(27, 217, 106, 0.534) -38.61%, diff --git a/packages/ui/src/components/skin/SkinLikeTextButton.vue b/packages/ui/src/components/skin/SkinLikeTextButton.vue index 59fffe239d..21562f8b69 100644 --- a/packages/ui/src/components/skin/SkinLikeTextButton.vue +++ b/packages/ui/src/components/skin/SkinLikeTextButton.vue @@ -51,8 +51,7 @@ const pressed = ref(false) } .skin-btn-bg.selected { - background: - linear-gradient( + background: linear-gradient( 157.61deg, var(--color-brand) -76.68%, rgba(27, 217, 106, 0.534) -38.61%, diff --git a/packages/ui/src/components/skin/SkinPreviewRenderer.vue b/packages/ui/src/components/skin/SkinPreviewRenderer.vue index dcb4f6749b..dc1526fca7 100644 --- a/packages/ui/src/components/skin/SkinPreviewRenderer.vue +++ b/packages/ui/src/components/skin/SkinPreviewRenderer.vue @@ -617,8 +617,11 @@ onUnmounted(() => {