.eslintrc.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /* eslint-disable quote-props */
  2. 'use strict'
  3. const svgPresentationAttributes = [
  4. 'alignment-baseline', 'baseline-shift', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolatio', 'color-interpolatio-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', 'dominant-baseline', 'enable-background', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'overflow', 'pointer-events', 'shape-rendering', 'stop-color', 'stop-opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'transform', 'transform-origin', 'unicode-bidi', 'vector-effect', 'visibility', 'word-spacing', 'writing-mod',
  5. ]
  6. module.exports = {
  7. root: true,
  8. extends: ['transloadit'],
  9. env: {
  10. es6: true,
  11. jest: true,
  12. node: true,
  13. // extra:
  14. browser: true,
  15. },
  16. globals: {
  17. globalThis: true,
  18. hexo: true,
  19. window: true,
  20. },
  21. plugins: [
  22. '@babel/eslint-plugin',
  23. 'jest',
  24. 'markdown',
  25. 'node',
  26. 'prefer-import',
  27. 'promise',
  28. 'react',
  29. // extra:
  30. 'compat',
  31. 'jsdoc',
  32. 'unicorn',
  33. ],
  34. parser: '@babel/eslint-parser',
  35. parserOptions: {
  36. sourceType: 'script',
  37. ecmaVersion: 2022,
  38. ecmaFeatures: {
  39. jsx: true,
  40. },
  41. },
  42. rules: {
  43. // transloadit rules we are actually ok with in the uppy repo
  44. 'import/extensions': 'off',
  45. 'object-shorthand': ['error', 'always'],
  46. 'strict': 'off',
  47. 'key-spacing': 'off',
  48. 'max-classes-per-file': ['error', 2],
  49. 'react/no-unknown-property': ['error', {
  50. ignore: svgPresentationAttributes,
  51. }],
  52. // rules we want to enforce
  53. 'array-callback-return': 'error',
  54. 'implicit-arrow-linebreak': 'error',
  55. 'import/no-dynamic-require': 'error',
  56. 'import/no-extraneous-dependencies': 'error',
  57. 'max-len': 'error',
  58. 'no-empty': 'error',
  59. 'no-bitwise': 'error',
  60. 'no-continue': 'error',
  61. 'no-lonely-if': 'error',
  62. 'no-nested-ternary': 'error',
  63. 'no-restricted-properties': 'error',
  64. 'no-return-assign': 'error',
  65. 'no-underscore-dangle': 'error',
  66. 'no-unused-expressions': 'error',
  67. 'no-unused-vars': 'error',
  68. 'no-useless-concat': 'error',
  69. 'no-var': 'error',
  70. 'node/handle-callback-err': 'error',
  71. 'prefer-destructuring': 'error',
  72. 'prefer-spread': 'error',
  73. 'unicorn/prefer-node-protocol': 'error',
  74. // transloadit rules we would like to enforce in the future
  75. // but will require separate PRs to gradually get there
  76. // and so the meantime: just warn
  77. 'class-methods-use-this': ['warn'],
  78. 'consistent-return': ['warn'],
  79. 'default-case': ['warn'],
  80. 'global-require': ['warn'],
  81. 'import/no-unresolved': ['warn'],
  82. 'import/order': ['warn'],
  83. 'no-mixed-operators': ['warn'],
  84. 'no-param-reassign': ['warn'],
  85. 'no-redeclare': ['warn'],
  86. 'no-shadow': ['warn'],
  87. 'no-use-before-define': ['warn', { 'functions': false }],
  88. 'radix': ['warn'],
  89. 'react/button-has-type': 'error',
  90. 'react/destructuring-assignment': ['warn'],
  91. 'react/forbid-prop-types': 'error',
  92. 'react/jsx-props-no-spreading': ['warn'],
  93. 'react/no-access-state-in-setstate': 'error',
  94. 'react/no-array-index-key': 'error',
  95. 'react/no-deprecated': 'error',
  96. 'react/no-this-in-sfc': 'error',
  97. 'react/no-will-update-set-state': 'error',
  98. 'react/prefer-stateless-function': 'error',
  99. 'react/sort-comp': 'error',
  100. 'react/style-prop-object': 'error',
  101. // accessibility
  102. 'jsx-a11y/alt-text': 'error',
  103. 'jsx-a11y/anchor-has-content': 'error',
  104. 'jsx-a11y/click-events-have-key-events': 'error',
  105. 'jsx-a11y/control-has-associated-label': 'error',
  106. 'jsx-a11y/label-has-associated-control': 'error',
  107. 'jsx-a11y/media-has-caption': 'error',
  108. 'jsx-a11y/mouse-events-have-key-events': 'error',
  109. 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
  110. 'jsx-a11y/no-noninteractive-element-interactions': 'error',
  111. 'jsx-a11y/no-static-element-interactions': 'error',
  112. // compat
  113. 'compat/compat': ['error'],
  114. // jsdoc
  115. 'jsdoc/check-alignment': 'error',
  116. 'jsdoc/check-examples': 'off', // cannot yet be supported for ESLint 8, see https://github.com/eslint/eslint/issues/14745
  117. 'jsdoc/check-param-names': ['warn'],
  118. 'jsdoc/check-syntax': ['warn'],
  119. 'jsdoc/check-tag-names': ['error', { jsxTags: true }],
  120. 'jsdoc/check-types': 'error',
  121. 'jsdoc/newline-after-description': 'error',
  122. 'jsdoc/valid-types': 'error',
  123. 'jsdoc/check-indentation': ['off'],
  124. },
  125. settings: {
  126. 'import/core-modules': ['tsd'],
  127. react: {
  128. pragma: 'h',
  129. },
  130. jsdoc: {
  131. mode: 'typescript',
  132. },
  133. polyfills: [
  134. 'Promise',
  135. 'fetch',
  136. 'Object.assign',
  137. 'document.querySelector',
  138. ],
  139. },
  140. overrides: [
  141. {
  142. files: [
  143. '*.jsx',
  144. 'packages/@uppy/react-native/**/*.js',
  145. ],
  146. parser: 'espree',
  147. parserOptions: {
  148. sourceType: 'module',
  149. ecmaFeatures: {
  150. jsx: true,
  151. },
  152. },
  153. rules: {
  154. 'no-restricted-globals': [
  155. 'error',
  156. {
  157. name: '__filename',
  158. message: 'Use import.meta.url instead',
  159. },
  160. {
  161. name: '__dirname',
  162. message: 'Not available in ESM',
  163. },
  164. {
  165. name: 'exports',
  166. message: 'Not available in ESM',
  167. },
  168. {
  169. name: 'module',
  170. message: 'Not available in ESM',
  171. },
  172. {
  173. name: 'require',
  174. message: 'Use import instead',
  175. },
  176. ],
  177. 'import/extensions': ['error', 'ignorePackages'],
  178. },
  179. },
  180. {
  181. files: [
  182. '*.mjs',
  183. 'e2e/clients/**/*.js',
  184. 'examples/aws-companion/*.js',
  185. 'examples/aws-presigned-url/*.js',
  186. 'examples/bundled/*.js',
  187. 'examples/custom-provider/client/*.js',
  188. 'private/dev/*.js',
  189. 'private/release/*.js',
  190. 'private/remark-lint-uppy/*.js',
  191. // Packages that have switched to ESM sources:
  192. 'packages/@uppy/audio/src/**/*.js',
  193. 'packages/@uppy/aws-s3-multipart/src/**/*.js',
  194. 'packages/@uppy/aws-s3/src/**/*.js',
  195. 'packages/@uppy/box/src/**/*.js',
  196. 'packages/@uppy/companion-client/src/**/*.js',
  197. 'packages/@uppy/compressor/src/**/*.js',
  198. 'packages/@uppy/core/src/**/*.js',
  199. 'packages/@uppy/dashboard/src/**/*.js',
  200. 'packages/@uppy/drag-drop/src/**/*.js',
  201. 'packages/@uppy/drop-target/src/**/*.js',
  202. 'packages/@uppy/dropbox/src/**/*.js',
  203. 'packages/@uppy/facebook/src/**/*.js',
  204. 'packages/@uppy/file-input/src/**/*.js',
  205. 'packages/@uppy/form/src/**/*.js',
  206. 'packages/@uppy/golden-retriever/src/**/*.js',
  207. 'packages/@uppy/google-drive/src/**/*.js',
  208. 'packages/@uppy/image-editor/src/**/*.js',
  209. 'packages/@uppy/informer/src/**/*.js',
  210. 'packages/@uppy/instagram/src/**/*.js',
  211. 'packages/@uppy/locales/src/**/*.js',
  212. 'packages/@uppy/locales/template.js',
  213. 'packages/@uppy/onedrive/src/**/*.js',
  214. 'packages/@uppy/progress-bar/src/**/*.js',
  215. 'packages/@uppy/provider-views/src/**/*.js',
  216. 'packages/@uppy/react/src/**/*.js',
  217. 'packages/@uppy/redux-dev-tools/src/**/*.js',
  218. 'packages/@uppy/remote-sources/src/**/*.js',
  219. 'packages/@uppy/screen-capture/src/**/*.js',
  220. 'packages/@uppy/status-bar/src/**/*.js',
  221. 'packages/@uppy/store-default/src/**/*.js',
  222. 'packages/@uppy/store-redux/src/**/*.js',
  223. 'packages/@uppy/svelte/rollup.config.js',
  224. 'packages/@uppy/svelte/src/**/*.js',
  225. 'packages/@uppy/thumbnail-generator/src/**/*.js',
  226. 'packages/@uppy/transloadit/src/**/*.js',
  227. 'packages/@uppy/tus/src/**/*.js',
  228. 'packages/@uppy/unsplash/src/**/*.js',
  229. 'packages/@uppy/url/src/**/*.js',
  230. 'packages/@uppy/utils/src/**/*.js',
  231. 'packages/@uppy/vue/src/**/*.js',
  232. 'packages/@uppy/webcam/src/**/*.js',
  233. 'packages/@uppy/xhr-upload/src/**/*.js',
  234. 'packages/@uppy/zoom/src/**/*.js',
  235. ],
  236. parser: 'espree',
  237. parserOptions: {
  238. sourceType: 'module',
  239. ecmaFeatures: {
  240. jsx: false,
  241. },
  242. },
  243. rules: {
  244. 'import/named': 'off', // Disabled because that rule tries and fails to parse JSX dependencies.
  245. 'import/no-named-as-default': 'off', // Disabled because that rule tries and fails to parse JSX dependencies.
  246. 'import/no-named-as-default-member': 'off', // Disabled because that rule tries and fails to parse JSX dependencies.
  247. 'no-restricted-globals': [
  248. 'error',
  249. {
  250. name: '__filename',
  251. message: 'Use import.meta.url instead',
  252. },
  253. {
  254. name: '__dirname',
  255. message: 'Not available in ESM',
  256. },
  257. {
  258. name: 'exports',
  259. message: 'Not available in ESM',
  260. },
  261. {
  262. name: 'module',
  263. message: 'Not available in ESM',
  264. },
  265. {
  266. name: 'require',
  267. message: 'Use import instead',
  268. },
  269. ],
  270. 'import/extensions': ['error', 'ignorePackages'],
  271. },
  272. },
  273. {
  274. files: ['packages/uppy/*.mjs'],
  275. rules: {
  276. 'import/first': 'off',
  277. 'import/newline-after-import': 'off',
  278. 'import/no-extraneous-dependencies': ['error', {
  279. devDependencies: true,
  280. }],
  281. },
  282. },
  283. {
  284. files: [
  285. 'packages/@uppy/*/types/*.d.ts',
  286. ],
  287. rules : {
  288. 'import/no-unresolved': 'off',
  289. 'max-classes-per-file': 'off',
  290. 'no-use-before-define': 'off',
  291. },
  292. },
  293. {
  294. files: [
  295. 'packages/@uppy/dashboard/src/components/**/*.jsx',
  296. ],
  297. rules: {
  298. 'react/destructuring-assignment': 'off',
  299. },
  300. },
  301. {
  302. files: [
  303. // Those need looser rules, and cannot be made part of the stricter rules above.
  304. // TODO: update those to more modern code when switch to ESM is complete
  305. 'examples/react-native-expo/*.js',
  306. 'examples/svelte-example/**/*.js',
  307. 'examples/vue/**/*.js',
  308. 'examples/vue3/**/*.js',
  309. ],
  310. parserOptions: {
  311. sourceType: 'module',
  312. },
  313. },
  314. {
  315. files: ['./packages/@uppy/companion/**/*.js'],
  316. rules: {
  317. 'no-underscore-dangle': 'off',
  318. // transloadit rules we would like to enforce in the future
  319. // but will require separate PRs to gradually get there
  320. // and so the meantime: just warn
  321. 'class-methods-use-this': 'warn',
  322. 'consistent-return': 'warn',
  323. 'global-require': 'warn',
  324. 'import/order': 'warn',
  325. 'no-param-reassign': 'warn',
  326. 'no-redeclare': 'warn',
  327. 'no-shadow': 'warn',
  328. 'no-use-before-define': 'warn',
  329. },
  330. },
  331. {
  332. files: [
  333. 'website/src/examples/*/*.es6',
  334. ],
  335. rules: {
  336. 'import/no-extraneous-dependencies': 'off',
  337. 'no-console': 'off',
  338. },
  339. },
  340. {
  341. files: [
  342. '*.test.js',
  343. 'test/endtoend/*.js',
  344. 'website/*.js',
  345. 'bin/**.js',
  346. ],
  347. rules: {
  348. 'compat/compat': ['off'],
  349. },
  350. },
  351. {
  352. files: [
  353. 'bin/**.js',
  354. 'bin/**.mjs',
  355. 'examples/**/*.config.js',
  356. 'examples/**/*.cjs',
  357. 'packages/@uppy/companion/test/**/*.js',
  358. 'test/**/*.js',
  359. 'test/**/*.ts',
  360. '*.test.js',
  361. '*.test-d.ts',
  362. 'postcss.config.js',
  363. '.eslintrc.js',
  364. 'website/*.js',
  365. 'website/**/*.js',
  366. 'private/**/*.js',
  367. ],
  368. rules: {
  369. 'no-console': 'off',
  370. 'import/no-extraneous-dependencies': ['error', {
  371. devDependencies: true,
  372. }],
  373. },
  374. },
  375. {
  376. files: [
  377. 'packages/@uppy/locales/src/*.js',
  378. 'packages/@uppy/locales/template.js',
  379. ],
  380. rules: {
  381. camelcase: ['off'],
  382. 'quote-props': ['error', 'as-needed', { 'numbers': true }],
  383. },
  384. },
  385. {
  386. files: [
  387. 'website/themes/uppy/source/js/*.js',
  388. ],
  389. rules: {
  390. 'prefer-const': ['off'],
  391. },
  392. },
  393. {
  394. files: ['test/endtoend/*/*.mjs', 'test/endtoend/*/*.ts'],
  395. rules: {
  396. // we mostly import @uppy stuff in these files.
  397. 'import/no-extraneous-dependencies': ['off'],
  398. },
  399. },
  400. {
  401. files: ['test/endtoend/*/*.js'],
  402. env: {
  403. mocha: true,
  404. },
  405. },
  406. {
  407. files: ['packages/@uppy/react/src/**/*.js'],
  408. rules: {
  409. 'import/no-extraneous-dependencies': ['error', {
  410. peerDependencies: true,
  411. }],
  412. },
  413. },
  414. {
  415. files: ['**/*.md', '*.md'],
  416. processor: 'markdown/markdown',
  417. },
  418. {
  419. files: ['**/*.md/*.js', '**/*.md/*.javascript'],
  420. parserOptions: {
  421. sourceType: 'module',
  422. },
  423. rules: {
  424. 'react/destructuring-assignment': 'off',
  425. 'no-restricted-globals': [
  426. 'error',
  427. {
  428. name: '__filename',
  429. message: 'Use import.meta.url instead',
  430. },
  431. {
  432. name: '__dirname',
  433. message: 'Not available in ESM',
  434. },
  435. {
  436. name: 'exports',
  437. message: 'Not available in ESM',
  438. },
  439. {
  440. name: 'module',
  441. message: 'Not available in ESM',
  442. },
  443. {
  444. name: 'require',
  445. message: 'Use import instead',
  446. },
  447. ],
  448. },
  449. },
  450. {
  451. files: ['**/*.ts', '**/*.md/*.ts', '**/*.md/*.typescript'],
  452. excludedFiles: ['examples/angular-example/**/*.ts', 'packages/@uppy/angular/**/*.ts'],
  453. parser: '@typescript-eslint/parser',
  454. settings: {
  455. 'import/resolver': {
  456. node: {
  457. extensions: ['.js', '.jsx', '.ts', '.tsx'],
  458. },
  459. },
  460. },
  461. plugins: ['@typescript-eslint'],
  462. extends: [
  463. 'eslint:recommended',
  464. 'plugin:@typescript-eslint/eslint-recommended',
  465. 'plugin:@typescript-eslint/recommended',
  466. ],
  467. rules: {
  468. 'import/prefer-default-export': 'off',
  469. '@typescript-eslint/no-explicit-any': 'off',
  470. '@typescript-eslint/no-namespace': 'off',
  471. },
  472. },
  473. {
  474. files: ['**/*.md/*.*'],
  475. rules: {
  476. 'import/no-extraneous-dependencies': 'off',
  477. 'import/no-unresolved': 'off',
  478. 'no-console': 'off',
  479. 'no-undef': 'off',
  480. 'no-unused-vars': 'off',
  481. },
  482. },
  483. {
  484. files: ['**/react/*.md/*.js', '**/react.md/*.js', '**/react-*.md/*.js'],
  485. settings: {
  486. react: { pragma: 'React' },
  487. },
  488. },
  489. {
  490. files: ['e2e/**/*.ts'],
  491. extends: ['plugin:cypress/recommended'],
  492. },
  493. {
  494. files: ['e2e/**/*.ts', 'e2e/**/*.js', 'e2e/**/*.jsx'],
  495. rules: { 'import/no-extraneous-dependencies': 'off', 'no-unused-expressions': 'off' },
  496. },
  497. ],
  498. }