diff --git a/app/features/art/components/ArtImageFormField.tsx b/app/features/art/components/ArtImageFormField.tsx index 42e0e2d42..3ed9b5f87 100644 --- a/app/features/art/components/ArtImageFormField.tsx +++ b/app/features/art/components/ArtImageFormField.tsx @@ -98,6 +98,7 @@ function compressToDataUrl( options: Compressor.Options, ): Promise { return new Promise((resolve, reject) => { + // biome-ignore lint/correctness/noUnusedInstantiation: Compressor does its work through the success/error callbacks new Compressor(file, { ...options, success(result) { diff --git a/app/features/chat/chat-message-links.ts b/app/features/chat/chat-message-links.ts index 947564b71..24c100fdc 100644 --- a/app/features/chat/chat-message-links.ts +++ b/app/features/chat/chat-message-links.ts @@ -3,7 +3,7 @@ const SPLATNET_ROOM_PATH_PATTERN = /^\/[A-Za-z0-9/_-]+$/; const SPLATNET_ROOM_CANDIDATE_PATTERN = /https:\/\/s\.nintendo\.com\/\S+/g; export function isSplatnetRoomUrl(url: string): boolean { - if (!canParseUrl(url)) return false; + if (!URL.canParse(url)) return false; const parsed = new URL(url); return ( parsed.protocol === "https:" && @@ -29,15 +29,6 @@ export function findRoomLinks( return results; } -function canParseUrl(url: string): boolean { - try { - new URL(url); - return true; - } catch { - return false; - } -} - function isAllowedSplatnetSearch(params: URLSearchParams): boolean { if (params.size === 0) return true; if (params.size > 1) return false; diff --git a/app/features/timezone/timezone-cookie.ts b/app/features/timezone/timezone-cookie.ts index c09a57580..eb1b9af58 100644 --- a/app/features/timezone/timezone-cookie.ts +++ b/app/features/timezone/timezone-cookie.ts @@ -9,7 +9,7 @@ const ianaTimezone = v.pipe( v.maxLength(100), v.check((value) => { try { - new Intl.DateTimeFormat("en-US", { timeZone: value }); + Intl.DateTimeFormat("en-US", { timeZone: value }); return true; } catch { return false; diff --git a/app/features/user-page/core/widgets/widget-form-schemas.ts b/app/features/user-page/core/widgets/widget-form-schemas.ts index b3d0803bd..ee7dfac69 100644 --- a/app/features/user-page/core/widgets/widget-form-schemas.ts +++ b/app/features/user-page/core/widgets/widget-form-schemas.ts @@ -12,6 +12,7 @@ import { select, selectDynamic, stageSelect, + textArea, textAreaOptional, textField, weaponSelect, diff --git a/app/form/fields/ImageFormField.tsx b/app/form/fields/ImageFormField.tsx index b06e64a83..b51f24cbb 100644 --- a/app/form/fields/ImageFormField.tsx +++ b/app/form/fields/ImageFormField.tsx @@ -57,6 +57,7 @@ export function ImageFormField({ const uploadedFile = event.target.files?.[0]; if (!uploadedFile) return; + // biome-ignore lint/correctness/noUnusedInstantiation: Compressor does its work through the success/error callbacks new Compressor(uploadedFile, { width: resolvedDimensions.width, height: resolvedDimensions.height, diff --git a/biome.json b/biome.json index 18acc7fe2..fe68e703b 100644 --- a/biome.json +++ b/biome.json @@ -19,7 +19,34 @@ "suspicious": { "noExplicitAny": "off", "noArrayIndexKey": "off", - "noConsole": { "level": "error" } + "noConsole": { "level": "error" }, + "noDeprecatedImports": "error", + "noVar": "error", + "noForIn": "error", + "useGuardForIn": "error", + "noConstantBinaryExpressions": "error", + "noUnassignedVariables": "error", + "noDuplicatedSpreadProps": "error", + "noUnknownAttribute": "error", + "useErrorMessage": "error", + "useNumberToFixedDigitsArgument": { + "fix": "safe", + "level": "error" + }, + "noSkippedTests": "error", + "noParametersOnlyUsedInRecursion": "error" + }, + "correctness": { + "noUndeclaredVariables": "error", + "noUnusedInstantiation": "error", + "noNestedComponentDefinitions": "error", + "noReactPropAssignments": "error", + "noGlobalDirnameFilename": { + "fix": "safe", + "level": "error" + }, + "useSingleJsDocAsterisk": "error", + "noUndeclaredDependencies": "error" }, "style": { "noNonNullAssertion": "off", @@ -43,7 +70,43 @@ "useSingleVarDeclarator": "error", "useNumberNamespace": "error", "noInferrableTypes": "error", - "noUselessElse": "error" + "noUselessElse": "error", + "noEnum": "error", + "noCommonJs": "error", + "noParameterProperties": "error", + "noMultiAssign": "error", + "noMultilineString": "error", + "noYodaExpression": { + "fix": "safe", + "level": "error" + }, + "useTrimStartEnd": { + "fix": "safe", + "level": "error" + }, + "useObjectSpread": { + "fix": "safe", + "level": "error" + }, + "useNodeAssertStrict": { + "fix": "safe", + "level": "error" + }, + "useCollapsedElseIf": { + "fix": "safe", + "level": "error" + }, + "useSymbolDescription": "error", + "useGroupedAccessorPairs": "error", + "useSpreadOverApply": "error", + "useFilenamingConvention": { + "level": "error", + "options": { + "filenameCases": ["kebab-case", "PascalCase", "camelCase"], + "strictCase": false, + "requireAscii": true + } + } }, "a11y": { "useKeyWithClickEvents": "off", @@ -55,7 +118,14 @@ "fix": "safe", "level": "error" }, - "noImportantStyles": "off" + "noImportantStyles": "off", + "useWhile": { + "fix": "safe", + "level": "error" + } + }, + "performance": { + "noSyncScripts": "error" } } }, @@ -74,6 +144,21 @@ } }, "overrides": [ + { + "includes": [ + "app/features/*/routes/**", + "app/modules/*/routes/**", + "app/features/*/loaders/**", + "app/features/*/actions/**" + ], + "linter": { + "rules": { + "style": { + "useFilenamingConvention": "off" + } + } + } + }, { "includes": ["app/**", "!app/modules/search-params/**"], "plugins": ["./biome-plugins/no-raw-search-params.grit"]