Skip to content

Commit c3fb25a

Browse files
committed
* add option for rule @typescript-eslint/restrict-template-expressions
* fix `Parse errors in imported module '': parserPath or languageOptions.parser is required!`: un-ts/eslint-plugin-import-x#85 (comment) @ eslint.config.js * re-plug eslint: pzmosquito/eslint-import-resolver-vite#12 (comment) @ package.json * fix some violations of eslint rules @ fe
1 parent 07865ef commit c3fb25a

File tree

8 files changed

+38
-35
lines changed

8 files changed

+38
-35
lines changed

fe/eslint.config.js

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ const rules = [{ // as of eslint-plugin-unicorn@50.0.1
382382
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
383383
'@typescript-eslint/no-unsafe-unary-minus': 'error',
384384
'@typescript-eslint/parameter-properties': ['error', { prefer: 'parameter-property' }],
385+
'@typescript-eslint/restrict-template-expressions': ['error', { allowNumber: true }],
385386
},
386387
}, { // as of eslint-plugin-vue@9.19.2
387388
optout: {
@@ -520,20 +521,25 @@ const rules = [{ // as of eslint-plugin-unicorn@50.0.1
520521
},
521522
}];
522523

523-
import viteConfig from './vite.config.ts';
524-
import pluginStylistic from '@stylistic/eslint-plugin';
525-
import pluginImportX from 'eslint-plugin-import-x';
526-
import pluginUnicorn from 'eslint-plugin-unicorn';
527-
import * as typescriptESLintParserForExtraFiles from 'typescript-eslint-parser-for-extra-files';
528524
import * as vueESLintParser from 'vue-eslint-parser';
525+
// eslint-disable-next-line import-x/extensions
529526
import vueESLintConfigTypescriptRecommendedExtends from '@vue/eslint-config-typescript/recommended.js';
530527
import pluginVue from 'eslint-plugin-vue';
531528
import { fixupConfigRules } from '@eslint/compat';
532529
import { FlatCompat } from '@eslint/eslintrc';
533530
import eslintJs from '@eslint/js';
531+
import pluginStylistic from '@stylistic/eslint-plugin';
534532
import stylisticMigrate from '@stylistic/eslint-plugin-migrate';
533+
import pluginImportX from 'eslint-plugin-import-x';
534+
import pluginUnicorn from 'eslint-plugin-unicorn';
535+
// eslint-disable-next-line import-x/extensions
536+
import { tsImport } from 'tsx/esm/api';
537+
import * as typescriptESLintParserForExtraFiles from 'typescript-eslint-parser-for-extra-files';
535538
import * as _ from 'lodash-es';
536539

540+
// https://github.com/pzmosquito/eslint-import-resolver-vite/issues/12#issuecomment-2151349705
541+
const viteConfig = await tsImport('./vite.config.ts', import.meta.url);
542+
537543
// https://github.com/eslint/eslint/issues/18093
538544
// https://github.com/eslint/eslint/issues/18391
539545
const compat = new FlatCompat();
@@ -546,8 +552,11 @@ export default [
546552
'plugin:@typescript-eslint/strict-type-checked',
547553
'plugin:@typescript-eslint/stylistic-type-checked',
548554
),
549-
...compat.config(pluginImportX.configs.recommended), // https://github.com/un-ts/eslint-plugin-import-x/issues/29#issuecomment-2148843214
550-
...compat.config(pluginImportX.configs.typescript),
555+
{ // https://github.com/un-ts/eslint-plugin-import-x/pull/85#issuecomment-2153376351
556+
plugins: { 'import-x': { rules: pluginImportX.rules } },
557+
rules: pluginImportX.configs.recommended.rules,
558+
}, // https://github.com/import-js/eslint-plugin-import/issues/2556#issuecomment-2119520339
559+
pluginImportX.configs.typescript,
551560
...fixupConfigRules(...compat.extends(
552561
'plugin:@tanstack/eslint-plugin-query/recommended', // https://github.com/TanStack/query/pull/7253
553562
)),
@@ -562,6 +571,12 @@ export default [
562571
tsconfigRootDir: import.meta.dirname,
563572
},
564573
},
574+
settings: {
575+
'import-x/resolver': {
576+
typescript: true,
577+
vite: { viteConfig }, // https://github.com/pzmosquito/eslint-import-resolver-vite/issues/12#issuecomment-2148676875
578+
},
579+
},
565580
plugins: { '@stylistic': pluginStylistic },
566581

