configured eslint and typescript; added prebuild linting and typechecking

main
Inga 🏳‍🌈 6 months ago
parent 43bbe13ded
commit c5aaaf8124
  1. 175
      .eslint-config-preact-nojest.cjs
  2. 33
      .eslintrc.cjs
  3. 5
      .prettierrc
  4. 802
      package-lock.json
  5. 49
      package.json
  6. 84
      src/index.tsx
  7. 1
      tsconfig.json

@ -0,0 +1,175 @@
// Code taken from https://github.com/preactjs/eslint-config-preact/blob/v1.3.0/index.js
// and modified to remove all jest mentions, because jest plugin is incompatible with typescript-eslint plugin v6
// (see https://github.com/jest-community/eslint-plugin-jest/pull/1401 for more details)
// and to change it from JSM to CJS
module.exports = {
// TODO: this is really only required for class property initializer methods, which are seeing declining usage.
// At some point, we should un-ship the custom parser and let ESLint use esprima.
parser: require.resolve('@babel/eslint-parser'),
// Currently ignored due to the custom parser.
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: {
modules: true,
impliedStrict: true,
jsx: true,
},
requireConfigFile: false,
babelOptions: {
plugins: [
'@babel/plugin-syntax-class-properties',
[
'@babel/plugin-syntax-decorators',
{ decoratorsBeforeExport: false },
],
'@babel/plugin-syntax-jsx',
],
},
},
// We don't use plugin:react/recommended here to avoid React-specific rules.
extends: ['eslint:recommended'],
// TODO: preact-cli ships Jest now, Mocha may be a candidate for removal.
plugins: ['compat', 'react', 'react-hooks'],
env: {
browser: true,
es6: true,
node: true,
},
globals: {
expect: true,
browser: true,
global: true,
},
settings: {
// Preact CLI provides these defaults
targets: ['last 2 versions'],
polyfills: ['fetch', 'Promise'],
react: {
// eslint-plugin-preact interprets this as "h.createElement",
// however we only care about marking h() as being a used variable.
pragma: 'h',
// We use "react 16.0" to avoid pushing folks to UNSAFE_ methods.
version: '16.0',
},
},
rules: {
/**
* Preact / JSX rules
*/
'react/no-deprecated': 2,
'react/react-in-jsx-scope': 0, // handled this automatically
'react/display-name': [1, { ignoreTranspilerName: false }],
'react/jsx-no-bind': [
1,
{
ignoreRefs: true,
allowFunctions: true,
allowArrowFunctions: true,
},
],
'react/jsx-no-comment-textnodes': 2,
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-target-blank': 2,
'react/jsx-no-undef': 2,
'react/jsx-tag-spacing': [2, { beforeSelfClosing: 'always' }],
'react/jsx-uses-react': 2, // debatable
'react/jsx-uses-vars': 2,
'react/jsx-key': [2, { checkFragmentShorthand: true }],
'react/self-closing-comp': 2,
'react/prefer-es6-class': 2,
'react/prefer-stateless-function': 1,
'react/require-render-return': 2,
'react/no-danger': 1,
// Legacy APIs not supported in Preact:
'react/no-did-mount-set-state': 2,
'react/no-did-update-set-state': 2,
'react/no-find-dom-node': 2,
'react/no-is-mounted': 2,
'react/no-string-refs': 2,
/**
* Hooks
*/
'react-hooks/rules-of-hooks': 2,
'react-hooks/exhaustive-deps': 1,
/**
* General JavaScript error avoidance
*/
'constructor-super': 2,
'no-caller': 2,
'no-const-assign': 2,
'no-delete-var': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-imports': 2,
'no-else-return': 1,
'no-empty-pattern': 0,
'no-empty': 0,
'no-extra-parens': 0,
'no-iterator': 2,
'no-lonely-if': 2,
'no-mixed-spaces-and-tabs': [1, 'smart-tabs'],
'no-multi-str': 1,
'no-new-wrappers': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-shadow-restricted-names': 2,
'no-shadow': 0,
'no-spaced-func': 2,
'no-this-before-super': 2,
'no-undef-init': 2,
'no-unneeded-ternary': 2,
'no-unused-vars': [
2,
{
args: 'after-used',
ignoreRestSiblings: true,
},
],
'no-useless-call': 1,
'no-useless-computed-key': 1,
'no-useless-concat': 1,
'no-useless-constructor': 1,
'no-useless-escape': 1,
'no-useless-rename': 1,
'no-var': 1,
'no-with': 2,
/**
* General JavaScript stylistic rules (disabled)
*/
semi: 0,
strict: [2, 'never'], // assume type=module output (cli default)
'object-curly-spacing': [0, 'always'],
'rest-spread-spacing': 0,
'space-before-function-paren': [0, 'always'],
'space-in-parens': [0, 'never'],
'object-shorthand': 1,
'prefer-arrow-callback': 1,
'prefer-rest-params': 1,
'prefer-spread': 1,
'prefer-template': 1,
quotes: [
0,
'single',
{
avoidEscape: true,
allowTemplateLiterals: true,
},
],
'quote-props': [2, 'as-needed'],
radix: 1, // parseInt(x, 10)
'unicode-bom': 2,
'valid-jsdoc': 0,
},
};

