parent
ad0940badb
commit
599dcc2a0c
@ -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,30 @@ |
|||||||
|
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/restrict-template-expressions': [ |
||||||
|
'error', |
||||||
|
{ allowNever: true }, |
||||||
|
], |
||||||
|
}, |
||||||
|
}; |
@ -0,0 +1,5 @@ |
|||||||
|
{ |
||||||
|
"tabWidth": 4, |
||||||
|
"singleQuote": true, |
||||||
|
"trailingComma": "all" |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8" /> |
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
||||||
|
<link href='https://fonts.cdnfonts.com/css/atkinson-hyperlegible' rel='stylesheet'> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<meta name="color-scheme" content="light dark" /> |
||||||
|
<title>Spell checker</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="app"></div> |
||||||
|
<script type="module" src="/src/index.tsx"></script> |
||||||
|
</body> |
||||||
|
</html> |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@ |
|||||||
|
{ |
||||||
|
"private": true, |
||||||
|
"type": "module", |
||||||
|
"scripts": { |
||||||
|
"dev": "vite", |
||||||
|
"build": "vite build", |
||||||
|
"start-release": "npm run build && serve dist", |
||||||
|
"lint": "eslint \"{src,test}/**/*.{ts,tsx}\"", |
||||||
|
"typecheck": "tsc --noEmit", |
||||||
|
"test": "tap run", |
||||||
|
"prebuild": "npm run lint && npm run typecheck && npm run test", |
||||||
|
"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", |
||||||
|
"serve": "^14.2.1", |
||||||
|
"tap": "^18.6.1", |
||||||
|
"typescript": "^5.2.2", |
||||||
|
"vite": "^4.3.2" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,14 @@ |
|||||||
|
import { render } from 'preact'; |
||||||
|
|
||||||
|
import './style.css'; |
||||||
|
|
||||||
|
export function App() { |
||||||
|
return <h1>Hello world</h1>; |
||||||
|
} |
||||||
|
|
||||||
|
const app = document.getElementById('app'); |
||||||
|
if (app) { |
||||||
|
render(<App />, app); |
||||||
|
} else { |
||||||
|
console.error('Cannot find app container'); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
:root { |
||||||
|
font-family: system-ui, 'Atkinson Hyperlegible', sans-serif; |
||||||
|
line-height: 1.5; |
||||||
|
font-weight: 400; |
||||||
|
|
||||||
|
font-synthesis: none; |
||||||
|
text-rendering: optimizeLegibility; |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
-moz-osx-font-smoothing: grayscale; |
||||||
|
-webkit-text-size-adjust: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
padding: 1rem; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
|
||||||
|
#app { |
||||||
|
max-width: 1280px; |
||||||
|
margin: 0 auto; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
img { |
||||||
|
margin-bottom: 1.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
img:hover { |
||||||
|
filter: drop-shadow(0 0 2em #673ab8aa); |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
{ |
||||||
|
"extends": "@tsconfig/strictest/tsconfig.json", |
||||||
|
"compilerOptions": { |
||||||
|
"target": "ES2020", |
||||||
|
"module": "ESNext", |
||||||
|
"moduleResolution": "bundler", |
||||||
|
"noEmit": true, |
||||||
|
"allowJs": true, |
||||||
|
"checkJs": true, |
||||||
|
|
||||||
|
/* Preact Config */ |
||||||
|
"jsx": "react-jsx", |
||||||
|
"jsxImportSource": "preact", |
||||||
|
"skipLibCheck": true, |
||||||
|
"paths": { |
||||||
|
"react": ["./node_modules/preact/compat/"], |
||||||
|
"react-dom": ["./node_modules/preact/compat/"] |
||||||
|
} |
||||||
|
}, |
||||||
|
"include": ["node_modules/vite/client.d.ts", "**/*"], |
||||||
|
"exclude": ["dist"], |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
import { defineConfig } from 'vite'; |
||||||
|
import preact from '@preact/preset-vite'; |
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({ |
||||||
|
base: './', |
||||||
|
plugins: [preact()], |
||||||
|
}); |
Loading…
Reference in new issue