refactor: switch to using slugify module

v1.18.x
Barış Soner Uşaklı 4 years ago
parent bddfcb5867
commit dc29f4dca2

@ -46,8 +46,8 @@ var web = module.exports;
var scripts = [
'node_modules/jquery/dist/jquery.js',
'public/vendor/xregexp/xregexp.js',
'public/vendor/xregexp/unicode/unicode-base.js',
'node_modules/xregexp/xregexp-all.js',
'public/src/modules/slugify.js',
'public/src/utils.js',
'public/src/installer/install.js',
'node_modules/zxcvbn/dist/zxcvbn.js',

@ -1,8 +1,8 @@
'use strict';
define('admin/manage/users', [
'translator', 'benchpress', 'autocomplete', 'api',
], function (translator, Benchpress, autocomplete, api) {
'translator', 'benchpress', 'autocomplete', 'api', 'slugify',
], function (translator, Benchpress, autocomplete, api, slugify) {
var Users = {};
Users.init = function () {
@ -110,7 +110,7 @@ define('admin/manage/users', [
var groupCard = $(this).parents('[data-group-name]');
var groupName = groupCard.attr('data-group-name');
var uid = $(this).parents('[data-uid]').attr('data-uid');
api.del('/groups/' + utils.slugify(groupName) + '/membership/' + uid, undefined, () => {
api.del('/groups/' + slugify(groupName) + '/membership/' + uid, undefined, () => {
groupCard.remove();
}, 'default');
return false;

@ -1,6 +1,8 @@
'use strict';
define('forum/account/edit/username', ['forum/account/header', 'api'], function (header, api) {
define('forum/account/edit/username', [
'forum/account/header', 'api', 'slugify',
], function (header, api, slugify) {
var AccountEditUsername = {};
AccountEditUsername.init = function () {
@ -26,7 +28,7 @@ define('forum/account/edit/username', ['forum/account/header', 'api'], function
api.put('/users/' + userData.uid, userData, (res) => {
btn.removeClass('disabled').find('i').addClass('hide');
var userslug = utils.slugify(userData.username);
var userslug = slugify(userData.username);
if (userData.username && userslug && parseInt(userData.uid, 10) === parseInt(app.user.uid, 10)) {
$('[component="header/profilelink"]').attr('href', config.relative_path + '/user/' + userslug);
$('[component="header/profilelink/edit"]').attr('href', config.relative_path + '/user/' + userslug + '/edit');

@ -8,7 +8,8 @@ define('forum/groups/details', [
'pictureCropper',
'translator',
'api',
], function (memberList, iconSelect, components, coverPhoto, pictureCropper, translator, api) {
'slugify',
], function (memberList, iconSelect, components, coverPhoto, pictureCropper, translator, api, slugify) {
var Details = {};
var groupName;
@ -208,7 +209,7 @@ define('forum/groups/details', [
if (settings.name) {
var pathname = window.location.pathname;
pathname = pathname.substr(1, pathname.lastIndexOf('/'));
ajaxify.go(pathname + utils.slugify(settings.name));
ajaxify.go(pathname + slugify(settings.name));
} else {
ajaxify.refresh();
}

@ -1,7 +1,9 @@
'use strict';
define('forum/register', ['translator', 'zxcvbn', 'jquery-form'], function (translator, zxcvbn) {
define('forum/register', [
'translator', 'zxcvbn', 'slugify', 'jquery-form',
], function (translator, zxcvbn, slugify) {
var Register = {};
var validationError = false;
var successIcon = '';
@ -32,7 +34,7 @@ define('forum/register', ['translator', 'zxcvbn', 'jquery-form'], function (tran
// Update the "others can mention you via" text
username.on('keyup', function () {
$('#yourUsername').text(this.value.length > 0 ? utils.slugify(this.value) : 'username');
$('#yourUsername').text(this.value.length > 0 ? slugify(this.value) : 'username');
});
username.on('blur', function () {
@ -154,7 +156,7 @@ define('forum/register', ['translator', 'zxcvbn', 'jquery-form'], function (tran
showError(username_notify, '[[error:username-too-short]]');
} else if (username.length > ajaxify.data.maximumUsernameLength) {
showError(username_notify, '[[error:username-too-long]]');
} else if (!utils.isUserNameValid(username) || !utils.slugify(username)) {
} else if (!utils.isUserNameValid(username) || !slugify(username)) {
showError(username_notify, '[[error:invalid-username]]');
} else {
socket.emit('user.exists', {

@ -355,7 +355,14 @@ define('forum/topic/postTools', [
}
if (post.length) {
slug = utils.slugify(post.attr('data-username'), true);
slug = post.attr('data-userslug');
if (!slug) {
if (post.attr('data-uid') !== '0') {
slug = '[[global:former_user]]';
} else {
slug = '[[global:guest]]';
}
}
}
if (post.length && post.attr('data-uid') !== '0') {
slug = '@' + slug;

@ -1,6 +1,6 @@
'use strict';
/* global zxcvbn */
/* global zxcvbn, slugify */
$('document').ready(function () {
setupInputs();
@ -61,7 +61,7 @@ $('document').ready(function () {
var help = parent.children('.help-text');
function validateUsername(field) {
if (!utils.isUserNameValid(field) || !utils.slugify(field)) {
if (!utils.isUserNameValid(field) || !slugify(field)) {
parent.addClass('error');
help.html('Invalid Username.');
} else {

@ -1,10 +1,13 @@
'use strict';
/* global XRegExp */
(function (factory) {
if (typeof module === 'object' && module.exports) {
if (typeof define === 'function' && define.amd) {
define('slugify', ['xregexp'], factory);
} else if (typeof exports === 'object') {
module.exports = factory(require('xregexp'));
} else {
define('slugify', ['xregexp'], factory);
window.slugify = factory(XRegExp);
}
}(function (XRegExp) {
var invalidUnicodeChars = XRegExp('[^\\p{L}\\s\\d\\-_]', 'g');

@ -7,6 +7,7 @@ const db = require('../database');
const plugins = require('../plugins');
const privileges = require('../privileges');
const utils = require('../utils');
const slugify = require('../slugify');
const cache = require('../cache');
module.exports = function (Categories) {
@ -15,7 +16,7 @@ module.exports = function (Categories) {
const cid = await db.incrObjectField('global', 'nextCid');
data.name = data.name || 'Category ' + cid;
const slug = cid + '/' + utils.slugify(data.name);
const slug = cid + '/' + slugify(data.name);
const order = data.order || cid; // If no order provided, place it at the end
const colours = Categories.assignColours();

@ -5,6 +5,7 @@ const async = require('async');
const db = require('../database');
const meta = require('../meta');
const utils = require('../utils');
const slugify = require('../slugify');
const translator = require('../translator');
const plugins = require('../plugins');
const cache = require('../cache');
@ -24,7 +25,7 @@ module.exports = function (Categories) {
if (modifiedFields.hasOwnProperty('name')) {
const translated = await translator.translate(modifiedFields.name);
modifiedFields.slug = cid + '/' + utils.slugify(translated);
modifiedFields.slug = cid + '/' + slugify(translated);
}
const result = await plugins.fireHook('filter:category.update', { cid: cid, category: modifiedFields });

@ -13,6 +13,7 @@ const meta = require('../meta');
const user = require('../user');
const plugins = require('../plugins');
const utils = require('../utils');
const slugify = require('../slugify');
const translator = require('../translator');
const helpers = require('./helpers');
const privileges = require('../privileges');
@ -81,7 +82,7 @@ authenticationController.register = async function (req, res) {
throw new Error('[[error:invalid-email]]');
}
if (!userData.username || userData.username.length < meta.config.minimumUsernameLength || utils.slugify(userData.username).length < meta.config.minimumUsernameLength) {
if (!userData.username || userData.username.length < meta.config.minimumUsernameLength || slugify(userData.username).length < meta.config.minimumUsernameLength) {
throw new Error('[[error:username-too-short]]');
}
@ -356,7 +357,7 @@ authenticationController.localLogin = async function (req, username, password, n
return next(new Error('[[error:password-too-long]]'));
}
const userslug = utils.slugify(username);
const userslug = slugify(username);
const uid = await user.getUidByUserslug(userslug);
try {
const [userData, isAdminOrGlobalMod, banned, hasLoginPrivilege] = await Promise.all([

@ -6,7 +6,7 @@ const user = require('../../user');
const groups = require('../../groups');
const events = require('../../events');
const meta = require('../../meta');
const utils = require('../../utils');
const slugify = require('../../slugify');
const notifications = require('../../notifications');
const helpers = require('../helpers');
@ -114,7 +114,7 @@ Groups.leave = async (req, res) => {
type: 'group-leave',
bodyShort: '[[groups:membership.leave.notification-title, ' + username + ', ' + group.name + ']]',
nid: 'group:' + validator.escape(group.name) + ':uid:' + req.params.uid + ':group-leave',
path: '/groups/' + utils.slugify(group.name),
path: '/groups/' + slugify(group.name),
});
const uids = await groups.getOwners(group.name);
await notifications.push(notification, uids);

@ -8,7 +8,7 @@ const mkdirp = require('mkdirp');
const mime = require('mime');
const graceful = require('graceful-fs');
const utils = require('./utils');
const slugify = require('./slugify');
graceful.gracefulify(fs);
@ -18,7 +18,7 @@ file.saveFileToLocal = async function (filename, folder, tempPath) {
/*
* remarkable doesn't allow spaces in hyperlinks, once that's fixed, remove this.
*/
filename = filename.split('.').map(name => utils.slugify(name)).join('.');
filename = filename.split('.').map(name => slugify(name)).join('.');
const uploadPath = path.join(nconf.get('upload_path'), folder, filename);
if (!uploadPath.startsWith(nconf.get('upload_path'))) {

@ -2,7 +2,7 @@
const meta = require('../meta');
const plugins = require('../plugins');
const utils = require('../utils');
const slugify = require('../slugify');
const db = require('../database');
module.exports = function (Groups) {
@ -27,7 +27,7 @@ module.exports = function (Groups) {
const isPrivate = data.hasOwnProperty('private') && data.private !== undefined ? parseInt(data.private, 10) === 1 : true;
let groupData = {
name: data.name,
slug: utils.slugify(data.name),
slug: slugify(data.name),
createtime: timestamp,
userTitle: data.userTitle || data.name,
userTitleEnabled: parseInt(data.userTitleEnabled, 10) === 1 ? 1 : 0,
@ -88,7 +88,7 @@ module.exports = function (Groups) {
throw new Error('[[error:invalid-group-name]]');
}
if (name.includes('/') || !utils.slugify(name)) {
if (name.includes('/') || !slugify(name)) {
throw new Error('[[error:invalid-group-name]]');
}
};

@ -1,7 +1,7 @@
'use strict';
const plugins = require('../plugins');
const utils = require('../utils');
const slugify = require('../slugify');
const db = require('../database');
const batch = require('../batch');
@ -27,7 +27,7 @@ module.exports = function (Groups) {
);
});
const sets = groupNames.map(groupName => groupName.toLowerCase() + ':' + groupName);
const fields = groupNames.map(groupName => utils.slugify(groupName));
const fields = groupNames.map(groupName => slugify(groupName));
await Promise.all([
db.deleteAll(keys),

@ -3,7 +3,7 @@
const user = require('../user');
const db = require('../database');
const plugins = require('../plugins');
const utils = require('../utils');
const slugify = require('../slugify');
const Groups = module.exports;
@ -28,7 +28,7 @@ Groups.ephemeralGroups = ['guests', 'spiders'];
Groups.getEphemeralGroup = function (groupName) {
return {
name: groupName,
slug: utils.slugify(groupName),
slug: slugify(groupName),
description: '',
deleted: '0',
hidden: '0',
@ -217,12 +217,12 @@ async function isFieldOn(groupName, field) {
Groups.exists = async function (name) {
if (Array.isArray(name)) {
const slugs = name.map(groupName => utils.slugify(groupName));
const slugs = name.map(groupName => slugify(groupName));
const isMembersOfRealGroups = await db.isSortedSetMembers('groups:createtime', name);
const isMembersOfEphemeralGroups = slugs.map(slug => Groups.ephemeralGroups.includes(slug));
return name.map((n, index) => isMembersOfRealGroups[index] || isMembersOfEphemeralGroups[index]);
}
const slug = utils.slugify(name);
const slug = slugify(name);
const isMemberOfRealGroups = await db.isSortedSetMember('groups:createtime', name);
const isMemberOfEphemeralGroups = Groups.ephemeralGroups.includes(slug);
return isMemberOfRealGroups || isMemberOfEphemeralGroups;

@ -4,7 +4,7 @@ const _ = require('lodash');
const db = require('../database');
const user = require('../user');
const utils = require('../utils');
const slugify = require('../slugify');
const plugins = require('../plugins');
const notifications = require('../notifications');
@ -18,7 +18,7 @@ module.exports = function (Groups) {
bodyShort: '[[groups:request.notification_title, ' + username + ']]',
bodyLong: '[[groups:request.notification_text, ' + username + ', ' + groupName + ']]',
nid: 'group:' + groupName + ':uid:' + uid + ':request',
path: '/groups/' + utils.slugify(groupName),
path: '/groups/' + slugify(groupName),
from: uid,
}),
Groups.getOwners(groupName),
@ -35,7 +35,7 @@ module.exports = function (Groups) {
type: 'group-invite',
bodyShort: '[[groups:membership.accept.notification_title, ' + groupName + ']]',
nid: 'group:' + groupName + ':uid:' + uid + ':invite-accepted',
path: '/groups/' + utils.slugify(groupName),
path: '/groups/' + slugify(groupName),
});
await notifications.push(notification, [uid]);
};
@ -58,7 +58,7 @@ module.exports = function (Groups) {
bodyShort: '[[groups:invited.notification_title, ' + groupName + ']]',
bodyLong: '',
nid: 'group:' + groupName + ':uid:' + uid + ':invite',
path: '/groups/' + utils.slugify(groupName),
path: '/groups/' + slugify(groupName),
})));
await Promise.all(uids.map((uid, index) => notifications.push(notificationData[index], uid)));

@ -3,7 +3,7 @@
const winston = require('winston');
const plugins = require('../plugins');
const utils = require('../utils');
const slugify = require('../slugify');
const db = require('../database');
const user = require('../user');
const batch = require('../batch');
@ -132,8 +132,8 @@ module.exports = function (Groups) {
if (Groups.isPrivilegeGroup(newName)) {
throw new Error('[[error:invalid-group-name]]');
}
const currentSlug = utils.slugify(currentName);
const newSlug = utils.slugify(newName);
const currentSlug = slugify(currentName);
const newSlug = slugify(newName);
if (currentName === newName || currentSlug === newSlug) {
return;
}
@ -174,9 +174,9 @@ module.exports = function (Groups) {
await updateNavigationItems(oldName, newName);
await updateWidgets(oldName, newName);
await updateConfig(oldName, newName);
await db.setObject('group:' + oldName, { name: newName, slug: utils.slugify(newName) });
await db.setObject('group:' + oldName, { name: newName, slug: slugify(newName) });
await db.deleteObjectField('groupslug:groupname', group.slug);
await db.setObjectField('groupslug:groupname', utils.slugify(newName), newName);
await db.setObjectField('groupslug:groupname', slugify(newName), newName);
const allGroups = await db.getSortedSetRange('groups:createtime', 0, -1);
const keys = allGroups.map(group => 'group:' + group + ':members');

@ -5,7 +5,7 @@ const os = require('os');
const nconf = require('nconf');
const pubsub = require('../pubsub');
const utils = require('../utils');
const slugify = require('../slugify');
const Meta = module.exports;
@ -29,7 +29,7 @@ Meta.languages = require('./languages');
Meta.userOrGroupExists = async function (slug) {
const user = require('../user');
const groups = require('../groups');
slug = utils.slugify(slug);
slug = slugify(slug);
const [userExists, groupExists] = await Promise.all([
user.existsBySlug(slug),
groups.existsBySlug(slug),

@ -37,8 +37,10 @@ JS.scripts = {
'node_modules/jquery-serializeobject/jquery.serializeObject.js',
'public/vendor/bootbox/wrapper.js',
// TODO: remove xregexp on 1.16.0, it is loaded via require
'public/vendor/xregexp/xregexp.js',
'public/vendor/xregexp/unicode/unicode-base.js',
'public/src/utils.js',
'public/src/sockets.js',
'public/src/app.js',

@ -10,6 +10,7 @@ const meta = require('../meta');
const translator = require('../translator');
const widgets = require('../widgets');
const utils = require('../utils');
const slugify = require('../slugify');
module.exports = function (middleware) {
middleware.processRender = function processRender(req, res, next) {
@ -111,7 +112,7 @@ module.exports = function (middleware) {
const parts = clean.split('/').slice(0, 3);
parts.forEach(function (p, index) {
try {
p = utils.slugify(decodeURIComponent(p));
p = slugify(decodeURIComponent(p));
} catch (err) {
winston.error(err.stack);
p = '';
@ -122,7 +123,7 @@ module.exports = function (middleware) {
if (templateData.template.topic) {
parts.push('page-topic-category-' + templateData.category.cid);
parts.push('page-topic-category-' + utils.slugify(templateData.category.name));
parts.push('page-topic-category-' + slugify(templateData.category.name));
}
if (templateData.breadcrumbs) {
templateData.breadcrumbs.forEach(function (crumb) {

@ -11,6 +11,7 @@ const privileges = require('../privileges');
const plugins = require('../plugins');
const pubsub = require('../pubsub');
const utils = require('../utils');
const slugify = require('../slugify');
const translator = require('../translator');
module.exports = function (Posts) {
@ -114,7 +115,7 @@ module.exports = function (Posts) {
};
if (title) {
newTopicData.title = title;
newTopicData.slug = tid + '/' + (utils.slugify(title) || 'topic');
newTopicData.slug = tid + '/' + (slugify(title) || 'topic');
}
newTopicData.thumb = data.thumb || '';

@ -5,6 +5,7 @@ const groups = require('../groups');
const meta = require('../meta');
const user = require('../user');
const utils = require('../utils');
const slugify = require('../slugify');
const events = require('../events');
const privileges = require('../privileges');
const notifications = require('../notifications');
@ -94,7 +95,7 @@ SocketGroups.leave = async (socket, data) => {
type: 'group-leave',
bodyShort: '[[groups:membership.leave.notification_title, ' + username + ', ' + data.groupName + ']]',
nid: 'group:' + validator.escape(data.groupName) + ':uid:' + socket.uid + ':group-leave',
path: '/groups/' + utils.slugify(data.groupName),
path: '/groups/' + slugify(data.groupName),
});
const uids = await groups.getOwners(data.groupName);
await notifications.push(notification, uids);

@ -6,6 +6,7 @@ const validator = require('validator');
const db = require('../database');
const utils = require('../utils');
const slugify = require('../slugify');
const plugins = require('../plugins');
const analytics = require('../analytics');
const user = require('../user');
@ -29,7 +30,7 @@ module.exports = function (Topics) {
cid: data.cid,
mainPid: 0,
title: data.title,
slug: tid + '/' + (utils.slugify(data.title) || 'topic'),
slug: tid + '/' + (slugify(data.title) || 'topic'),
timestamp: timestamp,
lastposttime: 0,
postcount: 0,
@ -261,7 +262,7 @@ module.exports = function (Topics) {
if (data.handle.length > meta.config.maximumUsernameLength) {
throw new Error('[[error:guest-handle-invalid]]');
}
const exists = await user.existsBySlug(utils.slugify(data.handle));
const exists = await user.existsBySlug(slugify(data.handle));
if (exists) {
throw new Error('[[error:username-taken]]');
}

@ -9,12 +9,13 @@ const emailer = require('../emailer');
const notifications = require('../notifications');
const groups = require('../groups');
const utils = require('../utils');
const slugify = require('../slugify');
const plugins = require('../plugins');
module.exports = function (User) {
User.addToApprovalQueue = async function (userData) {
userData.username = userData.username.trim();
userData.userslug = utils.slugify(userData.username);
userData.userslug = slugify(userData.username);
await canQueue(userData);
const hashedPassword = await User.hashPassword(userData.password);
const data = {

@ -3,6 +3,7 @@
const zxcvbn = require('zxcvbn');
const db = require('../database');
const utils = require('../utils');
const slugify = require('../slugify');
const plugins = require('../plugins');
const groups = require('../groups');
const meta = require('../meta');
@ -10,7 +11,7 @@ const meta = require('../meta');
module.exports = function (User) {
User.create = async function (data) {
data.username = data.username.trim();
data.userslug = utils.slugify(data.username);
data.userslug = slugify(data.username);
if (data.email !== undefined) {
data.email = String(data.email).trim();
}
@ -63,7 +64,7 @@ module.exports = function (User) {
const userNameChanged = !!renamedUsername;
if (userNameChanged) {
userData.username = renamedUsername;
userData.userslug = utils.slugify(renamedUsername);
userData.userslug = slugify(renamedUsername);
}
const results = await plugins.fireHook('filter:user.create', { user: userData, data: data });

@ -5,6 +5,7 @@ const async = require('async');
const validator = require('validator');
const utils = require('../utils');
const slugify = require('../slugify');
const meta = require('../meta');
const db = require('../database');
const groups = require('../groups');
@ -113,7 +114,7 @@ module.exports = function (User) {
throw new Error('[[error:username-too-long]]');
}
const userslug = utils.slugify(data.username);
const userslug = slugify(data.username);
if (!utils.isUserNameValid(data.username) || !userslug) {
throw new Error('[[error:invalid-username]]');
}
@ -256,7 +257,7 @@ module.exports = function (User) {
if (userData.username === newUsername) {
return;
}
const newUserslug = utils.slugify(newUsername);
const newUserslug = slugify(newUsername);
const now = Date.now();
await Promise.all([
updateUidMapping('username', uid, newUsername, userData.username),

@ -4,6 +4,7 @@
var assert = require('assert');
var JSDOM = require('jsdom').JSDOM;
var utils = require('../public/src/utils.js');
var slugify = require('../src/slugify');
const db = require('./mocks/databasemock');
describe('Utility Methods', function () {
@ -41,14 +42,14 @@ describe('Utility Methods', function () {
});
it('should preserve case if requested', function (done) {
var slug = utils.slugify('UPPER CASE', true);
assert.equal(slug, 'UPPER-CASE');
assert.strictEqual(utils.slugify('UPPER CASE', true), 'UPPER-CASE');
assert.strictEqual(slugify('UPPER CASE', true), 'UPPER-CASE');
done();
});
it('should work if a number is passed in', function (done) {
var slug = utils.slugify(12345);
assert.strictEqual(slug, '12345');
assert.strictEqual(utils.slugify(12345), '12345');
assert.strictEqual(slugify(12345), '12345');
done();
});

Loading…
Cancel
Save