567582
// https://stackoverflow.com/questions/30221286/how-to-convert-an-array-of-objects-to-an-object-in-lodash/36692117#36692117
@@ -576,7 +591,6 @@ export default [
576591
{
577592
files: ['**/*.ts'],
578593
languageOptions: { parser: typescriptESLintParserForExtraFiles },
579-
settings: { 'import-x/resolver': { typescript: true } },
580594
},
581595
{
582596
files: ['**/*.vue'],
@@ -588,12 +602,6 @@ export default [
588602
tsconfigRootDir: import.meta.dirname,
589603
},
590604
},
591-
settings: {
592-
'import-x/resolver': {
593-
typescript: true,
594-
vite: { viteConfig }, // https://github.com/pzmosquito/eslint-import-resolver-vite/issues/12#issuecomment-2148676875
595-
},
596-
},
597605
},
598606
{
599607
files: ['eslint.config.js'],

fe/package.json

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
"scripts": {
77
"dev": "vite",
88
"build": "vue-tsc && vite build",
9-
"preview": "vite preview",
10-
"eslint": "tsx .yarn/unplugged/eslint-npm-*/node_modules/eslint/bin/eslint.js"
9+
"preview": "vite preview"
1110
},
1211
"dependencies": {
1312
"@fortawesome/fontawesome-svg-core": "^6.5.2",
@@ -81,10 +80,5 @@
8180
"not ie 11",
8281
"not dead"
8382
],
84-
"packageManager": "yarn@4.2.2",
85-
"dependenciesMeta": {
86-
"eslint@9.4.0": {
87-
"unplugged": true
88-
}
89-
}
83+
"packageManager": "yarn@4.2.2"
9084
}

