Use XO ESLint config

master
Michał Górny 2024-01-10 22:58:43 +01:00
rodzic 20b64d8cd9
commit 3d2f7d6744
13 zmienionych plików z 105 dodań i 165 usunięć

Wyświetl plik

@ -1,49 +1,36 @@
{ {
"env": { "env": {
"browser": true,
"node": true,
"es6": true "es6": true
}, },
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {"project": ["./tsconfig.json"]},
"ecmaVersion": 2018,
"sourceType": "module"
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts"]
}
}
},
"plugins": ["@typescript-eslint"], "plugins": ["@typescript-eslint"],
"extends": "airbnb-base", "extends": [
"xo/browser",
"xo-typescript"
],
"rules": { "rules": {
"indent": ["error", "tab"], "arrow-parens": ["error", "always"],
"no-tabs": "off", "curly": ["error", "multi-line"],
"object-curly-spacing": ["error", "never"], "padding-line-between-statements": "off",
"no-param-reassign": ["error", {"props": false}], "object-shorthand": ["error", "properties"],
"import/extensions": ["error", "ignorePackages", { "@typescript-eslint/ban-types": ["error", {"extendDefaults": true}],
"js": "never", "@typescript-eslint/member-delimiter-style": ["error", {
"ts": "never" "multiline": {
}] "delimiter": "comma",
}, "requireLast": true
"overrides": [ },
{ "singleline": {
"files": ["*.ts"], "delimiter": "comma",
"parser": "@typescript-eslint/parser", "requireLast": false
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"indent": "off",
"max-len": [2, 120],
"import/prefer-default-export": "off",
"@typescript-eslint/indent": ["error", "tab"],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-non-null-assertion": "off"
} }
}],
"@typescript-eslint/padding-line-between-statements": "off"
},
"overrides": [{
"files": ["test/*.ts"],
"rules": {
"@typescript-eslint/no-confusing-void-expression": "off"
} }
] }]
} }

1
.gitignore vendored
Wyświetl plik

@ -1,2 +1,3 @@
dist dist
node_modules node_modules
.eslintcache

