ui: update eslint rules

pull/421/head
undefined 2 years ago
parent 0e07c64cad
commit 5e8d2b1286

@ -1,6 +1,6 @@
root: true
extends:
- airbnb
- airbnb-base
- airbnb-typescript/base
env:
jquery: true

@ -32,13 +32,13 @@
"@types/autocannon": "^7.6.1",
"@types/cross-spawn": "^6.0.2",
"@types/mocha": "^9.1.1",
"@types/node": "^18.7.13",
"@types/node": "^18.7.14",
"@types/semver": "^7.3.12",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.35.1",
"@typescript-eslint/eslint-plugin": "^5.36.1",
"@typescript-eslint/parser": "^5.36.1",
"autocannon": "^7.9.0",
"cac": "^6.7.12",
"cac": "^6.7.14",
"cross-env": "^7.0.3",
"cross-spawn": "^7.0.3",
"esbuild": "0.15.2",
@ -49,14 +49,15 @@
"eslint-import-resolver-webpack": "^0.13.2",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.31.1",
"eslint-plugin-react": "^7.31.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"fs-extra": "^10.1.0",
"globby": "11.1.0",
"latest-version": "7.0.0",
"mocha": "^10.0.0",
"mongodb": "^3.7.3",
"mongodb-memory-server": "^8.9.0",
"mongodb-memory-server": "^8.9.1",
"nyc": "^15.1.0",
"ora": "^6.1.2",
"semver": "^7.3.7",

@ -6,6 +6,6 @@
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@elastic/elasticsearch": "^8.2.1"
"@elastic/elasticsearch": "^8.4.0"
}
}