fe/src/components/Post/queryForm/useQueryForm.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as _ from 'lodash-es';
88
export interface UnknownParam { name: string, value: unknown, subParam: ObjUnknown & { not?: boolean } }
99
export interface NamelessUnknownParam { value?: unknown, subParam?: ObjUnknown }
1010
export type ParamPreprocessorOrWatcher = (p: UnknownParam) => void;
11-
export default <
11+
const useQueryForm = <
1212
UniqueParams extends Record<string, UnknownParam> = Record<string, UnknownParam>,
1313
Params extends Record<string, UnknownParam> = Record<string, UnknownParam>
1414
>(
@@ -29,7 +29,7 @@ export default <
2929
const fillParamDefaultValue = <T extends Param | UniqueParam>
3030
(param: Partial<UnknownParam> & { name: string }, resetToDefault = false): T => {
3131
// prevent defaultsDeep mutate origin paramsDefaultValue
32-
const defaultParam = _.cloneDeep(deps.paramsDefaultValue[param.name]);
32+
const defaultParam = structuredClone(deps.paramsDefaultValue[param.name]);
3333
if (defaultParam === undefined)
3434
throw new Error(`Param ${param.name} not found in paramsDefaultValue`);
3535
defaultParam.subParam ??= {};
@@ -39,7 +39,7 @@ export default <
3939
if (resetToDefault)
4040
return _.defaultsDeep(defaultParam, param) as T;
4141

42-
return _.defaultsDeep(_.cloneDeep(param), defaultParam) as T;
42+
return _.defaultsDeep(structuredClone(param), defaultParam) as T;
4343
};
4444
const addParam = (name: string) => {
4545
params.value.push(fillParamDefaultValue({ name }));
@@ -57,14 +57,14 @@ export default <
5757
params.value.splice(paramIndex, 1);
5858
};
5959
const clearParamDefaultValue = <T extends UnknownParam>(param: UnknownParam): Partial<T | UnknownParam> | null => {
60-
const defaultParam = _.cloneDeep(deps.paramsDefaultValue[param.name]);
60+
const defaultParam = structuredClone(deps.paramsDefaultValue[param.name]);
6161
if (defaultParam === undefined)
6262
throw new Error(`Param ${param.name} not found in paramsDefaultValue`);
6363

6464
/** remove subParam.not: false, which previously added by {@link fillParamDefaultValue()} */
6565
if (defaultParam.subParam !== undefined)
6666
defaultParam.subParam.not ??= false;
67-
const newParam: Partial<UnknownParam> = _.cloneDeep(param); // prevent mutating origin param
67+
const newParam: Partial<UnknownParam> = structuredClone(param); // prevent mutating origin param
6868
/** number will consider as empty in {@link _.isEmpty()} */
6969
// to prevent this we use complex short circuit evaluate expression
7070
if (!(_.isNumber(newParam.value) || !_.isEmpty(newParam.value))
@@ -223,3 +223,4 @@ export default <
223223
generateParamRoute
224224
};
225225
};
226+
export default useQueryForm;

fe/src/components/Post/renderers/list/RendererList.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export type ThreadWithGroupedSubReplies<AdditionalSubReply extends SubReply = ne
3737
Thread & { replies: Array<Reply & { subReplies: Array<AdditionalSubReply | SubReply[]> }> };
3838
const posts = computed(() => {
3939
// https://github.com/microsoft/TypeScript/issues/33591
40-
const newPosts = _.cloneDeep(props.initialPosts) as
40+
const newPosts = structuredClone(props.initialPosts) as
4141
Modify<ApiPosts['response'], { threads: Array<ThreadWithGroupedSubReplies<SubReply>> }>;
4242
newPosts.threads = newPosts.threads.map(thread => {
4343
thread.replies = thread.replies.map(reply => {

fe/src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import App from '@/App.vue';
22
import router from '@/router';
33
import '@/styles/style.css';
4-
import 'bootstrap/dist/css/bootstrap.min.css';
54
import { createApp } from 'vue';
65
import { createPinia } from 'pinia';
76
import { VueQueryPlugin } from '@tanstack/vue-query';
87
import { createHead } from '@unhead/vue';
98
import 'bootstrap';
9+
import 'bootstrap/dist/css/bootstrap.min.css';
1010
import 'noty/lib/noty.css';
1111
import 'noty/lib/themes/mint.css';
1212
import nprogress from 'nprogress';
@@ -15,7 +15,7 @@ import 'nprogress/nprogress.css';
1515
nprogress.configure({ trickleSpeed: 200 });
1616

1717
if (import.meta.env.DEV) {
18-
// @ts-expect-error no .d.ts
18+
// @ts-expect-error too small to write a .d.ts for it
1919
await import('@/stats');
2020
await import('@/checkCSS');
2121
}

fe/src/router/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ const lazyLoadRouteView = async (lazyComponent: Promise<Component>) => {
4242
routeLazyComponent.isLoading = true;
4343

4444
return lazyComponent
45-
.catch((e: Error) => { notyShow('error', `${e.name}<br />${e.message}`) })
45+
.catch((e: unknown) => {
46+
if (e instanceof Error)
47+
notyShow('error', `${e.name}<br />${e.message}`);
48+
})
4649
.finally(() => { routeLazyComponent.isLoading = false });
4750
};
4851

fe/src/views/BilibiliVote.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ const loadCharts = {
576576
});
577577
578578
// clone last timeline option then transform it to official votes count option
579-
const originalTimelineOptions = _.cloneDeep(options.at(-1));
579+
const originalTimelineOptions = structuredClone(options.at(-1));
580580
if (originalTimelineOptions === undefined || !_.isArray(originalTimelineOptions.series))
581581
return;
582582
_.remove(originalTimelineOptions.series, { id: 'totalVotesValidation' });

fe/yarn.lock

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5685,9 +5685,6 @@ __metadata:
56855685
vue-eslint-parser: "npm:^9.4.3"
56865686
vue-router: "npm:^4.3.2"
56875687
vue-tsc: "npm:^2.0.19"
5688-
dependenciesMeta:
5689-
eslint@9.4.0:
5690-
unplugged: true
56915688
languageName: unknown
56925689
linkType: soft
56935690

0 commit comments

Comments
 (0)