diff --git a/apps/.eslintrc.cjs b/apps/.eslintrc.cjs new file mode 100644 index 00000000..03b295a7 --- /dev/null +++ b/apps/.eslintrc.cjs @@ -0,0 +1,60 @@ +// Per-package ESLint config for the Preact widget apps under `apps/`. +// +// `root: true` stops ESLint from walking up to the host's +// `cinny/.eslintrc.cjs`, which extends airbnb + the React plugin. Those +// rule sets are tuned for the React host and flag legitimate Preact / +// small-widget patterns as errors (`class=` attributes, arrow-fn +// components, inline icon sub-components, for-of loops, etc.). Keeping +// the hierarchy open would force every widget file to fight host style +// for no real win. +// +// Widgets keep a minimal but real lint pass via the rule sets below: +// +// * `eslint:recommended` — catches genuine bugs (no-undef, no-dupe-*, +// no-redeclare, no-unused-vars, …) without enforcing style. +// * `@typescript-eslint/recommended` — TS-aware variants of the above +// plus type-level checks the recommended set ships. +// +// We deliberately DON'T extend `plugin:react/recommended` — +// `react/react-in-jsx-scope` and `react/no-unknown-property` both flag +// Preact-correct code as errors, and disabling them one by one creates +// a long suppression list. Widget JSX is type-checked by each app's +// `tsc --noEmit` (run by `vite build`), which is the better signal for +// JSX correctness anyway. +module.exports = { + root: true, + // `node` covers `module.exports` in this very file (CommonJS config); + // `browser` is the runtime widget code itself sees. + env: { browser: true, es2021: true, node: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // preact/hooks has the same dep-array semantics as react/hooks, and + // the widget code already carries `// eslint-disable-next-line + // react-hooks/exhaustive-deps` directives at the relevant sites; + // loading the plugin (a) keeps those directives meaningful (without + // it ESLint errors on the «unknown rule» referenced by the comment) + // and (b) catches the real exhaustive-deps mistakes in widget hooks + // for free. + 'plugin:react-hooks/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + ecmaFeatures: { jsx: true }, + }, + plugins: ['@typescript-eslint', 'react-hooks'], + rules: { + // Underscore-prefixed args are intentionally unused (Preact event + // handlers receive args the body doesn't need); match the host's + // convention so lint reads consistently across both trees. + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], + // Widget bridge-protocol regexes occasionally escape `-` inside + // character classes for visual clarity (e.g. `[0-9\-]`). The escape + // is harmless and pre-existing across all three widgets — keeping + // the rule on would force a churn-y diff in code that's been stable + // since the v0.7.6 bridge dialect work. + 'no-useless-escape': 'off', + }, +};