@ -8,7 +8,7 @@
"dependencies": {
"@hydrooj/utils": "workspace:*",
"axios": "^0.27.2",
"cac": "^6.7.12",
"cac": "^6.7.14",
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",

@ -15,7 +15,7 @@
"@graphql-tools/schema": "^8.5.1",
"@hydrooj/utils": "workspace:*",
"adm-zip": "0.5.5",
"cac": "^6.7.12",
"cac": "^6.7.14",
"cookies": "^0.8.0",
"detect-browser": "^5.3.0",
"emoji-regex": "^10.1.0",
@ -34,7 +34,7 @@
"lodash": "^4.17.21",
"lru-cache": "7.12.0",
"mime-types": "^2.1.35",
"minio": "7.0.25",
"minio": "7.0.32",
"moment-timezone": "^0.5.37",
"mongodb": "^3.7.3",
"nanoid": "^4.0.0",
@ -43,7 +43,7 @@
"p-queue": "^7.3.0",
"path-to-regexp": "^6.2.1",
"require-resolve-hook": "^1.1.0",
"schemastery": "^3.5.3",
"schemastery": "^3.5.4",
"semver": "^7.3.7",
"serialize-javascript": "^6.0.0",
"superagent": "^8.0.0",

@ -13,7 +13,7 @@
"dependencies": {
"@hydrooj/utils": "workspace:*",
"js-yaml": "^4.1.0",
"mariadb": "^3.0.0",
"mariadb": "^3.0.1",
"mongodb": "^3.7.3",
"mysql": "^2.18.1",
"turndown": "^7.1.1"

@ -10,7 +10,11 @@ module.exports = {
jquery: true,
commonjs: true,
},
extends: ['airbnb'],
extends: [
'airbnb',
'airbnb/hooks',
'airbnb-typescript',
],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
@ -49,15 +53,19 @@ module.exports = {
JQuery: true,
},
rules: {
'react-hooks/exhaustive-deps': 'off',
'@typescript-eslint/dot-notation': 'off',
'@typescript-eslint/no-implied-eval': 'off',
'@typescript-eslint/no-throw-literal': 'off',
'@typescript-eslint/return-await': 'off',
'@typescript-eslint/no-shadow': 'warn',
'no-shadow': 'off',
'@typescript-eslint/quotes': ['warn', 'single', { avoidEscape: true }],
// FIXME A bug with eslint-parser
'template-curly-spacing': 'off',
// FIXME A bug with eslint-plugin-react
'react/no-unknown-property': ['error', { ignore: ['key'] }],
// Note: must disable the base rule as it can report incorrect errors
'no-use-before-define': 'off',
@ -86,7 +94,7 @@ module.exports = {
{ SwitchCase: 1 },
],
'max-len': ['error', 150],
quotes: 'warn',
quotes: ['warn', 'single', { avoidEscape: true }],
'class-methods-use-this': 'off',
'consistent-return': 'warn',
'func-names': 'off',

@ -1,5 +1,6 @@
/* eslint-disable no-await-in-loop */
// eslint-disable-next-line @typescript-eslint/naming-convention
const _hooks: Record<keyof any, Array<(...args: any[]) => any>> = {};
function isBailed(value: any) {
@ -45,12 +46,12 @@ export function prependListener<K extends keyof EventMap>(name: K, listener: Eve
export function once<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
let dispose;
function _listener(...args: any[]) {
function l(...args: any[]) {
dispose();
return listener.apply(this, args);
}
_listener.toString = () => `// Once \n${listener.toString()}`;
dispose = addListener(name, _listener);
l.toString = () => `// Once \n${listener.toString()}`;
dispose = addListener(name, l);
return dispose;
}

@ -56,8 +56,7 @@ export default class DOMAttachedObject {
static attachAll(container: Document | HTMLElement = document.body, ...args) {
if (process.env.NODE_ENV !== 'production') {
if (!this.DOMAttachSelector) {
// eslint-disable-next-line quotes
throw new Error(`'DOMAttachSelector' should be specified`);
throw new Error("'DOMAttachSelector' should be specified");
}
}
if (process.env.NODE_ENV !== 'production') {
@ -77,8 +76,7 @@ export default class DOMAttachedObject {
const selector = this.DOMDetachSelector || this.DOMAttachSelector;
if (process.env.NODE_ENV !== 'production') {
if (!selector) {
// eslint-disable-next-line quotes
throw new Error(`'DOMDetachSelector' or 'DOMAttachSelector' should be specified`);
throw new Error("'DOMDetachSelector' or 'DOMAttachSelector' should be specified");
}
}
if (process.env.NODE_ENV !== 'production') {
@ -102,8 +100,7 @@ export default class DOMAttachedObject {
static registerLifeCycleHooks(attach = true) {
if (process.env.NODE_ENV !== 'production') {
if (!this.DOMAttachSelector) {
// eslint-disable-next-line quotes
throw new Error(`'DOMAttachSelector' should be specified`);
throw new Error("'DOMAttachSelector' should be specified");
}
}
$(document).on('vjContentNew', (e) => this.attachAll(e.target));

@ -109,9 +109,12 @@ const AutoComplete = forwardRef(function Impl<T>(props: AutoCompleteProps<T>, re
const inputRef = useRef<HTMLInputElement>();
const listRef = useRef<HTMLUListElement>();
if (props.cacheKey) superCache[props.cacheKey] ||= { query: {}, value: {} };
const queryCache = props.cacheKey ? superCache[props.cacheKey].query : useRef({}).current;
const valueCache = props.cacheKey ? superCache[props.cacheKey].value : useRef({}).current;
let [queryCache, valueCache] = [useRef({}).current, useRef({}).current];
if (props.cacheKey) {
superCache[props.cacheKey] ||= { query: {}, value: {} };
queryCache = superCache[props.cacheKey].query;
valueCache = superCache[props.cacheKey].value;
}
const queryList = async (query) => {
if (!query && !allowEmptyQuery) {

@ -280,10 +280,8 @@ export default class Calendar {
for (; vIndex < vIndexMax; ++vIndex) {
if (_.every(_
.range(beginDay, endDay + 1)
.map((day) => !dayBitmap[day][vIndex]), // eslint-disable-line no-loop-func
)) { // eslint-disable-line function-paren-newline
break;
}
.map((day) => !dayBitmap[day][vIndex]), // eslint-disable-line
)) break;
}
// fill space
for (let i = beginDay; i <= endDay; ++i) {

@ -21,7 +21,7 @@ function scrollToViewport() {
}
}
export default function reducer(state = null, action) {
export default function reducer(state = null, action: any = {}) {
switch (action.type) {
case 'DIALOGUES_SWITCH_TO': {
scrollToViewport();

@ -1,6 +1,6 @@
import _ from 'lodash';
export default function reducer(state = {}, action) {
export default function reducer(state = {}, action = {}) {
switch (action.type) {
case 'DIALOGUES_LOAD_DIALOGUES_FULFILLED': {
const { messages } = action.payload;

@ -1,6 +1,6 @@
import _ from 'lodash';
export default function reducer(state = {}, action) {
export default function reducer(state = {}, action = {}) {
switch (action.type) {
case 'DIALOGUES_LOAD_DIALOGUES_FULFILLED': {
const dialogues = action.payload.messages;

@ -1,7 +1,7 @@
import _ from 'lodash';
import Notification from 'vj/components/notification';
export default function reducer(state = {}, action) {
export default function reducer(state = {}, action: any = {}) {
switch (action.type) {
case 'DIALOGUES_LOAD_DIALOGUES_FULFILLED': {
const dialogues = action.payload.messages;

@ -1,7 +1,7 @@
/* eslint-disable camelcase */
import en_GB from 'monaco-editor-nls/locale/en-gb.json';
function _format(message, args) {
function format(message, args) {
let result;
if (args.length === 0) {
result = message;
@ -33,7 +33,7 @@ function find(path, message) {
}
export function localize(path, message, ...args) {
return _format(find(path.key || path, message), args);
return format(find(path.key || path, message), args);
}
export function setLocaleData(data) {

@ -59,7 +59,7 @@ export function TestCaseEntry({ index, subindex }) {
output: useRef(),
};
for (const type of ['input', 'output']) {
useEffect(() => {
useEffect(() => { // eslint-disable-line
refs[type].current?.setSelectedItems(testcase[type] ? [testcase[type]] : []);
}, [testcase[type]]);
}

@ -5,7 +5,7 @@ import { cloneDeep } from 'lodash';
type State = ProblemConfigFile & { __loaded: boolean };
export default function reducer(state = { type: 'default', __loaded: false } as State, action): State {
export default function reducer(state = { type: 'default', __loaded: false } as State, action: any = {}): State {
switch (action.type) {
case 'CONFIG_LOAD_FULFILLED': {
return { ...state, ...yaml.load(action.payload.config) as object, __loaded: true };

@ -1,4 +1,4 @@
export default function reducer(state = [], action) {
export default function reducer(state = [], action: any = {}) {
switch (action.type) {
case 'CONFIG_LOAD_FULFILLED': {
return state.concat(action.payload.testdata);

@ -4,7 +4,7 @@ if (UiContext.tdoc?._id && UiContext.tdoc.rule !== 'homework') cacheKey += `@${U
export default function reducer(state = {
lang: localStorage.getItem(`${cacheKey}#lang`) || UiContext.codeLang,
code: localStorage.getItem(cacheKey) || UiContext.codeTemplate,
}, action) {
}, action: any = {}) {
if (action.type === 'SCRATCHPAD_EDITOR_UPDATE_CODE') {
localStorage.setItem(cacheKey, action.payload);
return {

@ -4,7 +4,7 @@ export default function reducer(state = {
input: '',
output: '',
rid: null,
}, action) {
}, action: any = {}) {
if (action.type === 'SCRATCHPAD_PRETEST_DATA_CHANGE') {
const { type, value } = action.payload;
return {

@ -3,7 +3,7 @@ import _ from 'lodash';
export default function reducer(state = {
rows: [],
items: {},
}, action) {
}, action: any = {}) {
switch (action.type) {
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_FULFILLED': {
const { rdocs } = action.payload;

@ -1,4 +1,4 @@
export default function reducer(state = {}, action) {
export default function reducer(state = {}, action: any = {}) {
if (action.type === 'SCRATCHPAD_STATE_UPDATE') {
const { key, value } = action.payload;
return {

@ -21,7 +21,7 @@ export default function reducer(state = {
waitSec: 0,
isWaiting: false,
activePage: 'problem',
}, action) {
}, action: any = {}) {
switch (action.type) {
case 'SCRATCHPAD_UI_CHANGE_SIZE': {
const { uiElement, size } = action.payload;

@ -14,7 +14,7 @@ interface UploadOptions {
pjax?: boolean;
singleFileUploadCallback?: (file: File) => any;
}
export default async function uploadFiles(endpoint = '', files: File[] | FileList, options: UploadOptions = {}) {
export default async function uploadFiles(endpoint = '', files: File[] | FileList = [], options: UploadOptions = {}) {
const dialog = new Dialog({
$body: `
<div class="file-label" style="text-align: center; margin-bottom: 5px; color: gray; font-size: small;"></div>

@ -1,12 +1,12 @@
type callback = (pagename: string, loadPage: (name: string) => Promise<any>) => any;
type Callback = (pagename: string, loadPage: (name: string) => Promise<any>) => any;
export class Page {
moduleName?: string;
autoload = false;
afterLoading?: callback;
beforeLoading?: callback;
constructor(pagename: string | string[], afterLoading?: callback, beforeLoading?: callback);
constructor(pagename: string | string[], moduleName: string, afterLoading?: callback, beforeLoading?: callback);
afterLoading?: Callback;
beforeLoading?: Callback;
constructor(pagename: string | string[], afterLoading?: Callback, beforeLoading?: Callback);
constructor(pagename: string | string[], moduleName: string, afterLoading?: Callback, beforeLoading?: Callback);
constructor(pagename: string | string[], ...args: any[]);
constructor(public name: string | string[], ...args: any[]) {
if (typeof args[0] === 'string') {
@ -16,16 +16,13 @@ export class Page {
}
if (process.env.NODE_ENV !== 'production') {
if (typeof name !== 'string' && !(name instanceof Array)) {
// eslint-disable-next-line quotes
throw new Error(`'name' should be a string or string[]`);
throw new Error("'name' should be a string or string[]");
}
if (typeof this.afterLoading !== 'function' && this.afterLoading != null) {
// eslint-disable-next-line quotes
throw new Error(`'afterLoading' should be a function`);
throw new Error("'afterLoading' should be a function");
}
if (typeof this.beforeLoading !== 'function' && this.beforeLoading != null) {
// eslint-disable-next-line quotes
throw new Error(`'beforeLoading' should be a function`);
throw new Error("'beforeLoading' should be a function");
}
}
}
@ -40,8 +37,8 @@ export class Page {
export class NamedPage extends Page { }
export class AutoloadPage extends Page {
constructor(pagename: string | string[], afterLoading?: callback, beforeLoading?: callback);
constructor(pagename: string | string[], moduleName: string, afterLoading?: callback, beforeLoading?: callback);
constructor(pagename: string | string[], afterLoading?: Callback, beforeLoading?: Callback);
constructor(pagename: string | string[], moduleName: string, afterLoading?: Callback, beforeLoading?: Callback);
constructor(pagename: string | string[], ...args: any[]) {
super(pagename, ...args);
this.autoload = true;

@ -18,7 +18,7 @@
"@fontsource/jetbrains-mono": "^4.5.10",
"@fontsource/pt-mono": "^4.5.10",
"@fontsource/roboto-mono": "^4.5.8",
"@fontsource/source-code-pro": "^4.5.11",
"@fontsource/source-code-pro": "^4.5.12",
"@fontsource/ubuntu-mono": "^4.5.11",
"@hydrooj/utils": "workspace:*",
"@svgr/webpack": "^6.3.1",
@ -112,7 +112,7 @@
"web-streams-polyfill": "^3.2.1",
"webpack": "^5.74.0",
"webpack-bundle-analyzer": "^4.6.1",
"webpack-dev-server": "^4.10.0",
"webpack-dev-server": "^4.10.1",
"webpackbar": "^5.0.2"
},
"dependencies": {
@ -121,7 +121,7 @@
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0",
"jsesc": "^3.0.2",
"katex": "^0.16.0",
"katex": "^0.16.2",
"lodash": "^4.17.21",
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.4",

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
declare let UserContext: any;
declare let UiContext: any;
// eslint-disable-next-line camelcase
// eslint-disable-next-line
declare let node_modules: any;
declare let LANGS: Record<string, any>;

@ -93,29 +93,25 @@ pjax.request = async (opt) => {
data.fragments.forEach((fragment) => {
if (process.env.NODE_ENV !== 'production') {
if (fragment.html === undefined) {
// eslint-disable-next-line quotes
throw new Error(`Fragement should contain 'html'`);
throw new Error("Fragement should contain 'html'");
}
}
const $el = $(fragment.html.trim());
if (process.env.NODE_ENV !== 'production') {
if ($el.length === 0) {
// eslint-disable-next-line quotes
throw new Error(`Unable to build elements from fragment 'html'`);
throw new Error("Unable to build elements from fragment 'html'");
}
}
const fragmentId = $el.attr('data-fragment-id');
if (process.env.NODE_ENV !== 'production') {
if (!fragmentId) {
// eslint-disable-next-line quotes
throw new Error(`Unable to extract fragment id from fragment 'html'`);
throw new Error("Unable to extract fragment id from fragment 'html'");
}
}
const $target = $(`[data-fragment-id="${fragmentId}"]`);
if (process.env.NODE_ENV !== 'production') {
if ($target.length === 0) {
// eslint-disable-next-line quotes
throw new Error(`Unable to get target fragment from fragment id`);
throw new Error('Unable to get target fragment from fragment id');
}
}
$target.trigger('vjContentRemove');

@ -8,7 +8,7 @@
"license": "AGPL-3.0-or-later",
"preferUnplugged": true,
"dependencies": {
"cac": "^6.7.12",
"cac": "^6.7.14",
"esbuild": "0.15.2",
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0",

Loading…
Cancel
Save