diff --git a/.eslintrc b/.eslintrc index c7ae618ffa..6bb90758a6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -43,6 +43,7 @@ }], "no-else-return": [ "error", { "allowElseIf": true } ], "operator-linebreak": [ "error", "after" ], + "arrow-parens": ["error", "as-needed"], // ES6 "prefer-rest-params": "off", diff --git a/install/package.json b/install/package.json index 0720a79423..bc9f4ec6b2 100644 --- a/install/package.json +++ b/install/package.json @@ -135,7 +135,7 @@ "@commitlint/config-angular": "8.1.0", "coveralls": "3.0.5", "eslint": "6.1.0", - "eslint-config-airbnb-base": "13.2.0", + "eslint-config-airbnb-base": "14.0.0", "eslint-plugin-import": "2.18.2", "grunt": "1.0.4", "grunt-contrib-watch": "1.1.0", diff --git a/public/src/modules/translator.js b/public/src/modules/translator.js index ae286fdc25..a861f8fc39 100644 --- a/public/src/modules/translator.js +++ b/public/src/modules/translator.js @@ -579,6 +579,7 @@ }, toggleTimeagoShorthand: function toggleTimeagoShorthand(callback) { + /* eslint "prefer-object-spread": "off" */ function toggle() { var tmp = assign({}, jQuery.timeago.settings.strings); jQuery.timeago.settings.strings = assign({}, adaptor.timeagoShort); diff --git a/src/categories/index.js b/src/categories/index.js index 7f2410efb5..395e0f1f56 100644 --- a/src/categories/index.js +++ b/src/categories/index.js @@ -146,7 +146,7 @@ Categories.getCategories = async function (cids, uid) { Categories.getTagWhitelist = async function (cids) { const cachedData = {}; - const nonCachedCids = cids.filter((cid) => { + const nonCachedCids = cids.filter(cid => { const data = cache.get('cid:' + cid + ':tag:whitelist'); const isInCache = data !== undefined; if (isInCache) { diff --git a/src/categories/recentreplies.js b/src/categories/recentreplies.js index 3e94cbf834..0c08c50b92 100644 --- a/src/categories/recentreplies.js +++ b/src/categories/recentreplies.js @@ -157,7 +157,7 @@ module.exports = function (Categories) { const bulkRemove = []; const bulkAdd = []; - postData.forEach((post) => { + postData.forEach(post => { bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids', post.pid]); bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids:votes', post.pid]); bulkAdd.push(['cid:' + cid + ':uid:' + post.uid + ':pids', post.timestamp, post.pid]); diff --git a/src/cli/package-install.js b/src/cli/package-install.js index 7baaee2a2b..699a5962bd 100644 --- a/src/cli/package-install.js +++ b/src/cli/package-install.js @@ -20,9 +20,7 @@ function updatePackageFile() { } var defaultPackageContents = JSON.parse(fs.readFileSync(packageDefaultFilePath, 'utf8')); - var packageContents = Object.assign({}, oldPackageContents, defaultPackageContents, { - dependencies: Object.assign({}, oldPackageContents.dependencies, defaultPackageContents.dependencies), - }); + var packageContents = { ...oldPackageContents, ...defaultPackageContents, dependencies: { ...oldPackageContents.dependencies, ...defaultPackageContents.dependencies } }; fs.writeFileSync(packageFilePath, JSON.stringify(packageContents, null, 2)); } diff --git a/src/controllers/accounts/helpers.js b/src/controllers/accounts/helpers.js index 10414467e8..3975a5c914 100644 --- a/src/controllers/accounts/helpers.js +++ b/src/controllers/accounts/helpers.js @@ -197,13 +197,12 @@ function filterLinks(links, states) { } // Default visibility - link.visibility = Object.assign({ - self: true, + link.visibility = { self: true, other: true, moderator: true, globalMod: true, admin: true, - }, link.visibility); + ...link.visibility }; var permit = Object.keys(states).some(function (state) { return states[state] && link.visibility[state]; diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index 968209f7d0..1840b372f8 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -202,7 +202,7 @@ authenticationController.registerComplete = function (req, res, next) { delete payload.uid; delete payload.returnTo; - Object.keys(payload).forEach((prop) => { + Object.keys(payload).forEach(prop => { if (typeof payload[prop] === 'boolean') { payload[prop] = payload[prop] ? 1 : 0; } diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 155c4d14f4..71a62d7bfd 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -238,7 +238,7 @@ async function addTags(topicData, req, res) { async function addOGImageTags(res, topicData, postAtIndex) { const uploads = postAtIndex ? await posts.uploads.listWithSizes(postAtIndex.pid) : []; - const images = uploads.map((upload) => { + const images = uploads.map(upload => { upload.name = nconf.get('url') + nconf.get('upload_url') + '/files/' + upload.name; return upload; }); diff --git a/src/controllers/unread.js b/src/controllers/unread.js index faafc50b83..710428dbc0 100644 --- a/src/controllers/unread.js +++ b/src/controllers/unread.js @@ -24,7 +24,7 @@ unreadController.get = function (req, res, next) { async.waterfall([ function (next) { - plugins.fireHook('filter:unread.getValidFilters', { filters: Object.assign({}, helpers.validFilters) }, next); + plugins.fireHook('filter:unread.getValidFilters', { filters: { ...helpers.validFilters } }, next); }, function (data, _next) { if (!data.filters[filter]) { @@ -98,7 +98,7 @@ unreadController.unreadTotal = function (req, res, next) { async.waterfall([ function (next) { - plugins.fireHook('filter:unread.getValidFilters', { filters: Object.assign({}, helpers.validFilters) }, next); + plugins.fireHook('filter:unread.getValidFilters', { filters: { ...helpers.validFilters } }, next); }, function (data, _next) { if (!data.filters[filter]) { diff --git a/src/database/index.js b/src/database/index.js index 818efb4fe0..ae1f0e5446 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -12,7 +12,7 @@ if (!databaseName) { var primaryDB = require('./' + databaseName); primaryDB.parseIntFields = function (data, intFields, requestedFields) { - intFields.forEach((field) => { + intFields.forEach(field => { if (!requestedFields.length || requestedFields.includes(field)) { data[field] = parseInt(data[field], 10) || 0; } diff --git a/src/database/mongo/hash.js b/src/database/mongo/hash.js index f9416d8206..9ffacbef31 100644 --- a/src/database/mongo/hash.js +++ b/src/database/mongo/hash.js @@ -86,7 +86,7 @@ module.exports = function (module) { const item = cachedData[key] || {}; const result = {}; - fields.forEach((field) => { + fields.forEach(field => { result[field] = item[field] !== undefined ? item[field] : null; }); return result; diff --git a/src/database/redis/hash.js b/src/database/redis/hash.js index 6dc2444283..8cb00b156f 100644 --- a/src/database/redis/hash.js +++ b/src/database/redis/hash.js @@ -117,7 +117,7 @@ module.exports = function (module) { const item = cachedData[key] || {}; const result = {}; - fields.forEach((field) => { + fields.forEach(field => { result[field] = item[field] !== undefined ? item[field] : null; }); return result; diff --git a/src/database/redis/sorted.js b/src/database/redis/sorted.js index 884d966df7..78077e1151 100644 --- a/src/database/redis/sorted.js +++ b/src/database/redis/sorted.js @@ -32,7 +32,7 @@ module.exports = function (module) { return []; } const batch = module.client.batch(); - key.forEach((key) => { + key.forEach(key => { batch[method]([key, start, stop, 'WITHSCORES']); }); let data = await helpers.execBatch(batch); diff --git a/src/emailer.js b/src/emailer.js index 996dab43ab..d8477a658b 100644 --- a/src/emailer.js +++ b/src/emailer.js @@ -194,7 +194,7 @@ Emailer.send = function (template, uid, params, callback) { } // Combined passed-in payload with default values - params = Object.assign({}, Emailer._defaultPayload, params); + params = { ...Emailer._defaultPayload, ...params }; async.waterfall([ function (next) { @@ -228,10 +228,9 @@ Emailer.sendToEmail = function (template, email, language, params, callback) { var lang = language || meta.config.defaultLang || 'en-GB'; // Add some default email headers based on local configuration - params.headers = Object.assign({ - 'List-Id': '<' + [template, params.uid, getHostname()].join('.') + '>', + params.headers = { 'List-Id': '<' + [template, params.uid, getHostname()].join('.') + '>', 'List-Unsubscribe': '<' + [nconf.get('url'), 'uid', params.uid, 'settings'].join('/') + '>', - }, params.headers); + ...params.headers }; // Digests and notifications can be one-click unsubbed let payload = { diff --git a/src/flags.js b/src/flags.js index eacfacf672..affb2ff440 100644 --- a/src/flags.js +++ b/src/flags.js @@ -93,17 +93,15 @@ Flags.get = function (flagId, callback) { targetObj: async.apply(Flags.getTarget, data.base.type, data.base.targetId, 0), }, function (err, payload) { // Final object return construction - next(err, Object.assign({ - state: 'open', - }, data.base, { + next(err, { state: 'open', + ...data.base, description: validator.escape(data.base.description), datetimeISO: utils.toISOString(data.base.datetime), target_readable: data.base.type.charAt(0).toUpperCase() + data.base.type.slice(1) + ' ' + data.base.targetId, target: payload.targetObj, history: data.history, notes: data.notes, - reporter: payload.userObj, - })); + reporter: payload.userObj }); }); }, function (flagObj, next) { @@ -181,16 +179,14 @@ Flags.list = function (filters, uid, callback) { async.apply(db.getObject, 'flag:' + flagId), function (flagObj, next) { user.getUserFields(flagObj.uid, ['username', 'picture'], function (err, userObj) { - next(err, Object.assign({ - state: 'open', - }, flagObj, { + next(err, { state: 'open', + ...flagObj, reporter: { username: userObj.username, picture: userObj.picture, 'icon:bgColor': userObj['icon:bgColor'], 'icon:text': userObj['icon:text'], - }, - })); + } }); }); }, ], function (err, flagObj) { diff --git a/src/messaging/create.js b/src/messaging/create.js index 7a126e1e60..6b83bee17e 100644 --- a/src/messaging/create.js +++ b/src/messaging/create.js @@ -6,7 +6,7 @@ var db = require('../database'); var user = require('../user'); module.exports = function (Messaging) { - Messaging.sendMessage = async (data) => { + Messaging.sendMessage = async data => { await Messaging.checkContent(data.content); const inRoom = await Messaging.isUserInRoom(data.uid, data.roomId); if (!inRoom) { @@ -16,7 +16,7 @@ module.exports = function (Messaging) { return await Messaging.addMessage(data); }; - Messaging.checkContent = async (content) => { + Messaging.checkContent = async content => { if (!content) { throw new Error('[[error:invalid-chat-message]]'); } @@ -32,7 +32,7 @@ module.exports = function (Messaging) { } }; - Messaging.addMessage = async (data) => { + Messaging.addMessage = async data => { const mid = await db.incrObjectField('global', 'nextMid'); const timestamp = data.timestamp || new Date().getTime(); let message = { diff --git a/src/messaging/data.js b/src/messaging/data.js index 982e51b746..54b891727f 100644 --- a/src/messaging/data.js +++ b/src/messaging/data.js @@ -77,7 +77,7 @@ module.exports = function (Messaging) { message.system = !!message.system; }); - messages = await Promise.all(messages.map(async (message) => { + messages = await Promise.all(messages.map(async message => { if (message.system) { return message; } diff --git a/src/messaging/index.js b/src/messaging/index.js index 2bcad1445b..1f1686de9b 100644 --- a/src/messaging/index.js +++ b/src/messaging/index.js @@ -20,7 +20,7 @@ require('./unread')(Messaging); require('./notifications')(Messaging); -Messaging.getMessages = async (params) => { +Messaging.getMessages = async params => { const isNew = params.isNew || false; const start = params.hasOwnProperty('start') ? params.start : 0; const stop = parseInt(start, 10) + ((params.count || 50) - 1); @@ -98,7 +98,7 @@ Messaging.getRecentChats = async (callerUid, uid, start, stop) => { const results = await utils.promiseParallel({ roomData: Messaging.getRoomsData(roomIds), unread: db.isSortedSetMembers('uid:' + uid + ':chat:rooms:unread', roomIds), - users: Promise.all(roomIds.map(async (roomId) => { + users: Promise.all(roomIds.map(async roomId => { let uids = await db.getSortedSetRevRange('chat:room:' + roomId + ':uids', 0, 9); uids = uids.filter(function (value) { return value && parseInt(value, 10) !== parseInt(uid, 10); diff --git a/src/messaging/rooms.js b/src/messaging/rooms.js index ed5ae4ec6b..6d8cce1870 100644 --- a/src/messaging/rooms.js +++ b/src/messaging/rooms.js @@ -9,7 +9,7 @@ var privileges = require('../privileges'); var meta = require('../meta'); module.exports = function (Messaging) { - Messaging.getRoomData = async (roomId) => { + Messaging.getRoomData = async roomId => { const data = await db.getObject('chat:room:' + roomId); if (!data) { throw new Error('[[error:no-chat-room]]'); @@ -19,7 +19,7 @@ module.exports = function (Messaging) { return data; }; - Messaging.getRoomsData = async (roomIds) => { + Messaging.getRoomsData = async roomIds => { const roomData = await db.getObjects(roomIds.map(function (roomId) { return 'chat:room:' + roomId; })); diff --git a/src/messaging/unread.js b/src/messaging/unread.js index 436b88d24c..7c202bddc6 100644 --- a/src/messaging/unread.js +++ b/src/messaging/unread.js @@ -4,7 +4,7 @@ var db = require('../database'); var sockets = require('../socket.io'); module.exports = function (Messaging) { - Messaging.getUnreadCount = async (uid) => { + Messaging.getUnreadCount = async uid => { if (parseInt(uid, 10) <= 0) { return 0; } @@ -12,7 +12,7 @@ module.exports = function (Messaging) { return await db.sortedSetCard('uid:' + uid + ':chat:rooms:unread'); }; - Messaging.pushUnreadCount = async (uid) => { + Messaging.pushUnreadCount = async uid => { if (parseInt(uid, 10) <= 0) { return; } diff --git a/src/meta/configs.js b/src/meta/configs.js index 560ad79517..2568241163 100644 --- a/src/meta/configs.js +++ b/src/meta/configs.js @@ -72,7 +72,7 @@ Configs.getFields = async function (fields) { values = await db.getObject('config'); } - values = Object.assign({}, defaults, values ? deserialize(values) : {}); + values = { ...defaults, ...(values ? deserialize(values) : {}) }; if (!fields.length) { values.version = nconf.get('version'); @@ -100,7 +100,7 @@ Configs.setMultiple = async function (data) { Configs.setOnEmpty = async function (values) { const data = await db.getObject('config'); - const config = Object.assign({}, values, data ? deserialize(data) : {}); + const config = { ...values, ...(data ? deserialize(data) : {}) }; await db.setObject('config', config); }; diff --git a/src/meta/debugFork.js b/src/meta/debugFork.js index 575eebd610..3ec746da10 100644 --- a/src/meta/debugFork.js +++ b/src/meta/debugFork.js @@ -30,9 +30,7 @@ function debugFork(modulePath, args, options) { } options = options || {}; - options = Object.assign({}, options, { - execArgv: execArgv, - }); + options = { ...options, execArgv: execArgv }; return fork(modulePath, args, options); } diff --git a/src/meta/templates.js b/src/meta/templates.js index 7397f6c9ea..358ffdb1bb 100644 --- a/src/meta/templates.js +++ b/src/meta/templates.js @@ -83,7 +83,7 @@ async function getTemplateDirs(activePlugins) { } async function getTemplateFiles(dirs) { - const buckets = await Promise.all(dirs.map(async (dir) => { + const buckets = await Promise.all(dirs.map(async dir => { let files = await file.walk(dir); files = files.filter(function (path) { return path.endsWith('.tpl'); @@ -132,7 +132,7 @@ async function compile() { files = await getTemplateDirs(files); files = await getTemplateFiles(files); - await Promise.all(Object.keys(files).map(async (name) => { + await Promise.all(Object.keys(files).map(async name => { const filePath = files[name]; let imported = await fsReadFile(filePath, 'utf8'); imported = await processImports(files, name, imported); diff --git a/src/meta/themes.js b/src/meta/themes.js index 9308b3d7fa..41ccdd333a 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -30,7 +30,7 @@ Themes.get = async () => { let themes = await getThemes(themePath); themes = _.flatten(themes).filter(Boolean); - themes = await Promise.all(themes.map(async (theme) => { + themes = await Promise.all(themes.map(async theme => { const config = path.join(themePath, theme, 'theme.json'); try { const file = await fsReadfile(config, 'utf8'); @@ -61,7 +61,7 @@ Themes.get = async () => { async function getThemes(themePath) { let dirs = await fsReaddir(themePath); dirs = dirs.filter(dir => themeNamePattern.test(dir) || dir.startsWith('@')); - return await Promise.all(dirs.map(async (dir) => { + return await Promise.all(dirs.map(async dir => { try { const dirpath = path.join(themePath, dir); const stat = await fsStat(dirpath); @@ -85,7 +85,7 @@ async function getThemes(themePath) { })); } -Themes.set = async (data) => { +Themes.set = async data => { const themeData = { 'theme:type': data.type, 'theme:id': data.id, diff --git a/src/middleware/header.js b/src/middleware/header.js index 3c14793b78..b723b009f5 100644 --- a/src/middleware/header.js +++ b/src/middleware/header.js @@ -238,7 +238,7 @@ module.exports = function (middleware) { function (data, next) { async.parallel({ scripts: async.apply(plugins.fireHook, 'filter:scripts.get', []), - timeagoLocale: (next) => { + timeagoLocale: next => { async.waterfall([ async.apply(languages.listCodes), (languageCodes, next) => { diff --git a/src/plugins/hooks.js b/src/plugins/hooks.js index 0adeadb8e9..260224aff8 100644 --- a/src/plugins/hooks.js +++ b/src/plugins/hooks.js @@ -54,7 +54,7 @@ module.exports = function (Plugins) { if (Array.isArray(data.method) && data.method.every(method => typeof method === 'function' || typeof method === 'string')) { // Go go gadget recursion! data.method.forEach(function (method) { - const singularData = Object.assign({}, data, { method: method }); + const singularData = { ...data, method: method }; Plugins.registerHook(id, singularData); }); } else if (typeof data.method === 'string' && data.method.length > 0) { @@ -157,7 +157,7 @@ module.exports = function (Plugins) { next(); }, 5000); - const onError = (err) => { + const onError = err => { winston.error('[plugins] Error executing \'' + hook + '\' in plugin \'' + hookObj.id + '\''); winston.error(err); clearTimeout(timeoutId); diff --git a/src/plugins/load.js b/src/plugins/load.js index 0da37acd27..9648e3168d 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -88,7 +88,7 @@ module.exports = function (Plugins) { const fields = _.uniq(_.flatMap(targets, target => map[target] || [])); // clear old data before build - fields.forEach((field) => { + fields.forEach(field => { switch (field) { case 'clientScripts': case 'acpScripts': diff --git a/src/posts/uploads.js b/src/posts/uploads.js index 8142f1b992..94fa9e36b0 100644 --- a/src/posts/uploads.js +++ b/src/posts/uploads.js @@ -108,7 +108,7 @@ module.exports = function (Posts) { ]); }; - Posts.uploads.saveSize = async (filePaths) => { + Posts.uploads.saveSize = async filePaths => { await Promise.all(filePaths.map(async function (fileName) { try { const size = await image.size(path.join(pathPrefix, fileName)); diff --git a/src/posts/user.js b/src/posts/user.js index 9205bed2f4..8db9c62947 100644 --- a/src/posts/user.js +++ b/src/posts/user.js @@ -207,7 +207,7 @@ module.exports = function (Posts) { const bulkAdd = []; const bulkRemove = []; const postsByUser = {}; - mainPosts.forEach((post) => { + mainPosts.forEach(post => { bulkRemove.push(['cid:' + post.cid + ':uid:' + post.uid + ':tids', post.tid]); bulkRemove.push(['uid:' + post.uid + ':topics', post.tid]); diff --git a/src/prestart.js b/src/prestart.js index 49f6336499..76190400c6 100644 --- a/src/prestart.js +++ b/src/prestart.js @@ -22,7 +22,7 @@ function setupWinston() { formats.push(winston.format.timestamp()); formats.push(winston.format.json()); } else { - const timestampFormat = winston.format((info) => { + const timestampFormat = winston.format(info => { var dateString = new Date().toISOString() + ' [' + nconf.get('port') + '/' + global.process.pid + ']'; info.level = dateString + ' - ' + info.level; return info; diff --git a/src/privileges/helpers.js b/src/privileges/helpers.js index 81659d510d..cad087d6f5 100644 --- a/src/privileges/helpers.js +++ b/src/privileges/helpers.js @@ -148,8 +148,8 @@ helpers.giveOrRescind = async function (method, privileges, cids, groupNames) { cids = Array.isArray(cids) ? cids : [cids]; for (const groupName of groupNames) { const groupKeys = []; - cids.forEach((cid) => { - privileges.forEach((privilege) => { + cids.forEach(cid => { + privileges.forEach(privilege => { groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege); }); }); diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index 1589fe1dad..c64b31cabc 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -166,7 +166,7 @@ SocketModules.chats.getUsersInRoom = function (socket, data, callback) { return callback(err); } - payload.users = payload.users.map((user) => { + payload.users = payload.users.map(user => { user.canKick = (parseInt(user.uid, 10) !== parseInt(socket.uid, 10)) && payload.isOwner; return user; }); diff --git a/src/topics/follow.js b/src/topics/follow.js index 957e97a6de..0c3ed1145b 100644 --- a/src/topics/follow.js +++ b/src/topics/follow.js @@ -90,7 +90,7 @@ module.exports = function (Topics) { return tids.map(() => ({ following: false, ignoring: false })); } const keys = []; - tids.forEach((tid) => { + tids.forEach(tid => { keys.push('tid:' + tid + ':followers', 'tid:' + tid + ':ignorers'); }); diff --git a/src/user/blocks.js b/src/user/blocks.js index c8fd75ed95..1466610360 100644 --- a/src/user/blocks.js +++ b/src/user/blocks.js @@ -98,7 +98,7 @@ module.exports = function (User) { property = 'uid'; } - if (!Array.isArray(set) || !set.length || !set.every((item) => { + if (!Array.isArray(set) || !set.length || !set.every(item => { if (!item) { return false; } diff --git a/src/user/invite.js b/src/user/invite.js index 1ad7acd467..8b742263b6 100644 --- a/src/user/invite.js +++ b/src/user/invite.js @@ -64,7 +64,7 @@ module.exports = function (User) { }; // Append default data to this email payload - data = Object.assign({}, emailer._defaultPayload, data); + data = { ...emailer._defaultPayload, ...data }; await emailer.sendToEmail('invitation', email, meta.config.defaultLang, data); };