Skip to content

Commit e94e100

Browse files
SoeckaTechQuery
andauthored
[add] Tailwind CSS & ESLint configuration (#5)
Co-authored-by: South Drifter <[email protected]>
1 parent 837d50e commit e94e100

File tree

11 files changed

+3663
-674
lines changed

11 files changed

+3663
-674
lines changed

.postcssrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
plugins: {
3+
"@tailwindcss/postcss": {}
4+
},
5+
}

eslint.config.ts

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import cspellPlugin from '@cspell/eslint-plugin';
2+
import eslint from '@eslint/js';
3+
import html from '@html-eslint/eslint-plugin';
4+
import stylistic from '@stylistic/eslint-plugin';
5+
import eslintConfigPrettier from 'eslint-config-prettier';
6+
import react from 'eslint-plugin-react';
7+
import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort';
8+
import globals from 'globals';
9+
import tsEslint from 'typescript-eslint';
10+
import { fileURLToPath } from 'url';
11+
12+
/**
13+
* @see{@link https://github.com/typescript-eslint/typescript-eslint/blob/main/eslint.config.mjs}
14+
* @see{@link https://github.com/vercel/next.js/issues/71763#issuecomment-2476838298}
15+
*/
16+
17+
const tsconfigRootDir = fileURLToPath(new URL('.', import.meta.url));
18+
19+
export default tsEslint.config(
20+
// register all of the plugins up-front
21+
{
22+
plugins: {
23+
'@typescript-eslint': tsEslint.plugin,
24+
react,
25+
'@stylistic': stylistic,
26+
'simple-import-sort': simpleImportSortPlugin,
27+
'@cspell': cspellPlugin
28+
}
29+
},
30+
{
31+
// config with just ignores is the replacement for `.eslintignore`
32+
ignores: ['**/node_modules/**', 'dist/**', '.parcel-cache/**']
33+
},
34+
35+
// extends ...
36+
eslint.configs.recommended,
37+
...tsEslint.configs.recommended,
38+
39+
// base config
40+
{
41+
languageOptions: {
42+
globals: { ...globals.es2020, ...globals.browser, ...globals.node },
43+
parserOptions: {
44+
projectService: true,
45+
tsconfigRootDir,
46+
warnOnUnsupportedTypeScriptVersion: false
47+
}
48+
},
49+
rules: {
50+
'arrow-body-style': ['error', 'as-needed'],
51+
'no-empty-pattern': 'warn',
52+
'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
53+
'consistent-return': 'warn',
54+
'prefer-destructuring': ['error', { object: true, array: true }],
55+
// react
56+
'react/no-unescaped-entities': 'off',
57+
'react/self-closing-comp': [
58+
'error',
59+
{ component: true, html: true }
60+
],
61+
'react/jsx-curly-brace-presence': [
62+
'error',
63+
{ props: 'never', children: 'never' }
64+
],
65+
'react/jsx-no-target-blank': 'warn',
66+
'react/jsx-sort-props': [
67+
'error',
68+
{
69+
reservedFirst: true,
70+
callbacksLast: true,
71+
noSortAlphabetically: true
72+
}
73+
],
74+
// typescript
75+
'@typescript-eslint/no-unused-vars': 'warn',
76+
'@typescript-eslint/no-explicit-any': 'warn',
77+
'@typescript-eslint/no-empty-object-type': 'off',
78+
'@typescript-eslint/no-unsafe-declaration-merging': 'warn',
79+
80+
// @typescript-eslint + eslint, works together
81+
'@typescript-eslint/consistent-type-definitions': [
82+
'error',
83+
'interface'
84+
],
85+
'no-restricted-syntax': [
86+
'error',
87+
{
88+
selector: "TSPropertySignature[key.name='children']",
89+
message:
90+
'Please use PropsWithChildren<T> instead of defining children manually'
91+
}
92+
],
93+
// stylistic
94+
'@stylistic/padding-line-between-statements': [
95+
'error',
96+
{ blankLine: 'always', prev: '*', next: 'return' },
97+
{ blankLine: 'always', prev: 'directive', next: '*' },
98+
{ blankLine: 'any', prev: 'directive', next: 'directive' },
99+
{
100+
blankLine: 'always',
101+
prev: '*',
102+
next: ['enum', 'interface', 'type']
103+
}
104+
],
105+
106+
// simple-import-sort
107+
'simple-import-sort/exports': 'error',
108+
'simple-import-sort/imports': 'error',
109+
// spellchecker
110+
'@cspell/spellchecker': [
111+
'warn',
112+
{
113+
cspell: {
114+
language: 'en',
115+
dictionaries: [
116+
'typescript',
117+
'node',
118+
'html',
119+
'css',
120+
'bash',
121+
'npm'
122+
]
123+
}
124+
}
125+
]
126+
}
127+
},
128+
{
129+
...html.configs['flat/recommended'],
130+
files: ['**/*.html'],
131+
rules: {
132+
'@html-eslint/sort-attrs': [
133+
'error',
134+
{ priority: ['rel', 'name', 'id', 'type', 'class', 'style'] }
135+
]
136+
}
137+
},
138+
eslintConfigPrettier
139+
);

