refactor: switch eslint configs to esm

add rules from https://eslint.style/
refactor for in loops to use Object.entries
This commit is contained in:
Barış Soner Uşaklı
2025-04-18 21:57:12 -04:00
parent 0c5ef0e866
commit 92d6e0220b
21 changed files with 93 additions and 132 deletions

View File

@@ -1,11 +1,14 @@
'use strict';
const serverConfig = require('eslint-config-nodebb');
const publicConfig = require('eslint-config-nodebb/public');
const { configs } = require('@eslint/js');
const globals = require('globals');
import serverConfig from 'eslint-config-nodebb';
import publicConfig from 'eslint-config-nodebb/public';
module.exports = [
import { defineConfig } from 'eslint/config';
import globals from 'globals';
import js from '@eslint/js';
export default defineConfig([
{
ignores: [
'node_modules/',
@@ -27,7 +30,6 @@ module.exports = [
'install/docker/',
],
},
configs.recommended,
{
rules: {
'no-bitwise': 'warn',
@@ -58,5 +60,5 @@ module.exports = [
},
...publicConfig,
...serverConfig
];
]);

View File

@@ -162,7 +162,8 @@
"@commitlint/config-angular": "19.8.0",
"coveralls": "3.1.1",
"@eslint/js": "9.24.0",
"eslint-config-nodebb": "1.0.7",
"@stylistic/eslint-plugin-js": "4.2.0",
"eslint-config-nodebb": "1.1.0",
"eslint-plugin-import": "2.31.0",
"grunt": "1.6.1",
"grunt-contrib-watch": "1.1.0",

View File

@@ -84,14 +84,10 @@ define('admin/extend/rewards', [
let inputs;
let html = '';
for (const reward in available) {
if (available.hasOwnProperty(reward)) {
if (available[reward].rid === el.attr('data-selected')) {
inputs = available[reward].inputs;
parent.attr('data-rid', available[reward].rid);
break;
}
}
const selectedReward = available.find(reward => reward.rid === el.attr('data-selected'));
if (selectedReward) {
inputs = selectedReward.inputs;
parent.attr('data-rid', selectedReward.rid);
}
if (!inputs) {
@@ -122,10 +118,8 @@ define('admin/extend/rewards', [
const div = $(this).find('.inputs');
const rewards = active[i].rewards;
for (const reward in rewards) {
if (rewards.hasOwnProperty(reward)) {
div.find('[name="' + reward + '"]').val(rewards[reward]);
}
for (const [reward, value] of Object.entries(rewards)) {
div.find('[name="' + reward + '"]').val(value);
}
});
}

View File

@@ -117,23 +117,21 @@ define('admin/extend/widgets', [
area.find('.widget-panel[data-widget]').each(function () {
const widgetData = {};
const data = $(this).find('form').serializeArray();
for (const d in data) {
if (data.hasOwnProperty(d)) {
if (data[d].name) {
if (widgetData[data[d].name]) {
if (!Array.isArray(widgetData[data[d].name])) {
widgetData[data[d].name] = [
widgetData[data[d].name],
];
}
widgetData[data[d].name].push(data[d].value);
} else {
widgetData[data[d].name] = data[d].value;
data.forEach((widgetField) => {
const { name, value } = widgetField;
if (name) {
if (widgetData[name]) {
if (!Array.isArray(widgetData[name])) {
widgetData[name] = [
widgetData[name],
];
}
widgetData[name].push(value);
} else {
widgetData[name] = value;
}
}
}
});
widgets.push({
widget: $(this).attr('data-widget'),

View File

@@ -215,10 +215,8 @@ define('admin/settings', [
return callback(err);
}
for (const field in data) {
if (data.hasOwnProperty(field)) {
app.config[field] = data[field];
}
for (const [field, value] of Object.entries(data)) {
app.config[field] = value;
}
callback();

View File

@@ -192,7 +192,6 @@ if (document.readyState === 'loading') {
const pageParams = utils.params();
function queryMatch(search) {
const mySearchParams = new URLSearchParams(search);
// eslint-disable-next-line no-restricted-syntax
for (const [key, value] of mySearchParams) {
if (pageParams[key] === value) {
return true;

View File

@@ -75,17 +75,15 @@ define('forum/account/settings', [
api.put(`/users/${ajaxify.data.uid}/settings`, { settings }).then((newSettings) => {
alerts.success('[[success:settings-saved]]');
let languageChanged = false;
for (const key in newSettings) {
if (newSettings.hasOwnProperty(key)) {
if (key === 'userLang' && config.userLang !== newSettings.userLang) {
languageChanged = true;
}
if (key === 'bootswatchSkin') {
savedSkin = newSettings.bootswatchSkin;
config.bootswatchSkin = savedSkin === 'noskin' ? '' : savedSkin;
} else if (config.hasOwnProperty(key)) {
config[key] = newSettings[key];
}
for (const [key, value] of Object.entries(newSettings)) {
if (key === 'userLang' && config.userLang !== newSettings.userLang) {
languageChanged = true;
}
if (key === 'bootswatchSkin') {
savedSkin = newSettings.bootswatchSkin;
config.bootswatchSkin = savedSkin === 'noskin' ? '' : savedSkin;
} else if (config.hasOwnProperty(key)) {
config[key] = value;
}
}

View File

@@ -103,10 +103,8 @@ export function enableFilterForm() {
});
} else {
// Persona; parse ajaxify data to set form values to reflect current filters
for (const filter in ajaxify.data.filters) {
if (ajaxify.data.filters.hasOwnProperty(filter)) {
$filtersEl.find('[name="' + filter + '"]').val(ajaxify.data.filters[filter]);
}
for (const [filter, value] of Object.entries(ajaxify.data.filters)) {
$filtersEl.find('[name="' + filter + '"]').val(value);
}
$filtersEl.find('[name="sort"]').val(ajaxify.data.sort);

View File

@@ -50,18 +50,14 @@ define('forum/topic/events', [
Events.init = function () {
Events.removeListeners();
for (const eventName in events) {
if (events.hasOwnProperty(eventName)) {
socket.on(eventName, events[eventName]);
}
for (const [eventName, handler] of Object.entries(events)) {
socket.on(eventName, handler);
}
};
Events.removeListeners = function () {
for (const eventName in events) {
if (events.hasOwnProperty(eventName)) {
socket.removeListener(eventName, events[eventName]);
}
for (const [eventName, handler] of Object.entries(events)) {
socket.removeListener(eventName, handler);
}
};

View File

@@ -180,14 +180,12 @@ module.exports = function (utils, Benchpress, relative_path) {
function spawnPrivilegeStates(cid, member, privileges, types) {
const states = [];
for (const priv in privileges) {
if (privileges.hasOwnProperty(priv)) {
states.push({
name: priv,
state: privileges[priv],
type: types[priv],
});
}
for (const [priv, state] of Object.entries(privileges)) {
states.push({
name: priv,
state: state,
type: types[priv],
});
}
return states.map(function (priv) {
const guestDisabled = ['groups:moderate', 'groups:posts:upvote', 'groups:posts:downvote', 'groups:local:login', 'groups:group:create'];

View File

@@ -255,7 +255,6 @@ define('iconSelect', ['benchpress', 'bootbox'], function (Benchpress, bootbox) {
className: 'btn-default',
callback: function () {
el.removeClass(selected.icon);
// eslint-disable-next-line no-restricted-syntax
for (const style of selected.styles) {
el.removeClass(style);
}
@@ -272,11 +271,9 @@ define('iconSelect', ['benchpress', 'bootbox'], function (Benchpress, bootbox) {
const newIcon = cleanFAClass(iconClass);
if (newIcon.icon) {
el.removeClass(selected.icon).addClass(newIcon.icon);
// eslint-disable-next-line no-restricted-syntax
for (const style of selected.styles || []) {
el.removeClass(style);
}
// eslint-disable-next-line no-restricted-syntax
for (const style of newIcon.styles || []) {
el.addClass(style);
}
@@ -391,7 +388,6 @@ define('iconSelect', ['benchpress', 'bootbox'], function (Benchpress, bootbox) {
function cleanFAClass(classList) {
const styles = [];
let icon;
// eslint-disable-next-line no-restricted-syntax
for (const className of classList) {
if (className.startsWith('fa-') && !excludedClassRegex.test(className)) {
if (styleRegex.test(className)) {

View File

@@ -267,7 +267,7 @@ define('search', [
function createQueryString(data) {
const searchIn = data.in || 'titles';
let term = data.term.replace(/^[ ?#]*/, '');
const term = data.term.replace(/^[ ?#]*/, '');
const query = {
...data,

View File

@@ -2,12 +2,9 @@
define('settings', ['hooks', 'alerts'], function (hooks, alerts) {
let Settings;
let onReady = [];
let waitingJobs = 0;
let helper;
/**
Returns the hook of given name that matches the given type or element.
@param type The type of the element to get the matching hook for, or the element itself.
@@ -29,7 +26,7 @@ define('settings', ['hooks', 'alerts'], function (hooks, alerts) {
return null;
}
helper = {
const helper = {
/**
@returns Object A deep clone of the given object.
*/
@@ -48,10 +45,8 @@ define('settings', ['hooks', 'alerts'], function (hooks, alerts) {
*/
createElement: function (tagName, data, text) {
const element = document.createElement(tagName);
for (const k in data) {
if (data.hasOwnProperty(k)) {
element.setAttribute(k, data[k]);
}
for (const [k, val] of Object.entries(data)) {
element.setAttribute(k, val);
}
if (text) {
element.appendChild(document.createTextNode(text));
@@ -331,7 +326,7 @@ define('settings', ['hooks', 'alerts'], function (hooks, alerts) {
},
};
Settings = {
const Settings = {
helper: helper,
plugins: {},
cfg: {},

View File

@@ -45,16 +45,13 @@ define('settings/array', function () {
element.attr('data-parent', '_' + key);
delete attributes['data-type'];
delete attributes.tagName;
for (const name in attributes) {
if (attributes.hasOwnProperty(name)) {
const val = attributes[name];
if (name.search('data-') === 0) {
element.data(name.substring(5), val);
} else if (name.search('prop-') === 0) {
element.prop(name.substring(5), val);
} else {
element.attr(name, val);
}
for (const [name, val] of Object.entries(attributes)) {
if (name.search('data-') === 0) {
element.data(name.substring(5), val);
} else if (name.search('prop-') === 0) {
element.prop(name.substring(5), val);
} else {
element.attr(name, val);
}
}
helper.fillField(element, value);

View File

@@ -25,16 +25,13 @@ define('settings/object', function () {
element.attr('data-prop', prop);
delete attributes['data-type'];
delete attributes.tagName;
for (const name in attributes) {
if (attributes.hasOwnProperty(name)) {
const val = attributes[name];
if (name.search('data-') === 0) {
element.data(name.substring(5), val);
} else if (name.search('prop-') === 0) {
element.prop(name.substring(5), val);
} else {
element.attr(name, val);
}
for (const [name, val] of Object.entries(attributes)) {
if (name.search('data-') === 0) {
element.data(name.substring(5), val);
} else if (name.search('prop-') === 0) {
element.prop(name.substring(5), val);
} else {
element.attr(name, val);
}
}
helper.fillField(element, value);
@@ -62,9 +59,7 @@ define('settings/object', function () {
const properties = element.data('attributes') || element.data('properties');
const key = element.data('key') || element.data('parent');
let separator = element.data('split') || ', ';
let propertyIndex;
let propertyName;
let attributes;
separator = (function () {
try {
return $(separator);
@@ -77,27 +72,26 @@ define('settings/object', function () {
if (typeof value !== 'object') {
value = {};
}
if (Array.isArray(properties)) {
for (propertyIndex in properties) {
if (properties.hasOwnProperty(propertyIndex)) {
attributes = properties[propertyIndex];
if (typeof attributes !== 'object') {
attributes = {};
}
propertyName = attributes['data-prop'] || attributes['data-property'] || propertyIndex;
if (value[propertyName] === undefined && attributes['data-new'] !== undefined) {
value[propertyName] = attributes['data-new'];
}
addObjectPropertyElement(
element,
key,
attributes,
propertyName,
value[propertyName],
separator.clone(),
function (el) { element.append(el); }
);
for (const [propertyIndex, attr] of Object.entries(properties)) {
let attributes = attr;
if (typeof attr !== 'object') {
attributes = {};
}
const propertyName = attributes['data-prop'] || attributes['data-property'] || propertyIndex;
if (value[propertyName] === undefined && attributes['data-new'] !== undefined) {
value[propertyName] = attributes['data-new'];
}
addObjectPropertyElement(
element,
key,
attributes,
propertyName,
value[propertyName],
separator.clone(),
function (el) { element.append(el); }
);
}
}
},

View File

@@ -64,7 +64,6 @@ define('settings/sorted-list', [
}));
// todo: parse() needs to be refactored to return the html, so multiple calls can be parallelized
// eslint-disable-next-line no-restricted-syntax
for (const { itemUUID, item } of items) {
// eslint-disable-next-line no-await-in-loop
const element = await parse($container, itemUUID, item);

View File

@@ -631,7 +631,6 @@ const utils = {
try {
str = JSON.parse(str);
// eslint-disable-next-line no-unused-vars
} catch (err) { /* empty */ }
return str;

View File

@@ -646,7 +646,7 @@ Mocks.notes.public = async (post) => {
content: post.content,
published,
attachment: normalizeAttachment(noteAttachment),
}
};
}
let context = await posts.getPostField(post.pid, 'context');

View File

@@ -4,7 +4,7 @@ const nconf = require('nconf');
const winston = require('winston');
const validator = require('validator');
const cronJob = require('cron').CronJob;
const { setTimeout } = require('timers/promises')
const { setTimeout } = require('timers/promises');
const db = require('../database');
const analytics = require('../analytics');

View File

@@ -46,7 +46,7 @@ utils.getSass = function () {
const sass = require('sass-embedded');
return sass;
} catch (err) {
console.error(err.message)
console.error(err.message);
return require('sass');
}
};

View File

@@ -285,7 +285,6 @@ describe('Utility Methods', () => {
});
it('should return passed in value if invalid', (done) => {
// eslint-disable-next-line no-loss-of-precision
const bigInt = -111111111111111111;
const result = utils.toISOString(bigInt);
assert.equal(bigInt, result);