@ -0,0 +1,33 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'./.eslint-config-preact-nojest.cjs',
'plugin:@typescript-eslint/strict-type-checked',
'plugin:prettier/recommended',
],
root: true,
env: {
/*node: true,
jest: true,*/
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/no-confusing-void-expression': [
'error',
{ ignoreArrowShorthand: true },
],
/*'@typescript-eslint/no-invalid-void-type': [
'error',
{ allowAsThisParameter: true },
],
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',*/
},
};

@ -0,0 +1,5 @@
{
"tabWidth": 4,
"singleQuote": true,
"trailingComma": "all"
}

802
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,19 +1,34 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"preact": "^10.13.1"
},
"devDependencies": {
"@preact/preset-vite": "^2.5.0",
"eslint": "^8.53.0",
"eslint-config-preact": "^1.3.0",
"typescript": "^5.2.2",
"vite": "^4.3.2"
}
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint \"{src,test}/**/*.{ts,tsx}\"",
"typecheck": "tsc --noEmit",
"prebuild": "npm run lint && npm run typecheck",
"preview": "vite preview"
},
"dependencies": {
"preact": "^10.13.1"
},
"devDependencies": {
"@babel/core": "^7.23.3",
"@babel/eslint-parser": "^7.23.3",
"@babel/plugin-syntax-class-properties": "^7.12.13",
"@babel/plugin-syntax-decorators": "^7.23.3",
"@babel/plugin-syntax-jsx": "^7.23.3",
"@preact/preset-vite": "^2.5.0",
"@tsconfig/strictest": "^2.0.2",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-compat": "^4.2.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"typescript": "^5.2.2",
"vite": "^4.3.2"
}
}

@ -1,42 +1,60 @@
import { render } from 'preact';
import { useState } from 'preact/hooks';
import preactLogo from './assets/preact.svg';
import './style.css';
export function App() {
return (
<div>
<a href="https://preactjs.com" target="_blank">
<img src={preactLogo} alt="Preact logo" height="160" width="160" />
</a>
<h1>Get Started building Vite-powered Preact Apps </h1>
<section>
<Resource
title="Learn Preact"
description="If you're new to Preact, try the interactive tutorial to learn important concepts"
href="https://preactjs.com/tutorial"
/>
<Resource
title="Differences to React"
description="If you're coming from React, you may want to check out our docs to see where Preact differs"
href="https://preactjs.com/guide/v10/differences-to-react"
/>
<Resource
title="Learn Vite"
description="To learn more about Vite and how you can customize it to fit your needs, take a look at their excellent documentation"
href="https://vitejs.dev"
/>
</section>
</div>
);
const [value, setValue] = useState(0);
return (
<div>
<a href="https://preactjs.com">
<img
src={preactLogo}
alt="Preact logo"
height="160"
width="160"
/>
</a>
<h1>Get Started building Vite-powered Preact Apps </h1>
<section>
<div>Counter: {value}</div>
<button onClick={() => setValue(value + 1)}>Increment</button>
<button onClick={() => setValue(value - 1)}>Decrement</button>
</section>
<section>
<Resource
title="Learn Preact"
description="If you're new to Preact, try the interactive tutorial to learn important concepts"
href="https://preactjs.com/tutorial"
/>
<Resource
title="Differences to React"
description="If you're coming from React, you may want to check out our docs to see where Preact differs"
href="https://preactjs.com/guide/v10/differences-to-react"
/>
<Resource
title="Learn Vite"
description="To learn more about Vite and how you can customize it to fit your needs, take a look at their excellent documentation"
href="https://vitejs.dev"
/>
</section>
</div>
);
}
function Resource(props) {
return (
<a href={props.href} target="_blank" class="resource">
<h2>{props.title}</h2>
<p>{props.description}</p>
</a>
);
function Resource(props: Record<'href' | 'title' | 'description', string>) {
return (
<a href={props.href} class="resource">
<h2>{props.title}</h2>
<p>{props.description}</p>
</a>
);
}
render(<App />, document.getElementById('app'));
const app = document.getElementById('app');
if (app) {
render(<App />, app);
} else {
console.error('Cannot find app container');
}

@ -1,4 +1,5 @@
{
"extends": "@tsconfig/strictest/tsconfig.json",
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",

Loading…
Cancel
Save