package.json

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "webcell-mobile",
3-
"version": "0.4.0",
3+
"version": "0.5.0",
44
"description": "Mobile App scaffold of WebCell v3, which is a PWA scaffold based on Material Design Web components, with Anti-996 sample data.",
55
"author": "[email protected]",
66
"homepage": "https://web-cell.dev/WebCell-mobile/",
@@ -13,28 +13,44 @@
1313
},
1414
"dependencies": {
1515
"browser-unhandled-rejection": "^1.0.2",
16-
"cell-router": "^3.0.1",
17-
"dom-renderer": "^2.6.1",
16+
"cell-router": "^3.0.3",
17+
"dom-renderer": "^2.6.2",
1818
"koajax": "^3.1.1",
1919
"mdui": "^2.1.3",
20-
"mobx": "^6.13.5",
21-
"web-cell": "^3.0.3",
22-
"web-utility": "^4.4.2"
20+
"mobx": "^6.13.6",
21+
"web-cell": "^3.0.4",
22+
"web-utility": "^4.4.3"
2323
},
2424
"devDependencies": {
25-
"@parcel/config-default": "~2.13.2",
26-
"@parcel/packager-raw-url": "~2.13.2",
27-
"@parcel/transformer-typescript-tsc": "~2.13.2",
28-
"@parcel/transformer-webmanifest": "~2.13.2",
29-
"@softonus/prettier-plugin-duplicate-remover": "^1.1.2",
30-
"@types/node": "^20.17.9",
25+
"@cspell/eslint-plugin": "^8.17.5",
26+
"@eslint/js": "^9.22.0",
27+
"@html-eslint/eslint-plugin": "^0.35.2",
28+
"@html-eslint/parser": "^0.35.2",
29+
"@parcel/config-default": "~2.13.3",
30+
"@parcel/packager-raw-url": "~2.13.3",
31+
"@parcel/transformer-typescript-tsc": "~2.13.3",
32+
"@parcel/transformer-webmanifest": "~2.13.3",
33+
"@stylistic/eslint-plugin": "^4.2.0",
34+
"@tailwindcss/postcss": "^4.0.14",
35+
"@types/eslint-config-prettier": "^6.11.3",
36+
"@types/node": "^22.13.10",
37+
"cross-env": "^7.0.3",
38+
"eslint": "^9.22.0",
39+
"eslint-config-prettier": "^10.1.1",
40+
"eslint-plugin-react": "^7.37.4",
41+
"eslint-plugin-simple-import-sort": "^12.1.1",
42+
"globals": "^16.0.0",
3143
"husky": "^9.1.7",
32-
"lint-staged": "^15.2.11",
33-
"parcel": "~2.13.2",
34-
"postcss": "^8.4.49",
35-
"prettier": "^3.4.2",
44+
"jiti": "^2.4.2",
45+
"lint-staged": "^15.5.0",
46+
"parcel": "~2.13.3",
47+
"postcss": "^8.5.3",
48+
"prettier": "^3.5.3",
3649
"prettier-plugin-css-order": "^2.1.2",
37-
"typescript": "~5.7.2",
50+
"prettier-plugin-tailwindcss": "^0.6.11",
51+
"tailwindcss": "^4.0.14",
52+
"typescript": "~5.8.2",
53+
"typescript-eslint": "^8.26.1",
3854
"workbox-cli": "^7.3.0"
3955
},
4056
"prettier": {
@@ -44,18 +60,19 @@
4460
"tabWidth": 4,
4561
"plugins": [
4662
"prettier-plugin-css-order",
47-
"@softonus/prettier-plugin-duplicate-remover"
63+
"prettier-plugin-tailwindcss"
4864
]
4965
},
5066
"lint-staged": {
51-
"*.{html,md,css,less,json,yml,js,ts,tsx}": "prettier --write"
67+
"*.{html,md,css,less,json,yml,js,ts,tsx}": "prettier --write",
68+
"*.{css,js,mjs,ts,tsx}": "eslint --fix"
5269
},
5370
"scripts": {
5471
"prepare": "husky",
5572
"test": "lint-staged",
5673
"clean": "rm -rf .parcel-cache/ dist/",
5774
"start": "npm run clean && parcel src/index.html",
58-
"pack": "parcel build src/index.html --public-url .",
75+
"pack": "cross-env PARCEL_WORKER_BACKEND=process parcel build src/index.html --public-url .",
5976
"build": "npm run clean && npm run pack && workbox generateSW"
6077
}
6178
}

0 commit comments

Comments
 (0)