mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
eslint: add github/array-foreach rule
This commit is contained in:
21 files changed
+59
-51
No files matched your search
@@ -12,6 +12,7 @@ plugins:
|
||||
- '@typescript-eslint'
|
||||
- simple-import-sort
|
||||
- eslint-plugin-import
|
||||
- eslint-plugin-github
|
||||
rules:
|
||||
'@typescript-eslint/no-shadow': 1
|
||||
|
||||
@@ -145,6 +146,8 @@ rules:
|
||||
message: Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.
|
||||
- selector: WithStatement
|
||||
message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.'
|
||||
|
||||
github/array-foreach: 1
|
||||
|
||||
simple-import-sort/imports:
|
||||
- warn
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"@typescript-eslint/parser": "^6.8.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-plugin-github": "^4.10.1",
|
||||
"eslint-plugin-import": "2.28.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
|
||||
@@ -637,9 +637,9 @@ export class ContestUserHandler extends ContestManagementBaseHandler {
|
||||
const tsdocs = await contest.getMultiStatus(domainId, { docId: tid }).project({
|
||||
uid: 1, attend: 1, startAt: 1, unrank: 1,
|
||||
}).toArray();
|
||||
tsdocs.forEach((i) => {
|
||||
i.endAt = (this.tdoc.duration && i.startAt) ? moment(i.startAt).add(this.tdoc.duration, 'hours').toDate() : null;
|
||||
});
|
||||
for (const tsdoc of tsdocs) {
|
||||
tsdoc.endAt = (this.tdoc.duration && tsdoc.startAt) ? moment(tsdoc.startAt).add(this.tdoc.duration, 'hours').toDate() : null;
|
||||
}
|
||||
const udict = await user.getListForRender(domainId, [this.tdoc.owner, ...tsdocs.map((i) => i.uid)]);
|
||||
this.response.body = { tdoc: this.tdoc, tsdocs, udict };
|
||||
this.response.pjax = 'partials/contest_user.html';
|
||||
|
||||
@@ -36,7 +36,7 @@ export class HomeHandler extends Handler {
|
||||
uids = new Set<number>();
|
||||
|
||||
collectUser(uids: number[]) {
|
||||
uids.forEach((uid) => this.uids.add(uid));
|
||||
for (const uid of uids) this.uids.add(uid);
|
||||
}
|
||||
|
||||
async getHomework(domainId: string, limit = 5) {
|
||||
|
||||
@@ -142,7 +142,7 @@ class DomainModel {
|
||||
const affected = await UserModel.getMulti({ _id: { $in: uid } })
|
||||
.project<{ _id: number, mail: string, uname: string }>({ mail: 1, uname: 1 })
|
||||
.toArray();
|
||||
affected.forEach((udoc) => deleteUserCache(udoc));
|
||||
for (const udoc of affected) deleteUserCache(udoc);
|
||||
return await collUser.updateMany({ domainId, uid: { $in: uid } }, { $set: { role } }, { upsert: true });
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function add(data: Partial<OplogDoc> & { type: string }): Promise<O
|
||||
|
||||
function safeKeys(data: any) {
|
||||
if (['string', 'number', 'boolean'].includes(typeof data)) return data;
|
||||
if (data instanceof Array) data.forEach(safeKeys);
|
||||
if (data instanceof Array) for (const d of data) safeKeys(d);
|
||||
else if (data instanceof ObjectId) return data;
|
||||
else if (data instanceof Object) {
|
||||
for (const key in data) {
|
||||
|
||||
@@ -398,7 +398,7 @@ export function Connection(
|
||||
closed = true;
|
||||
bus.emit('connection/close', h);
|
||||
if (interval) clearInterval(interval);
|
||||
disposables.forEach((d) => d());
|
||||
for (const d of disposables) d();
|
||||
h.cleanup?.(args);
|
||||
};
|
||||
interval = setInterval(() => {
|
||||
@@ -555,8 +555,10 @@ ${ctx.response.status} ${endTime - startTime}ms ${ctx.response.length}`);
|
||||
const layers = [baseLayer, rendererLayer(router, logger), responseLayer(logger), userLayer];
|
||||
app.use(async (ctx, next) => await next().catch(console.error)).use(domainLayer);
|
||||
app.use(router.routes()).use(router.allowedMethods());
|
||||
layers.forEach((layer) => router.use(layer as any));
|
||||
layers.forEach((layer) => app.use(layer as any));
|
||||
for (const layer of layers) {
|
||||
router.use(layer as any);
|
||||
app.use(layer);
|
||||
}
|
||||
app.use((ctx) => handle(ctx, NotFoundHandler, () => true));
|
||||
wsServer.on('connection', async (socket, request) => {
|
||||
socket.on('error', (err) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was adapted from @koishijs, MIT licensed.
|
||||
/* eslint-disable consistent-return */
|
||||
/* eslint-disable import/no-dynamic-require */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
@@ -13,7 +14,7 @@ function loadDependencies(filename: string, ignored: Set<string>) {
|
||||
function traverse({ filename, children }: NodeJS.Module) {
|
||||
if (ignored.has(filename) || dependencies.has(filename) || filename.includes('/node_modules/')) return;
|
||||
dependencies.add(filename);
|
||||
children.forEach(traverse);
|
||||
for (const c of children) traverse(c);
|
||||
}
|
||||
traverse(require.cache[filename]);
|
||||
return dependencies;
|
||||
@@ -87,13 +88,13 @@ export default class Watcher extends Service {
|
||||
this.accepted = new Set(this.stashed);
|
||||
this.declined = new Set(this.externals);
|
||||
|
||||
this.stashed.forEach((filename) => {
|
||||
for (const filename of this.stashed) {
|
||||
const { children } = require.cache[filename];
|
||||
for (const { filename } of children) {
|
||||
if (this.accepted.has(filename) || this.declined.has(filename) || filename.includes('/node_modules/')) continue;
|
||||
pending.push(filename);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
while (pending.length) {
|
||||
let index = 0;
|
||||
@@ -168,7 +169,7 @@ export default class Watcher extends Service {
|
||||
// we only detect reloads at plugin level
|
||||
// a plugin will be reloaded if any of its dependencies are accepted
|
||||
if (!dependencies.some((dep) => this.accepted.has(dep))) continue;
|
||||
dependencies.forEach((dep) => this.accepted.add(dep));
|
||||
for (const dep of dependencies) this.accepted.add(dep);
|
||||
|
||||
// prepare for reload
|
||||
let isMarked = false;
|
||||
|
||||
@@ -434,10 +434,10 @@ const scripts: UpgradeScript[] = [
|
||||
null,
|
||||
async function _65_66() {
|
||||
return await iterateAllDomain(async (ddoc) => {
|
||||
Object.keys(ddoc.roles).forEach((role) => {
|
||||
for (const role of Object.keys(ddoc.roles)) {
|
||||
if (['guest', 'root'].includes(role)) return;
|
||||
ddoc.roles[role] = (BigInt(ddoc.roles[role]) | PERM.PREM_VIEW_DISPLAYNAME).toString();
|
||||
});
|
||||
}
|
||||
await domain.setRoles(ddoc._id, ddoc.roles);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -331,19 +331,21 @@ export async function run({
|
||||
if (judgeState) {
|
||||
if (judgeState.compile?.message) data.compilerTexts.push(judgeState.compile.message.replace(/<.+?>/g, ''));
|
||||
if (judgeState.judge) {
|
||||
judgeState.judge.subtasks.forEach((subtask, index) => {
|
||||
subtask.cases.forEach((curCase, caseIndex) => {
|
||||
for (let i = 0; i < judgeState.judge.subtasks.length; i++) {
|
||||
const subtask = judgeState.judge.subtasks.length[i];
|
||||
for (let j = 0; j < subtask.cases.length; j++) {
|
||||
const curCase = subtask.cases[j];
|
||||
data.testCases.push({
|
||||
subtaskId: index + 1,
|
||||
id: caseIndex + 1,
|
||||
subtaskId: i + 1,
|
||||
id: j + 1,
|
||||
score: Math.trunc((curCase.result?.scoringRate || 0) * 100),
|
||||
time: curCase.result?.time || 0,
|
||||
memory: curCase.result?.memory || 0,
|
||||
message: curCase.result?.spjMessage || curCase.result?.systemMessage || curCase.result?.userError || '',
|
||||
status: curCase.status === 2 ? TestcaseJudgeStatusMap[curCase.result.type] : TestcaseStatusMap[curCase.status],
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rdoc.type) {
|
||||
|
||||
@@ -398,7 +398,7 @@ export async function run({
|
||||
try {
|
||||
const details = await xml2js.parseStringPromise(result.details);
|
||||
if (details.tests.subtask) {
|
||||
details.tests.subtask.forEach((subtask) => {
|
||||
for (const subtask of details.tests.subtask) {
|
||||
if (!subtask.test) {
|
||||
data.testCases.push({
|
||||
subtaskId: subtask.$.num,
|
||||
@@ -409,7 +409,7 @@ export async function run({
|
||||
message: 'Skipped',
|
||||
status: STATUS.STATUS_CANCELED,
|
||||
});
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
data.testCases.push(...subtask.test.map((curCase, caseIndex) => ({
|
||||
subtaskId: subtask.$.num,
|
||||
@@ -420,7 +420,7 @@ export async function run({
|
||||
message: curCase.res[0] || '',
|
||||
status: statusMap[curCase.$.info] || STATUS.STATUS_WAITING,
|
||||
})));
|
||||
});
|
||||
}
|
||||
} else if (details.tests.test) {
|
||||
data.testCases.push(...details.tests.test.map((curCase) => ({
|
||||
subtaskId: 1,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable github/array-foreach */
|
||||
import { $, addPage, AutoloadPage } from '@hydrooj/ui-default';
|
||||
|
||||
/* global DocsAPI */
|
||||
|
||||
@@ -20,13 +20,13 @@ export default async function readYamlCases(cfg: Record<string, any> = {}, check
|
||||
}
|
||||
if (cfg.interactor) config.interactor = checkFile(cfg.interactor, 'Cannot find interactor {0}.');
|
||||
if (cfg.validator) config.validator = checkFile(cfg.validator, 'Cannot find validator {0}.');
|
||||
['judge', 'user'].forEach((n) => {
|
||||
for (const n of ['judge', 'user']) {
|
||||
const conf = cfg[`${n}_extra_files`];
|
||||
if (!conf) return;
|
||||
if (!conf) continue;
|
||||
if (conf instanceof Array) {
|
||||
config[`${n}_extra_files`] = conf.map((file) => checkFile(file, `Cannot find ${n} extra file {0}.`));
|
||||
} else throw new Error(`Invalid ${n}_extra_files config.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (cfg.cases?.length) {
|
||||
config.subtasks = [{
|
||||
|
||||
@@ -27,7 +27,7 @@ export interface LangConfig {
|
||||
export function parseLang(config: string): Record<string, LangConfig> {
|
||||
const file = yaml.load(config) as Record<string, LangConfig>;
|
||||
if (typeof file === 'undefined' || typeof file === 'string' || typeof file === 'number') throw new Error();
|
||||
Object.keys(file).filter((i) => i.startsWith('_')).forEach((k) => delete file[k]);
|
||||
for (const key of Object.keys(file)) if (key.startsWith('_')) delete file[key];
|
||||
for (const key in file) {
|
||||
const entry = file[key];
|
||||
if (key.includes('.')) {
|
||||
|
||||
@@ -36,9 +36,7 @@ export function folderSize(folderPath: string) {
|
||||
size += stats.size;
|
||||
const files = fs.readdirSync(p);
|
||||
if (Array.isArray(files)) {
|
||||
files.forEach((file) => {
|
||||
_next(path.join(p, file));
|
||||
});
|
||||
for (const file of files) _next(path.join(p, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,9 +245,9 @@ export function CallableInstance(property = '__call__') {
|
||||
else func = this.constructor.prototype[property];
|
||||
const apply = function __call__(...args) { return func.apply(apply, ...args); };
|
||||
Object.setPrototypeOf(apply, this.constructor.prototype);
|
||||
Object.getOwnPropertyNames(func).forEach((p) => {
|
||||
for (const p of Object.getOwnPropertyNames(func)) {
|
||||
Object.defineProperty(apply, p, Object.getOwnPropertyDescriptor(func, p));
|
||||
});
|
||||
}
|
||||
return apply;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ class AccountService {
|
||||
await next({ status: STATUS.STATUS_JUDGING, message: `ID = ${rid}` });
|
||||
const nextFunction = (data) => {
|
||||
if (data.case) delete data.case.message;
|
||||
if (data.cases) data.cases.forEach((x) => delete x.message);
|
||||
if (data.cases) for (const x of data.cases) delete x.message;
|
||||
return next(data);
|
||||
};
|
||||
await this.api.waitForSubmission(rid, task.config?.detail === false ? nextFunction : next, end);
|
||||
|
||||
@@ -177,15 +177,15 @@ export default class CodeforcesProvider extends BasicFetcher implements IBasicPr
|
||||
const text = $dom.window.document.querySelector('.problem-statement').innerHTML;
|
||||
const { window: { document } } = new JSDOM(text);
|
||||
const files = {};
|
||||
document.querySelectorAll('img[src]').forEach((ele) => {
|
||||
for (const ele of document.querySelectorAll('img[src]')) {
|
||||
const src = ele.getAttribute('src');
|
||||
if (!src.startsWith('http')) return;
|
||||
if (!src.startsWith('http')) continue;
|
||||
const file = new PassThrough();
|
||||
this.get(src).pipe(file);
|
||||
const fid = String.random(8);
|
||||
files[`${fid}.png`] = file;
|
||||
ele.setAttribute('src', `file://${fid}.png`);
|
||||
});
|
||||
}
|
||||
const title = document.querySelector('.title').innerHTML.trim().split('. ')[1];
|
||||
const time = parseInt(document.querySelector('.time-limit').innerHTML.substr(53, 2), 10);
|
||||
const memory = parseInt(document.querySelector('.memory-limit').innerHTML.substr(55, 4), 10);
|
||||
@@ -200,11 +200,11 @@ export default class CodeforcesProvider extends BasicFetcher implements IBasicPr
|
||||
const note = document.querySelector('.note')?.innerHTML.trim();
|
||||
document.querySelector('.note')?.remove();
|
||||
document.querySelector('.sample-tests')?.remove();
|
||||
document.querySelectorAll('.section-title').forEach((ele) => {
|
||||
for (const ele of document.querySelectorAll('.section-title')) {
|
||||
const e = document.createElement('h2');
|
||||
e.innerHTML = ele.innerHTML;
|
||||
ele.replaceWith(e);
|
||||
});
|
||||
}
|
||||
const description = document.body.innerHTML.trim();
|
||||
return {
|
||||
title: id.startsWith('P921') ? title.replace('1', id.split('P921')[1]) : title,
|
||||
|
||||
@@ -93,12 +93,12 @@ export default class CSGOJProvider extends BasicFetcher implements IBasicProvide
|
||||
const pDescription = document.querySelector('div[name="Description"]');
|
||||
const files = {};
|
||||
const images = {};
|
||||
pDescription.querySelectorAll('img[src]').forEach((ele) => {
|
||||
for (const ele of pDescription.querySelectorAll('img[src]')) {
|
||||
let src = ele.getAttribute('src').replace('.svg', '.png');
|
||||
src = new URL(src, 'https://cpc.csgrandeur.cn').toString();
|
||||
if (images[src]) {
|
||||
ele.setAttribute('src', `file://${images[src]}.png`);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
const file = new PassThrough();
|
||||
this.get(src).pipe(file);
|
||||
@@ -106,7 +106,7 @@ export default class CSGOJProvider extends BasicFetcher implements IBasicProvide
|
||||
images[src] = fid;
|
||||
files[`${fid}.png`] = file;
|
||||
ele.setAttribute('src', `file://${fid}.png`);
|
||||
});
|
||||
}
|
||||
const description = [...pDescription.children].map((i) => i.outerHTML).join('');
|
||||
const input = [...document.querySelector('div[name="Input"]').children].map((i) => i.outerHTML).join('');
|
||||
const output = [...document.querySelector('div[name="Output"]').children].map((i) => i.outerHTML).join('');
|
||||
|
||||
@@ -113,11 +113,11 @@ export default class POJProvider extends BasicFetcher implements IBasicProvider
|
||||
content.children[0].remove();
|
||||
content.children[0].remove();
|
||||
content.children[0].remove();
|
||||
content.querySelectorAll('img[src]').forEach((ele) => {
|
||||
for (const ele of content.querySelectorAll('img[src]')) {
|
||||
const src = ele.getAttribute('src');
|
||||
if (images[src]) {
|
||||
ele.setAttribute('src', `file://${images[src]}.png`);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
const file = new PassThrough();
|
||||
this.get(src).pipe(file);
|
||||
@@ -125,7 +125,7 @@ export default class POJProvider extends BasicFetcher implements IBasicProvider
|
||||
images[src] = fid;
|
||||
files[`${fid}.png`] = file;
|
||||
ele.setAttribute('src', `file://${fid}.png`);
|
||||
});
|
||||
}
|
||||
let lastId = 0;
|
||||
let markNext = '';
|
||||
let html = '';
|
||||
|
||||
@@ -52,15 +52,15 @@ export default class SPOJProvider extends BasicFetcher implements IBasicProvider
|
||||
logger.info(id);
|
||||
const { document } = await this.html(`/problems/${id}/`);
|
||||
const files = {};
|
||||
document.querySelector('#problem-body').querySelectorAll('img[src]').forEach((ele) => {
|
||||
for (const ele of document.querySelector('#problem-body').querySelectorAll('img[src]')) {
|
||||
const src = ele.getAttribute('src');
|
||||
if (!src.startsWith('http')) return;
|
||||
if (!src.startsWith('http')) continue;
|
||||
const file = new PassThrough();
|
||||
this.get(src).pipe(file);
|
||||
const fid = String.random(8);
|
||||
files[`${fid}.png`] = file;
|
||||
ele.setAttribute('src', `file://${fid}.png`);
|
||||
});
|
||||
}
|
||||
const meta = document.querySelector('#problem-meta').children[1];
|
||||
const window = await this.html(`/submit/${id}/`);
|
||||
const langs = Array.from(window.document.querySelector('#lang').querySelectorAll('option'))
|
||||
|
||||
@@ -71,15 +71,15 @@ export default class UOJProvider extends BasicFetcher implements IBasicProvider
|
||||
const res = await this.get(`/problem/${id.split('P')[1]}`);
|
||||
const { window: { document } } = new JSDOM(res.text);
|
||||
const files = {};
|
||||
document.querySelectorAll('article>img[src]').forEach((ele) => {
|
||||
for (const ele of document.querySelectorAll('article>img[src]')) {
|
||||
const src = ele.getAttribute('src');
|
||||
if (!src.startsWith('http')) return;
|
||||
if (!src.startsWith('http')) continue;
|
||||
const file = new PassThrough();
|
||||
this.get(src).pipe(file);
|
||||
const fid = String.random(8);
|
||||
files[`${fid}.png`] = file;
|
||||
ele.setAttribute('src', `file://${fid}.png`);
|
||||
});
|
||||
}
|
||||
const contentNode = document.querySelector('article');
|
||||
const titles = contentNode.querySelectorAll('h3');
|
||||
for (const title of titles) {
|
||||
|
||||
Reference in new issue
Block a user