Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: eslint #32

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"macrolanguage",
"Subtag",
"subtags",
"tseslint",
"typecheck"
]
}
18 changes: 0 additions & 18 deletions components/language-chooser/common/find-language/.eslintrc.cjs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export interface ILanguage {
alternativeTags: string[];
isForMacrolanguageDisambiguation?: boolean;
isMacrolanguage?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any; // allow indexing by string
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// This file has lots of anys in order to parse and process langtags.json
import { iso15924 } from "iso-15924";
import langTagsJson from "./language-data/langtags.json" assert { type: "json" };
import fs from "fs";
Expand Down Expand Up @@ -92,7 +94,7 @@ function getAllPossibleNames(entry: any) {
function autonymOrFallback(entry: any, fallback: string | undefined) {
// We are currently ignoring the "localname" field because it appears to be more specific than what we want,
// e.g. the "es-Latn-ES" entry of langtags.json has "localname": "español de España" and "localnames": [ "castellano", "español" ]
return entry.localnames ? entry.localnames[0] : undefined ?? fallback;
return entry.localnames ? entry.localnames[0] : fallback;
}

// We want to have one entry for every ISO 639-3 code, whereas langtags.json sometimes has multiple entries per code
Expand Down Expand Up @@ -245,7 +247,7 @@ function parseLangTagsTxt() {
const langTagsTxtRaw = fs.readFileSync("language-data/langtags.txt", "utf8");
const langTagsTxt = langTagsTxtRaw.replaceAll("*", "");
const lines = langTagsTxt.split("\n");
const tagLookups = [];
const tagLookups: any[] = [];
for (const line of lines) {
if (line.length === 0) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function deepStripDemarcation<T>(demarcated: T): T {
return demarcated.map((element) => deepStripDemarcation(element)) as T;
}
if (typeof demarcated === "object") {
const newObject = {} as any;
const newObject: any = {};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these anys okay? Also on line 65. Would it be better to create a new interface e.g.
`
interface Foo {
[key: string]: T;
} and if so what should it be called? Seems like a lot of code for something so small?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok with me.

for (const key of Object.keys(demarcated)) {
newObject[key] = deepStripDemarcation((demarcated as any)[key]);
}
Expand All @@ -76,7 +76,7 @@ export function deepStripDemarcation<T>(demarcated: T): T {
export function demarcateExactMatches(searchString: string, result: ILanguage) {
for (const field of fieldsToSearch) {
if (Array.isArray(result[field])) {
result[field] = result[field].map((value: any) =>
result[field] = result[field].map((value: string) =>
demarcateExactMatchString(searchString, value)
);
} else if (typeof result[field] === "string") {
Expand Down
9 changes: 5 additions & 4 deletions components/language-chooser/common/find-language/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"main": "./index.js",
"types": "./index.d.ts",
"scripts": {
"langtag-processing": "ts-node-esm ./langtagProcessing.ts",
"langtag-processing": "tsx ./langtagProcessing.ts",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if we're going sticking with node 18 for now, I figure we might as well keep this change so that we can upgrade node in the future

"build": "nx vite:build",
"typecheck": "tsc",
"test": "nx vite:test --config vitest.config.ts"
"test": "nx vite:test --config vitest.config.ts",
"lint": "eslint ."
},
"dependencies": {
"fuse.js": "^7.0.0",
Expand All @@ -20,11 +21,11 @@
"devDependencies": {
"@nx/vite": "^19.1.2",
"@types/node": "^20.16.11",
"ts-node": "^10.9.2",
"tsx": "^4.19.2",
"typescript": "^5.2.2"
},
"// We've tested with 18 and have no reason to believe it won't work with higher versions": "",
"engines": {
"node": ">=18.0.0"
"node": ">=18.18"
}
}
4 changes: 2 additions & 2 deletions components/language-chooser/common/find-language/testUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ILanguage } from "./findLanguageInterfaces";
import { ILanguage, IScript } from "./findLanguageInterfaces";

interface ILanguageTestEntry {
autonym?: string;
Expand All @@ -7,7 +7,7 @@ interface ILanguageTestEntry {
languageSubtag?: string;
regionNames?: string;
names?: string[];
scripts?: any[];
scripts?: IScript[];
variants?: string;
alternativeTags?: string[];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"typecheck": "tsc",
"prebuild": "npm run typecheck",
"build": "nx vite:build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint": "eslint .",
"test": "nx vite:test --config vitest.config.ts"
},
"dependencies": {
Expand All @@ -23,17 +23,12 @@
"@types/lodash": "^4.17.7",
"@types/react": "^17",
"@types/react-dom": "^17",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"typescript": "^5.2.2",
"vite-plugin-dts": "^4.2.1"
},
"// We've tested with 18 and have no reason to believe it won't work with higher versions": "",
"// We've tested with 18.18 and have no reason to believe it won't work with higher versions": "",
"engines": {
"node": ">=18.0.0"
"node": ">=18.18"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useMemo, useState } from "react";
import { FuseResult } from "fuse.js";
import {
ICustomizableLanguageDetails,
IOrthography,
isUnlistedLanguage,
parseLangtagFromLangChooser,
UNLISTED_LANGUAGE,
Expand Down Expand Up @@ -145,7 +144,7 @@ export const useLanguageChooser = (
setSelectedLanguage(language);
setSelectedScript(
// If there is only one script option for this language, automatically select it
language.scripts.length == 1 ? language.scripts[0] : undefined
language.scripts.length === 1 ? language.scripts[0] : undefined
);
setCustomizableLanguageDetails({
displayName: stripDemarcation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"typecheck": "tsc",
"prebuild": "npm run typecheck",
"build": "nx vite:build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
"lint": "eslint ."
},
"dependencies": {
"lodash": "^4.17.21",
Expand All @@ -32,12 +32,6 @@
"@types/react": "^17",
"@types/react-dom": "^17",
"@types/react-lazyload": "^3.2.3",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"storybook": "^8.2.8",
"typescript": "^5.2.2",
"vite-plugin-dts": "^4.2.1"
Expand All @@ -52,6 +46,6 @@
},
"// We've tested with 18 and have no reason to believe it won't work with higher versions": "",
"engines": {
"node": ">=18.0.0"
"node": ">=18.18"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ import {
OptionCardPropsWithoutColors,
} from "./OptionCard";
import { ILanguage } from "@ethnolib/find-language";
import { memo } from "react";
import { PartiallyBoldedTypography } from "./PartiallyBoldedTypography";
import { COLORS } from "./colors";

const COMMA_SEPARATOR = ", ";

export const LanguageCard: React.FunctionComponent<
{ languageCardData: ILanguage } & OptionCardPropsWithoutColors
> = memo(({ languageCardData, ...partialOptionCardProps }) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memo was not making a noticeable difference in speed now that we lazyload

> = ({ languageCardData, ...partialOptionCardProps }) => {
const optionCardProps = {
...partialOptionCardProps,
backgroundColorWhenNotSelected: COLORS.white,
Expand Down Expand Up @@ -91,4 +90,4 @@ export const LanguageCard: React.FunctionComponent<
)}
</OptionCard>
);
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const LanguageChooser: React.FunctionComponent<{
props.initialSelectionLanguageTag,
props.initialCustomDisplayName
);
}, []);
}, []); // We only want this to run once

const [customizeLanguageDialogOpen, setCustomizeLanguageDialogOpen] =
useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const OptionCard: React.FunctionComponent<
? props.backgroundColorWhenSelected || COLORS.white
: props.backgroundColorWhenNotSelected || COLORS.white;
return (
<CardActionArea onClick={props.onClick || (() => {})}>
<CardActionArea onClick={props.onClick || (() => undefined)}>
<Card
variant="outlined"
css={css`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OptionCard } from "../OptionCard";
import { Typography } from "@mui/material";

// Just a quick dummy to demonstrate the right panel slot
export const DummyRightPanelComponent: React.FunctionComponent<{}> = () => {
export const DummyRightPanelComponent: React.FunctionComponent = () => {
const darkColor = "#800303";
const lightColor = "#e3dada";
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const darkColor = "#800303";
const mediumColor = "#bd746f";
const lightColor = "#e8caca";

export const PageDemo: React.FunctionComponent<{}> = (props) => {
export const PageDemo: React.FunctionComponent = () => {
return (
<div
css={css`
Expand Down Expand Up @@ -221,7 +221,7 @@ export const PageDemo: React.FunctionComponent<{}> = (props) => {
border-radius: 0px;
`}
searchResultModifier={defaultSearchResultModifier}
onClose={() => {}}
onClose={() => undefined}
/>
</div>
</div>
Expand Down
85 changes: 85 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// @ts-check
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should live-review this file? Let me know if you think that would be helpful

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is necessary. But happy to discuss if that helps.


import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import reactPlugin from "eslint-plugin-react";
import eslintConfigPrettier from "eslint-config-prettier";
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
// import eslintPluginReactHooks from "eslint-plugin-react-hooks";
// TODO future work: eslint-plugin-react-hooks support for flat-config looks like it's on it's way:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put adding eslint-plugin-react-hooks into the kanban

// https://github.com/facebook/react/pull/30774. I say we wait for it to be released then can easily add it

export default [
{
ignores: ["**/node_modules/**/*", "**/dist/**"],
},
eslint.configs.recommended,
eslintConfigPrettier, // disables eslint rules that could conflict with prettier
eslintPluginPrettierRecommended,
...tseslint.config(
// tseslint.config() is a helper function giving autocomplete and documentation https://typescript-eslint.io/packages/typescript-eslint#config
// not sure if we want this, we can get rid of it if it causes any trouble
...tseslint.configs.recommended,
{
files: ["**/*.{ts,tsx}"],
plugins: {
"@typescript-eslint": tseslint.plugin,
},
rules: {
// Copied from BloomDesktop
"prettier/prettier": "off",
"no-var": "warn",
"prefer-const": "warn",
"no-useless-escape": "off",
"no-irregular-whitespace": [
"error",
{ skipStrings: true, skipTemplates: true },
],
"no-warning-comments": [
1,
{ terms: ["nocommit"], location: "anywhere" },
],
// Downgraded from error to warnings
"@typescript-eslint/no-empty-function": "warn",
"@typescript-eslint/no-empty-interface": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
"@typescript-eslint/no-var-requires": "warn",
"no-case-declarations": "warn",
"prefer-rest-params": "warn",
"prefer-spread": "warn",
eqeqeq: ["warn", "always"],
// Disabled
"@typescript-eslint/ban-types": "off", // Record<string, never> is not intuitive for us compared to {}
"@typescript-eslint/no-inferrable-types": "off", // not worth worrying about (not even convinced it's a problem at all)
},
}
),

// React configs to be applied to react files only
...[
reactPlugin.configs.flat?.recommended,
reactPlugin.configs.flat?.["jsx-runtime"],
{
settings: {
react: {
version: "17.0", // React version. Should match the version which the react packages are using. Currently cannot be automatically detected because we don't have react installed at the root (here)
},
},
plugins: {
react: reactPlugin,
},
rules: {
// Copied from BloomDesktop
"react/no-unknown-property": ["error", { ignore: ["css"] }], // allow emotion css: https://emotion.sh/docs/eslint-plugin-react
"react/no-unescaped-entities": "off", // Complains about some special chars that sort of work, but due to the burden that enocded chars present to localizers, we'd prefer not to encode them if not necessary.
"react/prop-types": "off", // Seems to require validation on the props parameter itself, but Typescript can already figure out the types through annotations in different places, seems unnecessary
},
},
].map((c) => {
return { ...c, files: ["**/*.{jsx,mjsx,tsx,mtsx}"] };
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also limit things to folders, i.e. files: ["components/language-chooser/react/**/*/.{jsx,mjsx,tsx,mtsx}"]. Should we talk more about how to setup what eslint rules apply to where?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to discuss if that's helpful. But applying react rules to react files makes sense.

}),
];
Loading