Skip to content

Commit 1fd7421

Browse files
Fix some ESLint problems
1 parent 9e12d1c commit 1fd7421

13 files changed

+62
-60
lines changed

src/Classes/CustomElement.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { createElement, Fragment } from "react";
2-
import type { HTMLAttributes, ReactElement } from "react";
32

43
import styled from "@emotion/styled";
54

65
import type { ReactNode } from "../consts";
76
import type { Property } from "csstype";
7+
import type { HTMLAttributes, ReactElement } from "react";
88

99
const Missing = styled.span`
1010
&:after {
1111
content: "\xa0";
1212
}
1313
`;
1414

15-
type TagToProp = {
15+
interface TagToProp {
1616
f: undefined;
1717
b: undefined;
1818
i: undefined;
@@ -23,7 +23,7 @@ type TagToProp = {
2323
fg: Property.Color;
2424
bg: Property.BackgroundColor;
2525
size: Property.FontSize<string | number>;
26-
};
26+
}
2727

2828
type AllTags = keyof TagToProp;
2929
type Tag = {

src/Components/App.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import "purecss/build/pure.css";
2-
31
import { useCallback, useRef } from "react";
42

3+
import "purecss/build/pure.css";
4+
// NOTE sweetalert2's ESM export does not setup styles properly, manually importing
5+
import "sweetalert2/dist/sweetalert2.css";
6+
57
import { injectGlobal, css as stylesheet } from "@emotion/css";
68
import styled from "@emotion/styled";
79
import { faCirclePlay, faExternalLink, faInfo, faQuestion } from "@fortawesome/free-solid-svg-icons";
@@ -11,9 +13,7 @@ import Main from "./Main";
1113
import Swal from "../Classes/SwalReact";
1214
import { codeFontFamily, noop } from "../consts";
1315

14-
// NOTE sweetalert2's ESM export does not setup styles properly, manually importing
15-
import "sweetalert2/dist/sweetalert2.css";
16-
16+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
1717
injectGlobal`
1818
html,
1919
body {

src/Components/CreateSchemaDialog.tsx

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeEventHandler, forwardRef, RefObject, useCallback, useEffect, useMemo, useRef, useState } from "react";
1+
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
22
import { createPortal } from "react-dom";
33

44
import { css } from "@emotion/react";
@@ -10,11 +10,12 @@ import ExplorerFolder from "./ExplorerFolder";
1010
import Spinner from "./Spinner";
1111
import actions from "../actions";
1212
import Swal from "../Classes/SwalReact";
13-
import { invalidCharsRegex, newFileTemplate, tshetUinhExamplesURLPrefix, UseMainState } from "../consts";
13+
import { invalidCharsRegex, newFileTemplate, tshetUinhExamplesURLPrefix } from "../consts";
1414
import samples from "../samples";
1515
import { fetchFile, normalizeFileName } from "../utils";
1616

17-
import type { Folder, Sample, SchemaState } from "../consts";
17+
import type { Folder, Sample, SchemaState, UseMainState } from "../consts";
18+
import type { ChangeEventHandler, RefObject } from "react";
1819

1920
const Container = styled.dialog`
2021
transform: scale(0.9);
@@ -183,12 +184,12 @@ const CreateSchemaDialog = forwardRef<HTMLDialogElement, CreateSchemaDialogProps
183184
{ state: { schemas }, setState, getDefaultFileName, schemaLoaded, hasSchemaName },
184185
ref,
185186
) {
186-
const [createSchemaName, setCreateSchemaName] = useState(() => getDefaultFileName("") + ".js");
187+
const [createSchemaName, setCreateSchemaName] = useState(() => `${getDefaultFileName("")}.js`);
187188
const [createSchemaSample, setCreateSchemaSample] = useState<Sample | "">("");
188189
const [loading, setLoading] = useState(false);
189190

190191
const resetDialog = useCallback(() => {
191-
setCreateSchemaName(getDefaultFileName("") + ".js");
192+
setCreateSchemaName(`${getDefaultFileName("")}.js`);
192193
setCreateSchemaSample("");
193194
setLoading(false);
194195
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -199,7 +200,7 @@ const CreateSchemaDialog = forwardRef<HTMLDialogElement, CreateSchemaDialogProps
199200
const name = normalizeFileName(createSchemaName);
200201
if (!name) return "檔案名稱為空";
201202
if (invalidCharsRegex.test(name)) return "檔案名稱含有特殊字元";
202-
if (hasSchemaName(name + ".js")) return "檔案名稱與現有檔案重複";
203+
if (hasSchemaName(`${name}.js`)) return "檔案名稱與現有檔案重複";
203204
return "";
204205
}, [createSchemaName, hasSchemaName]);
205206

@@ -216,7 +217,7 @@ const CreateSchemaDialog = forwardRef<HTMLDialogElement, CreateSchemaDialogProps
216217
onClick={() => {
217218
const name = normalizeFileName(createSchemaName);
218219
if (!name || name === getDefaultFileName(createSchemaSample))
219-
setCreateSchemaName(getDefaultFileName(sample) + ".js");
220+
setCreateSchemaName(`${getDefaultFileName(sample)}.js`);
220221
setCreateSchemaSample(sample);
221222
}}>
222223
<div>
@@ -236,9 +237,9 @@ const CreateSchemaDialog = forwardRef<HTMLDialogElement, CreateSchemaDialogProps
236237
setLoading(true);
237238
try {
238239
schemaLoaded({
239-
name: normalizeFileName(createSchemaName) + ".js",
240+
name: `${normalizeFileName(createSchemaName)}.js`,
240241
input: createSchemaSample
241-
? await fetchFile(tshetUinhExamplesURLPrefix + createSchemaSample + ".js")
242+
? await fetchFile(`${tshetUinhExamplesURLPrefix + createSchemaSample}.js`)
242243
: newFileTemplate,
243244
});
244245
} catch {
@@ -266,7 +267,7 @@ const CreateSchemaDialog = forwardRef<HTMLDialogElement, CreateSchemaDialogProps
266267
setState(
267268
actions.addSchema({
268269
name: "tupa.js",
269-
input: await fetchFile(tshetUinhExamplesURLPrefix + "tupa.js"),
270+
input: await fetchFile(`${tshetUinhExamplesURLPrefix}tupa.js`),
270271
}),
271272
);
272273
Swal.close();
@@ -296,7 +297,7 @@ const CreateSchemaDialog = forwardRef<HTMLDialogElement, CreateSchemaDialogProps
296297
onClick={() => {
297298
const name = normalizeFileName(createSchemaName);
298299
if (!name || name === getDefaultFileName(createSchemaSample))
299-
setCreateSchemaName(getDefaultFileName("") + ".js");
300+
setCreateSchemaName(`${getDefaultFileName("")}.js`);
300301
setCreateSchemaSample("");
301302
}}>
302303
<div>

src/Components/Main.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MutableRefObject, useCallback, useEffect, useReducer, useRef, useState } from "react";
1+
import { useCallback, useEffect, useReducer, useRef, useState } from "react";
22
import { createPortal } from "react-dom";
33

44
import styled from "@emotion/styled";
@@ -16,6 +16,7 @@ import initialState, { stateStorageLocation } from "../state";
1616
import { copy, notifyError } from "../utils";
1717

1818
import type { MainState, Option, ReactNode } from "../consts";
19+
import type { MutableRefObject } from "react";
1920

2021
const dummyOutput = document.createElement("output");
2122

src/Components/SchemaEditor.tsx

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2-
import type { MouseEvent, MutableRefObject } from "react";
32
import { createPortal } from "react-dom";
43

54
import { css } from "@emotion/react";
@@ -18,6 +17,7 @@ import "../editor/setup";
1817
import { memoize, normalizeFileName, notifyError } from "../utils";
1918

2019
import type { UseMainState, ReactNode } from "../consts";
20+
import type { MouseEvent, MutableRefObject } from "react";
2121

2222
const TabBar = styled.div`
2323
display: flex;
@@ -234,10 +234,10 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
234234
sample ||= "untitled";
235235
const indices = schemaNames
236236
.map(name => {
237-
if (name === sample + ".js") return 0;
238-
if (!name.startsWith(sample + "-") || !name.endsWith(".js")) return -1;
237+
if (name === `${sample}.js`) return 0;
238+
if (!name.startsWith(`${sample}-`) || !name.endsWith(".js")) return -1;
239239
const start = sample.length + 1;
240-
for (let i = start; i < name.length - 3; i++) if (name[i] < +(i === start) + "" || name[i] > "9") return -1;
240+
for (let i = start; i < name.length - 3; i++) if (name[i] < `${+(i === start)}` || name[i] > "9") return -1;
241241
return +name.slice(start, -3);
242242
})
243243
.sort((a, b) => a - b);
@@ -268,10 +268,9 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
268268
for (const file of files) {
269269
// POSIX allows all characters other than `\0` and `/` in file names,
270270
// this is necessary to ensure that the file name is valid on all platforms.
271-
const name =
272-
getDefaultFileNameWithSchemaNames(currSchemaNames)(
273-
normalizeFileName(file.name).replace(invalidCharsRegex, "_"),
274-
) + ".js";
271+
const name = `${getDefaultFileNameWithSchemaNames(currSchemaNames)(
272+
normalizeFileName(file.name).replace(invalidCharsRegex, "_"),
273+
)}.js`;
275274
currSchemaNames.push(name);
276275
newState = actions.addSchema({ name, input: contents[i++] })(newState);
277276
}
@@ -408,7 +407,7 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
408407
const index = schemas.findIndex(schema => schema.name === name);
409408
const children = [].slice.call(tabBarRef.current.children, 0, -1) as HTMLElement[];
410409
const widths = children.map(element => element.getBoundingClientRect().width);
411-
const currentWidth = widths[index] + "px";
410+
const currentWidth = `${widths[index]}px`;
412411
const threshold: number[] = [];
413412
threshold[index] = 0;
414413

@@ -424,22 +423,22 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
424423
let clientX = startX;
425424

426425
function move(event: { clientX: number } | TouchEvent) {
427-
clientX = "clientX" in event ? event.clientX : (event.touches?.[0]?.clientX ?? clientX);
426+
clientX = "clientX" in event ? event.clientX : (event.touches[0].clientX ?? clientX);
428427
let value = clientX - startX;
429-
children[index].style.left = value + "px";
428+
children[index].style.left = `${value}px`;
430429
if (value < 0) {
431430
value = -value;
432431
for (let i = 0; i < index; i++) children[i].style.left = value >= threshold[i] ? currentWidth : "";
433432
for (let i = length - 1; i > index; i--) children[i].style.left = "";
434433
} else {
435434
for (let i = 0; i < index; i++) children[i].style.left = "";
436435
for (let i = length - 1; i > index; i--)
437-
children[i].style.left = value >= threshold[i] ? "-" + currentWidth : "";
436+
children[i].style.left = value >= threshold[i] ? `-${currentWidth}` : "";
438437
}
439438
}
440439

441440
function end(event: { clientX: number } | TouchEvent) {
442-
clientX = "clientX" in event ? event.clientX : (event.touches?.[0]?.clientX ?? clientX);
441+
clientX = "clientX" in event ? event.clientX : (event.touches[0].clientX ?? clientX);
443442
let value = clientX - startX;
444443
children.forEach(element => (element.style.left = ""));
445444
let i: number;
@@ -475,7 +474,7 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
475474
const hasSchemaName = (name: string) => schemas.find(schema => schema.name === name);
476475
if (!name) return "檔案名稱為空";
477476
if (invalidCharsRegex.test(name)) return "檔案名稱含有特殊字元";
478-
if (hasSchemaName(name + ".js")) return "檔案名稱與現有檔案重複";
477+
if (hasSchemaName(`${name}.js`)) return "檔案名稱與現有檔案重複";
479478
return "";
480479
}
481480

@@ -497,15 +496,15 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
497496
confirmButtonText: "確定",
498497
cancelButtonText: "取消",
499498
});
500-
const confirmButton = Swal.getConfirmButton() as HTMLButtonElement;
499+
const confirmButton = Swal.getConfirmButton()!;
501500
confirmButton.disabled = true;
502501
confirmButton.style.pointerEvents = "none";
503-
const input = Swal.getInput() as HTMLInputElement;
502+
const input = Swal.getInput()!;
504503
input.addEventListener("input", () => {
505504
const newName = normalizeFileName(input.value);
506505
const validation = validateFileName(newName);
507506
if (validation) {
508-
if (newName + ".js" !== name) {
507+
if (`${newName}.js` !== name) {
509508
const { selectionStart, selectionEnd, selectionDirection } = input;
510509
Swal.showValidationMessage(validation);
511510
input.setSelectionRange(selectionStart, selectionEnd, selectionDirection || undefined);
@@ -521,7 +520,7 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
521520
const { isConfirmed, value } = await promise;
522521
if (isConfirmed) {
523522
const newName = normalizeFileName(value);
524-
if (!validateFileName(newName)) setState(actions.renameSchema(name, newName + ".js"));
523+
if (!validateFileName(newName)) setState(actions.renameSchema(name, `${newName}.js`));
525524
}
526525
}
527526
}

src/Components/Tooltip.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { cloneElement, ReactElement, useCallback, useEffect, useRef } from "react";
2-
import type { SyntheticEvent } from "react";
1+
import { cloneElement, useCallback, useEffect, useRef } from "react";
32
import { createRoot } from "react-dom/client";
43

54
import { css as stylesheet } from "@emotion/css";
65

6+
import type { ReactElement, SyntheticEvent } from "react";
7+
78
function getPageWidth() {
89
return Math.max(
910
document.body.scrollWidth,
@@ -68,9 +69,9 @@ function TooltipAnchor({
6869
targetLeft = Math.min(getPageWidth() - oneRemSize - divInnerBox.width, Math.max(oneRemSize, targetLeft));
6970
targetLeft += window.scrollX;
7071

71-
div.className = tooltipStyle + (fixedWidth ? " " + fixedWidthStyle : "");
72-
div.style.top = targetTop + "px";
73-
div.style.left = targetLeft + "px";
72+
div.className = tooltipStyle + (fixedWidth ? ` ${fixedWidthStyle}` : "");
73+
div.style.top = `${targetTop}px`;
74+
div.style.left = `${targetLeft}px`;
7475
div.style.visibility = "visible";
7576
});
7677

src/Components/TooltipChar.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,9 @@ export default function TooltipChar({
112112
}
113113
}
114114
各反切. = new Set(Array.from(各反切.).filter(反切 => !各反切..has(反切)));
115-
const 反切text =
116-
(["反", "切"] as const)
117-
.flatMap(x => (各反切[x].size ? [[...各反切[x]].join("/") + x] : []))
118-
.join(" ") + " ";
115+
const 反切text = `${(["反", "切"] as const)
116+
.flatMap(x => (各反切[x].size ? [[...各反切[x]].join("/") + x] : []))
117+
.join(" ")} `;
119118
const 出處text = 來源 && ["廣韻", "王三"].includes(來源.文獻) ? `[${來源.文獻} ${來源.韻目}韻]` : "";
120119
return (
121120
<Fragment key={i}>

src/Yitizi.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
declare module "yitizi" {
2-
export const yitiziData: { [c: string]: string };
2+
export const yitiziData: Record<string, string>;
33
export function get(c: string): string[];
44
}

src/actions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export default {
5858
const schemas = [...state.schemas];
5959
const index = schemas.findIndex(schema => schema.name === name);
6060
const newState = { ...schemas[index], input };
61-
newState.parameters = newState.parameters?.refresh(input) || ParameterSet.from(input);
61+
newState.parameters = newState.parameters.refresh(input) || ParameterSet.from(input);
6262
schemas[index] = newState;
6363
return { ...state, schemas };
6464
},

src/consts.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import type { Dispatch, DispatchWithoutAction, ReactChild, ReactPortal, SetStateAction } from "react";
2-
31
import type { CustomNode } from "./Classes/CustomElement";
42
import type ParameterSet from "./Classes/ParameterSet";
53
import type samples from "./samples";
4+
import type { Dispatch, DispatchWithoutAction, ReactChild, ReactPortal, SetStateAction } from "react";
65
import type { 資料 } from "tshet-uinh";
76

87
export const tshetUinhExamplesURLPrefix = "https://cdn.jsdelivr.net/gh/nk2028/tshet-uinh-examples@main/";
@@ -85,7 +84,9 @@ export type Query = Readonly<Pick<資料.檢索結果, "字頭" | "音韻地位"
8584

8685
type Values<T> = T extends Record<PropertyKey, infer T> ? Values<T> : T;
8786
export type Sample = Values<typeof samples>;
88-
export type Folder = { [name: string]: Folder | Sample };
87+
export interface Folder {
88+
[name: string]: Folder | Sample;
89+
}
8990

9091
type UseGet<K extends string, T> = { [P in K]: T };
9192
type UseSet<K extends string, T> = { [P in `set${Capitalize<K>}`]: Dispatch<SetStateAction<T>> };

src/evaluate.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { 推導方案 } from "tshet-uinh-deriver-tools";
22

3-
import { CustomNode, Formatter } from "./Classes/CustomElement";
3+
import { Formatter } from "./Classes/CustomElement";
44
import { tshetUinhTextLabelURLPrefix } from "./consts";
55
import { evaluateOption, getArticle, setArticle } from "./options";
66
import { fetchFile, normalizeFileName, notifyError } from "./utils";
77

8+
import type { CustomNode } from "./Classes/CustomElement";
89
import type { MainState, ReactNode } from "./consts";
910
import type { 音韻地位 } from "tshet-uinh";
1011
import type { 原始推導函數, 推導函數 } from "tshet-uinh-deriver-tools";
@@ -26,7 +27,7 @@ export default async function evaluate(state: MainState): Promise<ReactNode> {
2627
const { schemas, option } = state;
2728

2829
if (option === "convertPresetArticle" && !getArticle())
29-
setArticle(await fetchFile(tshetUinhTextLabelURLPrefix + "index.txt"));
30+
setArticle(await fetchFile(`${tshetUinhTextLabelURLPrefix}index.txt`));
3031
else if (option === "compareSchemas" && schemas.length < 2) throw notifyError("此選項需要兩個或以上方案");
3132
else await new Promise(resolve => setTimeout(resolve));
3233

@@ -47,9 +48,9 @@ export default async function evaluate(state: MainState): Promise<ReactNode> {
4748

4849
function require(current: string, references: string[] = []): Require {
4950
const newReferences = references.concat(current);
50-
if (references.includes(current)) throw notifyError("Circular reference detected: " + newReferences.join(" -> "));
51+
if (references.includes(current)) throw notifyError(`Circular reference detected: ${newReferences.join(" -> ")}`);
5152
return (音韻地位, 字頭) => sample => {
52-
const schema = schemas.find(({ name }) => name === normalizeFileName(sample) + ".js");
53+
const schema = schemas.find(({ name }) => name === `${normalizeFileName(sample)}.js`);
5354
if (!schema) throw notifyError("Schema not found");
5455
return new SchemaFromRequire(rawDeriverFrom(schema.input), require(sample, newReferences), 音韻地位, 字頭);
5556
};

src/options.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Fragment } from "react";
2-
32
import { 資料, 音韻地位 } from "tshet-uinh";
43
import Yitizi from "yitizi";
54

@@ -192,7 +191,7 @@ export const evaluateOption: Record<Option, Handler> = {
192191
return (
193192
<Table
194193
head={[...title(schemas), "計數"]}
195-
body={result.sort((a, b) => b[2] - a[2]).map(([, 擬音陣列, count]) => [...wrap(擬音陣列), count + ""])}
194+
body={result.sort((a, b) => b[2] - a[2]).map(([, 擬音陣列, count]) => [...wrap(擬音陣列), `${count}`])}
196195
/>
197196
);
198197
},

0 commit comments

Comments
 (0)