From 1213044c300fea79b4667017df67c8c42d9d9a14 Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Wed, 15 Jul 2026 13:50:25 +0200 Subject: [PATCH 1/8] refactor(ui-scripts): relocate lint command out of legacy lib/test/ folder Move lint.ts from lib/test/ into lib/commands/, alongside the other yargs command modules (bump.ts, server.ts, etc.) it is registered with in commands/index.ts. The test/ directory is a leftover name from when ui-scripts absorbed the separate ui-test package. --- packages/ui-scripts/lib/__node_tests__/lint.test.ts | 2 +- packages/ui-scripts/lib/commands/index.ts | 2 +- packages/ui-scripts/lib/{test => commands}/lint.ts | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/ui-scripts/lib/{test => commands}/lint.ts (100%) diff --git a/packages/ui-scripts/lib/__node_tests__/lint.test.ts b/packages/ui-scripts/lib/__node_tests__/lint.test.ts index a6a494a680..af6fd3fe09 100644 --- a/packages/ui-scripts/lib/__node_tests__/lint.test.ts +++ b/packages/ui-scripts/lib/__node_tests__/lint.test.ts @@ -28,7 +28,7 @@ vi.mock('@instructure/command-utils', () => ({ runCommandSync: vi.fn() })) -import lint from '../test/lint.ts' +import lint from '../commands/lint.ts' import { runCommandSync } from '@instructure/command-utils' const runMock = vi.mocked(runCommandSync) diff --git a/packages/ui-scripts/lib/commands/index.ts b/packages/ui-scripts/lib/commands/index.ts index 19a03c28c7..2038bd633e 100644 --- a/packages/ui-scripts/lib/commands/index.ts +++ b/packages/ui-scripts/lib/commands/index.ts @@ -30,7 +30,7 @@ import publish from './publish.ts' import publishPrivate from './publish-private.ts' import visualDiff from './visual-diff.ts' import transpileDiff from './transpile-diff.ts' -import lint from '../test/lint.ts' +import lint from './lint.ts' import bundle from '../build/webpack.ts' import clean from '../build/clean.ts' import build from '../build/babel.ts' diff --git a/packages/ui-scripts/lib/test/lint.ts b/packages/ui-scripts/lib/commands/lint.ts similarity index 100% rename from packages/ui-scripts/lib/test/lint.ts rename to packages/ui-scripts/lib/commands/lint.ts From 41a0afe3fe2e6d6fb168042d2a549ae5b7d2af0c Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Wed, 15 Jul 2026 14:03:19 +0200 Subject: [PATCH 2/8] feat: add oxlint configuration and custom rule plugins Add .oxlintrc.json (workspace root and regression-test), porting the ESLint ruleset to oxlint and covering gaps with two custom rules and a jsPlugins bridge: - react-js/* (jsPlugins bridge to eslint-plugin-react): covers no-deprecated, prop-types, no-typos, require-default-props, forbid-foreign-prop-types, missing from oxlint's native react plugin. - instructure/no-relative-imports (custom): blocks relative imports that reach into another package's src, bypassing that package's public API. - notice/notice (custom): requires the MIT license header at the top of source files. - vitest/valid-expect (override, ui-truncate-text only): disabled because oxlint's vitest plugin does not recognize the chai-style assertions used in those tests. Nothing consumes oxlint yet. ESLint still runs via lint-staged, ui-scripts lint, and regression-test's lint script. --- .oxlintrc.json | 546 +++++++++++++++ package.json | 1 + pnpm-lock.yaml | 647 ++++++++++-------- regression-test/.oxlintrc.json | 24 + .../no-relative-imports/pkg-a/package.json | 4 + .../no-relative-imports/pkg-a/src/index.ts | 28 + .../no-relative-imports/pkg-a/src/sibling.ts | 25 + .../no-relative-imports/pkg-b/package.json | 4 + .../no-relative-imports/pkg-b/src/index.ts | 25 + .../no-relative-imports-plugin.test.ts | 117 ++++ .../__node_tests__/notice-plugin.test.ts | 109 +++ scripts/oxlint/no-relative-imports-plugin.mjs | 190 +++++ scripts/oxlint/notice-plugin.mjs | 123 ++++ 13 files changed, 1561 insertions(+), 282 deletions(-) create mode 100644 .oxlintrc.json create mode 100644 regression-test/.oxlintrc.json create mode 100644 scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/package.json create mode 100644 scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/index.ts create mode 100644 scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/sibling.ts create mode 100644 scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/package.json create mode 100644 scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/src/index.ts create mode 100644 scripts/oxlint/__node_tests__/no-relative-imports-plugin.test.ts create mode 100644 scripts/oxlint/__node_tests__/notice-plugin.test.ts create mode 100644 scripts/oxlint/no-relative-imports-plugin.mjs create mode 100644 scripts/oxlint/notice-plugin.mjs diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000000..d148424141 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,546 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["eslint", "typescript", "react"], + "categories": { + "correctness": "off", + "suspicious": "off", + "pedantic": "off", + "perf": "off", + "style": "off", + "restriction": "off", + "nursery": "off" + }, + "env": { + "builtin": true, + "browser": true + }, + "settings": { + "react": { + "version": "18.3.1" + } + }, + "options": { + "reportUnusedDisableDirectives": "error" + }, + "ignorePatterns": [ + "**/node_modules/**", + "**/types/**", + "**/es/**", + "packages/*/lib/**", + "!packages/{browserslist-config-instui,ui-babel-preset,ui-codemods,ui-stylelint-config,ui-scripts,ui-webpack-config,command-utils,instui-cli,babel-plugin-transform-imports}/lib/**", + "packages/ui-codemods/lib/__node_tests__/__testfixtures__/**", + "scripts/oxlint/__node_tests__/__testfixtures__/**", + "regression-test/**", + "coverage/**", + "**/stylelint.config.js", + "**/babel.config.js", + "**/.next/**", + "**/next-env.d.ts" + ], + "jsPlugins": [ + { + "name": "react-js", + "specifier": "eslint-plugin-react" + }, + "./scripts/oxlint/no-relative-imports-plugin.mjs", + "./scripts/oxlint/notice-plugin.mjs" + ], + "rules": { + "constructor-super": "error", + "for-direction": "error", + "getter-return": [ + "error", + { + "allowImplicit": false + } + ], + "no-async-promise-executor": "error", + "no-case-declarations": "error", + "no-class-assign": "error", + "no-compare-neg-zero": "error", + "no-cond-assign": ["error", "except-parens"], + "no-const-assign": "error", + "no-constant-binary-expression": "error", + "no-constant-condition": [ + "error", + { + "checkLoops": "allExceptWhileTrue" + } + ], + "no-control-regex": "error", + "no-debugger": "error", + "no-delete-var": "error", + "no-dupe-class-members": "error", + "no-dupe-else-if": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty": [ + "error", + { + "allowEmptyCatch": false + } + ], + "no-empty-character-class": "error", + "no-empty-pattern": [ + "error", + { + "allowObjectPatternsAsParameters": false + } + ], + "no-empty-static-block": "error", + "no-ex-assign": "error", + "no-extra-boolean-cast": ["error", {}], + "no-fallthrough": [ + "error", + { + "allowEmptyCase": false, + "reportUnusedFallthroughComment": false + } + ], + "no-func-assign": "error", + "no-global-assign": [ + "error", + { + "exceptions": [] + } + ], + "no-import-assign": "error", + "no-invalid-regexp": ["error", {}], + "no-irregular-whitespace": [ + "error", + { + "skipComments": false, + "skipJSXText": false, + "skipRegExps": false, + "skipStrings": true, + "skipTemplates": false + } + ], + "no-loss-of-precision": "error", + "no-misleading-character-class": [ + "error", + { + "allowEscape": false + } + ], + "no-new-native-nonconstructor": "error", + "no-nonoctal-decimal-escape": "error", + "no-obj-calls": "error", + "no-prototype-builtins": "error", + "no-redeclare": [ + "error", + { + "builtinGlobals": true + } + ], + "no-regex-spaces": "error", + "no-self-assign": [ + "error", + { + "props": true + } + ], + "no-setter-return": "error", + "no-shadow-restricted-names": [ + "error", + { + "reportGlobalThis": false + } + ], + "no-sparse-arrays": "error", + "no-this-before-super": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": [ + "error", + { + "enforceForOrderingRelations": false + } + ], + "no-unsafe-optional-chaining": [ + "error", + { + "disallowArithmeticOperators": false + } + ], + "no-unused-labels": "error", + "no-unused-private-class-members": "error", + "no-unused-vars": [ + "warn", + { + "args": "none", + "ignoreRestSiblings": true + } + ], + "no-useless-backreference": "error", + "no-useless-catch": "error", + "no-useless-escape": [ + "error", + { + "allowRegexCharacters": [] + } + ], + "no-with": "error", + "require-yield": "error", + "use-isnan": [ + "error", + { + "enforceForIndexOf": false, + "enforceForSwitchCase": true + } + ], + "valid-typeof": [ + "error", + { + "requireStringLiterals": false + } + ], + "no-var": "error", + "prefer-const": [ + "error", + { + "destructuring": "any", + "ignoreReadBeforeAssign": false + } + ], + "prefer-rest-params": "error", + "prefer-spread": "error", + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-ignore": "allow-with-description" + } + ], + "@typescript-eslint/no-array-constructor": "error", + "@typescript-eslint/no-duplicate-enum-values": "error", + "@typescript-eslint/no-empty-object-type": "error", + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "error", + "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-this-alias": "error", + "@typescript-eslint/no-unnecessary-type-constraint": "error", + "@typescript-eslint/no-unsafe-declaration-merging": "error", + "@typescript-eslint/no-unsafe-function-type": "error", + "no-unused-expressions": [ + "warn", + { + "allowShortCircuit": true, + "allowTernary": true, + "allowTaggedTemplates": true, + "enforceForJSX": false, + "ignoreDirectives": false + } + ], + "@typescript-eslint/no-unused-expressions": [ + "warn", + { + "allowShortCircuit": false, + "allowTaggedTemplates": false, + "allowTernary": false + } + ], + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-wrapper-object-types": "error", + "@typescript-eslint/prefer-as-const": "error", + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/triple-slash-reference": "error", + "react/display-name": "error", + "react/jsx-key": "error", + "react/jsx-no-comment-textnodes": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-target-blank": "error", + "react/jsx-no-undef": "error", + "react/no-children-prop": "error", + "react/no-danger-with-children": "error", + "react-js/no-deprecated": "warn", + "react/no-direct-mutation-state": "error", + "react/no-find-dom-node": "warn", + "react/no-is-mounted": "error", + "react/no-render-return-value": "error", + "react/no-string-refs": "error", + "react/no-unescaped-entities": "error", + "react/no-unknown-property": [ + "error", + { + "ignore": ["css", "componentRef"], + "requireDataLowercase": false + } + ], + "react-js/prop-types": [ + "error", + { + "skipUndeclared": true + } + ], + "react/require-render-return": "error", + "@typescript-eslint/no-empty-function": [ + "warn", + { + "allow": [] + } + ], + "react-js/forbid-foreign-prop-types": "error", + "react/no-danger": "error", + "react-js/require-default-props": "warn", + "react-js/no-typos": "error", + "no-console": [ + "error", + { + "allow": ["warn", "error", "time", "timeEnd"] + } + ], + "no-param-reassign": [ + "error", + { + "props": true + } + ], + "instructure/no-relative-imports": "error", + "notice/notice": "error", + "no-restricted-imports": [ + "error", + { + "patterns": [ + { + "group": ["*/src", "*/src/**"] + }, + { + "group": ["@instructure/ui-*/lib", "@instructure/ui-*/lib/**"] + }, + { + "group": ["@instructure/ui-*/es", "@instructure/ui-*/es/**"] + } + ] + } + ] + }, + "overrides": [ + { + "files": ["**/__tests__/**"], + "plugins": ["vitest"], + "rules": { + "vitest/expect-expect": [ + "error", + { + "assertFunctionNames": ["expect", "assert"], + "additionalTestBlockFunctions": [] + } + ], + "vitest/no-commented-out-tests": "warn", + "vitest/no-conditional-expect": "error", + "vitest/no-disabled-tests": "warn", + "vitest/no-focused-tests": "error", + "vitest/no-identical-title": "error", + "vitest/no-import-node-test": "error", + "vitest/no-interpolation-in-snapshots": "error", + "vitest/no-mocks-import": "error", + "vitest/no-standalone-expect": [ + "error", + { + "additionalTestBlockFunctions": [] + } + ], + "vitest/no-unneeded-async-expect-function": "error", + "vitest/prefer-called-exactly-once-with": "error", + "vitest/require-local-test-context-for-concurrent-snapshots": "error", + "vitest/valid-describe-callback": "error", + "vitest/valid-expect": [ + "error", + { + "alwaysAwait": false, + "asyncMatchers": ["toReject", "toResolve"], + "minArgs": 1, + "maxArgs": 1 + } + ], + "vitest/valid-expect-in-promise": "error", + "vitest/valid-title": [ + "warn", + { + "ignoreTypeOfDescribeName": false, + "allowArguments": false, + "disallowedWords": [] + } + ] + } + }, + { + "files": ["packages/ui-truncate-text/src/TruncateText/__tests__/**"], + "plugins": ["vitest"], + "rules": { + "vitest/valid-expect": "off" + } + }, + { + "files": ["**/*"], + "excludeFiles": ["**/__tests__/**"], + "plugins": ["jsx-a11y"], + "rules": { + "jsx-a11y/alt-text": "error", + "jsx-a11y/anchor-has-content": "error", + "jsx-a11y/anchor-is-valid": "error", + "jsx-a11y/aria-activedescendant-has-tabindex": "error", + "jsx-a11y/aria-props": "error", + "jsx-a11y/aria-proptypes": "error", + "jsx-a11y/aria-role": "error", + "jsx-a11y/aria-unsupported-elements": "error", + "jsx-a11y/autocomplete-valid": "error", + "jsx-a11y/click-events-have-key-events": "error", + "jsx-a11y/heading-has-content": "error", + "jsx-a11y/html-has-lang": "error", + "jsx-a11y/iframe-has-title": "error", + "jsx-a11y/img-redundant-alt": "error", + "jsx-a11y/interactive-supports-focus": [ + "error", + { + "tabbable": [ + "button", + "checkbox", + "link", + "searchbox", + "spinbutton", + "switch", + "textbox" + ] + } + ], + "jsx-a11y/label-has-associated-control": "error", + "jsx-a11y/media-has-caption": "error", + "jsx-a11y/mouse-events-have-key-events": "error", + "jsx-a11y/no-access-key": "error", + "jsx-a11y/no-autofocus": "error", + "jsx-a11y/no-distracting-elements": "error", + "jsx-a11y/no-interactive-element-to-noninteractive-role": [ + "error", + { + "tr": ["none", "presentation"], + "canvas": ["img"] + } + ], + "jsx-a11y/no-noninteractive-element-interactions": [ + "error", + { + "handlers": [ + "onClick", + "onError", + "onLoad", + "onMouseDown", + "onMouseUp", + "onKeyPress", + "onKeyDown", + "onKeyUp" + ], + "alert": ["onKeyUp", "onKeyDown", "onKeyPress"], + "body": ["onError", "onLoad"], + "dialog": ["onKeyUp", "onKeyDown", "onKeyPress"], + "iframe": ["onError", "onLoad"], + "img": ["onError", "onLoad"] + } + ], + "jsx-a11y/no-noninteractive-element-to-interactive-role": [ + "error", + { + "ul": [ + "listbox", + "menu", + "menubar", + "radiogroup", + "tablist", + "tree", + "treegrid" + ], + "ol": [ + "listbox", + "menu", + "menubar", + "radiogroup", + "tablist", + "tree", + "treegrid" + ], + "li": [ + "menuitem", + "menuitemradio", + "menuitemcheckbox", + "option", + "row", + "tab", + "treeitem" + ], + "table": ["grid"], + "td": ["gridcell"], + "fieldset": ["radiogroup", "presentation"] + } + ], + "jsx-a11y/no-noninteractive-tabindex": [ + "error", + { + "tags": [], + "roles": ["tabpanel"], + "allowExpressionValues": true + } + ], + "jsx-a11y/no-redundant-roles": "error", + "jsx-a11y/no-static-element-interactions": [ + "error", + { + "allowExpressionValues": true, + "handlers": [ + "onClick", + "onMouseDown", + "onMouseUp", + "onKeyPress", + "onKeyDown", + "onKeyUp" + ] + } + ], + "jsx-a11y/role-has-required-aria-props": "error", + "jsx-a11y/role-supports-aria-props": "error", + "jsx-a11y/scope": "error", + "jsx-a11y/tabindex-no-positive": "error" + } + }, + { + "files": [ + "packages/{browserslist-config-instui,ui-babel-preset,ui-codemods,ui-stylelint-config,ui-scripts,ui-webpack-config,command-utils,instui-cli,babel-plugin-transform-imports}/**/*", + "packages/__docs__/**/*.js", + "packages/__docs__/**/*.mjs" + ], + "rules": { + "no-console": "off" + }, + "env": { + "node": true + } + }, + { + "files": ["**/*"], + "excludeFiles": ["packages/**"], + "rules": { + "no-console": "off" + }, + "env": { + "node": true + } + }, + { + "files": ["packages/ui-codemods/**/*.js"], + "env": { + "jest": true + } + }, + { + "files": ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.jsx", "**/*.mjsx"], + "rules": { + "no-undef": "error", + "no-var": "off", + "prefer-const": "off", + "prefer-rest-params": "off", + "prefer-spread": "off" + } + } + ] +} diff --git a/package.json b/package.json index cf7817432f..aaf549f8b4 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "lerna": "9.0.7", "lint-staged": "^17.0.8", "moment-timezone": "^0.6.2", + "oxlint": "^1.72.0", "prettier": "2.8.8", "playwright": "1.61.1", "react": "18.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e4f0078d86..22d9a32d30 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,7 +80,7 @@ importers: version: 4.1.9(playwright@1.61.1)(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.9) '@vitest/eslint-plugin': specifier: ^1.6.20 - version: 1.6.20(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)(vitest@4.1.9) + version: 1.6.23(@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)(vitest@4.1.9) '@vitest/ui': specifier: 4.1.9 version: 4.1.9(vitest@4.1.9) @@ -122,28 +122,28 @@ importers: version: 4.5.0(webpack@5.107.2(esbuild@0.28.1)) eslint: specifier: ^9.39.4 - version: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + version: 9.39.4(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) + version: 10.1.8(eslint@9.39.4(jiti@2.6.1)) eslint-import-resolver-node: specifier: ^0.4.0 version: 0.4.0(supports-color@8.1.1) eslint-module-utils: specifier: 2.13.0 - version: 2.13.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-node@0.4.0(supports-color@8.1.1))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1) + version: 2.13.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-node@0.4.0(supports-color@8.1.1))(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1) eslint-plugin-compat: specifier: ^7.0.2 - version: 7.0.2(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) + version: 7.0.2(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 - version: 6.10.2(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) + version: 6.10.2(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-notice: specifier: ^1.0.0 - version: 1.0.0(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) + version: 1.0.0(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) + version: 7.37.5(eslint@9.39.4(jiti@2.6.1)) globals: specifier: ^17.7.0 version: 17.7.0 @@ -162,6 +162,9 @@ importers: moment-timezone: specifier: ^0.6.2 version: 0.6.2 + oxlint: + specifier: ^1.72.0 + version: 1.73.0 playwright: specifier: 1.61.1 version: 1.61.1 @@ -179,7 +182,7 @@ importers: version: 6.0.3 typescript-eslint: specifier: ^8.62.1 - version: 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + version: 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) vitest: specifier: ^4.1.9 version: 4.1.9(@types/node@24.1.0)(@vitest/browser-playwright@4.1.9)(@vitest/ui@4.1.9)(jsdom@29.1.1)(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0)) @@ -7558,6 +7561,128 @@ packages: '@octokit/types@13.10.0': resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} + '@oxlint/binding-android-arm-eabi@1.73.0': + resolution: {integrity: sha512-HZQRN/UMBu+Ut+/9MiAChkbP4qZqrNOWBcNI45vOT40GVhbGR0JgHB87L48D4iAqFQIdVmeQYtV9RF89AjTKkg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.73.0': + resolution: {integrity: sha512-Gp+KJRylv2aW7thRpG5p1KTxZq4ZJFbWowrKzufNq9d3ssl3r3JviYV45/+p+7CN1Nv0zDd1e8Ex0b/HUDq4TQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.73.0': + resolution: {integrity: sha512-3de96NdtXhxERMjIz7wsp2HYMY6pMQycGxFWac2mFecAx6VeARF/IqFb1QIaqiCRIdfzBwzTed+pCTCoiS+CYA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.73.0': + resolution: {integrity: sha512-5zx/uPW32TiaOeVY1dQ/H5iOf0K1HOdFKOJhLqGl4o63+i1fpzoqqu/mKtd7OFgFjNCdhlyTGgjVkQTZm1ELcg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.73.0': + resolution: {integrity: sha512-qNe4gKHaGnLuZJ8toUg90JAa0S2vTVvDw+0bRi3q1avXZXDT4u5mMeECf3nD4HYrbdn1O7dXqWut4onY/yx/Xg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.73.0': + resolution: {integrity: sha512-cCehYh5hTbfShm/fxTD6wwrGUWIpvX+N5OxmAMhFhDeTGXvw+BeNj889tpxsFQ9ZLatQ6wImuY8tsKLZ+FMz7w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.73.0': + resolution: {integrity: sha512-d5j5GDU/2dMgjVhw7TQT9ITrsIr1Y02KEXKyVGIXUkD+KiaxE9TP65FS2ZdgTBemQvoRL+gSBdbrIm3cQIeacg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.73.0': + resolution: {integrity: sha512-Eyf1SrP3+yR1DI3OJgOY2Pvrr9dWP9TK37xPaDYycwTtlGlI45erJAVIfH5/m/xosDt6BupJYEFi47bvbTuuyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-arm64-musl@1.73.0': + resolution: {integrity: sha512-IlT/OJApEDKaMmCooHuncgJZbbCe7T5QIWmTZBEtYscWvzPQuuEinVcid6kwQRVQOUdb7PUCz4jQHnaYXdfJXw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-ppc64-gnu@1.73.0': + resolution: {integrity: sha512-L+JYcb/vdg5fmcH08V6o0YYLU28cTH1SPNulwJdvK9NK49aXSkYy6oNpKBmddArVOXYqNepriDGiZ04G54kh1Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-gnu@1.73.0': + resolution: {integrity: sha512-Qtk0g3bKV6OwWjIm7R8kQN1uOZRKQt/MODK2a8QfkwhTpXBD53ozx5XLVWLGDQAVyp2otLW4D2wB98XfAfMPGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-musl@1.73.0': + resolution: {integrity: sha512-wX0NQKZVxltkAOVmzFcpOaMpdaUvsq1Eqpx9tkAfl71UdkTlSo1R4AdAnGccR1Fm2+TzFgZ22CyyGuZ41RDr/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-s390x-gnu@1.73.0': + resolution: {integrity: sha512-vPe7UGBMWyiLTtnqS4xxgMQFSFGmtQwhwCxuiw6lXygaO6bVt0D8dFVg8Xv05eaiN3ybC0HXXHUAohFMFvqoCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-gnu@1.73.0': + resolution: {integrity: sha512-2CwIWr9cemFC/CbRBWZvuk5mffz6ObmfFkfcC/9rTQ7f+icNhYr2kOjf9Rt8lLvugvkdGDOmkoVoFFHh6ClCTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-musl@1.73.0': + resolution: {integrity: sha512-nDadfJgg7NBBxG0N560wOe7LLX5QiYp6qBaI7viuk5EUORFBktU/NfV0MbTqU3gTqQDCh4VyxKdo5VADxk9w8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/binding-openharmony-arm64@1.73.0': + resolution: {integrity: sha512-wGjJC+NLH9xP+IKGn9RDW94ojJR/wPbg5WCnQjj/oReaOtCQthr8ws1zICe77JFmo4ouUdeTHHZL/ESGiF6Pmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.73.0': + resolution: {integrity: sha512-I7X47GPGljw225YUQ5SbC/rb1Kkdrd0yQf0x+hYxeKS6DpfjMbo9ccQPQ6LNY6BoJQ1sHhgDUGuMn5Vg5gHT6w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.73.0': + resolution: {integrity: sha512-5lWj+3h+74Fm1jYOO9qkJA4xkAlZA099DkXppuXsk7UpnpZLttsefrZU469vChGaG6hcSqrkKXQOvMTZtbjeNg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.73.0': + resolution: {integrity: sha512-WaNRvh4f6zY9CvUQk2YoA1O90ieWrIklI84+HXFr9Isjz9CSESrdqo/RtIYt4Dll/cAchqGDMehfaZd0vqEFZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@peculiar/asn1-cms@2.6.1': resolution: {integrity: sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw==} @@ -8026,100 +8151,63 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@typescript-eslint/eslint-plugin@8.62.1': - resolution: {integrity: sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==} + '@typescript-eslint/eslint-plugin@8.64.0': + resolution: {integrity: sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.62.1 + '@typescript-eslint/parser': ^8.64.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.62.1': - resolution: {integrity: sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==} + '@typescript-eslint/parser@8.64.0': + resolution: {integrity: sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.59.2': - resolution: {integrity: sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/project-service@8.62.1': - resolution: {integrity: sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==} + '@typescript-eslint/project-service@8.64.0': + resolution: {integrity: sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.59.2': - resolution: {integrity: sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/scope-manager@8.62.1': - resolution: {integrity: sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.59.2': - resolution: {integrity: sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==} + '@typescript-eslint/scope-manager@8.64.0': + resolution: {integrity: sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/tsconfig-utils@8.62.1': - resolution: {integrity: sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==} + '@typescript-eslint/tsconfig-utils@8.64.0': + resolution: {integrity: sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.62.1': - resolution: {integrity: sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==} + '@typescript-eslint/type-utils@8.64.0': + resolution: {integrity: sha512-XWG4Fmmv/6SvyS9nH8jWrKs6terwJvE8cyRt1CzYYqzp9OrPhCT4cMc/f7C6RZCwG+qMmiffJS1/qJP8G1URtg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.59.2': - resolution: {integrity: sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==} + '@typescript-eslint/types@8.64.0': + resolution: {integrity: sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.62.1': - resolution: {integrity: sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.59.2': - resolution: {integrity: sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==} + '@typescript-eslint/typescript-estree@8.64.0': + resolution: {integrity: sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/typescript-estree@8.62.1': - resolution: {integrity: sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/utils@8.59.2': - resolution: {integrity: sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/utils@8.62.1': - resolution: {integrity: sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==} + '@typescript-eslint/utils@8.64.0': + resolution: {integrity: sha512-aJUGVB3+U0htrrCjoA8qukw8cm8fNCGAxK/tVoS70k8aeb7DETKeFozRiVFIwEeN9WJLsjaP3ph8I60tY2XZoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.59.2': - resolution: {integrity: sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/visitor-keys@8.62.1': - resolution: {integrity: sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==} + '@typescript-eslint/visitor-keys@8.64.0': + resolution: {integrity: sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react@5.2.0': @@ -8139,8 +8227,8 @@ packages: peerDependencies: vitest: 4.1.9 - '@vitest/eslint-plugin@1.6.20': - resolution: {integrity: sha512-xRwWHFG0Utp6hXtbGiWk4VdKXCGdExD8kbWrrmFEiG5dk8anOJ+vbWbeOa8EbkocKQRTsx7JAWETccZiBgFp/Q==} + '@vitest/eslint-plugin@1.6.23': + resolution: {integrity: sha512-CbrXxQpIUMbeyylGlxaxTgnWYM44et4Nx58swl7+vrTyC9Ttx+hQoy8BGCregbbZ08K5qFhRHeoad1VvERUbkg==} engines: {node: '>=18'} peerDependencies: '@typescript-eslint/eslint-plugin': '*' @@ -8492,10 +8580,6 @@ packages: aws4@1.13.2: resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - axe-core@4.11.2: - resolution: {integrity: sha512-byD6KPdvo72y/wj2T/4zGEvvlis+PsZsn/yPS3pEO+sFpcrqRpX/TJCxvVaEsNeMrfQbCr7w163YqoD9IYwHXw==} - engines: {node: '>=4'} - axe-core@4.12.1: resolution: {integrity: sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==} engines: {node: '>=4'} @@ -8562,8 +8646,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.10.40: - resolution: {integrity: sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==} + baseline-browser-mapping@2.10.38: + resolution: {integrity: sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==} engines: {node: '>=6.0.0'} hasBin: true @@ -9504,9 +9588,6 @@ packages: es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} - es-module-lexer@2.2.0: - resolution: {integrity: sha512-3lGxdTXCLfe1MYfTz1y2ksAAUM4NAOP6rPEjxGJVKO7TZ5+tvHCaQWGpC4Y3IXvW3ece0Cz1cIP4FWBxOnGCTQ==} - es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -11566,6 +11647,19 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxlint@1.73.0: + resolution: {integrity: sha512-u91G9TJzU6yqKWNZUYprQB07W7YvntZXaRxQ6CkoytepYhLWUXWsr1M8zUJ34VatNPuUAr3Z8GH+O2A331CluQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.24.0' + vite-plus: '*' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -12686,6 +12780,11 @@ packages: uglify-js: optional: true + terser@5.46.2: + resolution: {integrity: sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==} + engines: {node: '>=10'} + hasBin: true + terser@5.48.0: resolution: {integrity: sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==} engines: {node: '>=10'} @@ -12924,8 +13023,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@8.62.1: - resolution: {integrity: sha512-vymnnM5g0AKQDSAyfP12nMIBvgwgA42syg74kkuZ4x1VuTzwQKwc5h9rGxeShCjny5o+zWAb6OEoz7XLgrIkIw==} + typescript-eslint@8.64.0: + resolution: {integrity: sha512-0qg+pDNMnqYzqH9AnNK+39tejHvsShUOUUoRUgtnTGE7QuMZhiFDnozq8nHJVq+Wae6NMLKNWLg5WmkcC/ndyQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -14496,7 +14595,7 @@ snapshots: '@commitlint/is-ignored@21.2.0': dependencies: '@commitlint/types': 21.2.0 - semver: 7.7.4 + semver: 7.8.5 '@commitlint/lint@21.2.0': dependencies: @@ -14600,7 +14699,7 @@ snapshots: dependencies: '@simple-libs/child-process-utils': 1.0.2 '@simple-libs/stream-utils': 1.2.0 - semver: 7.7.4 + semver: 7.8.5 optionalDependencies: conventional-commits-parser: 6.4.0 @@ -14943,11 +15042,6 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))': - dependencies: - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) - eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -14955,7 +15049,7 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.21.2(supports-color@8.1.1)': + '@eslint/config-array@0.21.2': dependencies: '@eslint/object-schema': 2.1.7 debug: 4.4.3(supports-color@8.1.1) @@ -14971,7 +15065,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.5(supports-color@8.1.1)': + '@eslint/eslintrc@3.3.5': dependencies: ajv: 6.14.0 debug: 4.4.3(supports-color@8.1.1) @@ -15587,7 +15681,7 @@ snapshots: proggy: 3.0.0 promise-all-reject-late: 1.0.1 promise-call-limit: 3.0.2 - semver: 7.7.4 + semver: 7.8.5 ssri: 12.0.0 treeverse: 3.0.0 walk-up-path: 4.0.0 @@ -15596,7 +15690,7 @@ snapshots: '@npmcli/fs@4.0.0': dependencies: - semver: 7.7.4 + semver: 7.8.5 '@npmcli/fs@5.0.0': dependencies: @@ -15610,7 +15704,7 @@ snapshots: npm-pick-manifest: 10.0.0 proc-log: 5.0.0 promise-retry: 2.0.1 - semver: 7.7.4 + semver: 7.8.5 which: 5.0.0 '@npmcli/git@7.0.2': @@ -15621,7 +15715,7 @@ snapshots: lru-cache: 11.2.7 npm-pick-manifest: 11.0.3 proc-log: 6.1.0 - semver: 7.7.4 + semver: 7.8.5 which: 6.0.1 '@npmcli/installed-package-contents@3.0.0': @@ -15647,7 +15741,7 @@ snapshots: json-parse-even-better-errors: 5.0.0 pacote: 21.5.0 proc-log: 6.1.0 - semver: 7.7.4 + semver: 7.8.5 transitivePeerDependencies: - supports-color @@ -15666,7 +15760,7 @@ snapshots: hosted-git-info: 9.0.2 json-parse-even-better-errors: 5.0.0 proc-log: 6.1.0 - semver: 7.7.4 + semver: 7.8.5 validate-npm-package-license: 3.0.4 '@npmcli/promise-spawn@8.0.3': @@ -15703,7 +15797,7 @@ snapshots: enquirer: 2.3.6 minimatch: 10.2.4 nx: 22.6.4 - semver: 7.7.4 + semver: 7.8.5 tslib: 2.8.1 yargs-parser: 21.1.1 @@ -15802,6 +15896,63 @@ snapshots: dependencies: '@octokit/openapi-types': 24.2.0 + '@oxlint/binding-android-arm-eabi@1.73.0': + optional: true + + '@oxlint/binding-android-arm64@1.73.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.73.0': + optional: true + + '@oxlint/binding-darwin-x64@1.73.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.73.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.73.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.73.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.73.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.73.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.73.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.73.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.73.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.73.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.73.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.73.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.73.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.73.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.73.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.73.0': + optional: true + '@peculiar/asn1-cms@2.6.1': dependencies: '@peculiar/asn1-schema': 2.6.0 @@ -16295,15 +16446,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.62.1 - '@typescript-eslint/type-utils': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.62.1 - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + '@typescript-eslint/parser': 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/type-utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.64.0 + eslint: 9.39.4(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -16311,130 +16462,79 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.62.1 - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.62.1 - debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.59.2(supports-color@8.1.1)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@6.0.3) - '@typescript-eslint/types': 8.59.2 + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.64.0 debug: 4.4.3(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.62.1(typescript@6.0.3)': + '@typescript-eslint/project-service@8.64.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.62.1(typescript@6.0.3) - '@typescript-eslint/types': 8.62.1 + '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@6.0.3) + '@typescript-eslint/types': 8.64.0 debug: 4.4.3(supports-color@8.1.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.59.2': + '@typescript-eslint/scope-manager@8.64.0': dependencies: - '@typescript-eslint/types': 8.59.2 - '@typescript-eslint/visitor-keys': 8.59.2 + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/visitor-keys': 8.64.0 - '@typescript-eslint/scope-manager@8.62.1': - dependencies: - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/visitor-keys': 8.62.1 - - '@typescript-eslint/tsconfig-utils@8.59.2(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.64.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/tsconfig-utils@8.62.1(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)': dependencies: - typescript: 6.0.3 - - '@typescript-eslint/type-utils@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3)': - dependencies: - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3) + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.59.2': {} - - '@typescript-eslint/types@8.62.1': {} + '@typescript-eslint/types@8.64.0': {} - '@typescript-eslint/typescript-estree@8.59.2(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.64.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.59.2(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@6.0.3) - '@typescript-eslint/types': 8.59.2 - '@typescript-eslint/visitor-keys': 8.59.2 + '@typescript-eslint/project-service': 8.64.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@6.0.3) + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/visitor-keys': 8.64.0 debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.5 - semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/typescript-estree@8.62.1(typescript@6.0.3)': - dependencies: - '@typescript-eslint/project-service': 8.62.1(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.62.1(typescript@6.0.3) - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/visitor-keys': 8.62.1 - debug: 4.4.3(supports-color@8.1.1) - minimatch: 10.2.5 - semver: 7.7.4 + semver: 7.8.5 tinyglobby: 0.2.15 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.2(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) - '@typescript-eslint/scope-manager': 8.59.2 - '@typescript-eslint/types': 8.59.2 - '@typescript-eslint/typescript-estree': 8.59.2(supports-color@8.1.1)(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3)': + '@typescript-eslint/utils@8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) - '@typescript-eslint/scope-manager': 8.62.1 - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) + eslint: 9.39.4(jiti@2.6.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.59.2': - dependencies: - '@typescript-eslint/types': 8.59.2 - eslint-visitor-keys: 5.0.1 - - '@typescript-eslint/visitor-keys@8.62.1': + '@typescript-eslint/visitor-keys@8.64.0': dependencies: - '@typescript-eslint/types': 8.62.1 + '@typescript-eslint/types': 8.64.0 eslint-visitor-keys: 5.0.1 '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0))': @@ -16479,13 +16579,13 @@ snapshots: - utf-8-validate - vite - '@vitest/eslint-plugin@1.6.20(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)(vitest@4.1.9)': + '@vitest/eslint-plugin@1.6.23(@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)(vitest@4.1.9)': dependencies: - '@typescript-eslint/scope-manager': 8.59.2 - '@typescript-eslint/utils': 8.59.2(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) + eslint: 9.39.4(jiti@2.6.1) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) typescript: 6.0.3 vitest: 4.1.9(@types/node@24.1.0)(@vitest/browser-playwright@4.1.9)(@vitest/ui@4.1.9)(jsdom@29.1.1)(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0)) transitivePeerDependencies: @@ -16656,9 +16756,9 @@ snapshots: dependencies: acorn: 8.17.0 - acorn-jsx@5.3.2(acorn@8.16.0): + acorn-jsx@5.3.2(acorn@8.17.0): dependencies: - acorn: 8.16.0 + acorn: 8.17.0 acorn-walk@8.3.5: dependencies: @@ -16864,8 +16964,6 @@ snapshots: aws4@1.13.2: {} - axe-core@4.11.2: {} - axe-core@4.12.1: {} axios@1.12.0: @@ -16950,7 +17048,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.10.40: {} + baseline-browser-mapping@2.10.38: {} basic-auth@2.0.1: dependencies: @@ -17039,7 +17137,7 @@ snapshots: browserslist@4.28.4: dependencies: - baseline-browser-mapping: 2.10.40 + baseline-browser-mapping: 2.10.38 caniuse-lite: 1.0.30001799 electron-to-chromium: 1.5.378 node-releases: 2.0.49 @@ -17457,7 +17555,7 @@ snapshots: handlebars: 4.7.9 json-stringify-safe: 5.0.1 meow: 8.1.2 - semver: 7.7.4 + semver: 7.8.5 split: 1.0.1 conventional-commit-types@3.0.0: {} @@ -18064,9 +18162,6 @@ snapshots: es-module-lexer@2.1.0: {} - es-module-lexer@2.2.0: - optional: true - es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -18193,9 +18288,9 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)): + eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.6.1)): dependencies: - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) eslint-import-resolver-node@0.4.0(supports-color@8.1.1): dependencies: @@ -18205,38 +18300,38 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.13.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-node@0.4.0(supports-color@8.1.1))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1): + eslint-module-utils@2.13.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-node@0.4.0(supports-color@8.1.1))(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + '@typescript-eslint/parser': 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) + eslint: 9.39.4(jiti@2.6.1) eslint-import-resolver-node: 0.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color - eslint-plugin-compat@7.0.2(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)): + eslint-plugin-compat@7.0.2(eslint@9.39.4(jiti@2.6.1)): dependencies: '@mdn/browser-compat-data': 6.1.5 ast-metadata-inferer: 0.8.1 browserslist: 4.28.4 - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) find-up: 5.0.0 globals: 15.15.0 lodash.memoize: 4.1.2 - semver: 7.7.4 + semver: 7.8.5 - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 - axe-core: 4.11.2 + axe-core: 4.12.1 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -18245,14 +18340,14 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-notice@1.0.0(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)): + eslint-plugin-notice@1.0.0(eslint@9.39.4(jiti@2.6.1)): dependencies: - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) find-root: 1.1.0 lodash: 4.18.1 metric-lcs: 0.1.2 - eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)): + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -18260,7 +18355,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.3.1 - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + eslint: 9.39.4(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -18294,57 +18389,16 @@ snapshots: dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.2(supports-color@8.1.1) + '@eslint/config-array': 0.21.2 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.5(supports-color@8.1.1) + '@eslint/eslintrc': 3.3.5 '@eslint/js': 9.39.4 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.14.0 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.5 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - - eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.2(supports-color@8.1.1) - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.5(supports-color@8.1.1) - '@eslint/js': 9.39.4 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 ajv: 6.14.0 chalk: 4.1.2 cross-spawn: 7.0.6 @@ -18381,8 +18435,8 @@ snapshots: espree@10.4.0: dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) eslint-visitor-keys: 4.2.1 esprima@4.0.1: {} @@ -18804,7 +18858,7 @@ snapshots: git-semver-tags@5.0.1: dependencies: meow: 8.1.2 - semver: 7.7.4 + semver: 7.8.5 git-up@7.0.0: dependencies: @@ -19029,7 +19083,7 @@ snapshots: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.48.0 + terser: 5.46.2 html-webpack-plugin@5.6.7(webpack@5.107.2(esbuild@0.28.1)(postcss@8.5.8)): dependencies: @@ -19210,7 +19264,7 @@ snapshots: npm-package-arg: 13.0.1 promzard: 2.0.0 read: 4.1.0 - semver: 7.7.4 + semver: 7.8.5 validate-npm-package-license: 3.0.4 validate-npm-package-name: 6.0.2 @@ -19838,7 +19892,7 @@ snapshots: npm-package-arg: 13.0.1 npm-registry-fetch: 19.1.0 proc-log: 5.0.0 - semver: 7.7.4 + semver: 7.8.5 sigstore: 4.1.0(supports-color@8.1.1) ssri: 12.0.0 transitivePeerDependencies: @@ -20306,7 +20360,7 @@ snapshots: make-fetch-happen: 14.0.3 nopt: 8.1.0 proc-log: 5.0.0 - semver: 7.7.4 + semver: 7.8.5 tar: 7.5.11 tinyglobby: 0.2.15 which: 5.0.0 @@ -20321,7 +20375,7 @@ snapshots: make-fetch-happen: 15.0.2 nopt: 9.0.0 proc-log: 6.1.0 - semver: 7.7.4 + semver: 7.8.5 tar: 7.5.11 tinyglobby: 0.2.15 which: 6.0.1 @@ -20349,7 +20403,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.7.4 + semver: 7.8.5 validate-npm-package-license: 3.0.4 normalize-package-data@8.0.0: @@ -20370,7 +20424,7 @@ snapshots: npm-install-checks@7.1.2: dependencies: - semver: 7.7.4 + semver: 7.8.5 npm-install-checks@8.0.0: dependencies: @@ -20391,7 +20445,7 @@ snapshots: dependencies: hosted-git-info: 9.0.2 proc-log: 5.0.0 - semver: 7.7.4 + semver: 7.8.5 validate-npm-package-name: 6.0.2 npm-packlist@10.0.3: @@ -20404,14 +20458,14 @@ snapshots: npm-install-checks: 7.1.2 npm-normalize-package-bin: 4.0.0 npm-package-arg: 12.0.2 - semver: 7.7.4 + semver: 7.8.5 npm-pick-manifest@11.0.3: dependencies: npm-install-checks: 8.0.0 npm-normalize-package-bin: 5.0.0 npm-package-arg: 13.0.1 - semver: 7.7.4 + semver: 7.8.5 npm-registry-fetch@19.1.0: dependencies: @@ -20462,7 +20516,7 @@ snapshots: ora: 5.3.0 picocolors: 1.1.1 resolve.exports: 2.0.3 - semver: 7.7.4 + semver: 7.8.5 string-width: 4.2.3 tar-stream: 2.2.0 tmp: 0.2.5 @@ -20606,6 +20660,28 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxlint@1.73.0: + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.73.0 + '@oxlint/binding-android-arm64': 1.73.0 + '@oxlint/binding-darwin-arm64': 1.73.0 + '@oxlint/binding-darwin-x64': 1.73.0 + '@oxlint/binding-freebsd-x64': 1.73.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.73.0 + '@oxlint/binding-linux-arm-musleabihf': 1.73.0 + '@oxlint/binding-linux-arm64-gnu': 1.73.0 + '@oxlint/binding-linux-arm64-musl': 1.73.0 + '@oxlint/binding-linux-ppc64-gnu': 1.73.0 + '@oxlint/binding-linux-riscv64-gnu': 1.73.0 + '@oxlint/binding-linux-riscv64-musl': 1.73.0 + '@oxlint/binding-linux-s390x-gnu': 1.73.0 + '@oxlint/binding-linux-x64-gnu': 1.73.0 + '@oxlint/binding-linux-x64-musl': 1.73.0 + '@oxlint/binding-openharmony-arm64': 1.73.0 + '@oxlint/binding-win32-arm64-msvc': 1.73.0 + '@oxlint/binding-win32-ia32-msvc': 1.73.0 + '@oxlint/binding-win32-x64-msvc': 1.73.0 + p-finally@1.0.0: {} p-limit@1.3.0: @@ -21881,6 +21957,13 @@ snapshots: optionalDependencies: esbuild: 0.28.1 + terser@5.46.2: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.17.0 + commander: 2.20.3 + source-map-support: 0.5.21 + terser@5.48.0: dependencies: '@jridgewell/source-map': 0.3.11 @@ -22114,13 +22197,13 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3): + typescript-eslint@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3) - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.1(eslint@9.39.4(jiti@2.6.1)(supports-color@8.1.1))(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1)(supports-color@8.1.1) + '@typescript-eslint/eslint-plugin': 8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/parser': 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) + eslint: 9.39.4(jiti@2.6.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -22567,7 +22650,7 @@ snapshots: browserslist: 4.28.4 chrome-trace-event: 1.0.4 enhanced-resolve: 5.24.0 - es-module-lexer: 2.2.0 + es-module-lexer: 2.1.0 eslint-scope: 5.1.1 events: 3.3.0 graceful-fs: 4.2.11 diff --git a/regression-test/.oxlintrc.json b/regression-test/.oxlintrc.json new file mode 100644 index 0000000000..05252e91fd --- /dev/null +++ b/regression-test/.oxlintrc.json @@ -0,0 +1,24 @@ +{ + "$schema": "../node_modules/oxlint/configuration_schema.json", + "extends": ["../.oxlintrc.json"], + "jsPlugins": [ + { + "name": "react-js", + "specifier": "eslint-plugin-react" + }, + "../scripts/oxlint/no-relative-imports-plugin.mjs", + "../scripts/oxlint/notice-plugin.mjs" + ], + "settings": { + "react": { + "version": "19.2.7" + } + }, + "ignorePatterns": [ + "**/node_modules/**", + "**/.next/**", + "**/next-env.d.ts", + "out/**", + "coverage/**" + ] +} diff --git a/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/package.json b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/package.json new file mode 100644 index 0000000000..5ccefeff02 --- /dev/null +++ b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/package.json @@ -0,0 +1,4 @@ +{ + "name": "@fixtures/pkg-a", + "private": true +} diff --git a/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/index.ts b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/index.ts new file mode 100644 index 0000000000..0f135dc548 --- /dev/null +++ b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/index.ts @@ -0,0 +1,28 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import sibling from './sibling' +import other from '../../pkg-b/src/index' + +export default { sibling, other } diff --git a/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/sibling.ts b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/sibling.ts new file mode 100644 index 0000000000..2828811353 --- /dev/null +++ b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-a/src/sibling.ts @@ -0,0 +1,25 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +export default 'sibling' diff --git a/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/package.json b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/package.json new file mode 100644 index 0000000000..05b7f8bda3 --- /dev/null +++ b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/package.json @@ -0,0 +1,4 @@ +{ + "name": "@fixtures/pkg-b", + "private": true +} diff --git a/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/src/index.ts b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/src/index.ts new file mode 100644 index 0000000000..2a7103beb9 --- /dev/null +++ b/scripts/oxlint/__node_tests__/__testfixtures__/no-relative-imports/pkg-b/src/index.ts @@ -0,0 +1,25 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +export default 'pkg-b' diff --git a/scripts/oxlint/__node_tests__/no-relative-imports-plugin.test.ts b/scripts/oxlint/__node_tests__/no-relative-imports-plugin.test.ts new file mode 100644 index 0000000000..9b35590681 --- /dev/null +++ b/scripts/oxlint/__node_tests__/no-relative-imports-plugin.test.ts @@ -0,0 +1,117 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import { describe, expect, it } from 'vitest' +import path from 'node:path' +import plugin, { + checkImportForRelativePackage, + findNamedPackage +} from '../no-relative-imports-plugin.mjs' + +const FIXTURES = path.join(__dirname, '__testfixtures__', 'no-relative-imports') +const PKG_A_INDEX = path.join(FIXTURES, 'pkg-a', 'src', 'index.ts') + +describe('no-relative-imports-plugin', () => { + describe('findNamedPackage', () => { + it('walks up from a file to the nearest named package.json', () => { + const found = findNamedPackage(PKG_A_INDEX) + expect(found.packageJson?.name).toBe('@fixtures/pkg-a') + }) + }) + + describe('checkImportForRelativePackage (pure rule logic)', () => { + it('flags a cross-package relative import, with the real error message format', () => { + const message = checkImportForRelativePackage( + '../../pkg-b/src/index', + PKG_A_INDEX + ) + expect(message).toBe( + 'Relative import from another package is not allowed. ' + + 'Use "@fixtures/pkg-b/index" instead of "../../pkg-b/src/index"' + ) + }) + + it('stays silent on a same-package sibling import', () => { + const message = checkImportForRelativePackage('./sibling', PKG_A_INDEX) + expect(message).toBeNull() + }) + + it('stays silent on a non-relative (bare specifier) import', () => { + const message = checkImportForRelativePackage( + '@instructure/ui-buttons', + PKG_A_INDEX + ) + expect(message).toBeNull() + }) + + it('stays silent when there is no context filename', () => { + const message = checkImportForRelativePackage('../../pkg-b/src/index', '') + expect(message).toBeNull() + }) + }) + + describe('the oxlint rule (create/visitor), independent of the oxlint CLI', () => { + function lintWithVisitor(filename: string, imports: string[]) { + const reports: unknown[] = [] + const context = { + filename, + report: (report: unknown) => reports.push(report) + } + const visitor = plugin.rules['no-relative-imports'].create( + context as never + ) + for (const source of imports) { + visitor.ImportDeclaration({ source: { value: source } } as never) + } + return reports + } + + it('reports exactly one violation for a cross-package import, none for a sibling import', () => { + const reports = lintWithVisitor(PKG_A_INDEX, [ + './sibling', + '../../pkg-b/src/index' + ]) + expect(reports).toHaveLength(1) + expect((reports[0] as { message: string }).message).toMatch( + /Relative import from another package/ + ) + }) + + it('handles CallExpression require() the same way as ImportDeclaration', () => { + const reports: unknown[] = [] + const context = { + filename: PKG_A_INDEX, + report: (report: unknown) => reports.push(report) + } + const visitor = plugin.rules['no-relative-imports'].create( + context as never + ) + visitor.CallExpression({ + callee: { type: 'Identifier', name: 'require' }, + arguments: [{ type: 'Literal', value: '../../pkg-b/src/index' }] + } as never) + expect(reports).toHaveLength(1) + }) + }) +}) diff --git a/scripts/oxlint/__node_tests__/notice-plugin.test.ts b/scripts/oxlint/__node_tests__/notice-plugin.test.ts new file mode 100644 index 0000000000..04dee503ee --- /dev/null +++ b/scripts/oxlint/__node_tests__/notice-plugin.test.ts @@ -0,0 +1,109 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import { describe, expect, it } from 'vitest' +import plugin, { + COPYRIGHT_NOTICE, + hasNoticeHeader, + insertNoticeHeader +} from '../notice-plugin.mjs' + +const CLEAN_SOURCE = 'export const x = 1\n' + +describe('notice-plugin', () => { + describe('hasNoticeHeader (pure rule logic)', () => { + it('is false for a file missing the header', () => { + expect(hasNoticeHeader(CLEAN_SOURCE)).toBe(false) + }) + + it('is true for a file that already has the real header', () => { + expect(hasNoticeHeader(COPYRIGHT_NOTICE + '\n' + CLEAN_SOURCE)).toBe(true) + }) + + it('is false for a header that merely resembles the real one (wrong text)', () => { + expect( + hasNoticeHeader('/* Copyright someone else */\n' + CLEAN_SOURCE) + ).toBe(false) + }) + }) + + describe('insertNoticeHeader (fixer logic)', () => { + it('prepends the exact real MIT header text', () => { + const fixed = insertNoticeHeader(CLEAN_SOURCE) + expect(fixed).toBe(COPYRIGHT_NOTICE + '\n' + CLEAN_SOURCE) + expect(fixed).toContain('The MIT License (MIT)') + expect(fixed).toContain('Copyright (c) 2015 - present Instructure, Inc.') + }) + + it('the fix is idempotent: applying it only when missing never duplicates the header', () => { + const applyFixIfNeeded = (text: string) => + hasNoticeHeader(text) ? text : insertNoticeHeader(text) + + const once = applyFixIfNeeded(CLEAN_SOURCE) + const twice = applyFixIfNeeded(once) + + expect(twice).toBe(once) + expect(once.match(/The MIT License \(MIT\)/g)).toHaveLength(1) + }) + }) + + describe('the oxlint rule (create/visitor), independent of the oxlint CLI', () => { + function lint(sourceText: string) { + const reports: Array<{ + message: string + fix?: (fixer: unknown) => unknown + }> = [] + const context = { + sourceCode: { getText: () => sourceText }, + report: (report: { + message: string + fix?: (fixer: unknown) => unknown + }) => reports.push(report) + } + const visitor = plugin.rules.notice.create(context as never) + visitor.Program({} as never) + return reports + } + + it('reports a missing header and the fix inserts the exact real header', () => { + const reports = lint(CLEAN_SOURCE) + expect(reports).toHaveLength(1) + + const fixer = { + insertTextBefore: (_node: unknown, text: string) => ({ text }) + } + const fixResult = reports[0].fix?.(fixer) as { text: string } | undefined + expect(fixResult?.text).toBe(COPYRIGHT_NOTICE + '\n') + }) + + it('stays silent when the header is already present', () => { + const reports = lint(COPYRIGHT_NOTICE + '\n' + CLEAN_SOURCE) + expect(reports).toHaveLength(0) + }) + + it('declares meta.fixable so oxlint accepts its fixer', () => { + expect(plugin.rules.notice.meta?.fixable).toBe('code') + }) + }) +}) diff --git a/scripts/oxlint/no-relative-imports-plugin.mjs b/scripts/oxlint/no-relative-imports-plugin.mjs new file mode 100644 index 0000000000..6cc5c1aafc --- /dev/null +++ b/scripts/oxlint/no-relative-imports-plugin.mjs @@ -0,0 +1,190 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import fs from 'node:fs' +import path from 'node:path' + +/** + * An oxlint JS-plugin that checks against local relative imports from another package. + * + * Reimplementation of `scripts/eslint/no-relative-imports-plugin.mjs` for oxlint's alpha + * JS-plugin system (https://oxc.rs/docs/guide/usage/linter/js-plugins.html). Oxlint's JS-plugin + * `context` does not provide `eslint-module-utils`'s resolver, so this version walks up from + * each side of a relative import to the nearest `package.json` using plain `fs`/`path` instead. + * + * This code will fail: + * `import { abc } from '../../packages/ui-i18n'` + * + * This code is OK: + * `import { abc } from '@instructure/ui-i18n'` + * + * Usage (in `.oxlintrc.json`): + * ```json + * { + * "jsPlugins": ["./scripts/oxlint/no-relative-imports-plugin.mjs"], + * "rules": { "instructure/no-relative-imports": "error" } + * } + * ``` + */ + +// from https://github.com/import-js/eslint-plugin-import/blob/main/src/core/importType.js#L48 +function isRelativeToParent(name) { + return (/^\.\.$|^\.\.[\\/]/).test(name) +} + +function isIndex(name) { + const indexFiles = ['.', './', './index', './index.js'] + return indexFiles.indexOf(name) !== -1 +} + +function isRelativeToSibling(name) { + return (/^\.[\\/]/).test(name) +} + +function isImportParentOrIndexOrSibling(name) { + if (isRelativeToParent(name)) return true + if (isIndex(name)) return true + if (isRelativeToSibling(name)) return true + return false +} + +// Walks up from `startPath` to the nearest directory that actually exists on disk - +// `startPath` itself may not exist yet (e.g. an import path resolved without an extension). +function nearestExistingDir(startPath) { + let dir = startPath + while (dir && !fs.existsSync(dir)) { + dir = path.dirname(dir) + } + if (dir && fs.existsSync(dir) && !fs.statSync(dir).isDirectory()) { + dir = path.dirname(dir) + } + return dir +} + +/** + * Walks up from `startPath` to find the nearest named `package.json`. + * Exported for direct unit testing (see `__node_tests__/no-relative-imports-plugin.test.ts`). + */ +export function findNamedPackage(startPath) { + let dir = nearestExistingDir(startPath) + while (dir) { + const pkgPath = path.join(dir, 'package.json') + if (fs.existsSync(pkgPath)) { + try { + const packageJson = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) + if (packageJson.name) { + return { path: dir, packageJson } + } + } catch { + // malformed package.json - keep walking up + } + } + const parent = path.dirname(dir) + if (parent === dir) break + dir = parent + } + return { path: startPath, packageJson: null } +} + +/** + * Pure rule logic, independent of oxlint's context/AST shape, so it can be unit-tested directly. + * Returns the violation message, or null when the import is fine. + */ +export function checkImportForRelativePackage(importPath, contextFilename) { + if (!isImportParentOrIndexOrSibling(importPath)) return null + if (!contextFilename) return null + const resolvedImport = path.resolve(path.dirname(contextFilename), importPath) + const importPkg = findNamedPackage(resolvedImport) + const contextPkg = findNamedPackage(contextFilename) + if ( + importPkg.packageJson && + contextPkg.packageJson && + importPkg.packageJson.name !== contextPkg.packageJson.name + ) { + const importBaseName = path.basename(importPath) + const importRoot = path.dirname(importPkg.path) + const properImport = path.join( + importPkg.packageJson.name, + importBaseName === path.basename(importRoot) ? '' : importBaseName + ) + return ( + 'Relative import from another package is not allowed. ' + + `Use "${properImport}" instead of "${importPath}"` + ) + } + return null +} + +function isStaticRequire(node) { + return ( + node && + node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'require' && + node.arguments.length === 1 && + node.arguments[0].type === 'Literal' && + typeof node.arguments[0].value === 'string' + ) +} + +// `meta.name` becomes the rule namespace prefix oxlint derives for a bare jsPlugins path entry +// (e.g. "instructure/no-relative-imports"), analogous to the original `@instructure` ESLint +// plugin scope used in eslint.config.mjs's `@instructure/no-relative-imports`. +const plugin = { + meta: { + name: 'instructure', + version: '1.0.0' + }, + rules: { + 'no-relative-imports': { + create(context) { + return { + ImportDeclaration(node) { + const message = checkImportForRelativePackage( + node.source.value, + context.filename + ) + if (message) { + context.report({ node: node.source, message }) + } + }, + CallExpression(node) { + if (isStaticRequire(node)) { + const [firstArgument] = node.arguments + const message = checkImportForRelativePackage( + firstArgument.value, + context.filename + ) + if (message) { + context.report({ node: firstArgument, message }) + } + } + } + } + } + } + } +} + +export default plugin diff --git a/scripts/oxlint/notice-plugin.mjs b/scripts/oxlint/notice-plugin.mjs new file mode 100644 index 0000000000..4c069d70cd --- /dev/null +++ b/scripts/oxlint/notice-plugin.mjs @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * An oxlint JS-plugin that reimplements `eslint-plugin-notice`'s `notice/notice` rule + * (https://oxc.rs/docs/guide/usage/linter/js-plugins.html) for this repo's exact config: + * + * ```js + * 'notice/notice': ['error', { mustMatch: 'The MIT License', template: COPYRIGHT_NOTICE }] + * ``` + * + * `eslint-plugin-notice`'s default behavior (see its `utils.js#resolveOptions`) that this + * mirrors: + * - `chars` defaults to 1000: only the first 1000 characters of the file are checked. + * - a string `mustMatch` is compiled into a `RegExp` and tested against those characters. + * - `onNonMatchingHeader` defaults to "prepend": the fixer always inserts the template at the + * very start of the file, regardless of whether a (non-matching) header comment exists. + * + * Usage (in `.oxlintrc.json`): + * ```json + * { + * "jsPlugins": ["./scripts/oxlint/notice-plugin.mjs"], + * "rules": { "notice/notice": "error" } + * } + * ``` + */ + +export const COPYRIGHT_NOTICE = '/*\n' + + ' * The MIT License (MIT)\n' + + ' *\n' + + ' * Copyright (c) 2015 - present Instructure, Inc.\n' + + ' *\n' + + ' * Permission is hereby granted, free of charge, to any person obtaining a copy\n' + + ' * of this software and associated documentation files (the "Software"), to deal\n' + + ' * in the Software without restriction, including without limitation the rights\n' + + ' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n' + + ' * copies of the Software, and to permit persons to whom the Software is\n' + + ' * furnished to do so, subject to the following conditions:\n' + + ' *\n' + + ' * The above copyright notice and this permission notice shall be included in all\n' + + ' * copies or substantial portions of the Software.\n' + + ' *\n' + + ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n' + + ' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n' + + ' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n' + + ' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n' + + ' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n' + + ' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n' + + ' * SOFTWARE.\n' + + ' */' + +const MUST_MATCH = 'The MIT License' +const CHARS = 1000 + +/** + * Pure rule logic, independent of oxlint's context/AST shape, so it can be unit-tested directly. + */ +export function hasNoticeHeader(sourceText) { + const leading = String(sourceText).replace(/\r\n/g, '\n').slice(0, CHARS) + return new RegExp(MUST_MATCH).test(leading) +} + +/** + * Prepends the real MIT header to `sourceText`. Mirrors eslint-plugin-notice's default + * `onNonMatchingHeader: "prepend"` behavior - always inserted at the very start of the file. + */ +export function insertNoticeHeader(sourceText) { + return COPYRIGHT_NOTICE + '\n' + sourceText +} + +// `meta.name` becomes the rule namespace prefix oxlint derives for a bare jsPlugins path entry, +// chosen here as "notice" so the resulting rule id ("notice/notice") matches the original +// `notice/notice` rule id from `eslint-plugin-notice` used in eslint.config.mjs. +const plugin = { + meta: { + name: 'notice', + version: '1.0.0' + }, + rules: { + notice: { + meta: { fixable: 'code' }, + create(context) { + return { + Program(node) { + const sourceCode = context.sourceCode + const text = sourceCode.getText() + if (hasNoticeHeader(text)) return + context.report({ + node, + message: 'Missing notice header', + fix(fixer) { + return fixer.insertTextBefore(node, COPYRIGHT_NOTICE + '\n') + } + }) + } + } + } + } + } +} + +export default plugin From cdeaf0e30090cf1b6c3e30cb129f05d485376049 Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Wed, 15 Jul 2026 14:12:37 +0200 Subject: [PATCH 3/8] feat: replace ESLint with oxlint across the workspace Wire oxlint into lint-staged, ui-scripts lint, and regression-test's lint script, replacing ESLint everywhere it ran. Remove ESLint's config files, its now-superseded custom plugin, and every dependency with no remaining consumer: eslint, @eslint/js, @vitest/eslint-plugin, eslint-config-prettier, eslint-import-resolver-node, eslint-module-utils, eslint-plugin-compat, eslint-plugin-jsx-a11y, eslint-plugin-notice, globals, and typescript-eslint. Keep eslint-plugin-react and read-package-up: both are still runtime dependencies of oxlint's jsPlugins bridge and custom rules, respectively. --- eslint.config.mjs | 230 --------- package.json | 15 +- .../lib/__node_tests__/lint.test.ts | 12 +- packages/ui-scripts/lib/commands/lint.ts | 2 +- packages/ui-scripts/package.json | 2 +- pnpm-lock.yaml | 465 +----------------- regression-test/eslint.config.mjs | 28 -- regression-test/package.json | 2 +- scripts/eslint/no-relative-imports-plugin.mjs | 166 ------- 9 files changed, 13 insertions(+), 909 deletions(-) delete mode 100644 eslint.config.mjs delete mode 100644 regression-test/eslint.config.mjs delete mode 100644 scripts/eslint/no-relative-imports-plugin.mjs diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 7e9e4ac2d7..0000000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,230 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import tseslint from 'typescript-eslint' -import eslint from '@eslint/js' -import reactPlugin from 'eslint-plugin-react' -import jsxA11y from 'eslint-plugin-jsx-a11y' -import notice from "eslint-plugin-notice" -import eslintConfigPrettier from "eslint-config-prettier" -import vitest from "@vitest/eslint-plugin" -import globals from 'globals' -import instructurePlugin from './scripts/eslint/no-relative-imports-plugin.mjs' - -const COPYRIGHT_NOTICE = "/*\n" + - " * The MIT License (MIT)\n" + - " *\n" + - " * Copyright (c) 2015 - present Instructure, Inc.\n" + - " *\n" + - " * Permission is hereby granted, free of charge, to any person obtaining a copy\n" + - " * of this software and associated documentation files (the \"Software\"), to deal\n" + - " * in the Software without restriction, including without limitation the rights\n" + - " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" + - " * copies of the Software, and to permit persons to whom the Software is\n" + - " * furnished to do so, subject to the following conditions:\n" + - " *\n" + - " * The above copyright notice and this permission notice shall be included in all\n" + - " * copies or substantial portions of the Software.\n" + - " *\n" + - " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" + - " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" + - " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" + - " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" + - " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" + - " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" + - " * SOFTWARE.\n" + - " */" - -const NODE_PACKAGES = [ - 'browserslist-config-instui', - 'ui-babel-preset', - 'ui-codemods', - 'ui-stylelint-config', - 'ui-scripts', - 'ui-webpack-config', - 'command-utils', - 'instui-cli', - 'babel-plugin-transform-imports' -].join("|") - -const finalConfig = tseslint.config( - { - // ignoring is a mess in ESLint, if these are put here it will be ignored globally - // https://github.com/eslint/eslint/discussions/18304#discussioncomment-9069706 - ignores: [ // global ignores - "**/node_modules/**", - "packages/ui-codemods/lib/__node_tests__/__testfixtures__/**", - "**/types/**", - "**/es/**", - "packages/!(" + NODE_PACKAGES + ")/lib/**/*", - "/regression-test/**", - "/coverage/**", - "**/stylelint.config.js", - "**/babel.config.js", - "**/.next/**", - "**/next-env.d.ts" - ] - }, - eslint.configs.recommended, - ...tseslint.configs.recommended, - ...instructurePlugin.configs.recommended, - { - name: "instUI-eslint-config", - linterOptions: { - reportUnusedDisableDirectives: "error" - }, - languageOptions: { - ...reactPlugin.configs.flat.recommended.languageOptions, - }, - plugins: { - ...reactPlugin.configs.flat['jsx-runtime'].plugins, - notice - }, - rules: { - ...reactPlugin.configs.flat.recommended.rules, - ...eslint.configs.recommended.rules, - ...eslintConfigPrettier.rules, - // value is 'off' or 'warn' or 'error' - // https://eslint.org/docs/latest/use/configure/rules#rule-severities - // overrides for typescript-eslint - '@typescript-eslint/ban-ts-comment': ['error', - { 'ts-ignore': 'allow-with-description' } - ], - '@typescript-eslint/no-require-imports': 'off', // https://typescript-eslint.io/rules/no-require-imports - '@typescript-eslint/no-unused-expressions': 'warn', - '@typescript-eslint/no-empty-function': 'warn', - '@typescript-eslint/no-explicit-any': 'warn', - '@typescript-eslint/no-unused-vars': 'warn', - '@typescript-eslint/explicit-module-boundary-types': 'off', // https://typescript-eslint.io/rules/explicit-module-boundary-types - // overrides for eslint-plugin-react - 'react/no-deprecated': 'warn', - 'react/display-name': 'error', - 'react/no-find-dom-node': 'warn', - 'react/forbid-foreign-prop-types': 'error', - 'react/no-danger': 'error', - 'react/prop-types': ['error', { skipUndeclared: true }], - 'react/require-default-props': 'warn', - 'react/no-typos': 'error', - 'react/no-unknown-property': ['error', { ignore: ['css', 'componentRef'] }], - // overrides for eslint-plugin-notice - 'notice/notice': ['error', - { - mustMatch: 'The MIT License', - template: COPYRIGHT_NOTICE - } - ], - // overrides for built-in rules - 'no-undef': 'off', // https://eslint.org/docs/latest/rules/no-undef#handled_by_typescript - 'no-console': ['error', { allow: ['warn', 'error', 'time', 'timeEnd'] }], - 'no-unused-vars': ['warn', {args: 'none', ignoreRestSiblings: true}], - 'no-shadow-restricted-names': 'error', - semi: ['error', 'never'], - 'semi-spacing': ['error', { before: false, after: true }], - 'no-trailing-spaces': 'error', - 'no-param-reassign': ['error', { props: true }], - 'no-restricted-imports': [ - 'error', - { - patterns: ['*/src', '@instructure/ui-*/lib', '@instructure/ui-*/es'] - } - ], - 'no-unused-expressions': [ // https://typescript-eslint.io/rules/no-unused-expressions - 'warn', - { - allowShortCircuit: true, - allowTernary: true, - allowTaggedTemplates: true - } - ], - "react/react-in-jsx-scope": "off" - }, - settings: { - react: { - version: process.env.REACT_VERSION || '18.3.1' - } - } - }, - { - // Vitest tests - files: [ - '**/__tests__/**' - ], - plugins: { - vitest - }, - rules: { - ...vitest.configs.recommended.rules, - 'vitest/valid-title': 'warn', - 'vitest/no-commented-out-tests': 'warn' - } - }, - { // Do not check unit tests for a11y - ignores: [ - '**/__tests__/**' - ], - plugins: { - 'jsx-a11y': jsxA11y, - }, - rules: { - ...jsxA11y.configs.recommended.rules, - } - }, - {// Node scripts - files: [ - "packages/+(" + NODE_PACKAGES + ")/**/*", - 'packages/__docs__/**/*.js', // docs is a mess - 'packages/__docs__/**/*.mjs', // docs is a mess - '!packages/**' // every file not in packages - ], - rules: { - "no-console": "off" - }, - languageOptions: { - globals: { - ...globals.node - } - } - }, - {// ui-codemods in Vitest TODO convert fully to TS to remove this part - files: [ - 'packages/ui-codemods/**/*.js', - ], - languageOptions: { - globals: { - ...globals.jest - } - } - }, - { - // plain JS files anywhere - files:['**/*.{js,mjs,cjs,jsx,mjsx}'], - rules: { 'no-undef': 'error' } - } -) - -// code to print out the whole config -//import { inspect } from 'util' -//throw (new Error(inspect(tsEslint.configs.recommended))) - -export default finalConfig diff --git a/package.json b/package.json index aaf549f8b4..8377a9546d 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "@commitlint/config-conventional": "^21.2.0", "@emotion/cache": "^11.14.0", "@emotion/react": "^11.14.0", - "@eslint/js": "^9.39.4", "@instructure/browserslist-config-instui": "workspace:*", "@instructure/ui-babel-preset": "workspace:*", "@instructure/ui-scripts": "workspace:*", @@ -78,7 +77,6 @@ "@vitejs/plugin-react": "^5.2.0", "@vitest/browser": "4.1.9", "@vitest/browser-playwright": "4.1.9", - "@vitest/eslint-plugin": "^1.6.20", "@vitest/ui": "4.1.9", "babel-loader": "^10.1.1", "babel-plugin-add-import-extension": "^1.6.0", @@ -92,15 +90,7 @@ "cz-git": "^1.13.1", "esbuild": "^0.28.1", "esbuild-loader": "^4.5.0", - "eslint": "^9.39.4", - "eslint-config-prettier": "^10.1.8", - "eslint-import-resolver-node": "^0.4.0", - "eslint-module-utils": "2.13.0", - "eslint-plugin-compat": "^7.0.2", - "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-notice": "^1.0.0", "eslint-plugin-react": "^7.37.5", - "globals": "^17.7.0", "husky": "^9.1.7", "jsdom": "^29.1.1", "lerna": "9.0.7", @@ -112,7 +102,6 @@ "react": "18.3.1", "read-package-up": "^12.0.0", "typescript": "6.0.3", - "typescript-eslint": "^8.62.1", "vitest": "^4.1.9", "vitest-browser-react": "2.2.0", "webpack": "^5.107.2" @@ -121,8 +110,6 @@ "scripts": "The '--' at the end of commands is needed so user parameters are passed forward", "danger": "^11.3.1 -- add this back if we use it in pr-validation.yml", "tar": "Lerna 8 needs tar for this fixed(?) bug: https://github.com/lerna/lerna/issues/4005", - "eslint-import-resolver-typescript": "^3.6.1 not supported by ESLint 9", - "eslint-plugin-import-x": "^3.1.0 not supported by ESLint 9", "@types/jest": "needed because https://github.com/testing-library/jest-dom/issues/544 recheck if fixed", "git-raw-commits>dargs": "Force dargs@7.0.0 (CommonJS) for git-raw-commits@3.0.0 used by lerna. pnpm hoisting was causing ESM dargs@8.1.0 to be resolved instead, breaking 'pnpm run bump' with 'TypeError: dargs is not a function'" }, @@ -138,7 +125,7 @@ }, "lint-staged": { "*.{js,ts,tsx}": [ - "eslint --quiet", + "oxlint -c .oxlintrc.json --fix", "prettier --write" ], "*.{json,jsx,md,mdx,html}": [ diff --git a/packages/ui-scripts/lib/__node_tests__/lint.test.ts b/packages/ui-scripts/lib/__node_tests__/lint.test.ts index af6fd3fe09..1a129643bb 100644 --- a/packages/ui-scripts/lib/__node_tests__/lint.test.ts +++ b/packages/ui-scripts/lib/__node_tests__/lint.test.ts @@ -40,7 +40,7 @@ describe('lint handler', () => { it('lints "." when no positional paths are provided', async () => { await lint.handler({ _: ['lint'] }) - expect(runMock).toHaveBeenCalledWith('eslint', ['.']) + expect(runMock).toHaveBeenCalledWith('oxlint', ['.']) }) it('keeps only .js, .jsx, .ts, .tsx paths', async () => { @@ -56,23 +56,23 @@ describe('lint handler', () => { expect(runMock).not.toHaveBeenCalled() }) - it('passes --fix to eslint when argv.fix is true', async () => { + it('passes --fix to oxlint when argv.fix is true', async () => { await lint.handler({ _: ['lint', 'a.ts'], fix: true }) - expect(runMock).toHaveBeenCalledWith('eslint', ['a.ts', '--fix']) + expect(runMock).toHaveBeenCalledWith('oxlint', ['a.ts', '--fix']) }) it('does not pass --fix when argv.fix is false', async () => { await lint.handler({ _: ['lint', 'a.ts'], fix: false }) - expect(runMock).toHaveBeenCalledWith('eslint', ['a.ts']) + expect(runMock).toHaveBeenCalledWith('oxlint', ['a.ts']) }) it('does not pass --fix when argv.fix is undefined', async () => { await lint.handler({ _: ['lint', 'a.ts'] }) - expect(runMock).toHaveBeenCalledWith('eslint', ['a.ts']) + expect(runMock).toHaveBeenCalledWith('oxlint', ['a.ts']) }) it('appends --fix even when linting the default "." path', async () => { await lint.handler({ _: ['lint'], fix: true }) - expect(runMock).toHaveBeenCalledWith('eslint', ['.', '--fix']) + expect(runMock).toHaveBeenCalledWith('oxlint', ['.', '--fix']) }) }) diff --git a/packages/ui-scripts/lib/commands/lint.ts b/packages/ui-scripts/lib/commands/lint.ts index d63a2eadd9..31c29fb419 100644 --- a/packages/ui-scripts/lib/commands/lint.ts +++ b/packages/ui-scripts/lib/commands/lint.ts @@ -43,7 +43,7 @@ export default { ) } if (jspaths.length) { - runCommandSync('eslint', argv.fix ? [...jspaths, '--fix'] : jspaths) + runCommandSync('oxlint', argv.fix ? [...jspaths, '--fix'] : jspaths) } } } diff --git a/packages/ui-scripts/package.json b/packages/ui-scripts/package.json index 773d94eb00..7f47b9cede 100644 --- a/packages/ui-scripts/package.json +++ b/packages/ui-scripts/package.json @@ -40,7 +40,7 @@ "yargs": "^18.0.0" }, "peerDependencies": { - "eslint": "^9", + "oxlint": "^1.72.0", "react": ">=18 <=19", "webpack": "^5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22d9a32d30..dbc2bba445 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,9 +33,6 @@ importers: '@emotion/react': specifier: ^11.14.0 version: 11.14.0(@types/react@18.3.26)(react@18.3.1) - '@eslint/js': - specifier: ^9.39.4 - version: 9.39.4 '@instructure/browserslist-config-instui': specifier: workspace:* version: link:packages/browserslist-config-instui @@ -78,9 +75,6 @@ importers: '@vitest/browser-playwright': specifier: 4.1.9 version: 4.1.9(playwright@1.61.1)(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.9) - '@vitest/eslint-plugin': - specifier: ^1.6.20 - version: 1.6.23(@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)(vitest@4.1.9) '@vitest/ui': specifier: 4.1.9 version: 4.1.9(vitest@4.1.9) @@ -120,33 +114,9 @@ importers: esbuild-loader: specifier: ^4.5.0 version: 4.5.0(webpack@5.107.2(esbuild@0.28.1)) - eslint: - specifier: ^9.39.4 - version: 9.39.4(jiti@2.6.1) - eslint-config-prettier: - specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.4(jiti@2.6.1)) - eslint-import-resolver-node: - specifier: ^0.4.0 - version: 0.4.0(supports-color@8.1.1) - eslint-module-utils: - specifier: 2.13.0 - version: 2.13.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-node@0.4.0(supports-color@8.1.1))(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1) - eslint-plugin-compat: - specifier: ^7.0.2 - version: 7.0.2(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-jsx-a11y: - specifier: ^6.10.2 - version: 6.10.2(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-notice: - specifier: ^1.0.0 - version: 1.0.0(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-react: specifier: ^7.37.5 version: 7.37.5(eslint@9.39.4(jiti@2.6.1)) - globals: - specifier: ^17.7.0 - version: 17.7.0 husky: specifier: ^9.1.7 version: 9.1.7 @@ -180,9 +150,6 @@ importers: typescript: specifier: 6.0.3 version: 6.0.3 - typescript-eslint: - specifier: ^8.62.1 - version: 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) vitest: specifier: ^4.1.9 version: 4.1.9(@types/node@24.1.0)(@vitest/browser-playwright@4.1.9)(@vitest/ui@4.1.9)(jsdom@29.1.1)(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0)) @@ -3938,9 +3905,6 @@ importers: dprint: specifier: ^0.55.1 version: 0.55.1 - eslint: - specifier: ^9 - version: 9.39.4(jiti@2.6.1) http-server: specifier: ^14.1.1 version: 14.1.1(supports-color@8.1.1) @@ -3956,6 +3920,9 @@ importers: lucide-react: specifier: 1.23.0 version: 1.23.0(react@18.3.1) + oxlint: + specifier: ^1.72.0 + version: 1.73.0 pixelmatch: specifier: ^7.2.0 version: 7.2.0 @@ -7328,12 +7295,6 @@ packages: '@marijn/find-cluster-break@1.0.2': resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} - '@mdn/browser-compat-data@5.7.6': - resolution: {integrity: sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==} - - '@mdn/browser-compat-data@6.1.5': - resolution: {integrity: sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==} - '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} @@ -8151,65 +8112,6 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@typescript-eslint/eslint-plugin@8.64.0': - resolution: {integrity: sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.64.0 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/parser@8.64.0': - resolution: {integrity: sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/project-service@8.64.0': - resolution: {integrity: sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/scope-manager@8.64.0': - resolution: {integrity: sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.64.0': - resolution: {integrity: sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/type-utils@8.64.0': - resolution: {integrity: sha512-XWG4Fmmv/6SvyS9nH8jWrKs6terwJvE8cyRt1CzYYqzp9OrPhCT4cMc/f7C6RZCwG+qMmiffJS1/qJP8G1URtg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/types@8.64.0': - resolution: {integrity: sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.64.0': - resolution: {integrity: sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/utils@8.64.0': - resolution: {integrity: sha512-aJUGVB3+U0htrrCjoA8qukw8cm8fNCGAxK/tVoS70k8aeb7DETKeFozRiVFIwEeN9WJLsjaP3ph8I60tY2XZoQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/visitor-keys@8.64.0': - resolution: {integrity: sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@5.2.0': resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8227,22 +8129,6 @@ packages: peerDependencies: vitest: 4.1.9 - '@vitest/eslint-plugin@1.6.23': - resolution: {integrity: sha512-CbrXxQpIUMbeyylGlxaxTgnWYM44et4Nx58swl7+vrTyC9Ttx+hQoy8BGCregbbZ08K5qFhRHeoad1VvERUbkg==} - engines: {node: '>=18'} - peerDependencies: - '@typescript-eslint/eslint-plugin': '*' - eslint: '>=8.57.0' - typescript: '>=5.0.0' - vitest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - typescript: - optional: true - vitest: - optional: true - '@vitest/expect@4.1.9': resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} @@ -8546,12 +8432,6 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - ast-metadata-inferer@0.8.1: - resolution: {integrity: sha512-ht3Dm6Zr7SXv6t1Ra6gFo0+kLDglHGrEbYihTkcycrbHw7WCcuhBzPlJYHEsIpycaUwzsJHje+vUcxXUX4ztTA==} - - ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} @@ -8587,10 +8467,6 @@ packages: axios@1.12.0: resolution: {integrity: sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==} - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - babel-loader@10.1.1: resolution: {integrity: sha512-JwKSzk2kjIe7mgPK+/lyZ2QAaJcpahNAdM+hgR2HI8D0OJVkdj8Rl6J3kaLYki9pwF7P2iWnD8qVv80Lq1ABtg==} engines: {node: ^18.20.0 || ^20.10.0 || >=22.0.0} @@ -9248,9 +9124,6 @@ packages: resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} engines: {node: '>=0.12'} - damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dargs@7.0.0: resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} engines: {node: '>=8'} @@ -9659,53 +9532,6 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - eslint-config-prettier@10.1.8: - resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-import-resolver-node@0.4.0: - resolution: {integrity: sha512-wV22NewD4lwrMp94THds3/MjW7qPYupLj3wxLZCYkKrSLfVslRS/7lcbogiEwn9oT4cunDDCsTiBo/V16WlEUQ==} - - eslint-module-utils@2.13.0: - resolution: {integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - - eslint-plugin-compat@7.0.2: - resolution: {integrity: sha512-gN8hF+4NzMsHUbr4m/TYZK0FtW3DcV4g8rXpTsY2EV5xiRD8jsilUlB9lNSkGGX0veDCxMhKSWbSd+faJByQDA==} - engines: {node: '>=22.x'} - peerDependencies: - eslint: ^9.0.0 || ^10.0.0 - - eslint-plugin-jsx-a11y@6.10.2: - resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - - eslint-plugin-notice@1.0.0: - resolution: {integrity: sha512-M3VLQMZzZpvfTZ/vy9FmClIKq5rLBbQpM0KgfLZPJPrVXpmJYeobmmb+lfJzHWdNm8PWwvw8KlafQWo2N9xx1Q==} - peerDependencies: - eslint: '>=3.0.0' - eslint-plugin-react@7.37.5: resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} @@ -9728,10 +9554,6 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@5.0.1: - resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@9.39.4: resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -10180,14 +10002,6 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.15.0: - resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} - engines: {node: '>=18'} - - globals@17.7.0: - resolution: {integrity: sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==} - engines: {node: '>=18'} - globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -10261,10 +10075,6 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hasown@2.0.4: - resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} - engines: {node: '>= 0.4'} - he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true @@ -10568,10 +10378,6 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - is-core-module@2.16.2: - resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} - engines: {node: '>= 0.4'} - is-data-view@1.0.2: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} @@ -10957,13 +10763,6 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} - - language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} - launch-editor@2.14.1: resolution: {integrity: sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==} @@ -11048,9 +10847,6 @@ packages: lodash.map@4.6.0: resolution: {integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -11208,9 +11004,6 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - metric-lcs@0.1.2: - resolution: {integrity: sha512-+TZ5dUDPKPJaU/rscTzxyN8ZkX7eAVLAiQU/e+YINleXPv03SCmJShaMT1If1liTH8OcmWXZs0CmzCBRBLcMpA==} - microbuffer@1.0.0: resolution: {integrity: sha512-O/SUXauVN4x6RaEJFqSPcXNtLFL+QzJHKZlyDVYFwcDDRVca3Fa/37QXXC+4zAGGa4YhHrHxKXuuHvLDIQECtA==} @@ -12244,11 +12037,6 @@ packages: engines: {node: '>= 0.4'} hasBin: true - resolve@2.0.0-next.7: - resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} - engines: {node: '>= 0.4'} - hasBin: true - restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -12593,10 +12381,6 @@ packages: resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} engines: {node: '>=20'} - string.prototype.includes@2.0.1: - resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} - engines: {node: '>= 0.4'} - string.prototype.matchall@4.0.12: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} @@ -12922,12 +12706,6 @@ packages: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} - ts-api-utils@2.5.0: - resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - tsconfig-paths@4.2.0: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} @@ -13023,13 +12801,6 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@8.64.0: - resolution: {integrity: sha512-0qg+pDNMnqYzqH9AnNK+39tejHvsShUOUUoRUgtnTGE7QuMZhiFDnozq8nHJVq+Wae6NMLKNWLg5WmkcC/ndyQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -15603,10 +15374,6 @@ snapshots: '@marijn/find-cluster-break@1.0.2': {} - '@mdn/browser-compat-data@5.7.6': {} - - '@mdn/browser-compat-data@6.1.5': {} - '@napi-rs/wasm-runtime@0.2.4': dependencies: '@emnapi/core': 1.9.2 @@ -16446,97 +16213,6 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.64.0 - '@typescript-eslint/type-utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.64.0 - eslint: 9.39.4(jiti@2.6.1) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.64.0 - '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.64.0 - debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.4(jiti@2.6.1) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.64.0(typescript@6.0.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@6.0.3) - '@typescript-eslint/types': 8.64.0 - debug: 4.4.3(supports-color@8.1.1) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.64.0': - dependencies: - '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/visitor-keys': 8.64.0 - - '@typescript-eslint/tsconfig-utils@8.64.0(typescript@6.0.3)': - dependencies: - typescript: 6.0.3 - - '@typescript-eslint/type-utils@8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)': - dependencies: - '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.4(jiti@2.6.1) - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.64.0': {} - - '@typescript-eslint/typescript-estree@8.64.0(typescript@6.0.3)': - dependencies: - '@typescript-eslint/project-service': 8.64.0(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@6.0.3) - '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/visitor-keys': 8.64.0 - debug: 4.4.3(supports-color@8.1.1) - minimatch: 10.2.5 - semver: 7.8.5 - tinyglobby: 0.2.15 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.64.0 - '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.64.0': - dependencies: - '@typescript-eslint/types': 8.64.0 - eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.0 @@ -16579,18 +16255,6 @@ snapshots: - utf-8-validate - vite - '@vitest/eslint-plugin@1.6.23(@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3)(vitest@4.1.9)': - dependencies: - '@typescript-eslint/scope-manager': 8.64.0 - '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1) - optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - typescript: 6.0.3 - vitest: 4.1.9(@types/node@24.1.0)(@vitest/browser-playwright@4.1.9)(@vitest/ui@4.1.9)(jsdom@29.1.1)(vite@7.3.1(@types/node@24.1.0)(jiti@2.6.1)(terser@5.48.0)(yaml@2.9.0)) - transitivePeerDependencies: - - supports-color - '@vitest/expect@4.1.9': dependencies: '@standard-schema/spec': 1.1.0 @@ -16938,12 +16602,6 @@ snapshots: assertion-error@2.0.1: {} - ast-metadata-inferer@0.8.1: - dependencies: - '@mdn/browser-compat-data': 5.7.6 - - ast-types-flow@0.0.8: {} - ast-types@0.16.1: dependencies: tslib: 2.8.1 @@ -16974,8 +16632,6 @@ snapshots: transitivePeerDependencies: - debug - axobject-query@4.1.0: {} - babel-loader@10.1.1(@babel/core@7.29.0)(webpack@5.107.2(esbuild@0.28.1)(postcss@8.5.8)): dependencies: '@babel/core': 7.29.0 @@ -17785,8 +17441,6 @@ snapshots: es5-ext: 0.10.64 type: 2.7.3 - damerau-levenshtein@1.0.8: {} - dargs@7.0.0: {} dashdash@1.14.1: @@ -18288,65 +17942,6 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.6.1)): - dependencies: - eslint: 9.39.4(jiti@2.6.1) - - eslint-import-resolver-node@0.4.0(supports-color@8.1.1): - dependencies: - debug: 3.2.7(supports-color@8.1.1) - is-core-module: 2.16.2 - resolve: 2.0.0-next.7 - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.13.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-node@0.4.0(supports-color@8.1.1))(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1): - dependencies: - debug: 3.2.7(supports-color@8.1.1) - optionalDependencies: - '@typescript-eslint/parser': 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1) - eslint-import-resolver-node: 0.4.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - eslint-plugin-compat@7.0.2(eslint@9.39.4(jiti@2.6.1)): - dependencies: - '@mdn/browser-compat-data': 6.1.5 - ast-metadata-inferer: 0.8.1 - browserslist: 4.28.4 - eslint: 9.39.4(jiti@2.6.1) - find-up: 5.0.0 - globals: 15.15.0 - lodash.memoize: 4.1.2 - semver: 7.8.5 - - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)): - dependencies: - aria-query: 5.3.2 - array-includes: 3.1.9 - array.prototype.flatmap: 1.3.3 - ast-types-flow: 0.0.8 - axe-core: 4.12.1 - axobject-query: 4.1.0 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 9.39.4(jiti@2.6.1) - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.5 - object.fromentries: 2.0.8 - safe-regex-test: 1.1.0 - string.prototype.includes: 2.0.1 - - eslint-plugin-notice@1.0.0(eslint@9.39.4(jiti@2.6.1)): - dependencies: - eslint: 9.39.4(jiti@2.6.1) - find-root: 1.1.0 - lodash: 4.18.1 - metric-lcs: 0.1.2 - eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): dependencies: array-includes: 3.1.9 @@ -18383,8 +17978,6 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint-visitor-keys@5.0.1: {} - eslint@9.39.4(jiti@2.6.1): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) @@ -18944,10 +18537,6 @@ snapshots: globals@14.0.0: {} - globals@15.15.0: {} - - globals@17.7.0: {} - globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -19026,10 +18615,6 @@ snapshots: dependencies: function-bind: 1.1.2 - hasown@2.0.4: - dependencies: - function-bind: 1.1.2 - he@1.2.0: {} hoist-non-react-statics@3.3.2: @@ -19387,10 +18972,6 @@ snapshots: dependencies: hasown: 2.0.2 - is-core-module@2.16.2: - dependencies: - hasown: 2.0.4 - is-data-view@1.0.2: dependencies: call-bound: 1.0.4 @@ -19786,12 +19367,6 @@ snapshots: kind-of@6.0.3: {} - language-subtag-registry@0.3.23: {} - - language-tags@1.0.9: - dependencies: - language-subtag-registry: 0.3.23 - launch-editor@2.14.1: dependencies: picocolors: 1.1.1 @@ -19976,8 +19551,6 @@ snapshots: lodash.map@4.6.0: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} lodash.once@4.1.1: {} @@ -20173,8 +19746,6 @@ snapshots: methods@1.1.2: {} - metric-lcs@0.1.2: {} - microbuffer@1.0.0: {} micromatch@4.0.8: @@ -21302,15 +20873,6 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - resolve@2.0.0-next.7: - dependencies: - es-errors: 1.3.0 - is-core-module: 2.16.2 - node-exports-info: 1.6.0 - object-keys: 1.1.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - restore-cursor@3.1.0: dependencies: onetime: 5.1.2 @@ -21740,12 +21302,6 @@ snapshots: get-east-asian-width: 1.5.0 strip-ansi: 7.2.0 - string.prototype.includes@2.0.1: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 @@ -22083,10 +21639,6 @@ snapshots: trim-newlines@3.0.1: {} - ts-api-utils@2.5.0(typescript@6.0.3): - dependencies: - typescript: 6.0.3 - tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 @@ -22197,17 +21749,6 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/parser': 8.64.0(eslint@9.39.4(jiti@2.6.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.64.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.64.0(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.3) - eslint: 9.39.4(jiti@2.6.1) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - typescript@5.9.3: {} typescript@6.0.3: {} diff --git a/regression-test/eslint.config.mjs b/regression-test/eslint.config.mjs deleted file mode 100644 index 97a42d6719..0000000000 --- a/regression-test/eslint.config.mjs +++ /dev/null @@ -1,28 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -// eslint-disable-next-line @instructure/no-relative-imports -import cfg from '../eslint.config.mjs' - -export default cfg diff --git a/regression-test/package.json b/regression-test/package.json index eb1ab7f521..c7c34f6672 100644 --- a/regression-test/package.json +++ b/regression-test/package.json @@ -7,7 +7,7 @@ "dev": "next dev --webpack", "build": "next build --webpack", "start": "http-server out -p 3000 -s --no-dotfiles", - "lint": "eslint .", + "lint": "oxlint .", "cypress": "ELECTRON_EXTRA_LAUNCH_ARGS=--remote-debugging-port=9222 cypress run", "cypress-chrome": "cypress open --browser chrome" }, diff --git a/scripts/eslint/no-relative-imports-plugin.mjs b/scripts/eslint/no-relative-imports-plugin.mjs deleted file mode 100644 index 630322e96b..0000000000 --- a/scripts/eslint/no-relative-imports-plugin.mjs +++ /dev/null @@ -1,166 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import path from 'path' -import { readPackageUpSync } from 'read-package-up' -import { default as resolve } from 'eslint-module-utils/resolve' -import fs from 'fs' - -/** - * An ESLint plugin that checks against local relative imports from another package - * - * This code will fail: - * `import { abc } from '../../packages/ui-i18n'` - * - * This code is OK: - * `import { abc } from '@instructure/ui-i18n'` - * - * Usage: - * Add `instructurePlugin.configs.recommended` to your flat ESLint configuration - */ -const plugin = { - meta: { - name: "instructure-no-relative-imports-plugin", - version: "1.0.0" - }, - configs: {}, - rules: { - "no-relative-imports": { - create(context) { - return { - ImportDeclaration(node) { - checkImportForRelativePackage(node.source.value, node.source, context) - }, - CallExpression(node) { - if (isStaticRequire(node)) { - const [firstArgument] = node.arguments - checkImportForRelativePackage(firstArgument.value, firstArgument, context) - } - } - } - } - } - } -} - -function findNamedPackage(filePath) { - const found = readPackageUpSync({ - cwd: fs.realpathSync(filePath), - normalize: false - }) - if (found.packageJson && !found.packageJson.name) { - return findNamedPackage(path.join(found.path, '../..')) - } - return found -} - -function checkImportForRelativePackage(importPath, node, context) { - if (!isImportParentOrIndexOrSibling(importPath, context)) { - return - } - const resolvedImport = resolve.default(importPath, context) - const resolvedContext = context.getFilename() - if (!resolvedImport || !resolvedContext) { - return - } - const importPkg = findNamedPackage(resolvedImport) - const contextPkg = findNamedPackage(resolvedContext) - if ( - importPkg.packageJson && - contextPkg.packageJson && - importPkg.packageJson.name !== contextPkg.packageJson.name - ) { - const importBaseName = path.basename(importPath) - const importRoot = path.dirname(importPkg.path) - const properImport = path.join( - importPkg.packageJson.name, - importBaseName === path.basename(importRoot) ? '' : importBaseName - ) - context.report({ - node, - message: - 'Relative import from another package is not allowed. ' + - `Use "${properImport}" instead of "${importPath}"` - }) - } -} - -// from https://github.com/import-js/eslint-plugin-import/blob/main/src/core/importType.js#L48 -function isRelativeToParent(name) { - return (/^\.\.$|^\.\.[\\/]/).test(name) -} - -function isIndex(name) { - const indexFiles = ['.', './', './index', './index.js'] - return indexFiles.indexOf(name) !== -1 -} - -function isRelativeToSibling(name) { - return (/^\.[\\/]/).test(name) -} - -function isImportParentOrIndexOrSibling(name, context) { - const path = resolve.default(name, context) - const { settings } = context - if (isRelativeToParent(name, settings, path)) { return true } - if (isIndex(name, settings, path)) { return true } - if (isRelativeToSibling(name, settings, path)) { return true } - return false -} - -function isStaticRequire(node) { - return ( - node && - node.callee && - node.callee.type === 'Identifier' && - node.callee.name === 'require' && - node.arguments.length === 1 && - node.arguments[0].type === 'Literal' && - typeof node.arguments[0].value === 'string' - ) -} - -// assign configs here so we can reference `plugin` -Object.assign(plugin.configs, { - recommended: [{ - plugins: { - "@instructure": plugin - }, - settings: { - // The rule resolves import paths via eslint-module-utils. Without - // TypeScript extensions the default node resolver can't resolve .ts/.tsx - // files, resolve.default() returns undefined and the rule silently bails. - "import/resolver": { - node: { - extensions: [".js", ".jsx", ".ts", ".tsx", ".json"] - } - } - }, - rules: { - "@instructure/no-relative-imports": "error" - } - }] -}) - -export default plugin From 729de124b79668deddb8f59e1f3bde094e80f3bf Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Wed, 15 Jul 2026 14:14:19 +0200 Subject: [PATCH 4/8] fix(many): update eslint-disable comments for oxlint's rule IDs Two disable comments reference rule names that do not match oxlint's actual rule IDs, so they silently stopped suppressing anything: - packages/__docs__/globals.ts: @instructure/no-relative-imports -> instructure/no-relative-imports. oxlint's custom rule has no @ scope prefix. - packages/ui-i18n/src/textDirectionContextConsumer.tsx: react/forbid-foreign-prop-types -> react-js/forbid-foreign-prop-types. The bridged eslint-plugin-react is aliased react-js. Delete 6 jsx_a11y/role-has-required-aria-props disable comments in TreeBrowser's TreeCollection (v1 and v2): - oxlint's rule does not require aria-selected for the treeitem role at all, unlike e.g. checkbox, which requires aria-checked, so there was nothing for these comments to suppress. oxlint accepts both jsx-a11y/* and jsx_a11y/* spellings for disable comments, so the unrelated jsx-a11y/* comments in Checkbox, FileDrop, Img, NumberInput, and RadioInput needed no change. Also trims a trailing space in one ColorPreset test title, an unrelated vitest/valid-title auto-fix. --- packages/__docs__/globals.ts | 4 ++-- .../src/ColorPreset/__tests__/ColorPreset.test.tsx | 2 +- packages/ui-i18n/src/textDirectionContextConsumer.tsx | 2 +- .../src/TreeBrowser/v1/TreeCollection/index.tsx | 3 --- .../src/TreeBrowser/v2/TreeCollection/index.tsx | 3 --- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/__docs__/globals.ts b/packages/__docs__/globals.ts index 783c8c1ac8..8f1c07bcde 100644 --- a/packages/__docs__/globals.ts +++ b/packages/__docs__/globals.ts @@ -42,11 +42,11 @@ import { dark, light } from '@instructure/ui-themes' import { debounce } from '@instructure/debounce' // @ts-expect-error no type declarations for CSS side-effect import -// eslint-disable-next-line @instructure/no-relative-imports +// eslint-disable-next-line instructure/no-relative-imports import '../ui-icons/src/generated/icon-font/Solid/InstructureIcons-Solid.css' // @ts-expect-error no type declarations for CSS side-effect import -// eslint-disable-next-line @instructure/no-relative-imports +// eslint-disable-next-line instructure/no-relative-imports import '../ui-icons/src/generated/icon-font/Line/InstructureIcons-Line.css' import { DateTime } from '@instructure/ui-i18n' diff --git a/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx b/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx index 3d9f65abb7..ba34294191 100644 --- a/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx +++ b/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx @@ -89,7 +89,7 @@ describe('', () => { }) }) - it('should default to using the hex code as aria-label when colorScreenReaderLabel is not provided ', async () => { + it('should default to using the hex code as aria-label when colorScreenReaderLabel is not provided', async () => { render() const buttons = screen.getAllByRole('button') diff --git a/packages/ui-i18n/src/textDirectionContextConsumer.tsx b/packages/ui-i18n/src/textDirectionContextConsumer.tsx index abc39c5c00..e51c935369 100644 --- a/packages/ui-i18n/src/textDirectionContextConsumer.tsx +++ b/packages/ui-i18n/src/textDirectionContextConsumer.tsx @@ -171,7 +171,7 @@ const textDirectionContextConsumer: TextDirectionContextConsumerType = TextDirectionContextConsumerForwardingRef.defaultProps = ComposedComponent.defaultProps TextDirectionContextConsumerForwardingRef.propTypes = - // eslint-disable-next-line react/forbid-foreign-prop-types + // eslint-disable-next-line react-js/forbid-foreign-prop-types ComposedComponent.propTypes TextDirectionContextConsumerForwardingRef.allowedProps = ComposedComponent.allowedProps diff --git a/packages/ui-tree-browser/src/TreeBrowser/v1/TreeCollection/index.tsx b/packages/ui-tree-browser/src/TreeBrowser/v1/TreeCollection/index.tsx index fdd00d30b7..e53484f5c4 100644 --- a/packages/ui-tree-browser/src/TreeBrowser/v1/TreeCollection/index.tsx +++ b/packages/ui-tree-browser/src/TreeBrowser/v1/TreeCollection/index.tsx @@ -233,7 +233,6 @@ class TreeCollection extends Component< return (
  • Date: Tue, 28 Jul 2026 12:52:02 +0200 Subject: [PATCH 5/8] fix: require the oxlint notice-plugin to match the full copyright header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the loose mustMatch: 'The MIT License' substring check with an exact match against the full COPYRIGHT_NOTICE text. The old check only looked for that one phrase in the first 1000 characters, so a header with the phrase present but other lines altered, wrong, or missing was accepted as valid. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- scripts/oxlint/notice-plugin.mjs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/scripts/oxlint/notice-plugin.mjs b/scripts/oxlint/notice-plugin.mjs index 4c069d70cd..9b4aeeb366 100644 --- a/scripts/oxlint/notice-plugin.mjs +++ b/scripts/oxlint/notice-plugin.mjs @@ -27,15 +27,12 @@ * (https://oxc.rs/docs/guide/usage/linter/js-plugins.html) for this repo's exact config: * * ```js - * 'notice/notice': ['error', { mustMatch: 'The MIT License', template: COPYRIGHT_NOTICE }] + * 'notice/notice': ['error', { template: COPYRIGHT_NOTICE }] * ``` * - * `eslint-plugin-notice`'s default behavior (see its `utils.js#resolveOptions`) that this - * mirrors: - * - `chars` defaults to 1000: only the first 1000 characters of the file are checked. - * - a string `mustMatch` is compiled into a `RegExp` and tested against those characters. - * - `onNonMatchingHeader` defaults to "prepend": the fixer always inserts the template at the - * very start of the file, regardless of whether a (non-matching) header comment exists. + * this requires the file to start with the exact `COPYRIGHT_NOTICE` text - a + * header that merely resembles the real one (e.g. a subtly reworded clause) + * is treated as missing. * * Usage (in `.oxlintrc.json`): * ```json @@ -70,15 +67,11 @@ export const COPYRIGHT_NOTICE = '/*\n' + ' * SOFTWARE.\n' + ' */' -const MUST_MATCH = 'The MIT License' -const CHARS = 1000 - /** * Pure rule logic, independent of oxlint's context/AST shape, so it can be unit-tested directly. */ export function hasNoticeHeader(sourceText) { - const leading = String(sourceText).replace(/\r\n/g, '\n').slice(0, CHARS) - return new RegExp(MUST_MATCH).test(leading) + return String(sourceText).replace(/\r\n/g, '\n').startsWith(COPYRIGHT_NOTICE) } /** @@ -89,9 +82,6 @@ export function insertNoticeHeader(sourceText) { return COPYRIGHT_NOTICE + '\n' + sourceText } -// `meta.name` becomes the rule namespace prefix oxlint derives for a bare jsPlugins path entry, -// chosen here as "notice" so the resulting rule id ("notice/notice") matches the original -// `notice/notice` rule id from `eslint-plugin-notice` used in eslint.config.mjs. const plugin = { meta: { name: 'notice', From 527cc7d3b5cac1a73b27eff8fba9582bc23291c4 Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Tue, 28 Jul 2026 13:55:48 +0200 Subject: [PATCH 6/8] chore(many): fix incorrect copyright header text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct license headers that drifted from the canonical text and were missed by the old loose oxlint notice check: wrong copyright start years (2018/2021 instead of 2015) in ui-date-time-input, ui-editable, ui-i18n and ui-tree-browser, a "copyrigfht" typo in ui-color-picker, and an extra period after "(MIT)" in vitest.config.mts, vitest.setup.ts, vitest.setup.browser.ts, and a ui-portal test file. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../src/ColorMixer/v1/ColorPalette/index.tsx | 2 +- .../src/ColorMixer/v2/ColorPalette/index.tsx | 2 +- .../src/DateTimeInput/__tests__/DateTimeInput.test.tsx | 2 +- packages/ui-date-time-input/src/DateTimeInput/v1/index.tsx | 2 +- packages/ui-date-time-input/src/DateTimeInput/v2/index.tsx | 2 +- .../ui-editable/src/Editable/__tests__/Editable.test.tsx | 2 +- packages/ui-editable/src/Editable/v1/index.tsx | 3 ++- .../src/InPlaceEdit/__tests__/InPlaceEdit.test.tsx | 2 +- packages/ui-editable/src/InPlaceEdit/v1/index.tsx | 2 +- packages/ui-editable/src/InPlaceEdit/v2/index.tsx | 2 +- packages/ui-editable/src/exports/a.ts | 2 +- packages/ui-editable/src/exports/b.ts | 2 +- packages/ui-i18n/src/getTextDirection.ts | 2 +- packages/ui-popover/src/Popover/__tests__/Popover.test.tsx | 6 ++---- packages/ui-portal/src/Portal/__tests__/Portal.test.tsx | 1 - .../src/TreeBrowser/__tests__/TreeNode.test.tsx | 2 +- .../ui-tree-browser/src/TreeBrowser/v1/TreeNode/index.tsx | 2 +- .../ui-tree-browser/src/TreeBrowser/v2/TreeNode/index.tsx | 2 +- vitest.config.mts | 2 +- vitest.setup.browser.ts | 2 +- vitest.setup.ts | 2 +- 21 files changed, 22 insertions(+), 24 deletions(-) diff --git a/packages/ui-color-picker/src/ColorMixer/v1/ColorPalette/index.tsx b/packages/ui-color-picker/src/ColorMixer/v1/ColorPalette/index.tsx index b86808c477..c38d3ef166 100644 --- a/packages/ui-color-picker/src/ColorMixer/v1/ColorPalette/index.tsx +++ b/packages/ui-color-picker/src/ColorMixer/v1/ColorPalette/index.tsx @@ -10,7 +10,7 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyrigfht notice and this permission notice shall be included in all + * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR diff --git a/packages/ui-color-picker/src/ColorMixer/v2/ColorPalette/index.tsx b/packages/ui-color-picker/src/ColorMixer/v2/ColorPalette/index.tsx index d1f9345316..0f1ea70f18 100644 --- a/packages/ui-color-picker/src/ColorMixer/v2/ColorPalette/index.tsx +++ b/packages/ui-color-picker/src/ColorMixer/v2/ColorPalette/index.tsx @@ -10,7 +10,7 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyrigfht notice and this permission notice shall be included in all + * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR diff --git a/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx b/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx index 8b6f4c6769..6e9f63822e 100644 --- a/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx +++ b/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-date-time-input/src/DateTimeInput/v1/index.tsx b/packages/ui-date-time-input/src/DateTimeInput/v1/index.tsx index 261fc56005..b4283686b3 100644 --- a/packages/ui-date-time-input/src/DateTimeInput/v1/index.tsx +++ b/packages/ui-date-time-input/src/DateTimeInput/v1/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-date-time-input/src/DateTimeInput/v2/index.tsx b/packages/ui-date-time-input/src/DateTimeInput/v2/index.tsx index 99657701a6..d85b18d5fe 100644 --- a/packages/ui-date-time-input/src/DateTimeInput/v2/index.tsx +++ b/packages/ui-date-time-input/src/DateTimeInput/v2/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx b/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx index f9c2b113c7..7d73a2bf21 100644 --- a/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx +++ b/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-editable/src/Editable/v1/index.tsx b/packages/ui-editable/src/Editable/v1/index.tsx index b883750f0e..aaf3cbfeb9 100644 --- a/packages/ui-editable/src/Editable/v1/index.tsx +++ b/packages/ui-editable/src/Editable/v1/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ + import { Component } from 'react' import { deepEqual } from '@instructure/ui-utils' diff --git a/packages/ui-editable/src/InPlaceEdit/__tests__/InPlaceEdit.test.tsx b/packages/ui-editable/src/InPlaceEdit/__tests__/InPlaceEdit.test.tsx index a6dbab2845..207c4cc829 100644 --- a/packages/ui-editable/src/InPlaceEdit/__tests__/InPlaceEdit.test.tsx +++ b/packages/ui-editable/src/InPlaceEdit/__tests__/InPlaceEdit.test.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-editable/src/InPlaceEdit/v1/index.tsx b/packages/ui-editable/src/InPlaceEdit/v1/index.tsx index 069bada78d..1f3110dab0 100644 --- a/packages/ui-editable/src/InPlaceEdit/v1/index.tsx +++ b/packages/ui-editable/src/InPlaceEdit/v1/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-editable/src/InPlaceEdit/v2/index.tsx b/packages/ui-editable/src/InPlaceEdit/v2/index.tsx index 22588c53d2..e40b968c48 100644 --- a/packages/ui-editable/src/InPlaceEdit/v2/index.tsx +++ b/packages/ui-editable/src/InPlaceEdit/v2/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-editable/src/exports/a.ts b/packages/ui-editable/src/exports/a.ts index ae2e8475f4..9db62704f9 100644 --- a/packages/ui-editable/src/exports/a.ts +++ b/packages/ui-editable/src/exports/a.ts @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-editable/src/exports/b.ts b/packages/ui-editable/src/exports/b.ts index 2f512d37ec..2cfebd7681 100644 --- a/packages/ui-editable/src/exports/b.ts +++ b/packages/ui-editable/src/exports/b.ts @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-i18n/src/getTextDirection.ts b/packages/ui-i18n/src/getTextDirection.ts index b95aa658a9..7e64a2678e 100644 --- a/packages/ui-i18n/src/getTextDirection.ts +++ b/packages/ui-i18n/src/getTextDirection.ts @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx b/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx index c2a59c5a25..5920d23be8 100644 --- a/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx +++ b/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx @@ -1,5 +1,5 @@ /* - * The MIT License (MIT). + * The MIT License (MIT) * * Copyright (c) 2015 - present Instructure, Inc. * @@ -319,9 +319,7 @@ describe('', () => { ) const content = await screen.findByTestId('content') - expect( - content.closest('[class*="popover__scrollContainer"]') - ).toBeNull() + expect(content.closest('[class*="popover__scrollContainer"]')).toBeNull() }) it('wraps content in an overflow:auto + auto-fit max-height container when set', async () => { diff --git a/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx b/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx index 098ffafa17..9c3c0f12af 100644 --- a/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx +++ b/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx @@ -4,7 +4,6 @@ * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy - * * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell diff --git a/packages/ui-tree-browser/src/TreeBrowser/__tests__/TreeNode.test.tsx b/packages/ui-tree-browser/src/TreeBrowser/__tests__/TreeNode.test.tsx index 77fb033c74..90b64e5442 100644 --- a/packages/ui-tree-browser/src/TreeBrowser/__tests__/TreeNode.test.tsx +++ b/packages/ui-tree-browser/src/TreeBrowser/__tests__/TreeNode.test.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-tree-browser/src/TreeBrowser/v1/TreeNode/index.tsx b/packages/ui-tree-browser/src/TreeBrowser/v1/TreeNode/index.tsx index 2e7c3d5a9f..73645a1fcb 100644 --- a/packages/ui-tree-browser/src/TreeBrowser/v1/TreeNode/index.tsx +++ b/packages/ui-tree-browser/src/TreeBrowser/v1/TreeNode/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/packages/ui-tree-browser/src/TreeBrowser/v2/TreeNode/index.tsx b/packages/ui-tree-browser/src/TreeBrowser/v2/TreeNode/index.tsx index 09ed7076b9..2169cc85f0 100644 --- a/packages/ui-tree-browser/src/TreeBrowser/v2/TreeNode/index.tsx +++ b/packages/ui-tree-browser/src/TreeBrowser/v2/TreeNode/index.tsx @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021 - present Instructure, Inc. + * Copyright (c) 2015 - present Instructure, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/vitest.config.mts b/vitest.config.mts index 301659c505..aec897ec5a 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -1,5 +1,5 @@ /* - * The MIT License (MIT). + * The MIT License (MIT) * * Copyright (c) 2015 - present Instructure, Inc. * diff --git a/vitest.setup.browser.ts b/vitest.setup.browser.ts index 4b2931efbb..67f282f3c0 100644 --- a/vitest.setup.browser.ts +++ b/vitest.setup.browser.ts @@ -1,5 +1,5 @@ /* - * The MIT License (MIT). + * The MIT License (MIT) * * Copyright (c) 2015 - present Instructure, Inc. * diff --git a/vitest.setup.ts b/vitest.setup.ts index 4d2c118f96..c8f2495163 100644 --- a/vitest.setup.ts +++ b/vitest.setup.ts @@ -1,5 +1,5 @@ /* - * The MIT License (MIT). + * The MIT License (MIT) * * Copyright (c) 2015 - present Instructure, Inc. * From e6ccfd106646f1ae916eeecaefe7129658e35080 Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Tue, 28 Jul 2026 14:23:40 +0200 Subject: [PATCH 7/8] test(ui-truncate-text): use vitest matchers instead of chai's to.equal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace expect(...).to.equal(...) chai-style assertions with vitest's native toEqual() in cleanString.test.tsx and cleanData.test.tsx. These were leftover from an old Mocha/Chai migration and were the only reason oxlint's vitest/valid-expect rule was disabled for this package's tests. Remove that now-unneeded per-file override from .oxlintrc.json so the rule applies uniformly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .oxlintrc.json | 7 ------- .../TruncateText/__tests__/cleanData.test.tsx | 18 +++++++++--------- .../__tests__/cleanString.test.tsx | 8 ++++---- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index d148424141..5e73cf691a 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -366,13 +366,6 @@ ] } }, - { - "files": ["packages/ui-truncate-text/src/TruncateText/__tests__/**"], - "plugins": ["vitest"], - "rules": { - "vitest/valid-expect": "off" - } - }, { "files": ["**/*"], "excludeFiles": ["**/__tests__/**"], diff --git a/packages/ui-truncate-text/src/TruncateText/__tests__/cleanData.test.tsx b/packages/ui-truncate-text/src/TruncateText/__tests__/cleanData.test.tsx index f51d4a3863..3c83b7414d 100644 --- a/packages/ui-truncate-text/src/TruncateText/__tests__/cleanData.test.tsx +++ b/packages/ui-truncate-text/src/TruncateText/__tests__/cleanData.test.tsx @@ -35,7 +35,7 @@ describe('cleanData', () => { ignore: [' '] } const newData = cleanData(data, options) - expect(newData[0].join('')).to.equal('Test...') + expect(newData[0].join('')).toEqual('Test...') }) it('should remove spaces from the end of word data', async () => { @@ -47,7 +47,7 @@ describe('cleanData', () => { } const newData = cleanData(data, options) - expect(newData[0].join('')).to.equal('Test...') + expect(newData[0].join('')).toEqual('Test...') }) it('should remove spaces from the middle of character data', async () => { @@ -61,7 +61,7 @@ describe('cleanData', () => { } const newData = cleanData(data, options) - expect(newData[0].join('')).to.equal('Hello...world') + expect(newData[0].join('')).toEqual('Hello...world') }) it('should remove spaces from the middle of word data', async () => { @@ -73,7 +73,7 @@ describe('cleanData', () => { } const newData = cleanData(data, options) - expect(newData[0].join('')).to.equal('Hello...world') + expect(newData[0].join('')).toEqual('Hello...world') }) it('should do a thorough cleaning', async () => { @@ -85,7 +85,7 @@ describe('cleanData', () => { } const newData = cleanData(data, options, true) - expect(newData[0].join('')).to.equal('Test...') + expect(newData[0].join('')).toEqual('Test...') }) it('should remove spaces from the end of complex character data', async () => { @@ -106,8 +106,8 @@ describe('cleanData', () => { newData = cleanData(data, options) const text2 = newData[0].join('') + newData[1].join('') - expect(text).to.equal('Hello...') - expect(text2).to.equal('Hello world...') + expect(text).toEqual('Hello...') + expect(text2).toEqual('Hello world...') }) it('should remove spaces from the middle of complex word data', async () => { @@ -125,7 +125,7 @@ describe('cleanData', () => { newData = cleanData(data, options) const text2 = newData[0].join('') + newData[1].join('') - expect(text).to.equal('Hello...world') - expect(text2).to.equal('Hello...world') + expect(text).toEqual('Hello...world') + expect(text2).toEqual('Hello...world') }) }) diff --git a/packages/ui-truncate-text/src/TruncateText/__tests__/cleanString.test.tsx b/packages/ui-truncate-text/src/TruncateText/__tests__/cleanString.test.tsx index c9ab83cdd0..885a06d723 100644 --- a/packages/ui-truncate-text/src/TruncateText/__tests__/cleanString.test.tsx +++ b/packages/ui-truncate-text/src/TruncateText/__tests__/cleanString.test.tsx @@ -31,27 +31,27 @@ describe('cleanSring', () => { const string = ' Hello world ' const newString = cleanString(string, [' ']) - expect(newString).to.equal('Hello world') + expect(newString).toEqual('Hello world') }) it('should remove spaces from only the end of string', async () => { const string = ' Hello world ' const newString = cleanString(string, [' '], false) - expect(newString).to.equal(' Hello world') + expect(newString).toEqual(' Hello world') }) it('should remove spaces and commas', async () => { const string = ' Hello world,' const newString = cleanString(string, [' ', ',']) - expect(newString).to.equal('Hello world') + expect(newString).toEqual('Hello world') }) it('should do a thorough cleaning', async () => { const string = 'Hello world. ' const newString = cleanString(string, [' ', '.'], false, true, true) - expect(newString).to.equal('Hello world') + expect(newString).toEqual('Hello world') }) }) From e9c9aa09f1970553e46959a76015a9931fb8fe3e Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Tue, 28 Jul 2026 14:33:33 +0200 Subject: [PATCH 8/8] docs: document oxlint usage in contributing getting-started guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the Linters and Code Formatting section to reflect the ESLint to oxlint migration: list the lint/lint:fix/lint:changes commands and swap the ESLint/Stylelint VSCode plugin recommendation for the Oxc extension. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../contributing/contributing-getting-started.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/contributing/contributing-getting-started.md b/docs/contributing/contributing-getting-started.md index 3d40c97019..b968fa50c5 100644 --- a/docs/contributing/contributing-getting-started.md +++ b/docs/contributing/contributing-getting-started.md @@ -45,10 +45,20 @@ See the [testing documentation](testing-overview) for details. ### Linters and Code Formatting -Linters are run as part of the build. If you use VSCode, you can set up the following plugins to catch lint and formatting errors earlier. +Linting is run as part of the build via [oxlint](https://oxc.rs/docs/guide/usage/linter). -1. Install the _Eslint_ plugin [VSCode](https://github.com/Microsoft/vscode-eslint) -1. Install the _Stylelint_ plugin [VSCode](https://github.com/stylelint/vscode-stylelint) +Useful commands: + +- `pnpm run lint` — lint the whole workspace. +- `pnpm run lint:fix` — lint the whole workspace and auto-fix what it can. +- `pnpm run lint:changes` — lint only files changed since the last commit. +- `pnpm --filter lint` / `lint:fix` — lint a single package. + +Lint errors are also fixed automatically on commit for staged files via `lint-staged` (see the `pre-commit` git hook). + +If you use VSCode, you can set up the following plugin to catch lint errors earlier. + +1. Install the _Oxc_ plugin [VSCode](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) 1. Run `pnpm install` to install the dependencies 1. Restart your editor