Wyświetl plik

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention */
const reporters = ['default']; const reporters = ['default'];
module.exports = { module.exports = {

122
package-lock.json wygenerowano
Wyświetl plik

@ -16,7 +16,7 @@
"@babel/preset-env": "^7.22.10", "@babel/preset-env": "^7.22.10",
"@babel/preset-typescript": "^7.22.5", "@babel/preset-typescript": "^7.22.5",
"@testing-library/dom": "^9.3.1", "@testing-library/dom": "^9.3.1",
"@testing-library/jest-dom": "^6.0.1", "@testing-library/jest-dom": "^6.1.6",
"@types/html-webpack-plugin": "^3.2.6", "@types/html-webpack-plugin": "^3.2.6",
"@types/jest": "^29.5.3", "@types/jest": "^29.5.3",
"@types/pug": "^2.0.6", "@types/pug": "^2.0.6",
@ -28,9 +28,9 @@
"css-loader": "^6.8.1", "css-loader": "^6.8.1",
"cssnano": "^6.0.1", "cssnano": "^6.0.1",
"eslint": "^8.47.0", "eslint": "^8.47.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-xo": "^0.43.1",
"eslint-config-xo-typescript": "^1.0.1",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.28.1",
"eslint-webpack-plugin": "^4.0.1",
"gh-pages": "^6.0.0", "gh-pages": "^6.0.0",
"html-webpack-plugin": "^5.5.3", "html-webpack-plugin": "^5.5.3",
"jest": "^29.6.2", "jest": "^29.6.2",
@ -45,7 +45,6 @@
"pug": "^3.0.2", "pug": "^3.0.2",
"stylelint": "^14.16.1", "stylelint": "^14.16.1",
"stylelint-config-standard": "^29.0.0", "stylelint-config-standard": "^29.0.0",
"stylelint-webpack-plugin": "^4.1.1",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.1",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^5.1.6", "typescript": "^5.1.6",
@ -64,9 +63,9 @@
} }
}, },
"node_modules/@adobe/css-tools": { "node_modules/@adobe/css-tools": {
"version": "4.3.1", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz",
"integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==",
"dev": true "dev": true
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
@ -3786,12 +3785,12 @@
} }
}, },
"node_modules/@testing-library/jest-dom": { "node_modules/@testing-library/jest-dom": {
"version": "6.1.4", "version": "6.1.6",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.4.tgz", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.6.tgz",
"integrity": "sha512-wpoYrCYwSZ5/AxcrjLxJmCU6I5QAJXslEeSiMQqaWmP2Kzpd1LvF/qxmAIW2qposULGWq2gw30GgVNFLSc2Jnw==", "integrity": "sha512-YwuiOdYEcxhfC2u5iNKlvg2Q5MgbutovP6drq7J1HrCbvR+G58BbtoCoq+L/kNlrNFsu2Kt3jaFAviLVxYHJZg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@adobe/css-tools": "^4.3.1", "@adobe/css-tools": "^4.3.2",
"@babel/runtime": "^7.9.2", "@babel/runtime": "^7.9.2",
"aria-query": "^5.0.0", "aria-query": "^5.0.0",
"chalk": "^3.0.0", "chalk": "^3.0.0",
@ -7507,23 +7506,40 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint-config-airbnb-base": { "node_modules/eslint-config-xo": {
"version": "15.0.0", "version": "0.43.1",
"resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.43.1.tgz",
"integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "integrity": "sha512-azv1L2PysRA0NkZOgbndUpN+581L7wPqkgJOgxxw3hxwXAbJgD6Hqb/SjHRiACifXt/AvxCzE/jIKFAlI7XjvQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"confusing-browser-globals": "^1.0.10", "confusing-browser-globals": "1.0.11"
"object.assign": "^4.1.2",
"object.entries": "^1.1.5",
"semver": "^6.3.0"
}, },
"engines": { "engines": {
"node": "^10.12.0 || >=12.0.0" "node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^7.32.0 || ^8.2.0", "eslint": ">=8.27.0"
"eslint-plugin-import": "^2.25.2" }
},
"node_modules/eslint-config-xo-typescript": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/eslint-config-xo-typescript/-/eslint-config-xo-typescript-1.0.1.tgz",
"integrity": "sha512-vPQssnRSUgBFOEfB/KY12CXwltwFSn4RSCfa+w7gjBC2PFQ7Yfgmyei+1XUZ3K+8LRGef2NMJUcxts7PldhDjg==",
"dev": true,
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": ">=6.0.0",
"@typescript-eslint/parser": ">=6.0.0",
"eslint": ">=8.0.0",
"typescript": ">=4.7"
} }
}, },
"node_modules/eslint-import-resolver-node": { "node_modules/eslint-import-resolver-node": {
@ -7652,30 +7668,6 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint-webpack-plugin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-4.0.1.tgz",
"integrity": "sha512-fUFcXpui/FftGx3NzvWgLZXlLbu+m74sUxGEgxgoxYcUtkIQbS6SdNNZkS99m5ycb23TfoNYrDpp1k/CK5j6Hw==",
"dev": true,
"dependencies": {
"@types/eslint": "^8.37.0",
"jest-worker": "^29.5.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"schema-utils": "^4.0.0"
},
"engines": {
"node": ">= 14.15.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"eslint": "^8.0.0",
"webpack": "^5.0.0"
}
},
"node_modules/eslint/node_modules/ansi-styles": { "node_modules/eslint/node_modules/ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -12701,20 +12693,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/object.entries": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
"integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.2.0",
"es-abstract": "^1.22.1"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/object.fromentries": { "node_modules/object.fromentries": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
@ -16047,30 +16025,6 @@
"stylelint": "^14.14.0" "stylelint": "^14.14.0"
} }
}, },
"node_modules/stylelint-webpack-plugin": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/stylelint-webpack-plugin/-/stylelint-webpack-plugin-4.1.1.tgz",
"integrity": "sha512-yOyd2AfrxfawxKDememazGVJX2vMq9o11E6HvBu4+SKvgK3ZulkjpYdI1muBTxItwoxH2UmfIZzQM+/M5V3kTQ==",
"dev": true,
"dependencies": {
"globby": "^11.1.0",
"jest-worker": "^29.5.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"schema-utils": "^4.0.0"
},
"engines": {
"node": ">= 14.15.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0",
"webpack": "^5.0.0"
}
},
"node_modules/stylelint/node_modules/@csstools/selector-specificity": { "node_modules/stylelint/node_modules/@csstools/selector-specificity": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz",

Wyświetl plik

@ -9,6 +9,10 @@
"scripts": { "scripts": {
"start": "webpack-dev-server --mode=development", "start": "webpack-dev-server --mode=development",
"test": "jest", "test": "jest",
"typecheck": "npx tsc",
"lint:js": "npx eslint . --ext .ts --cache",
"lint:css": "npx stylelint \"src/**/*.css\"",
"lint": "npm run lint:js; npm run lint:css",
"build": "webpack --mode=production", "build": "webpack --mode=production",
"deploy": "gh-pages -d dist" "deploy": "gh-pages -d dist"
}, },
@ -26,7 +30,7 @@
"@babel/preset-env": "^7.22.10", "@babel/preset-env": "^7.22.10",
"@babel/preset-typescript": "^7.22.5", "@babel/preset-typescript": "^7.22.5",
"@testing-library/dom": "^9.3.1", "@testing-library/dom": "^9.3.1",
"@testing-library/jest-dom": "^6.0.1", "@testing-library/jest-dom": "^6.1.6",
"@types/html-webpack-plugin": "^3.2.6", "@types/html-webpack-plugin": "^3.2.6",
"@types/jest": "^29.5.3", "@types/jest": "^29.5.3",
"@types/pug": "^2.0.6", "@types/pug": "^2.0.6",
@ -38,9 +42,9 @@
"css-loader": "^6.8.1", "css-loader": "^6.8.1",
"cssnano": "^6.0.1", "cssnano": "^6.0.1",
"eslint": "^8.47.0", "eslint": "^8.47.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-xo": "^0.43.1",
"eslint-config-xo-typescript": "^1.0.1",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.28.1",
"eslint-webpack-plugin": "^4.0.1",
"gh-pages": "^6.0.0", "gh-pages": "^6.0.0",
"html-webpack-plugin": "^5.5.3", "html-webpack-plugin": "^5.5.3",
"jest": "^29.6.2", "jest": "^29.6.2",
@ -55,7 +59,6 @@
"pug": "^3.0.2", "pug": "^3.0.2",
"stylelint": "^14.16.1", "stylelint": "^14.16.1",
"stylelint-config-standard": "^29.0.0", "stylelint-config-standard": "^29.0.0",
"stylelint-webpack-plugin": "^4.1.1",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.1",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^5.1.6", "typescript": "^5.1.6",

Wyświetl plik

@ -1,4 +1,4 @@
import { import type {
PastSupport, PastSupport,
Committee, Committee,
Constituency, Constituency,

Wyświetl plik

@ -61,7 +61,7 @@ const displayUrl = (support: number[]) => {
if (s > 0) searchParams.append(committees[i].id, s.toString()); if (s > 0) searchParams.append(committees[i].id, s.toString());
}); });
const urlWithoutSearchString = location.href.split('?')[0]; const urlWithoutSearchString = location.href.split('?')[0];
const url = `${urlWithoutSearchString}?${searchParams}`; const url = `${urlWithoutSearchString}?${searchParams.toString()}`;
document.getElementById('url')!.innerHTML = `Link do wyników: ${url.link(url)}`; document.getElementById('url')!.innerHTML = `Link do wyników: ${url.link(url)}`;
} }
}; };
@ -147,7 +147,7 @@ const displayConstituencyResults = () => {
const data = (constituency.mandates && constituency.support) const data = (constituency.mandates && constituency.support)
? constituency.mandates.map((mandates, committeeIndex) => ({ ? constituency.mandates.map((mandates, committeeIndex) => ({
committee: committees[committeeIndex], committee: committees[committeeIndex],
support: (constituency.support as number[])[committeeIndex], support: (constituency.support!)[committeeIndex],
mandates, mandates,
})) }))
: []; : [];
@ -164,7 +164,7 @@ const displayConstituencyResults = () => {
const pathElement = event.target as SVGPathElement; const pathElement = event.target as SVGPathElement;
pathElement.style.stroke = '#444'; pathElement.style.stroke = '#444';
constituencyNumber.innerHTML = `Okręg nr ${pathElement.dataset.cid}`; constituencyNumber.innerHTML = `Okręg nr ${pathElement.dataset.cid}`;
constituencyName.innerHTML = pathElement.dataset.cname as string; constituencyName.innerHTML = pathElement.dataset.cname!;
}); });
path.addEventListener('mouseout', (event) => { path.addEventListener('mouseout', (event) => {
const pathElement = event.target as SVGPathElement; const pathElement = event.target as SVGPathElement;
@ -187,7 +187,9 @@ const displayConstituencyResults = () => {
}; };
const validate = (form: HTMLFormElement, inputs: NodeListOf<HTMLInputElement>, support: number[]) => { const validate = (form: HTMLFormElement, inputs: NodeListOf<HTMLInputElement>, support: number[]) => {
inputs.forEach((input) => input.setCustomValidity('')); inputs.forEach((input) => {
input.setCustomValidity('');
});
support.some((inputValue, index) => { support.some((inputValue, index) => {
if (inputValue < 0) { if (inputValue < 0) {
@ -225,9 +227,11 @@ export const calculate = (): void => {
pieChart = displayPieChart(mandates); pieChart = displayPieChart(mandates);
displayConstituencyResults(); displayConstituencyResults();
inputs.forEach((input) => input.addEventListener('input', () => { inputs.forEach((input) => {
clearResults(); input.addEventListener('input', () => {
})); clearResults();
});
});
}; };
export const generateTable = (): void => { export const generateTable = (): void => {

Wyświetl plik

@ -1,5 +1,5 @@
import {committees, constituencies, pastSupport} from './data'; import {committees, constituencies, pastSupport} from './data';
import {Constituency} from './types'; import type {Constituency} from './types';
const calculateLocalSupport = ( const calculateLocalSupport = (
support: number[], support: number[],
@ -31,7 +31,7 @@ export default (support: number[]): number[] => {
.map((pastCommittee) => pastSupport[pastCommittee[0]] * pastCommittee[1]) .map((pastCommittee) => pastSupport[pastCommittee[0]] * pastCommittee[1])
.reduce((a, b) => a + b, 0) .reduce((a, b) => a + b, 0)
)); ));
const mandates: number[] = new Array(support.length + 1).fill(0); const mandates = new Array(support.length + 1).fill(0) as number[];
constituencies.forEach((constituency) => { constituencies.forEach((constituency) => {
const localSupport = calculateLocalSupport(support, pastSupportProjection, constituency); const localSupport = calculateLocalSupport(support, pastSupportProjection, constituency);
constituency.support = localSupport; constituency.support = localSupport;
@ -40,7 +40,7 @@ export default (support: number[]): number[] => {
if (support[index] < committees[index].threshold) return 0; if (support[index] < committees[index].threshold) return 0;
return localCommitteeSupport; return localCommitteeSupport;
}); });
const quotients: {quotient: number; committeeIndex: number}[] = []; const quotients: Array<{quotient: number, committeeIndex: number}> = [];
for (let divisor = 1; divisor <= constituency.size; divisor += 1) { for (let divisor = 1; divisor <= constituency.size; divisor += 1) {
for (let committeeIndex = 0; committeeIndex < localSupport.length; committeeIndex += 1) { for (let committeeIndex = 0; committeeIndex < localSupport.length; committeeIndex += 1) {
quotients.push({ quotients.push({

Wyświetl plik

@ -1,5 +1,5 @@
declare module '*.pug' { declare module '*.pug' {
import pug = require('pug'); import type pug from 'pug';
const content: pug.compileTemplate; const content: pug.compileTemplate;
export = content; export = content;

Wyświetl plik

@ -1,21 +1,21 @@
type PastCommiteeId = 'pis' | 'ko' | 'td' | 'lewica' | 'konfederacja' type PastCommiteeId = 'pis' | 'ko' | 'td' | 'lewica' | 'konfederacja';
export type PastSupport = { export type PastSupport = {
[pastCommitteeId in PastCommiteeId]: number; [pastCommitteeId in PastCommiteeId]: number;
} };
export type Committee = { export type Committee = {
id: string; id: string,
name: string; name: string,
shortName: string; shortName: string,
threshold: number; threshold: number,
pastSupportEquivalence: [PastCommiteeId, number][]; pastSupportEquivalence: Array<[PastCommiteeId, number]>,
} };
export type Constituency = { export type Constituency = {
name: string; name: string,
size: number; size: number,
pastSupport: PastSupport; pastSupport: PastSupport,
support?: number[]; support?: number[],
mandates?: number[]; mandates?: number[],
} };

Wyświetl plik

@ -1,4 +1,4 @@
window.matchMedia = jest.fn().mockImplementation((query) => ({ window.matchMedia = jest.fn().mockImplementation((query: string) => ({
matches: false, matches: false,
media: query, media: query,
onchange: null, onchange: null,

Wyświetl plik

@ -5,6 +5,7 @@
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "./dist/", "outDir": "./dist/",
"removeComments": true, "removeComments": true,
"skipLibCheck": true,
"sourceMap": true, "sourceMap": true,
"strict": true, "strict": true,
"target": "ES5" "target": "ES5"

Wyświetl plik

@ -1,9 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import path from 'path'; import path from 'path';
import ESLintPlugin from 'eslint-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import StyleLintPlugin from 'stylelint-webpack-plugin';
export default { export default {
target: 'web', target: 'web',
@ -63,14 +60,6 @@ export default {
filename: '[name].css', filename: '[name].css',
chunkFilename: '[id].css', chunkFilename: '[id].css',
}), }),
new ESLintPlugin({
files: ['./*.[jt]s', './src/**/*.[jt]s'],
}),
new StyleLintPlugin({
configFile: path.resolve(__dirname, '.stylelintrc.json'),
context: path.resolve(__dirname, './src'),
files: '**/*.css',
}),
], ],
devServer: { devServer: {
watchFiles: ['src/**/*'], watchFiles: ['src/**/*'],