diff --git a/.editorconfig b/.editorconfig index 665a74a09a..e6bda814c1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,26 +22,15 @@ indent_size = 4 [*.html] indent_size = 2 -insert_final_newline = false -trim_trailing_whitespace = false -[{*.js,*.jsx,*.mjs,*.ts,*.tsx}] +[{*.js,*.jsx,*.mjs,*.ts,*.tsx,*.mts}] indent_size = 2 [*.css] -# CSS files typically use an indent size of 2 spaces for better readability and alignment with community standards. indent_size = 2 [*.{yml,yaml}] -# YAML files use an indent size of 2 spaces to maintain consistency with common YAML formatting practices. -indent_size = 2 -insert_final_newline = false -trim_trailing_whitespace = false - -[*.json] -# JSON files use an indent size of 2 spaces, which is the standard for JSON formatting. indent_size = 2 -[*.jsonc] -# JSONC (JSON with comments) files also follow the standard JSON formatting with an indent size of 2 spaces. +[*.{json,jsonc}] indent_size = 2 diff --git a/.taskfiles/frontend.yml b/.taskfiles/frontend.yml index f5325c9ed7..844306824d 100644 --- a/.taskfiles/frontend.yml +++ b/.taskfiles/frontend.yml @@ -375,13 +375,13 @@ tasks: desc: "Auto-fix code formatting" deps: [install] cmds: - - npx prettier --write . + - npx oxfmt --write . format:check: desc: "Check code formatting" deps: [install] cmds: - - npx prettier --check . + - npx oxfmt --check . fix: desc: "Auto-fix lint and format" @@ -554,6 +554,7 @@ tasks: deps: [install, ":backend:swagger"] cmds: - npx tsx editor/scripts/generate-tool-api-types.mts --spec ../SwaggerDoc.json --output editor/src/core/types/toolApiTypes.ts --io-output editor/src/core/types/toolIO.ts + - task: format sources: - editor/scripts/generate-tool-api-types.mts - ../SwaggerDoc.json @@ -563,9 +564,9 @@ tasks: tool-models:check: desc: "Fail if committed tool API types are out of date" - deps: [install, ":backend:swagger"] cmds: - - npx tsx editor/scripts/generate-tool-api-types.mts --spec ../SwaggerDoc.json --output editor/src/core/types/toolApiTypes.ts --io-output editor/src/core/types/toolIO.ts --check + - task: tool-models + - git diff --exit-code -- editor/src/core/types/toolApiTypes.ts editor/src/core/types/toolIO.ts licenses:generate: desc: "Generate frontend license report" diff --git a/frontend/.oxfmtrc.json b/frontend/.oxfmtrc.json new file mode 100644 index 0000000000..cb801651b8 --- /dev/null +++ b/frontend/.oxfmtrc.json @@ -0,0 +1,33 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "endOfLine": "lf", + "sortPackageJson": false, + "ignorePatterns": [ + "dist/", + "editor/dist/", + "editor/src-tauri/**/target/", + "editor/src-tauri/gen/", + "node_modules/", + "editor/public/vendor/", + "editor/public/mockServiceWorker.js", + "editor/public/og-metadata.json", + "editor/public/og-metadata.saas.json", + "editor/src/core/data/ogImageMap.json", + "editor/src/portal/generated/docsManifest.json", + "editor/public/pdfjs*/", + "editor/public/js/thirdParty/", + "editor/public/css/cookieconsent.css", + "storybook-static/", + "playwright-report/", + "editor/playwright-report/", + "test-results/", + "editor/test-results/", + "*.min.*", + "*.md", + "*.wxs", + "*.toml", + "editor/src/output.css" + ] +} diff --git a/frontend/.prettierignore b/frontend/.prettierignore deleted file mode 100644 index fa8ab6c502..0000000000 --- a/frontend/.prettierignore +++ /dev/null @@ -1,30 +0,0 @@ -dist/ -editor/dist/ -# Tauri/Cargo build output (binary assets named *.js etc. confuse Prettier). -# Match nested target/ dirs too - provisioner/ and thumbnail-handler/ each -# have their own Cargo workspace under src-tauri/. -editor/src-tauri/**/target/ -editor/src-tauri/gen/ -node_modules/ -editor/public/vendor/ -# Auto-generated by MSW (`msw init`); regenerated verbatim, not hand-formatted. -editor/public/mockServiceWorker.js -# Auto-generated OG/social-preview metadata (scripts/generate-og-metadata.mjs); regenerated verbatim. -editor/public/og-metadata.json -editor/public/og-metadata.saas.json -editor/src/core/data/ogImageMap.json -# Auto-generated portal docs manifest (scripts/sync-portal-docs.mts); regenerated verbatim. -editor/src/portal/generated/docsManifest.json -editor/public/pdfjs*/ -editor/public/js/thirdParty/ -editor/public/css/cookieconsent.css -# Build / test artifacts that may exist locally even though they're gitignored -storybook-static/ -playwright-report/ -editor/playwright-report/ -test-results/ -editor/test-results/ -*.min.* -*.md -*.wxs -editor/src/output.css diff --git a/frontend/.prettierrc b/frontend/.prettierrc deleted file mode 100644 index 58bc875631..0000000000 --- a/frontend/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "printWidth": 80, - "tabWidth": 2, - "useTabs": false, - "endOfLine": "lf" -} diff --git a/frontend/README.md b/frontend/README.md index ea759538e6..a4945ffae1 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -18,7 +18,7 @@ For desktop app development, see the [Tauri](#tauri) section below. `frontend/` is a workspace containing one or more apps. Today it holds the PDF editor under `frontend/editor/`; new apps (the developer portal, etc.) will sit alongside it as siblings. Shared tooling — `package.json`, `node_modules`, -`.storybook/`, oxlint, Prettier — lives at `frontend/` so every app installs +`.storybook/`, oxlint, oxfmt — lives at `frontend/` so every app installs once and lints with the same config. ## Environment Variables diff --git a/frontend/editor/scripts/generate-tool-api-types.mts b/frontend/editor/scripts/generate-tool-api-types.mts index 38eb7fe7b6..23daa1dd76 100644 --- a/frontend/editor/scripts/generate-tool-api-types.mts +++ b/frontend/editor/scripts/generate-tool-api-types.mts @@ -10,7 +10,6 @@ import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { parseArgs } from "node:util"; import { compile, type JSONSchema } from "json-schema-to-typescript"; -import * as prettier from "prettier"; // The API namespaces whose endpoints a pipeline can reference. `/api/v1/ai/tools/` // is absent from the spec, so it cannot appear here. Extend this list when other @@ -227,11 +226,7 @@ function collectToolIO( return { table, dropped }; } -async function renderToolIO( - spec: Json, - table: Record, - outputPath: string, -): Promise { +function renderToolIO(spec: Json, table: Record): string { if (Object.keys(table).length === 0) { throw new Error( `No ${IO_EXTENSION} declarations in the spec. The backend publishes these from @ToolIO; regenerate with 'task backend:swagger'.`, @@ -312,33 +307,12 @@ export function toolIOFor( } `; - const prettierConfig = await prettier.resolveConfig(outputPath); - return prettier.format(body, { ...prettierConfig, parser: "typescript" }); + return body; } -/** In check mode, fail when the committed file is out of date. */ -function writeOrCheck( - outputPath: string, - formatted: string, - check: boolean, - task: string, -): void { - if (check) { - let current = ""; - try { - current = readFileSync(outputPath, "utf-8"); - } catch { - // Missing file counts as out of date. - } - if (current !== formatted) { - throw new Error( - `${outputPath} is out of date. Run '${task}' and commit the result.`, - ); - } - return; - } +function writeOutput(outputPath: string, contents: string): void { mkdirSync(dirname(outputPath), { recursive: true }); - writeFileSync(outputPath, formatted, "utf-8"); + writeFileSync(outputPath, contents, "utf-8"); } async function main(): Promise { @@ -347,12 +321,11 @@ async function main(): Promise { spec: { type: "string" }, output: { type: "string" }, "io-output": { type: "string" }, - check: { type: "boolean", default: false }, }, }); if (!values.spec || !values.output || !values["io-output"]) { throw new Error( - "Usage: generate-tool-api-types.mts --spec --output --io-output [--check]", + "Usage: generate-tool-api-types.mts --spec --output --io-output ", ); } const specPath = resolve(values.spec); @@ -478,14 +451,9 @@ async function main(): Promise { `Dropped ${dropped.length} @ToolIO declaration(s) on paths that are not tool endpoints. Add the namespace to ALLOWED_PATH_PREFIXES if a pipeline can contain these steps:\n ${dropped.join("\n ")}`, ); } - writeOrCheck( - ioOutputPath, - await renderToolIO(spec, ioDeclarations, ioOutputPath), - values.check ?? false, - "task frontend:tool-models", - ); + writeOutput(ioOutputPath, renderToolIO(spec, ioDeclarations)); console.log( - `${values.check ? "Up to date" : "Generated"}: ${Object.keys(ioDeclarations).length} tool I/O declarations.`, + `Generated ${Object.keys(ioDeclarations).length} tool I/O declarations.`, ); // Transitively inline every referenced component into `definitions`, rewriting its refs too. @@ -508,7 +476,6 @@ async function main(): Promise { definitions, fileFieldsByClass, outputPath, - values.check ?? false, skipped, ); } @@ -518,7 +485,6 @@ async function compileAndWrite( definitions: Record, fileFieldsByClass: Record, outputPath: string, - check: boolean, skipped: string[], ): Promise { // json-schema-to-typescript only emits a named, exported interface per schema @@ -597,17 +563,9 @@ async function compileAndWrite( ].join("\n"); const body = `${FILE_HEADER}\n\n${models}\n\n${footer}\n`; - const prettierConfig = await prettier.resolveConfig(outputPath); - const formatted = await prettier.format(body, { - ...prettierConfig, - parser: "typescript", - }); - - writeOrCheck(outputPath, formatted, check, "task frontend:tool-models"); - console.log( - `${check ? "Up to date" : "Generated"}: ${tools.length} tool endpoints.`, - ); - if (!check && skipped.length > 0) { + writeOutput(outputPath, body); + console.log(`Generated ${tools.length} tool endpoints.`); + if (skipped.length > 0) { console.log( `Skipped ${skipped.length} POST endpoint(s) with no request body: ${skipped.join(", ")}`, ); diff --git a/frontend/editor/src/portal/components/users/UsersDirectory.stories.tsx b/frontend/editor/src/portal/components/users/UsersDirectory.stories.tsx index 2925958efd..75da086806 100644 --- a/frontend/editor/src/portal/components/users/UsersDirectory.stories.tsx +++ b/frontend/editor/src/portal/components/users/UsersDirectory.stories.tsx @@ -215,22 +215,19 @@ const BIG_MEMBERS: Member[] = [ isSelf: true, portalAccess: "admin", }, - ...Array.from( - { length: 11 }, - (_, i): Member => ({ - id: `big-${i}`, - name: `Teammate ${i + 1}`, - email: `teammate${i + 1}@acme.com`, - role: i === 0 ? "team_owner" : "member", - status: "active", - lastActive: `${i + 1}h ago`, - username: `tm${i + 1}`, - teamId: 9, - teamName: "Platform", - teamLead: i === 0, - portalAccess: i === 0 ? "role" : "none", - }), - ), + ...Array.from({ length: 11 }, (_, i): Member => ({ + id: `big-${i}`, + name: `Teammate ${i + 1}`, + email: `teammate${i + 1}@acme.com`, + role: i === 0 ? "team_owner" : "member", + status: "active", + lastActive: `${i + 1}h ago`, + username: `tm${i + 1}`, + teamId: 9, + teamName: "Platform", + teamLead: i === 0, + portalAccess: i === 0 ? "role" : "none", + })), ]; const TEAMS: Team[] = [ diff --git a/frontend/editor/src/proprietary/components/shared/ChangeUserPasswordModal.tsx b/frontend/editor/src/proprietary/components/shared/ChangeUserPasswordModal.tsx index 89d648fcc5..a482b3fab1 100644 --- a/frontend/editor/src/proprietary/components/shared/ChangeUserPasswordModal.tsx +++ b/frontend/editor/src/proprietary/components/shared/ChangeUserPasswordModal.tsx @@ -38,7 +38,7 @@ function generateSecurePassword() { const uint8Array = new Uint8Array(length); window.crypto.getRandomValues(uint8Array); // To avoid modulo bias, discard values >= 256 - (256 % charsetLength) - for (let i = 0; password.length < length; ) { + for (let i = 0; password.length < length;) { const randomByte = uint8Array[i]; i++; if (randomByte >= Math.floor(256 / charsetLength) * charsetLength) { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9de0a5bf6a..6ade3d2a28 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -121,12 +121,12 @@ "license-checker": "^25.0.1", "msw": "^2.14.6", "msw-storybook-addon": "^2.0.7", + "oxfmt": "^0.62.0", "oxlint": "^1.77.0", "postcss": "^8.5.12", "postcss-cli": "^11.0.1", "postcss-preset-mantine": "^1.18.0", "postcss-simple-vars": "^7.0.1", - "prettier": "^3.8.1", "puppeteer": "^24.25.0", "rollup-plugin-visualizer": "^7.0.1", "storybook": "^9.1.20", @@ -2905,6 +2905,329 @@ "dev": true, "license": "MIT" }, + "node_modules/@oxfmt/binding-android-arm-eabi": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.62.0.tgz", + "integrity": "sha512-pdsv0C4gPjJ8H1+sd8u0BDx+yLACTL+rgeMIOL1ln4ihSnhw8CWXtYWgvcSkyTfgGBIzFKab+d8rx9Xl4en/Kw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-android-arm64": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.62.0.tgz", + "integrity": "sha512-WC3YQ7uS/KtDrjmqwBviwFKe9qeoi+eXx8aX1z/ffG23Md75myjrJaQqTuJvdOLPoa4EYTjDWH0dHXfwulCVog==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-darwin-arm64": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.62.0.tgz", + "integrity": "sha512-GM8Yf3LjjaR1I8PD0SfeoIlwhsh9GvSF+cQ8sf624Yxnjsyumn95aFzYfKJVefblfDIiOAnZ7QVm2sa21Er/0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-darwin-x64": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.62.0.tgz", + "integrity": "sha512-d5THp7F8bCxLqNogEXDORRsQD6dosf3EyFtnXfBer6v+8tGdcWIjoDX9WaXrrF/26zOmL8qHpPTKCEvpBDmZkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-freebsd-x64": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.62.0.tgz", + "integrity": "sha512-1DnrtXGZooOZ0fHgAXZUaDQzBVh1CM2MNW4oBXyQ2aWKvCHjyljvT9fgBkOM0fEOb96X5eqtcfJ0YUVt9jj66g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.62.0.tgz", + "integrity": "sha512-4pQDHOYRH+Huqe0StIaWyvk2CVl/aTaqSrbZpA3/pLS2xH24ME7lBgYprhQF2fRkHBzhGGGKliwxFsDdHwx59g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm-musleabihf": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.62.0.tgz", + "integrity": "sha512-X0jAaZJFMCVKhB6YyWVTQ/wN2DLsBcZKSMqTS76bF6riT+XZdtg2FPEdjDvdVbunO9cG+tWiVaEs4Zs38lxYog==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm64-gnu": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.62.0.tgz", + "integrity": "sha512-682Z8T5s8T5ATArYtsejKvbIfd8LEAXyyDkKkoZVq8HND7Vx8TYLlrDjDSeYfodMeVwHOgkj13lJYR8cj6vUSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm64-musl": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.62.0.tgz", + "integrity": "sha512-lk25fAl7KWaLWVJcW0CHEXB7QlQZtx5eDkjpaGMK0hzXTjUe0Wmlu8IKuFHoviSOcEJedRTs4VE/506VqGxGew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-ppc64-gnu": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.62.0.tgz", + "integrity": "sha512-SFyNqHQLwySceWNLhiSldx7wPXRAzP0L0WcW9GegP3uWrpZGJiZlQO85NbHAFPEfxR9PhZ9qSnZryEh7+v+4Gw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-riscv64-gnu": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.62.0.tgz", + "integrity": "sha512-KYj55C1ywJfHo6+aKDuEmUtVEdJALsC5GwayDGsI6FGz2GxFqNr/mA8nxVsNbJzm7sE5MRqTQ9ziImSzhYXysA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-riscv64-musl": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.62.0.tgz", + "integrity": "sha512-BhZDNo5GOU5nC378RhD0/XpvaEBHsH3HLgJp8YZX3A0InC7oivzA63HsRmiXFLtLSHAstEVrDf6fbC7Rs8Jh/A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-s390x-gnu": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.62.0.tgz", + "integrity": "sha512-UyAFmyHkgSgUJ/wOM4p3U8AC2yAFvRH5PNBs7TnK0fObTT/XSWcdr/lAzPSWaekHaZFaMeFZyk9n93Joq3J93A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-x64-gnu": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.62.0.tgz", + "integrity": "sha512-1iYMP0leytWazFubD/WnINJuIrzRPuoL1aWEJdlGezEzDbTxcd29R4r8IUzP2oWeKst5V02uMJgR2NILlPlG6w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-x64-musl": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.62.0.tgz", + "integrity": "sha512-4rA/URtJSTVNVAQz6Q8wf7SaRvOXVy+TizriT9hs/Y1XhLR/R+92uWKRQG8yFWRAIEBbFHJ6WevQcl/G9SXEfw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-openharmony-arm64": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.62.0.tgz", + "integrity": "sha512-mSZuFHU2ar1KLUjXpI2QBQcJ1VsOB3mOCgQXuXCpKs19dgh4u+OaovNfrWDfiJb+ihJ2+f7YFcaO9bS2dlTCXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-arm64-msvc": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.62.0.tgz", + "integrity": "sha512-OfwuhkcjDlqC4EgDojtiV9mzpLqeB9KqTOWPOjLEYBVdDCVSxqW3qzp/xcIxsbtI0UgGCnKvAqYKyY25kf5JZw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-ia32-msvc": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.62.0.tgz", + "integrity": "sha512-P9uDDNFRzghO3X8QAzhkjKhK7JvtABsVn8UYtFX7uor12IAnwNt8nNIctvfWj1JkQU/kE+fmLRPiw7XlrIHsZw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-x64-msvc": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.62.0.tgz", + "integrity": "sha512-dlI5SY7XYQCiCBafntWagCR6HcAJB/NpsLtdlPx8x08+Osz8Ok1HHz1GZuusegCe/VoJ6pAnF5a4pd5OZAq7qQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@oxlint/binding-android-arm-eabi": { "version": "1.77.0", "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.77.0.tgz", @@ -12611,6 +12934,68 @@ "dev": true, "license": "MIT" }, + "node_modules/oxfmt": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.62.0.tgz", + "integrity": "sha512-vxgGHTmnDU9j4CX7dDBLzxgmHxfda/yPcgJkGCMUSCwRmz+euo/V08xXLNgXTeqAB9Fhf3Pe2nO1RNKLCVgphQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinypool": "2.1.0" + }, + "bin": { + "oxfmt": "bin/oxfmt" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxfmt/binding-android-arm-eabi": "0.62.0", + "@oxfmt/binding-android-arm64": "0.62.0", + "@oxfmt/binding-darwin-arm64": "0.62.0", + "@oxfmt/binding-darwin-x64": "0.62.0", + "@oxfmt/binding-freebsd-x64": "0.62.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.62.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.62.0", + "@oxfmt/binding-linux-arm64-gnu": "0.62.0", + "@oxfmt/binding-linux-arm64-musl": "0.62.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.62.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.62.0", + "@oxfmt/binding-linux-riscv64-musl": "0.62.0", + "@oxfmt/binding-linux-s390x-gnu": "0.62.0", + "@oxfmt/binding-linux-x64-gnu": "0.62.0", + "@oxfmt/binding-linux-x64-musl": "0.62.0", + "@oxfmt/binding-openharmony-arm64": "0.62.0", + "@oxfmt/binding-win32-arm64-msvc": "0.62.0", + "@oxfmt/binding-win32-ia32-msvc": "0.62.0", + "@oxfmt/binding-win32-x64-msvc": "0.62.0" + }, + "peerDependencies": { + "svelte": "^5.0.0", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/oxfmt/node_modules/tinypool": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", + "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.0.0 || >=22.0.0" + } + }, "node_modules/oxlint": { "version": "1.77.0", "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.77.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 6bbb3e9137..71a71661e7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -143,12 +143,12 @@ "license-checker": "^25.0.1", "msw": "^2.14.6", "msw-storybook-addon": "^2.0.7", + "oxfmt": "^0.62.0", "oxlint": "^1.77.0", "postcss": "^8.5.12", "postcss-cli": "^11.0.1", "postcss-preset-mantine": "^1.18.0", "postcss-simple-vars": "^7.0.1", - "prettier": "^3.8.1", "puppeteer": "^24.25.0", "rollup-plugin-visualizer": "^7.0.1", "storybook": "^9.1.20", diff --git a/frontend/stylelint.config.mjs b/frontend/stylelint.config.mjs index 2781e78516..79f3108c9c 100644 --- a/frontend/stylelint.config.mjs +++ b/frontend/stylelint.config.mjs @@ -1,4 +1,4 @@ -// Deliberately minimal: Prettier owns formatting and `task frontend:lint:colors` +// Deliberately minimal: oxfmt owns formatting and `task frontend:lint:colors` // owns the theme tokens, so this only carries rules that catch real bugs. export default { ignoreFiles: [