From 95979d9d97ecc549da92a7a17df91a05120ebf64 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 13:38:46 -0400 Subject: [PATCH 01/90] closes #1947 --- src/controllers/tags.js | 2 +- src/topics/tags.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/controllers/tags.js b/src/controllers/tags.js index 1b59483a4c..cb03e14589 100644 --- a/src/controllers/tags.js +++ b/src/controllers/tags.js @@ -13,7 +13,7 @@ tagsController.getTag = function(req, res, next) { return next(err); } - if (!tids || !tids.length) { + if (Array.isArray(tids) && !tids.length) { topics.deleteTag(tag); return res.render('tag', {topics: [], tag:tag}); } diff --git a/src/topics/tags.js b/src/topics/tags.js index c18289cf37..15fd437a26 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -47,7 +47,6 @@ module.exports = function(Topics) { return ''; } tag = tag.trim().toLowerCase(); - tag = tag.replace(/&/g, '&'); tag = tag.replace(/[,\/#!$%\^\*;:{}=_`<>'"~()?\|]/g, ''); tag = tag.substr(0, meta.config.maximumTagLength || 15); var matches = tag.match(/^[.-]*(.+?)[.-]*$/); From 378fd095eb3191baa1b5d2a08be7e0d9b4ac69e1 Mon Sep 17 00:00:00 2001 From: Filips Alpe Date: Tue, 5 Aug 2014 21:31:51 +0300 Subject: [PATCH 02/90] Leave the chat window within the screen On smaller screens, the top of the chat window can appear so high that it is outside the screen, this fixes that. --- public/src/modules/chat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 78d5b6c546..cc4fbb1f42 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -249,7 +249,7 @@ define('chat', ['taskbar', 'string', 'sounds', 'forum/chats'], function(taskbar, module.center = function(chatModal) { chatModal.css("left", Math.max(0, (($(window).width() - $(chatModal).outerWidth()) / 2) + $(window).scrollLeft()) + "px"); - chatModal.css("top", $(window).height() / 4 - $(chatModal).outerHeight() / 2); + chatModal.css("top", Math.max(0, $(window).height() / 4 - $(chatModal).outerHeight() / 2)); chatModal.css("zIndex", 2000); chatModal.find('#chat-message-input').focus(); return chatModal; From bb48bdb008bee529406db7553003e6b7501abe98 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 5 Aug 2014 15:12:17 -0400 Subject: [PATCH 03/90] closes #1942 --- src/controllers/accounts.js | 2 ++ src/user/jobs.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 2225373ee2..0c906e562c 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -365,6 +365,8 @@ accountsController.accountSettings = function(req, res, next) { userData.settings = results.settings; userData.languages = results.languages; + userData.disableEmailSubscriptions = meta.config.disableEmailSubscriptions !== undefined && parseInt(meta.config.disableEmailSubscriptions, 10) === 1; + res.render('account/settings', userData); }); }); diff --git a/src/user/jobs.js b/src/user/jobs.js index 7659a87aea..160f3bb33c 100644 --- a/src/user/jobs.js +++ b/src/user/jobs.js @@ -22,6 +22,11 @@ module.exports = function(User) { }; User.sendDailyDigests = function() { + var digestsDisabled = meta.config.disableEmailSubscriptions !== undefined && parseInt(meta.config.disableEmailSubscriptions, 10) === 1; + if (digestsDisabled) { + return winston.log('[user/jobs] Did not send daily digests because subscription system is disabled.'); + } + async.parallel({ recent: function(next) { topics.getLatestTopics(0, 0, 10, 'day', next); From eb297d7eab2969766117a2d119ad2f77fb7726e0 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 5 Aug 2014 16:00:52 -0400 Subject: [PATCH 04/90] client side hooks: action:composer.topics.post, action:composer.posts.reply, action:composer.posts.edit --- public/src/modules/composer.js | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/public/src/modules/composer.js b/public/src/modules/composer.js index 05b0f82c41..478c7738dc 100644 --- a/public/src/modules/composer.js +++ b/public/src/modules/composer.js @@ -360,33 +360,45 @@ define('composer', dependencies, function(taskbar, controls, uploads, formatting return composerAlert('[[error:content-too-short, ' + config.minimumPostLength + ']]'); } + var composerData = {}, action; + if (parseInt(postData.cid, 10) > 0) { - socket.emit('topics.post', { + composerData = { title: titleEl.val(), content: bodyEl.val(), topic_thumb: thumbEl.val() || '', category_id: postData.cid, tags: tags.getTags(post_uuid) - }, function(err, topic) { + }; + + action = 'topics.post'; + socket.emit(action, composerData, function(err, topic) { done(err); + if (!err) { ajaxify.go('topic/' + topic.slug); } }); } else if (parseInt(postData.tid, 10) > 0) { - socket.emit('posts.reply', { + composerData = { tid: postData.tid, content: bodyEl.val(), toPid: postData.toPid - }, done); + }; + + action = 'posts.reply'; + socket.emit(action, composerData, done); } else if (parseInt(postData.pid, 10) > 0) { - socket.emit('posts.edit', { + composerData = { pid: postData.pid, content: bodyEl.val(), title: titleEl.val(), topic_thumb: thumbEl.val() || '', tags: tags.getTags(post_uuid) - }, done); + }; + + action = 'posts.edit'; + socket.emit(action, composerData, done); } function done(err) { @@ -401,6 +413,8 @@ define('composer', dependencies, function(taskbar, controls, uploads, formatting discard(post_uuid); drafts.removeDraft(postData.save_id); + + $(window).trigger('action:composer.' + action, composerData); } } From 39d6941603833bee78e58314cd03a680dabe944b Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 5 Aug 2014 16:25:02 -0400 Subject: [PATCH 05/90] remove chat/flag for new incoming posts --- public/src/forum/topic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 7cf40d1fca..3b540a0391 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -364,7 +364,7 @@ define('forum/topic', dependencies, function(pagination, infinitescroll, threadT postHtml.find('.move').toggleClass('none', !privileges.move); postHtml.find('.reply, .quote').toggleClass('none', !$('.post_reply').length); var isSelfPost = parseInt(postHtml.attr('data-uid'), 10) === parseInt(app.uid, 10); - postHtml.find('.chat, .flag').toggleClass('none', isSelfPost); + postHtml.find('.chat, .flag').toggleClass('none', isSelfPost || !app.uid); } function loadMorePosts(direction) { From 5ce0ebb4acfc29225bb6011e47159f7505a85aca Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 17:09:52 -0400 Subject: [PATCH 06/90] single socket call on topic enter --- public/src/forum/topic.js | 4 +--- src/socket.io/topics.js | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 3b540a0391..06d0167a53 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -72,9 +72,7 @@ define('forum/topic', dependencies, function(pagination, infinitescroll, threadT $(window).trigger('action:topic.loaded'); - socket.emit('topics.markAsRead', tid); - socket.emit('topics.markTopicNotificationsRead', tid); - socket.emit('topics.increaseViewCount', tid); + socket.emit('topics.enter', tid); }; Topic.toTop = function() { diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index 8e71b9b98d..97e9b36e30 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -54,6 +54,15 @@ SocketTopics.post = function(socket, data, callback) { }); }; +SocketTopics.enter = function(socket, tid, callback) { + if (!tid || !socket.uid) { + return; + } + SocketTopics.markAsRead(socket, tid); + topics.markTopicNotificationsRead(tid, socket.uid); + topics.increaseViewCount(tid); +}; + SocketTopics.postcount = function(socket, tid, callback) { topics.getTopicField(tid, 'postcount', callback); }; From 631edc92d31e69ba09a540804cc581cc62d7779d Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 5 Aug 2014 17:05:08 -0400 Subject: [PATCH 07/90] extra var --- src/middleware/middleware.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index 831b506f5e..7db87f35c2 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -6,7 +6,6 @@ var app, path = require('path'), winston = require('winston'), validator = require('validator'), - fs = require('fs'), nconf = require('nconf'), plugins = require('./../plugins'), meta = require('./../meta'), From a880ac6e9f0d1ca44e81ccc5fc0c99fa8511e9de Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 5 Aug 2014 17:16:18 -0400 Subject: [PATCH 08/90] do one api call for template configs rather than two on cold load --- public/src/ajaxify.js | 6 +++--- src/routes/api.js | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index fb02bd675c..1e772957e7 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -329,9 +329,9 @@ var ajaxify = ajaxify || {}; templates.registerLoader(ajaxify.loadTemplate); - $.when($.getJSON(RELATIVE_PATH + '/templates/config.json'), $.getJSON(RELATIVE_PATH + '/api/get_templates_listing')).done(function (config_data, templates_data) { - templatesConfig = config_data[0]; - availableTemplates = templates_data[0]; + $.getJSON(RELATIVE_PATH + '/api/get_templates_listing', function (data) { + templatesConfig = data.templatesConfig; + availableTemplates = data.availableTemplates; app.load(); }); diff --git a/src/routes/api.js b/src/routes/api.js index 56cf9a4592..e080df9277 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -135,10 +135,10 @@ function getModerators(req, res, next) { }); } -var templatesListingCache = []; +var templatesListingCache = {}; function getTemplatesListing(req, res, next) { - if (templatesListingCache.length) { + if (templatesListingCache.availableTemplates && templatesListingCache.templatesConfig) { return res.json(templatesListingCache); } @@ -148,11 +148,15 @@ function getTemplatesListing(req, res, next) { }, extended: function(next) { plugins.fireHook('filter:templates.get_virtual', [], next); - } + }, + config: function(next) { + fs.readFile(path.join(nconf.get('views_dir'), 'config.json'), next); + }, }, function(err, results) { if (err) { return next(err); } + var data = []; data = results.views.filter(function(value, index, self) { return self.indexOf(value) === index; @@ -161,8 +165,13 @@ function getTemplatesListing(req, res, next) { }); data = data.concat(results.extended); - templatesListingCache = data; - res.json(data); + + templatesListingCache = { + availableTemplates: data, + templatesConfig: results.config + }; + + res.json(templatesListingCache); }); } From d4dc716acd278e923cc7970e2a850267ade24bf9 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 5 Aug 2014 17:17:05 -0400 Subject: [PATCH 09/90] filter:templates.get_config, allows you to modify template config as found here https://github.com/NodeBB/nodebb-theme-vanilla/blob/master/templates/config.json @Schamper --- src/routes/api.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/routes/api.js b/src/routes/api.js index e080df9277..e152715beb 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -150,7 +150,10 @@ function getTemplatesListing(req, res, next) { plugins.fireHook('filter:templates.get_virtual', [], next); }, config: function(next) { - fs.readFile(path.join(nconf.get('views_dir'), 'config.json'), next); + fs.readFile(path.join(nconf.get('views_dir'), 'config.json'), function(err, config) { + config = JSON.parse(config.toString()); + plugins.fireHook('filter:templates.get_config', config, next); + }); }, }, function(err, results) { if (err) { From f49c95c16f2990524199d04c715c880f942d1f45 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 18:18:34 -0400 Subject: [PATCH 10/90] closes #1950 --- public/language/en_GB/topic.json | 1 + public/src/forum/topic/postTools.js | 19 ++++++++++++++++--- src/socket.io/posts.js | 23 ++--------------------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index 8c77751419..c6fe5bc4ad 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -105,6 +105,7 @@ "more_users_and_guests": "%1 more user(s) and %2 guest(s)", "more_users": "%1 more user(s)", "more_guests": "%1 more guest(s)", + "users_and_others": "%1 and %2 others", "sort_by": "Sort by", "oldest_to_newest": "Oldest to Newest", diff --git a/public/src/forum/topic/postTools.js b/public/src/forum/topic/postTools.js index 24d7491fa5..b71263bc75 100644 --- a/public/src/forum/topic/postTools.js +++ b/public/src/forum/topic/postTools.js @@ -36,13 +36,26 @@ define('forum/topic/postTools', ['composer', 'share', 'navigator'], function(com }; function addFavouriteHandler() { - $('#post-container').on('mouseenter', '.favourite-tooltip', function(e) { + $('#post-container').on('mouseenter', '.favourite-tooltip', function() { if (!$(this).data('users-loaded')) { - $(this).data('users-loaded', "true"); + $(this).data('users-loaded', 'true'); var pid = $(this).parents('.post-row').attr('data-pid'); var el = $(this).attr('title', "Loading..."); socket.emit('posts.getFavouritedUsers', pid, function(err, usernames) { - el.attr('title', usernames).tooltip('show'); + if (err) { + return; + } + if (usernames.length > 6) { + var otherCount = usernames.length - 5; + usernames = usernames.slice(0, 5).join(', ').replace(/,/g, '|'); + translator.translate('[[topic:users_and_others, ' + usernames + ', ' + otherCount + ']]', function(translated) { + translated = translated.replace(/\|/g, ','); + el.attr('title', translated).tooltip('show'); + }); + } else { + usernames = usernames.join(', '); + el.attr('title', usernames).tooltip('show'); + } }); } }); diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 9f6156c89f..9364124ff2 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -241,37 +241,18 @@ SocketPosts.getPrivileges = function(socket, pid, callback) { }; SocketPosts.getFavouritedUsers = function(socket, pid, callback) { - favourites.getFavouritedUidsByPids([pid], function(err, data) { - if(err) { return callback(err); } if(!Array.isArray(data) || !data.length) { - callback(null, ""); + callback(null, []); } - var max = 5; //hardcoded - var finalText = ""; - var pid_uids = data[0]; - var rest_amount = 0; - if (pid_uids.length > max) { - rest_amount = pid_uids.length - max; - pid_uids = pid_uids.slice(0, max); - } - - user.getUsernamesByUids(pid_uids, function(err, usernames) { - if(err) { - return callback(err); - } - - finalText = usernames.join(', ') + (rest_amount > 0 ? - (" and " + rest_amount + (rest_amount > 1 ? " others" : " other")) : ""); - callback(null, finalText); - }); + user.getUsernamesByUids(pid_uids, callback); }); }; From 100328ef06160a466b1cf810481580ae99bdfcd0 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 22:52:33 -0400 Subject: [PATCH 11/90] shorter markAsUnread --- src/categories.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/categories.js b/src/categories.js index ceae7d8f01..ef91a035f1 100644 --- a/src/categories.js +++ b/src/categories.js @@ -237,11 +237,8 @@ var db = require('./database'), }; Categories.markAsUnreadForAll = function(cid, callback) { - db.delete('cid:' + cid + ':read_by_uid', function(err) { - if(typeof callback === 'function') { - callback(err); - } - }); + callback = callback || function() {}; + db.delete('cid:' + cid + ':read_by_uid', callback); }; Categories.hasReadCategories = function(cids, uid, callback) { From f55d1897c80f85e466f62485b9ae9825e4df595c Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 22:59:29 -0400 Subject: [PATCH 12/90] fix categories.loadMore so it checks read permission --- src/socket.io/categories.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index 1771311d3a..fb2fa98032 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -44,6 +44,10 @@ SocketCategories.loadMore = function(socket, data, callback) { return callback(err); } + if (!results.privileges.read) { + return callback(new Error('[[error:no-privileges]]')); + } + var start = parseInt(data.after, 10), end = start + results.settings.topicsPerPage - 1; From 805e6934b9eb5cd3d6deb43181da24fe18bd003a Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 23:10:45 -0400 Subject: [PATCH 13/90] derp this function should only return err --- src/categories.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/categories.js b/src/categories.js index ef91a035f1..f63b096477 100644 --- a/src/categories.js +++ b/src/categories.js @@ -238,7 +238,9 @@ var db = require('./database'), Categories.markAsUnreadForAll = function(cid, callback) { callback = callback || function() {}; - db.delete('cid:' + cid + ':read_by_uid', callback); + db.delete('cid:' + cid + ':read_by_uid', function(err) { + callback(err); + }); }; Categories.hasReadCategories = function(cids, uid, callback) { From 90ac399f6dbb28103f90647eae7962eaf0a2cb0d Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 23:22:21 -0400 Subject: [PATCH 14/90] fix topics.loadMore so it checks read permission --- src/socket.io/topics.js | 23 +++++++++++++++++------ src/topics.js | 6 +++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index 97e9b36e30..bc6667657e 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -342,20 +342,31 @@ SocketTopics.loadMore = function(socket, data, callback) { return callback(new Error('[[error:invalid-data]]')); } - user.getSettings(socket.uid, function(err, settings) { - if(err) { + async.parallel({ + settings: function(next) { + user.getSettings(socket.uid, next); + }, + privileges: function(next) { + privileges.topics.get(data.tid, socket.uid, next); + } + }, function(err, results) { + if (err) { return callback(err); } + if (!results.privileges.read) { + return callback(new Error('[[error:no-privileges]]')); + } + var start = Math.max(parseInt(data.after, 10) - 1, 0), - end = start + settings.postsPerPage - 1; + end = start + results.settings.postsPerPage - 1; var set = 'tid:' + data.tid + ':posts', reverse = false; - if (settings.topicPostSort === 'newest_to_oldest') { + if (results.settings.topicPostSort === 'newest_to_oldest') { reverse = true; - } else if (settings.topicPostSort === 'most_votes') { + } else if (results.settings.topicPostSort === 'most_votes') { reverse = true; set = 'tid:' + data.tid + ':posts:votes'; } @@ -365,7 +376,7 @@ SocketTopics.loadMore = function(socket, data, callback) { topics.getTopicPosts(data.tid, set, start, end, socket.uid, reverse, next); }, privileges: function(next) { - privileges.topics.get(data.tid, socket.uid, next); + next(null, results.privileges); }, 'reputation:disabled': function(next) { next(null, parseInt(meta.config['reputation:disabled'], 10) === 1); diff --git a/src/topics.js b/src/topics.js index 0214f912bf..dcee9e4063 100644 --- a/src/topics.js +++ b/src/topics.js @@ -413,8 +413,12 @@ var async = require('async'), }; Topics.isOwner = function(tid, uid, callback) { + uid = parseInt(uid, 10); + if (uid === 0) { + return callback(null, false); + } Topics.getTopicField(tid, 'uid', function(err, author) { - callback(err, parseInt(author, 10) === parseInt(uid, 10)); + callback(err, parseInt(author, 10) === uid); }); }; From 906e1a3846c9ed68891a3374f6451cfc748957a1 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 23:29:49 -0400 Subject: [PATCH 15/90] removed unused meta --- src/socket.io/categories.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index fb2fa98032..dbbb606224 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -4,7 +4,6 @@ var async = require('async'), db = require('../database'), categories = require('../categories'), privileges = require('../privileges'), - meta = require('../meta'), user = require('../user'), SocketCategories = {}; From 59d4d2880ff43fabca996e7e134d2ca76dd698bf Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 5 Aug 2014 23:47:17 -0400 Subject: [PATCH 16/90] fixed markAsUnreadForAll permissions --- src/socket.io/topics.js | 57 ++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index bc6667657e..4c66db8cb1 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -150,25 +150,58 @@ SocketTopics.markCategoryTopicsRead = function(socket, cid, callback) { }; SocketTopics.markAsUnreadForAll = function(socket, tids, callback) { - if(!Array.isArray(tids)) { + if (!Array.isArray(tids)) { return callback(new Error('[[error:invalid-tid]]')); } - async.each(tids, function(tid, next) { - topics.markAsUnreadForAll(tid, function(err) { - if(err) { - return next(err); - } + if (!socket.uid) { + return callback(new Error('[[error:no-privileges]]')); + } - db.sortedSetAdd('topics:recent', Date.now(), tid, function(err) { - if(err) { + user.isAdministrator(socket.uid, function(err, isAdmin) { + if (err) { + return callback(err); + } + + async.each(tids, function(tid, next) { + async.waterfall([ + function(next) { + threadTools.exists(tid, next); + }, + function(exists, next) { + if (!exists) { + return next(new Error('[[error:invalid-tid]]')); + } + topics.getTopicField(tid, 'cid', next); + }, + function(cid, next) { + user.isModerator(socket.uid, cid, next); + } + ], function(err, isMod) { + if (err) { return next(err); } - topics.pushUnreadCount(); - next(); + + if (!isAdmin && !isMod) { + return next(new Error('[[error:no-privileges]]')); + } + + topics.markAsUnreadForAll(tid, function(err) { + if(err) { + return next(err); + } + + db.sortedSetAdd('topics:recent', Date.now(), tid, function(err) { + if(err) { + return next(err); + } + topics.pushUnreadCount(); + next(); + }); + }); }); - }); - }, callback); + }, callback); + }); }; SocketTopics.delete = function(socket, data, callback) { From 76b257f7b8ee8059ebbace84fb84bf5edde8d2ca Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 6 Aug 2014 12:39:14 -0400 Subject: [PATCH 17/90] optimized User.getUsers --- src/groups.js | 4 ++++ src/user.js | 52 +++++++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/groups.js b/src/groups.js index 13e9917520..acbc2158a5 100644 --- a/src/groups.js +++ b/src/groups.js @@ -156,6 +156,10 @@ db.isSetMember('group:' + groupName + ':members', uid, callback); }; + Groups.isMembers = function(uids, groupName, callback) { + db.isSetMembers('group:' + groupName + ':members', uids, callback); + }; + Groups.isMemberOfGroups = function(uid, groups, callback) { groups = groups.map(function(groupName) { return 'group:' + groupName + ':members'; diff --git a/src/user.js b/src/user.js index f20686fc7c..3a6bcb4607 100644 --- a/src/user.js +++ b/src/user.js @@ -239,36 +239,32 @@ var bcrypt = require('bcryptjs'), }; User.getUsers = function(uids, callback) { - function loadUserInfo(user, callback) { - if (!user) { - return callback(null, user); + async.parallel({ + userData: function(next) { + User.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture', 'status', 'banned', 'postcount', 'reputation'], next); + }, + isAdmin: function(next) { + User.isAdministrator(uids, next); + }, + isOnline: function(next) { + db.isSortedSetMembers('users:online', uids, next); } - - async.waterfall([ - function(next) { - User.isAdministrator(user.uid, next); - }, - function(isAdmin, next) { - user.status = !user.status ? 'online' : user.status; - user.administrator = isAdmin; - user.banned = parseInt(user.banned, 10) === 1; - db.isSortedSetMember('users:online', user.uid, next); - }, - function(isMember, next) { - if (!isMember) { - user.status = 'offline'; - } - next(null, user); - } - ], callback); - } - - User.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture', 'status', 'banned', 'postcount', 'reputation'], function(err, usersData) { + }, function(err, results) { if (err) { return callback(err); } - async.map(usersData, loadUserInfo, callback); + results.userData.forEach(function(user, index) { + if (!user) { + return; + } + user.status = !user.status ? 'online' : user.status; + user.status = !results.isOnline[index] ? 'offline' : user.status; + user.administrator = results.isAdmin[index]; + user.banned = parseInt(user.banned, 10) === 1; + }); + + callback(err, results.userData); }); }; @@ -410,7 +406,11 @@ var bcrypt = require('bcryptjs'), }; User.isAdministrator = function(uid, callback) { - groups.isMember(uid, 'administrators', callback); + if (Array.isArray(uid)) { + groups.isMembers(uid, 'administrators', callback); + } else { + groups.isMember(uid, 'administrators', callback); + } }; User.isOnline = function(uid, callback) { From c88327d075e8f91e43838cf24b024332a760fcbc Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 13:51:37 -0400 Subject: [PATCH 18/90] added filter:category.get --- src/categories.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/categories.js b/src/categories.js index f63b096477..8fb459728d 100644 --- a/src/categories.js +++ b/src/categories.js @@ -93,7 +93,9 @@ var db = require('./database'), category.pageCount = results.pageCount; category.topic_row_size = 'col-md-9'; - callback(null, category); + plugins.fireHook('filter:category.get', category, function(err, category) { + callback(null, category); + }); }); }); }; From 4cda8207e2a83b228b339122219850acf4d75835 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 13:56:05 -0400 Subject: [PATCH 19/90] adding uid to filter:category.get --- src/categories.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/categories.js b/src/categories.js index 8fb459728d..46299454b2 100644 --- a/src/categories.js +++ b/src/categories.js @@ -93,7 +93,7 @@ var db = require('./database'), category.pageCount = results.pageCount; category.topic_row_size = 'col-md-9'; - plugins.fireHook('filter:category.get', category, function(err, category) { + plugins.fireHook('filter:category.get', category, uid, function(err, category) { callback(null, category); }); }); From 3a32058be17a1cbf70aceca22a27c33016a1c147 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 18:48:46 -0400 Subject: [PATCH 20/90] closes #1958 --- src/controllers/tags.js | 17 +++++++++++++++++ src/meta/title.js | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/src/controllers/tags.js b/src/controllers/tags.js index cb03e14589..74c21a17fa 100644 --- a/src/controllers/tags.js +++ b/src/controllers/tags.js @@ -2,6 +2,7 @@ var tagsController = {}, async = require('async'), + nconf = require('nconf'), topics = require('./../topics'); tagsController.getTag = function(req, res, next) { @@ -22,6 +23,22 @@ tagsController.getTag = function(req, res, next) { if (err) { return next(err); } + + res.locals.metaTags = [ + { + name: "title", + content: tag + }, + { + property: 'og:title', + content: tag + }, + { + property: "og:url", + content: nconf.get('url') + '/tags/' + tag + } + ]; + data.tag = tag; res.render('tag', data); }); diff --git a/src/meta/title.js b/src/meta/title.js index 58a03876d5..a05de31c67 100644 --- a/src/meta/title.js +++ b/src/meta/title.js @@ -9,6 +9,7 @@ module.exports = function(Meta) { var tests = { isCategory: /^category\/\d+\/?/, isTopic: /^topic\/\d+\/?/, + isTag: /^tags\/[\s\S]+\/?/, isUserPage: /^user\/[^\/]+(\/[\w]+)?/ }; @@ -25,6 +26,7 @@ module.exports = function(Meta) { }; Meta.title.parseFragment = function (urlFragment, language, callback) { + console.log(urlFragment); var translated = ['', 'recent', 'unread', 'users', 'notifications']; if (translated.indexOf(urlFragment) !== -1) { if (!urlFragment.length) { @@ -42,6 +44,9 @@ module.exports = function(Meta) { var tid = urlFragment.match(/topic\/(\d+)/)[1]; require('../topics').getTopicField(tid, 'title', callback); + } else if (tests.isTag.test(urlFragment)) { + var tag = urlFragment.match(/tags\/([\s\S]+)/)[1]; + callback(null, tag); } else if (tests.isUserPage.test(urlFragment)) { var matches = urlFragment.match(/user\/([^\/]+)\/?([\w]+)?/), userslug = matches[1], From 38dc35f48007b9f02a35bdf505a15bc10c639f78 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 18:49:11 -0400 Subject: [PATCH 21/90] console.log --- src/meta/title.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/meta/title.js b/src/meta/title.js index a05de31c67..bb2333ed56 100644 --- a/src/meta/title.js +++ b/src/meta/title.js @@ -26,7 +26,6 @@ module.exports = function(Meta) { }; Meta.title.parseFragment = function (urlFragment, language, callback) { - console.log(urlFragment); var translated = ['', 'recent', 'unread', 'users', 'notifications']; if (translated.indexOf(urlFragment) !== -1) { if (!urlFragment.length) { From b1ef42889d6fdd3bf589aa297b0a7114bb65a0c8 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 18:51:32 -0400 Subject: [PATCH 22/90] updated site title for tags page to be more user friendly --- public/language/en_GB/pages.json | 1 + src/meta/title.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/public/language/en_GB/pages.json b/public/language/en_GB/pages.json index a91aec5e8e..c4b35171e8 100644 --- a/public/language/en_GB/pages.json +++ b/public/language/en_GB/pages.json @@ -5,6 +5,7 @@ "recent": "Recent Topics", "users": "Registered Users", "notifications": "Notifications", + "tags": "Topics tagged under %1", "user.edit": "Editing \"%1\"", "user.following": "People %1 Follows", "user.followers": "People who Follow %1", diff --git a/src/meta/title.js b/src/meta/title.js index bb2333ed56..652001af97 100644 --- a/src/meta/title.js +++ b/src/meta/title.js @@ -45,7 +45,10 @@ module.exports = function(Meta) { require('../topics').getTopicField(tid, 'title', callback); } else if (tests.isTag.test(urlFragment)) { var tag = urlFragment.match(/tags\/([\s\S]+)/)[1]; - callback(null, tag); + + translator.translate('[[pages:tags, ' + tag + ']]', language, function(translated) { + callback(null, translated); + }); } else if (tests.isUserPage.test(urlFragment)) { var matches = urlFragment.match(/user\/([^\/]+)\/?([\w]+)?/), userslug = matches[1], From 9a5ed0bf2782741886351160883602165a60b82c Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 18:52:04 -0400 Subject: [PATCH 23/90] forgot err, thanks @barisusakli --- src/categories.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/categories.js b/src/categories.js index 46299454b2..59c0829473 100644 --- a/src/categories.js +++ b/src/categories.js @@ -94,7 +94,7 @@ var db = require('./database'), category.topic_row_size = 'col-md-9'; plugins.fireHook('filter:category.get', category, uid, function(err, category) { - callback(null, category); + callback(err, category); }); }); }); From c6ced111b5827ee9009b05069814c24f4c7e4dc2 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 18:53:00 -0400 Subject: [PATCH 24/90] quotes are better --- public/language/en_GB/pages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/language/en_GB/pages.json b/public/language/en_GB/pages.json index c4b35171e8..3d444963e1 100644 --- a/public/language/en_GB/pages.json +++ b/public/language/en_GB/pages.json @@ -5,7 +5,7 @@ "recent": "Recent Topics", "users": "Registered Users", "notifications": "Notifications", - "tags": "Topics tagged under %1", + "tags": "Topics tagged under \"%1\"", "user.edit": "Editing \"%1\"", "user.following": "People %1 Follows", "user.followers": "People who Follow %1", From 528ee335d50c88a9a163c60f0b2be884ca6f42e0 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 6 Aug 2014 21:30:06 -0400 Subject: [PATCH 25/90] optimize getTopicsByTids and getTeasers --- src/categories.js | 7 ++ src/controllers/categories.js | 25 +---- src/database/level/sets.js | 4 + src/database/mongo/sets.js | 18 +++ src/database/redis/sets.js | 8 ++ src/privileges/categories.js | 22 ++++ src/topics.js | 206 +++++++++++++++++++++------------- src/topics/tags.js | 19 ++++ 8 files changed, 210 insertions(+), 99 deletions(-) diff --git a/src/categories.js b/src/categories.js index 59c0829473..4011f459e0 100644 --- a/src/categories.js +++ b/src/categories.js @@ -296,6 +296,13 @@ var db = require('./database'), db.getObjectField('category:' + cid, field, callback); }; + Categories.getMultipleCategoryFields = function(cids, fields, callback) { + var keys = cids.map(function(cid) { + return 'category:' + cid; + }); + db.getObjectsFields(keys, fields, callback); + }; + Categories.getCategoryFields = function(cid, fields, callback) { db.getObjectFields('category:' + cid, fields, callback); }; diff --git a/src/controllers/categories.js b/src/controllers/categories.js index dffe49bcbc..506747f741 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -74,22 +74,16 @@ categoriesController.get = function(req, res, next) { }, function(disabled, next) { if (parseInt(disabled, 10) === 1) { - return next(new Error('category-disabled')); + return next(new Error('[[error:category-disabled]]')); } - privileges.categories.get(cid, uid, function(err, categoryPrivileges) { - if (err) { - return next(err); - } - - if (!categoryPrivileges.read) { - return next(new Error('[[error:no-privileges]]')); - } - - next(null, categoryPrivileges); - }); + privileges.categories.get(cid, uid, next); }, function (privileges, next) { + if (!privileges.read) { + return next(new Error('[[error:no-privileges]]')); + } + user.getSettings(uid, function(err, settings) { if (err) { return next(err); @@ -111,12 +105,6 @@ categoriesController.get = function(req, res, next) { return next(err); } - if (categoryData) { - if (parseInt(categoryData.disabled, 10) === 1) { - return next(new Error('[[error:category-disabled]]')); - } - } - categoryData.privileges = privileges; next(err, categoryData); }); @@ -189,7 +177,6 @@ categoriesController.get = function(req, res, next) { active: x === parseInt(page, 10) }); } - res.render('category', data); }); }; diff --git a/src/database/level/sets.js b/src/database/level/sets.js index bc5aacf1b5..5d6ffabf6c 100644 --- a/src/database/level/sets.js +++ b/src/database/level/sets.js @@ -51,6 +51,10 @@ module.exports = function(db, module) { }); }; + module.getSetsMembers = function(keys, callback) { + throw new Error('not-implemented'); + }; + module.setCount = function(key, callback) { module.getListRange(key, 0, -1, function(err, set) { callback(err, set.length); diff --git a/src/database/mongo/sets.js b/src/database/mongo/sets.js index fb5f16343a..6b00ec5142 100644 --- a/src/database/mongo/sets.js +++ b/src/database/mongo/sets.js @@ -91,6 +91,24 @@ module.exports = function(db, module) { }); }; + module.getSetsMembers = function(keys, callback) { + db.collection('objects').find({_key: {$in: keys}}, {_key: 1, members: 1}).toArray(function(err, data) { + if (err) { + return callback(err); + } + var sets = {}; + data.forEach(function(set) { + sets[set._key] = set.members || []; + }); + + var returnData = new Array(keys.length); + for(var i=0; i Date: Wed, 6 Aug 2014 21:30:41 -0400 Subject: [PATCH 26/90] send callback directly --- src/topics.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/topics.js b/src/topics.js index 990d09832b..d55e6caf17 100644 --- a/src/topics.js +++ b/src/topics.js @@ -294,9 +294,7 @@ var async = require('async'), topicData.locked = parseInt(topicData.locked, 10) === 1; topicData.pinned = parseInt(topicData.pinned, 10) === 1; - plugins.fireHook('filter:topic.get', topicData, function(err, topicData) { - callback(null, topicData); - }); + plugins.fireHook('filter:topic.get', topicData, callback); }); }); }; From 90513be3216d0af68a37e22806a9a074ebaf770d Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 6 Aug 2014 21:42:23 -0400 Subject: [PATCH 27/90] send callback directly except this time I'm fixing my own derps instead of @barisusakli --- src/categories.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/categories.js b/src/categories.js index 4011f459e0..bf42392596 100644 --- a/src/categories.js +++ b/src/categories.js @@ -93,9 +93,7 @@ var db = require('./database'), category.pageCount = results.pageCount; category.topic_row_size = 'col-md-9'; - plugins.fireHook('filter:category.get', category, uid, function(err, category) { - callback(err, category); - }); + plugins.fireHook('filter:category.get', category, uid, callback); }); }); }; From 84aadc03fd15df5c130bd111faf15ec367beea50 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 6 Aug 2014 22:04:31 -0400 Subject: [PATCH 28/90] fix filter condition --- src/topics.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/topics.js b/src/topics.js index d55e6caf17..03071beb32 100644 --- a/src/topics.js +++ b/src/topics.js @@ -244,9 +244,9 @@ var async = require('async'), } topics = topics.filter(function(topic) { - return !topic.category.disabled || - !topic.deleted || (topic.deleted && isAdminOrMod[topic.cid]) || - parseInt(topic.uid, 10) === parseInt(uid, 10); + return !topic.category.disabled && + (!topic.deleted || (topic.deleted && isAdminOrMod[topic.cid]) || + parseInt(topic.uid, 10) === parseInt(uid, 10)); }); plugins.fireHook('filter:topics.get', topics, callback); From 8e8b678d401af4dce4441fba6c8d9b1f7705c053 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 00:02:20 -0400 Subject: [PATCH 29/90] small tweak --- src/topics.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/topics.js b/src/topics.js index 03071beb32..c32f14bcb6 100644 --- a/src/topics.js +++ b/src/topics.js @@ -26,11 +26,7 @@ var async = require('async'), Topics.getTopicData = function(tid, callback) { Topics.getTopicsData([tid], function(err, topics) { - if (err) { - return callback(err); - } - - callback(null, topics ? topics[0] : null); + callback(err, Array.isArray(topics) && topics.length ? topics[0] : null); }); }; From cb519d53a1841686bf51eb24af4712a80983cbaa Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 00:06:13 -0400 Subject: [PATCH 30/90] isArray check --- src/topics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/topics.js b/src/topics.js index c32f14bcb6..86faf28bf1 100644 --- a/src/topics.js +++ b/src/topics.js @@ -124,7 +124,7 @@ var async = require('async'), nextStart: 0 }; - if (!tids || !tids.length) { + if (!Array.isArray(tids) || !tids.length) { return callback(null, returnTopics); } From f39d772a40c20ca9361654383996278dabda75f3 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 00:17:26 -0400 Subject: [PATCH 31/90] if notification is purged delete from user mapping as well --- src/user/notifications.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/user/notifications.js b/src/user/notifications.js index 591f799ca0..f6e85aa05f 100644 --- a/src/user/notifications.js +++ b/src/user/notifications.js @@ -55,6 +55,7 @@ var async = require('async'), } db.sortedSetRemove(set, nidsToUniqueIds[nid]); + db.deleteObjectField('uid:' + uid + ':notifications:uniqueId:nid', nidsToUniqueIds[nid]); return next(); } @@ -141,7 +142,7 @@ var async = require('async'), } notifs = notifs.filter(function(notif) { - return notif !== null; + return !!notif; }).sort(function(a, b) { return parseInt(b.datetime, 10) - parseInt(a.datetime, 10); }).map(function(notif) { From 7d179b68dfd10e916d23b316fb313e3d844dda1b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 00:44:25 -0400 Subject: [PATCH 32/90] faster notif prune --- src/notifications.js | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/notifications.js b/src/notifications.js index 4d03e22140..bb473d4235 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -285,11 +285,21 @@ var async = require('async'), return winston.error(err.message); } - async.filter(nids, function(nid, next) { - db.getObjectField('notifications:' + nid, 'datetime', function(err, datetime) { - next(!err && parseInt(datetime, 10) < cutoffTime); + var keys = nids.map(function(nid) { + return 'notifications:' + nid; + }); + + db.getObjectsFields(keys, ['nid', 'datetime'], function(err, notifs) { + if (err) { + return winston.error(err.message); + } + + var expiredNids = notifs.filter(function(notif) { + return notif && parseInt(notif.datetime, 10) < cutoffTime; + }).map(function(notif) { + return notif.nid; }); - }, function(expiredNids) { + async.each(expiredNids, function(nid, next) { async.parallel([ function(next) { @@ -303,15 +313,15 @@ var async = require('async'), next(err); }); }, function(err) { - if (!err) { - if (process.env.NODE_ENV === 'development') { - winston.info('[notifications.prune] Notification pruning completed. ' + numPruned + ' expired notification' + (numPruned !== 1 ? 's' : '') + ' removed.'); - } - var diff = process.hrtime(start); - events.log('Pruning notifications took : ' + (diff[0] * 1e3 + diff[1] / 1e6) + ' ms'); - } else { - winston.error('Encountered error pruning notifications: ' + err.message); + if (err) { + return winston.error('Encountered error pruning notifications: ' + err.message); } + + if (process.env.NODE_ENV === 'development') { + winston.info('[notifications.prune] Notification pruning completed. ' + numPruned + ' expired notification' + (numPruned !== 1 ? 's' : '') + ' removed.'); + } + var diff = process.hrtime(start); + events.log('Pruning '+ numPruned + 'notifications took : ' + (diff[0] * 1e3 + diff[1] / 1e6) + ' ms'); }); }); }); From 84f3fee48847bddec113d9fbdb32d63386892b73 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Aug 2014 10:25:03 -0400 Subject: [PATCH 33/90] latest translations --- public/language/et/global.json | 4 +-- public/language/et/topic.json | 2 +- public/language/pt_BR/email.json | 22 +++++++-------- public/language/pt_BR/error.json | 2 +- public/language/pt_BR/notifications.json | 6 ++-- public/language/ru/email.json | 36 ++++++++++++------------ public/language/ru/error.json | 8 +++--- public/language/ru/global.json | 2 +- public/language/ru/groups.json | 10 +++---- public/language/ru/modules.json | 18 ++++++------ public/language/ru/notifications.json | 6 ++-- public/language/ru/recent.json | 2 +- public/language/ru/search.json | 2 +- public/language/ru/topic.json | 2 +- public/language/ru/user.json | 2 +- public/language/ru/users.json | 2 +- public/language/tr/email.json | 36 ++++++++++++------------ public/language/tr/groups.json | 10 +++---- public/language/tr/search.json | 2 +- public/language/zh_CN/email.json | 36 ++++++++++++------------ public/language/zh_CN/groups.json | 10 +++---- public/language/zh_CN/search.json | 2 +- 22 files changed, 111 insertions(+), 111 deletions(-) diff --git a/public/language/et/global.json b/public/language/et/global.json index 45608e00bf..3cfa44bef3 100644 --- a/public/language/et/global.json +++ b/public/language/et/global.json @@ -50,9 +50,9 @@ "read_more": "loe veel", "posted_ago_by_guest": "postitatud %1 tagasi külalise poolt", "posted_ago_by": "postitatud %1 tagasi kasutaja %2 poolt", - "posted_ago": "postitatud %1 tagasi", + "posted_ago": "postitatud %1", "posted_in_ago_by_guest": "postitatud kategooriasse %1 %2 tagasi külalise poolt", - "posted_in_ago_by": "postitatud kategooriasse %1 %2 aega tagasi kasutaja %3 poolt", + "posted_in_ago_by": "postitatud kategooriasse %1 %2 kasutaja %3 poolt", "posted_in_ago": "postitatud kategooriasse %1 %2 tagasi", "replied_ago": "vastas %1", "user_posted_ago": "kasutaja %1 postitas %2 tagasi", diff --git a/public/language/et/topic.json b/public/language/et/topic.json index ff182da119..2bb35ffe5a 100644 --- a/public/language/et/topic.json +++ b/public/language/et/topic.json @@ -41,7 +41,7 @@ "thread_tools.pin": "Tõsta esile teema", "thread_tools.unpin": "Märgista teema", "thread_tools.lock": "Lukusta teema", - "thread_tools.unlock": "Eemalda märgistatud teema", + "thread_tools.unlock": "Taasava teema", "thread_tools.move": "Liiguta teema", "thread_tools.move_all": "Liiguta kõik", "thread_tools.fork": "Fork Topic", diff --git a/public/language/pt_BR/email.json b/public/language/pt_BR/email.json index 98e591ab02..92f058e6ff 100644 --- a/public/language/pt_BR/email.json +++ b/public/language/pt_BR/email.json @@ -1,20 +1,20 @@ { - "password-reset-requested": "Password Reset Requested - %1!", - "welcome-to": "Welcome to %1", - "greeting_no_name": "Hello", - "greeting_with_name": "Hello %1", - "welcome.text1": "Thank you for registering with %1!", + "password-reset-requested": "Recuperação de Senha Solicitada - %1!", + "welcome-to": "Bem vindo a %1", + "greeting_no_name": "Olá", + "greeting_with_name": "Olà %1", + "welcome.text1": "Obrigado por se registrar com %1!", "welcome.text2": "To fully activate your account, we need to verify that you own the email address you registered with.", - "welcome.cta": "Click here to confirm your email address", + "welcome.cta": "Clique aqui para confirmar seu endereço de email", "reset.text1": "We received a request to reset your password, possibly because you have forgotten it. If this is not the case, please ignore this email.", "reset.text2": "To continue with the password reset, please click on the following link:", - "reset.cta": "Click here to reset your password", + "reset.cta": "Clique aqui para recuperar sua senha", "digest.notifications": "You have some unread notifications from %1:", - "digest.latest_topics": "Latest topics from %1", - "digest.cta": "Click here to visit %1", + "digest.latest_topics": "Últimos tópicos de %1", + "digest.cta": "Clique aqui para visitar %1", "digest.unsub.info": "This digest was sent to you due to your subscription settings.", - "digest.unsub.cta": "Click here to alter those settings", + "digest.unsub.cta": "Clique aqui para alterar suas configurações", "digest.daily.no_topics": "There have been no active topics in the past day", "test.text1": "This is a test email to verify that the emailer is set up correctly for your NodeBB.", - "closing": "Thanks!" + "closing": "Obrigado!" } \ No newline at end of file diff --git a/public/language/pt_BR/error.json b/public/language/pt_BR/error.json index 0f1f906336..9dca9b0ae2 100644 --- a/public/language/pt_BR/error.json +++ b/public/language/pt_BR/error.json @@ -25,7 +25,7 @@ "no-user": "Usuário não existe", "no-teaser": "Chamada não existe", "no-privileges": "Você não possui permissões para esta ação.", - "no-emailers-configured": "No email plugins were loaded, so a test email could not be sent", + "no-emailers-configured": "Nenhum plugin de email foi carregado, por isso o email de teste não pode ser enviado", "category-disabled": "Categoria desativada", "topic-locked": "Tópico trancado", "still-uploading": "Aguarde a conclusão dos uploads.", diff --git a/public/language/pt_BR/notifications.json b/public/language/pt_BR/notifications.json index 58e0bda322..08a4240c19 100644 --- a/public/language/pt_BR/notifications.json +++ b/public/language/pt_BR/notifications.json @@ -4,9 +4,9 @@ "see_all": "Visualizar todas as notificações", "back_to_home": "Voltar para %1", "outgoing_link": "Link Externo", - "outgoing_link_message": "You are now leaving %1.", - "continue_to": "Continue to %1", - "return_to": "Return to %1", + "outgoing_link_message": "Você deixou de seguir %1.", + "continue_to": "Continuar para %1", + "return_to": "Voltar para %1", "new_notification": "Nova notificação", "you_have_unread_notifications": "Você possui notificações não lidas.", "new_message_from": "Nova mensagem de %1", diff --git a/public/language/ru/email.json b/public/language/ru/email.json index 98e591ab02..d0fc8fabed 100644 --- a/public/language/ru/email.json +++ b/public/language/ru/email.json @@ -1,20 +1,20 @@ { - "password-reset-requested": "Password Reset Requested - %1!", - "welcome-to": "Welcome to %1", - "greeting_no_name": "Hello", - "greeting_with_name": "Hello %1", - "welcome.text1": "Thank you for registering with %1!", - "welcome.text2": "To fully activate your account, we need to verify that you own the email address you registered with.", - "welcome.cta": "Click here to confirm your email address", - "reset.text1": "We received a request to reset your password, possibly because you have forgotten it. If this is not the case, please ignore this email.", - "reset.text2": "To continue with the password reset, please click on the following link:", - "reset.cta": "Click here to reset your password", - "digest.notifications": "You have some unread notifications from %1:", - "digest.latest_topics": "Latest topics from %1", - "digest.cta": "Click here to visit %1", - "digest.unsub.info": "This digest was sent to you due to your subscription settings.", - "digest.unsub.cta": "Click here to alter those settings", - "digest.daily.no_topics": "There have been no active topics in the past day", - "test.text1": "This is a test email to verify that the emailer is set up correctly for your NodeBB.", - "closing": "Thanks!" + "password-reset-requested": "Пароль сброшен - %1!", + "welcome-to": "Добро пожаловать на %1", + "greeting_no_name": "Здравствуйте!", + "greeting_with_name": "Здравствуйте, %1!", + "welcome.text1": "Благодарим за регистрацию %1! ", + "welcome.text2": "Для активации вашей учетной записи мы должны убедиться, что вы указали верный email адрес.", + "welcome.cta": "Перейдите по ссылке для подтверждения вашего email", + "reset.text1": "Мы получили запрос на изменение вашего пароля. Если не подавали запрос на изменение пароля, пожалуйста, проигнорируйте это сообщение.", + "reset.text2": "Для продолжения процедуры изменения пароля, пожалуйста, перейдите по ссылке:", + "reset.cta": "Кликните здесь для изменения пароля", + "digest.notifications": "У вас есть непрочитанные уведомления от %1:", + "digest.latest_topics": "Последние темы %1", + "digest.cta": "Кликните здесь для просмотра %1", + "digest.unsub.info": "Вам была выслана сводка новостей в соответствии с вашими настройками.", + "digest.unsub.cta": "Кликните здесь для изменения ваших настроек.", + "digest.daily.no_topics": "За минувший день новых тем нет.", + "test.text1": "Это тестовое сообщение для проверки почтового сервиса NodeBB.", + "closing": "Спасибо!" } \ No newline at end of file diff --git a/public/language/ru/error.json b/public/language/ru/error.json index e3afcd6dda..63a6a93355 100644 --- a/public/language/ru/error.json +++ b/public/language/ru/error.json @@ -15,7 +15,7 @@ "invalid-pagination-value": "Неверное значение пагинации", "username-taken": "Имя пользователя занято", "email-taken": "Email занят", - "email-not-confirmed": "Your email is not confirmed, please click here to confirm your email.", + "email-not-confirmed": "Ваш email не подтвержден, нажмите для подтверждения.", "username-too-short": "Слишком короткое имя пользователя", "user-banned": "Пользователь заблокирован", "no-category": "Несуществующая категория", @@ -25,10 +25,10 @@ "no-user": "Несуществующий пользователь", "no-teaser": "Несуществующее превью", "no-privileges": "У вас недостаточно прав, чтобы совершить данное действие.", - "no-emailers-configured": "No email plugins were loaded, so a test email could not be sent", + "no-emailers-configured": "Не подключен ни один плагин для отправки почты, поэтому тестовый email не может быть отправлен", "category-disabled": "Категория отключена", - "topic-locked": "Тема закрыт", - "still-uploading": "Пожалуйста, подождите завершения загрузки", + "topic-locked": "Тема закрыта", + "still-uploading": "Пожалуйста, подождите завершения загрузки.", "content-too-short": "Пост должен содержать минимум %1 символов.", "title-too-short": "Заголовок должен содержать минимум %1 символов.", "title-too-long": "Заголовок не может быть длиннее %1 символов.", diff --git a/public/language/ru/global.json b/public/language/ru/global.json index ced82c04eb..e83c49da26 100644 --- a/public/language/ru/global.json +++ b/public/language/ru/global.json @@ -13,7 +13,7 @@ "please_log_in": "Пожалуйста, войдите под своим аккаунтом", "logout": "Выйти", "posting_restriction_info": "Сообщения могут оставлять только зарегистрированные пользователи, нажмите сюда, чтобы войти", - "welcome_back": "Welcome Back", + "welcome_back": "С возвращением", "you_have_successfully_logged_in": "Вы вышли из аккаунта", "save_changes": "Сохранить изменения", "close": "Закрыть", diff --git a/public/language/ru/groups.json b/public/language/ru/groups.json index c00c111e11..a82a2bfc4b 100644 --- a/public/language/ru/groups.json +++ b/public/language/ru/groups.json @@ -1,7 +1,7 @@ { - "view_group": "View Group", - "details.title": "Group Details", - "details.members": "Member List", - "details.has_no_posts": "This group's members have not made any posts.", - "details.latest_posts": "Latest Posts" + "view_group": "Просмотр группы", + "details.title": "Информация о группе", + "details.members": "Список пользователей", + "details.has_no_posts": "Пользователями этой группы не публиковали никаких записей", + "details.latest_posts": "Последние записи" } \ No newline at end of file diff --git a/public/language/ru/modules.json b/public/language/ru/modules.json index 92d22ffa20..5cd840d3d0 100644 --- a/public/language/ru/modules.json +++ b/public/language/ru/modules.json @@ -1,18 +1,18 @@ { "chat.chatting_with": "Чат с ", - "chat.placeholder": "Type chat message here, press enter to send", + "chat.placeholder": "Введите сообщение, нажмите ENTER для отправки", "chat.send": "Отправить", "chat.no_active": "У вас нет активных чатов.", "chat.user_typing": "%1 печатает ...", "chat.user_has_messaged_you": "%1 отправил вам сообщение.", "chat.see_all": "Просмотр всех диалогов", - "chat.no-messages": "Please select a recipient to view chat message history", - "chat.recent-chats": "Recent Chats", - "chat.contacts": "Contacts", - "chat.message-history": "Message History", - "chat.pop-out": "Pop out chat", - "chat.maximize": "Maximize", - "composer.user_said_in": "%1 said in %2:", - "composer.user_said": "%1 said:", + "chat.no-messages": "Пожалуйста, выберите собеседника для просмотра истории сообщений", + "chat.recent-chats": "Последние переписки", + "chat.contacts": "Контакты", + "chat.message-history": "История сообщений", + "chat.pop-out": "Покинуть диалог", + "chat.maximize": "Развернуть", + "composer.user_said_in": "%1 сказал %2:", + "composer.user_said": "%1 сказал:", "composer.discard": "Вы уверены, что хотите отказаться от этого поста?" } \ No newline at end of file diff --git a/public/language/ru/notifications.json b/public/language/ru/notifications.json index fa840319ba..1648ebc8f8 100644 --- a/public/language/ru/notifications.json +++ b/public/language/ru/notifications.json @@ -4,9 +4,9 @@ "see_all": "Просмотреть все уведомления", "back_to_home": "Назад к %1", "outgoing_link": "Внешняя ссылка", - "outgoing_link_message": "You are now leaving %1.", - "continue_to": "Continue to %1", - "return_to": "Return to %1", + "outgoing_link_message": "Вы покидаете %1.", + "continue_to": "Перейти на %1", + "return_to": "Вернуться к %1", "new_notification": "Новое Уведомление", "you_have_unread_notifications": "У вас есть непрочитанные уведомления", "new_message_from": "Новое сообщение от %1", diff --git a/public/language/ru/recent.json b/public/language/ru/recent.json index 6e0ecb69ad..7dabef695e 100644 --- a/public/language/ru/recent.json +++ b/public/language/ru/recent.json @@ -3,6 +3,6 @@ "day": "День", "week": "Неделя", "month": "Месяц", - "year": "Year", + "year": "Год", "no_recent_topics": "Нет свежих тем." } \ No newline at end of file diff --git a/public/language/ru/search.json b/public/language/ru/search.json index d0ffc64f36..5f0a069bef 100644 --- a/public/language/ru/search.json +++ b/public/language/ru/search.json @@ -1,3 +1,3 @@ { - "results_matching": "%1 result(s) matching \"%2\", (%3 seconds)" + "results_matching": "%1 результатов по фразе \"%2\", (%3 секунды) " } \ No newline at end of file diff --git a/public/language/ru/topic.json b/public/language/ru/topic.json index ba7e7662c2..554d1371de 100644 --- a/public/language/ru/topic.json +++ b/public/language/ru/topic.json @@ -54,7 +54,7 @@ "topic_move_success": "Эта тема успешно перемещена в %1", "post_delete_confirm": "Вы уверены, что хотите удалить этот пост?", "post_restore_confirm": "Вы уверены, что хотите восстановить этот пост?", - "post_purge_confirm": "Are you sure you want to purge this post?", + "post_purge_confirm": "Вы уверены, что хотите очистить эту запись?", "load_categories": "Загружаем Категории", "disabled_categories_note": "Отключенные категории затемненны", "confirm_move": "Перенести", diff --git a/public/language/ru/user.json b/public/language/ru/user.json index c3493e26ce..6f3e7c92e2 100644 --- a/public/language/ru/user.json +++ b/public/language/ru/user.json @@ -3,7 +3,7 @@ "offline": "Не в сети", "username": "Имя пользователя", "email": "Email", - "confirm_email": "Confirm Email", + "confirm_email": "Подтвердить Email", "fullname": "Полное имя", "website": "Сайт", "location": "Откуда", diff --git a/public/language/ru/users.json b/public/language/ru/users.json index b4121f10c8..46ebc41b69 100644 --- a/public/language/ru/users.json +++ b/public/language/ru/users.json @@ -6,5 +6,5 @@ "enter_username": "Введите имя пользователя для поиска", "load_more": "Загрузить еще", "user-not-found": "Пользователь не найден!", - "users-found-search-took": "Нашел %1 пользователя(ей)! Поиск занял %2 ms." + "users-found-search-took": "Нашел %1 пользователя(ей)! Поиск занял %2 мс." } \ No newline at end of file diff --git a/public/language/tr/email.json b/public/language/tr/email.json index 98e591ab02..96fd81431e 100644 --- a/public/language/tr/email.json +++ b/public/language/tr/email.json @@ -1,20 +1,20 @@ { - "password-reset-requested": "Password Reset Requested - %1!", - "welcome-to": "Welcome to %1", - "greeting_no_name": "Hello", - "greeting_with_name": "Hello %1", - "welcome.text1": "Thank you for registering with %1!", - "welcome.text2": "To fully activate your account, we need to verify that you own the email address you registered with.", - "welcome.cta": "Click here to confirm your email address", - "reset.text1": "We received a request to reset your password, possibly because you have forgotten it. If this is not the case, please ignore this email.", - "reset.text2": "To continue with the password reset, please click on the following link:", - "reset.cta": "Click here to reset your password", - "digest.notifications": "You have some unread notifications from %1:", - "digest.latest_topics": "Latest topics from %1", - "digest.cta": "Click here to visit %1", - "digest.unsub.info": "This digest was sent to you due to your subscription settings.", - "digest.unsub.cta": "Click here to alter those settings", - "digest.daily.no_topics": "There have been no active topics in the past day", - "test.text1": "This is a test email to verify that the emailer is set up correctly for your NodeBB.", - "closing": "Thanks!" + "password-reset-requested": "Parola Değiştirme İsteği Gönderildi", + "welcome-to": "Hoşgeldiniz", + "greeting_no_name": "Merhaba", + "greeting_with_name": "Merhaba %1", + "welcome.text1": "Kaydolduğunuz için teşekkürler!", + "welcome.text2": "Hesabınızı aktif hale getirmek için, kaydolduğunuz e-posta adresinin size ait olduğunu onaylamamız gerekiyor.", + "welcome.cta": "E-posta adresinizi onaylamak için buraya tıklayın", + "reset.text1": "Şifrenizi değiştirmek istediğinize dair bir ileti aldık. Eğer böyle bir istek göndermediyseniz, lütfen bu e-postayı görmezden gelin.", + "reset.text2": "Parola değiştirme işlemine devam etmek için aşağıdaki bağlantıya tıklayın:", + "reset.cta": "Parolanızı değiştirmek için buraya tıklayın", + "digest.notifications": "Okunmamış bazı bildirimleriniz var", + "digest.latest_topics": "En güncel konular", + "digest.cta": "Ziyaret etmek için buraya tıklayın", + "digest.unsub.info": "Bu e-posta seçtiğiniz ayarlar nedeniyle gönderildi.", + "digest.unsub.cta": "Bu ayarları değiştirmek için buraya tıklayın", + "digest.daily.no_topics": "Geçtiğimiz gün içinde aktif bir konu yok.", + "test.text1": "Bu ileti NodeBB e-posta ayarlarınızın doğru çalışıp çalışmadığını kontrol etmek için gönderildi.", + "closing": "Teşekkürler!" } \ No newline at end of file diff --git a/public/language/tr/groups.json b/public/language/tr/groups.json index c00c111e11..804046d192 100644 --- a/public/language/tr/groups.json +++ b/public/language/tr/groups.json @@ -1,7 +1,7 @@ { - "view_group": "View Group", - "details.title": "Group Details", - "details.members": "Member List", - "details.has_no_posts": "This group's members have not made any posts.", - "details.latest_posts": "Latest Posts" + "view_group": "Grubu Gör", + "details.title": "Grup Detayları", + "details.members": "Üye Listesi", + "details.has_no_posts": "Bu grubun üyeleri henüz bir ileti göndermedi.", + "details.latest_posts": "En son iletiler" } \ No newline at end of file diff --git a/public/language/tr/search.json b/public/language/tr/search.json index d0ffc64f36..b384c82c72 100644 --- a/public/language/tr/search.json +++ b/public/language/tr/search.json @@ -1,3 +1,3 @@ { - "results_matching": "%1 result(s) matching \"%2\", (%3 seconds)" + "results_matching": "%1 tane “%2“ bulundu (%3 saniye)" } \ No newline at end of file diff --git a/public/language/zh_CN/email.json b/public/language/zh_CN/email.json index 98e591ab02..ae359e04fb 100644 --- a/public/language/zh_CN/email.json +++ b/public/language/zh_CN/email.json @@ -1,20 +1,20 @@ { - "password-reset-requested": "Password Reset Requested - %1!", - "welcome-to": "Welcome to %1", - "greeting_no_name": "Hello", - "greeting_with_name": "Hello %1", - "welcome.text1": "Thank you for registering with %1!", - "welcome.text2": "To fully activate your account, we need to verify that you own the email address you registered with.", - "welcome.cta": "Click here to confirm your email address", - "reset.text1": "We received a request to reset your password, possibly because you have forgotten it. If this is not the case, please ignore this email.", - "reset.text2": "To continue with the password reset, please click on the following link:", - "reset.cta": "Click here to reset your password", - "digest.notifications": "You have some unread notifications from %1:", - "digest.latest_topics": "Latest topics from %1", - "digest.cta": "Click here to visit %1", - "digest.unsub.info": "This digest was sent to you due to your subscription settings.", - "digest.unsub.cta": "Click here to alter those settings", - "digest.daily.no_topics": "There have been no active topics in the past day", - "test.text1": "This is a test email to verify that the emailer is set up correctly for your NodeBB.", - "closing": "Thanks!" + "password-reset-requested": "密码重设申请 - %1!", + "welcome-to": "欢迎来到 %1", + "greeting_no_name": "您好", + "greeting_with_name": "%1,您好", + "welcome.text1": "谢谢您使用 %1 注册帐户!", + "welcome.text2": "如需完全激活您的帐户,我们需要校验您注册的电子邮箱地址。", + "welcome.cta": "点击这里确认您的电子邮箱地址", + "reset.text1": "我们收到了重置您密码的申请,可能因为您忘记了密码。如果不是,请忽略这封邮件。", + "reset.text2": "如需继续重置密码,请点击下面的链接:", + "reset.cta": "点击这里重设您的密码", + "digest.notifications": "您有一些来自 %1 的未读通知:", + "digest.latest_topics": "来自 %1 的最新主题", + "digest.cta": "点击这里访问 %1", + "digest.unsub.info": "根据您的订阅设置,为您发送此摘要。", + "digest.unsub.cta": "点击这里修改这些设置", + "digest.daily.no_topics": "最近几天有一些未激活的主题", + "test.text1": "这是一封测试邮件,用来验证 NodeBB 的邮件配置是否设置正确。", + "closing": "谢谢!" } \ No newline at end of file diff --git a/public/language/zh_CN/groups.json b/public/language/zh_CN/groups.json index c00c111e11..42cd7e9ccd 100644 --- a/public/language/zh_CN/groups.json +++ b/public/language/zh_CN/groups.json @@ -1,7 +1,7 @@ { - "view_group": "View Group", - "details.title": "Group Details", - "details.members": "Member List", - "details.has_no_posts": "This group's members have not made any posts.", - "details.latest_posts": "Latest Posts" + "view_group": "查看用户组", + "details.title": "用户组详情", + "details.members": "会员列表", + "details.has_no_posts": "此用户组的会员尚未发表任何帖子。", + "details.latest_posts": "最新帖子" } \ No newline at end of file diff --git a/public/language/zh_CN/search.json b/public/language/zh_CN/search.json index d0ffc64f36..acbed61943 100644 --- a/public/language/zh_CN/search.json +++ b/public/language/zh_CN/search.json @@ -1,3 +1,3 @@ { - "results_matching": "%1 result(s) matching \"%2\", (%3 seconds)" + "results_matching": "%1 条结果,匹配 \"%2\",(耗时 %3 秒)" } \ No newline at end of file From 215ec041bb5d124aba6ad2b036b36aad35785c71 Mon Sep 17 00:00:00 2001 From: RefinedSoftwareLLC Date: Thu, 7 Aug 2014 09:14:28 -0600 Subject: [PATCH 34/90] Corrected node.js version requirement. package.json was being told that nodebb only required version >=0.8.x of node. Per documentation and communication with developers this should be >=0.10.x Changing this should help users who accidentally run nodebb on node.js 0.8 to run it on a supported version of 0.10.x or highter. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9440e3b6b3..9c596d0b3d 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "url": "https://github.com/NodeBB/NodeBB/issues" }, "engines": { - "node": ">=0.8" + "node": ">=0.10" }, "maintainers": [ { From 049d7f766ed6c2d0370cddff2e3ac4934b9b2089 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 13:48:03 -0400 Subject: [PATCH 35/90] use getSetsMembers instead of async.map --- src/favourites.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/favourites.js b/src/favourites.js index 69a611248d..c887c5c7e7 100644 --- a/src/favourites.js +++ b/src/favourites.js @@ -247,9 +247,10 @@ var async = require('async'), }; Favourites.getFavouritedUidsByPids = function(pids, callback) { - async.map(pids, function(pid, next) { - db.getSetMembers('pid:' + pid + ':users_favourited', next); - }, callback); + var sets = pids.map(function(pid) { + return 'pid:' + pid + ':users_favourited'; + }); + db.getSetsMembers(sets, callback); }; }(exports)); From e77491fcbbba8c79b6d9b9e0d936a596e0a5ffeb Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 7 Aug 2014 16:02:18 -0400 Subject: [PATCH 36/90] closes #1956 --- src/install.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/install.js b/src/install.js index 6793034515..0f30631354 100644 --- a/src/install.js +++ b/src/install.js @@ -266,12 +266,19 @@ function setOnEmpty(key1, key2) { function enableDefaultTheme(next) { var meta = require('./meta'); - winston.info('Enabling default theme: Lavender'); - meta.themes.set({ - type: 'local', - id: 'nodebb-theme-lavender' - }, next); + meta.configs.get('theme:id', function(err, id) { + if (err || id) { + winston.info('Previous theme detected, skipping enabling default theme'); + return next(err); + } + + winston.info('Enabling default theme: Lavender'); + meta.themes.set({ + type: 'local', + id: 'nodebb-theme-lavender' + }, next); + }); } function createAdministrator(next) { From db2ef15a0912d56bb198236cfa98b5a2001d70ca Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 7 Aug 2014 16:06:23 -0400 Subject: [PATCH 37/90] linting --- src/messaging.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/messaging.js b/src/messaging.js index 7d7018d388..b220cbb728 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -258,7 +258,9 @@ var db = require('./database'), db.sortedSetAdd('uid:' + uid + ':chats:unread', Date.now(), toUid, callback); }; - // todo #1798 -- this utility method creates a room name given an array of uids. + /* + todo #1798 -- this utility method creates a room name given an array of uids. + Messaging.uidsToRoom = function(uids, callback) { uid = parseInt(uid, 10); if (typeof uid === 'number' && Array.isArray(roomUids)) { @@ -274,7 +276,7 @@ var db = require('./database'), } else { callback(new Error('invalid-uid-or-participant-uids')); } - }; + };*/ Messaging.verifySpammer = function(uid, callback) { var messagesToCompare = 10; From 46398fa92487ab2b3eac791485c3f66dbef245fe Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 16:20:46 -0400 Subject: [PATCH 38/90] removed unused require --- src/topics.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/topics.js b/src/topics.js index 86faf28bf1..8618f9d985 100644 --- a/src/topics.js +++ b/src/topics.js @@ -1,12 +1,11 @@ "use strict"; var async = require('async'), - gravatar = require('gravatar'), validator = require('validator'), db = require('./database'), posts = require('./posts'), - utils = require('./../public/src/utils'), + utils = require('../public/src/utils'), plugins = require('./plugins'), user = require('./user'), categories = require('./categories'), From ee108ed963ada7c49a745367d2f5eeb23038f4f9 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 7 Aug 2014 17:44:37 -0400 Subject: [PATCH 39/90] bumping up templates.js version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9440e3b6b3..04ee8c12c3 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.8" + "templates.js": "0.0.9" }, "devDependencies": { "mocha": "~1.13.0" From 025403b9a8f996b75b49c2927bbf4fd7aed08671 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 7 Aug 2014 17:52:03 -0400 Subject: [PATCH 40/90] optimizing data transfer *rolls eyes* --- public/src/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/helpers.js b/public/src/helpers.js index 4dbd5419bc..a89aeae0e2 100644 --- a/public/src/helpers.js +++ b/public/src/helpers.js @@ -14,7 +14,7 @@ property = tag.property ? 'property="' + tag.property + '" ' : '', content = tag.content ? 'content="' + tag.content.replace(/\n/g, ' ') + '" ' : ''; - return ''; + return ''; }; if ('undefined' !== typeof window) { From df0a5e780ae22fda7acf64d25764380f39bad1e0 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 20:03:56 -0400 Subject: [PATCH 41/90] prevent edit to change title length above max --- src/socket.io/posts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 9364124ff2..328eda21f2 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -161,6 +161,8 @@ SocketPosts.edit = function(socket, data, callback) { return callback(new Error('[[error:invalid-data]]')); } else if (!data.title || data.title.length < parseInt(meta.config.minimumTitleLength, 10)) { return callback(new Error('[[error:title-too-short, ' + meta.config.minimumTitleLength + ']]')); + } else if (data.title.length > parseInt(meta.config.maximumTitleLength, 10)) { + return callback(new Error('[[error:title-too-long, ' + meta.config.maximumTitleLength + ']]')); } else if (!data.content || data.content.length < parseInt(meta.config.minimumPostLength, 10)) { return callback(new Error('[[error:content-too-short, ' + meta.config.minimumPostLength + ']]')); } From 5c6e26832ee69421ebbe52f7a94ed0e4ab624250 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 Aug 2014 21:31:34 -0400 Subject: [PATCH 42/90] removed console.logs --- src/sitemap.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sitemap.js b/src/sitemap.js index 7bf9445596..e01a2cde3e 100644 --- a/src/sitemap.js +++ b/src/sitemap.js @@ -76,10 +76,8 @@ var path = require('path'), }, render: function(callback) { if (sitemap.obj !== undefined && sitemap.obj.cache.length) { - console.log('using sitemap from cache!'); sitemap.obj.toXML(callback); } else { - console.log('generating new sitemap!', sitemap.obj); async.parallel([sitemap.getStaticUrls, sitemap.getDynamicUrls], function(err, urls) { urls = urls[0].concat(urls[1]); sitemap.obj = sm.createSitemap({ From 193832ea9befc5a83ad23e787559a599037efe4d Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 8 Aug 2014 13:15:27 -0400 Subject: [PATCH 43/90] closes #1957 --- public/src/ajaxify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 1e772957e7..dc00cdbdb0 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -203,7 +203,7 @@ var ajaxify = ajaxify || {}; } var location = document.location || window.location, - api_url = (url === '' || url === '/') ? 'home' : url, + api_url = (url === RELATIVE_PATH || url === '/' + RELATIVE_PATH) ? 'home' : url, tpl_url = ajaxify.getCustomTemplateMapping(url.split('?')[0]); if (!tpl_url) { From a2bb8029fec5ade4c747bc368e9a9164e2c19c14 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 Aug 2014 15:28:39 -0400 Subject: [PATCH 44/90] use utils.toISOString --- src/messaging.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/messaging.js b/src/messaging.js index b220cbb728..9b74bc4df4 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -6,6 +6,7 @@ var db = require('./database'), user = require('./user'), plugins = require('./plugins'), meta = require('./meta'), + utils = require('../public/src/utils'), notifications = require('./notifications'), userNotifications = require('./user/notifications'); @@ -128,7 +129,7 @@ var db = require('./database'), var self = parseInt(message.fromuid, 10) === parseInt(fromuid, 10); message.fromUser = self ? userData[0] : userData[1]; message.toUser = self ? userData[1] : userData[0]; - message.timestampISO = new Date(parseInt(message.timestamp, 10)).toISOString(); + message.timestampISO = utils.toISOString(message.timestamp); message.self = self ? 1 : 0; message.newSet = false; @@ -260,7 +261,7 @@ var db = require('./database'), /* todo #1798 -- this utility method creates a room name given an array of uids. - + Messaging.uidsToRoom = function(uids, callback) { uid = parseInt(uid, 10); if (typeof uid === 'number' && Array.isArray(roomUids)) { From ea2975cb3f267a37f7f8b913840dab703ccd18af Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 Aug 2014 16:28:29 -0400 Subject: [PATCH 45/90] eachLimit on expire nids --- src/notifications.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/notifications.js b/src/notifications.js index bb473d4235..b5d61895e5 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -300,7 +300,7 @@ var async = require('async'), return notif.nid; }); - async.each(expiredNids, function(nid, next) { + async.eachLimit(expiredNids, 50, function(nid, next) { async.parallel([ function(next) { db.setRemove('notifications', nid, next); @@ -321,7 +321,7 @@ var async = require('async'), winston.info('[notifications.prune] Notification pruning completed. ' + numPruned + ' expired notification' + (numPruned !== 1 ? 's' : '') + ' removed.'); } var diff = process.hrtime(start); - events.log('Pruning '+ numPruned + 'notifications took : ' + (diff[0] * 1e3 + diff[1] / 1e6) + ' ms'); + events.log('Pruning '+ numPruned + ' notifications took : ' + (diff[0] * 1e3 + diff[1] / 1e6) + ' ms'); }); }); }); From 4e4a583d9dbdfb82a2c70bcd242a8b331d2f7702 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 Aug 2014 17:30:37 -0400 Subject: [PATCH 46/90] took out the meta config check from image.js --- src/controllers/accounts.js | 8 ++++++-- src/image.js | 6 ++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 0c906e562c..f2be462147 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -404,7 +404,11 @@ accountsController.uploadPicture = function (req, res, next) { image.resizeImage(req.files.userPhoto.path, extension, 128, 128, next); }, function(next) { - image.convertImageToPng(req.files.userPhoto.path, extension, next); + if (parseInt(meta.config['profile:convertProfileImageToPNG'], 10) === 1) { + image.convertImageToPng(req.files.userPhoto.path, extension, next); + } else { + next(); + } }, function(next) { user.getUidByUserslug(req.params.userslug, next); @@ -450,7 +454,7 @@ accountsController.uploadPicture = function (req, res, next) { return plugins.fireHook('filter:uploadImage', req.files.userPhoto, done); } - var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10); + var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10) === 1; var filename = updateUid + '-profileimg' + (convertToPNG ? '.png' : extension); user.getUserField(updateUid, 'uploadedpicture', function (err, oldpicture) { diff --git a/src/image.js b/src/image.js index 73bb85599d..0b2cea24cb 100644 --- a/src/image.js +++ b/src/image.js @@ -1,8 +1,7 @@ 'use strict'; var fs = require('fs'), - gm = require('gm').subClass({imageMagick: true}), - meta = require('./meta'); + gm = require('gm').subClass({imageMagick: true}); var image = {}; @@ -28,8 +27,7 @@ image.resizeImage = function(path, extension, width, height, callback) { }; image.convertImageToPng = function(path, extension, callback) { - var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10); - if(convertToPNG && extension !== '.png') { + if(extension !== '.png') { gm(path).toBuffer('png', function(err, buffer) { if (err) { return callback(err); From 5b681678b125c67eaccec6ed1e3ce500698f52d8 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 Aug 2014 17:42:03 -0400 Subject: [PATCH 47/90] could use async.apply here hm --- src/user/delete.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/user/delete.js b/src/user/delete.js index 8ab14c4cea..7a91603438 100644 --- a/src/user/delete.js +++ b/src/user/delete.js @@ -18,14 +18,11 @@ module.exports = function(User) { }, function(next) { deleteTopics(uid, next); + }, + function(next) { + deleteAccount(uid, next); } - ], function(err) { - if (err) { - return callback(err); - } - - deleteAccount(uid, callback); - }); + ], callback); }; function deletePosts(uid, callback) { From b8279dc7377ed2232bd744e1a74c0d6274d97e64 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sat, 9 Aug 2014 02:07:03 -0400 Subject: [PATCH 48/90] optimize getUserGroups to work with multiple user ids --- src/groups.js | 27 +++++++++++++++------------ src/posts.js | 40 +++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/groups.js b/src/groups.js index acbc2158a5..b47b069b8a 100644 --- a/src/groups.js +++ b/src/groups.js @@ -438,7 +438,7 @@ }); }; - Groups.getUserGroups = function(uid, callback) { + Groups.getUserGroups = function(uids, callback) { var ignoredGroups = ['registered-users']; db.getSetMembers('groups', function(err, groupNames) { @@ -466,19 +466,22 @@ return 'group:' + group.name + ':members'; }); - db.isMemberOfSets(groupSets, uid, function(err, isMembers) { - if (err) { - return callback(err); - } - - for(var i=isMembers.length - 1; i>=0; --i) { - if (!isMembers[i]) { - groupData.splice(i, 1); + async.map(uids, function(uid, next) { + db.isMemberOfSets(groupSets, uid, function(err, isMembers) { + if (err) { + return next(err); } - } - callback(null, groupData); - }); + var memberOf = []; + isMembers.forEach(function(isMember, index) { + if (isMember) { + memberOf.push(groupData[index]); + } + }); + + next(null, memberOf); + }); + }, callback); }); }); }; diff --git a/src/posts.js b/src/posts.js index 3ebb14d859..7c7d5ff849 100644 --- a/src/posts.js +++ b/src/posts.js @@ -222,21 +222,31 @@ var async = require('async'), }; Posts.getUserInfoForPosts = function(uids, callback) { - user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) { + async.parallel({ + groups: function(next) { + groups.getUserGroups(uids, next); + }, + userData: function(next) { + user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], next); + } + }, function(err, results) { if (err) { return callback(err); } + var userData = results.userData; + for(var i=0; i Date: Sat, 9 Aug 2014 13:30:13 -0400 Subject: [PATCH 49/90] moved newlines from language file to core --- public/language/en_GB/modules.json | 4 ++-- public/src/forum/topic/postTools.js | 2 +- public/src/modules/composer.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/public/language/en_GB/modules.json b/public/language/en_GB/modules.json index fdaf14dd5b..9bf107bec6 100644 --- a/public/language/en_GB/modules.json +++ b/public/language/en_GB/modules.json @@ -13,7 +13,7 @@ "chat.pop-out": "Pop out chat", "chat.maximize": "Maximize", - "composer.user_said_in": "%1 said in %2:\n", - "composer.user_said": "%1 said:\n", + "composer.user_said_in": "%1 said in %2:", + "composer.user_said": "%1 said:", "composer.discard": "Are you sure you wish to discard this post?" } \ No newline at end of file diff --git a/public/src/forum/topic/postTools.js b/public/src/forum/topic/postTools.js index b71263bc75..5fe564c3db 100644 --- a/public/src/forum/topic/postTools.js +++ b/public/src/forum/topic/postTools.js @@ -150,7 +150,7 @@ define('forum/topic/postTools', ['composer', 'share', 'navigator'], function(com if($('.composer').length) { composer.addQuote(tid, ajaxify.variables.get('topic_slug'), getData(button, 'data-index'), pid, topicName, username, quoted); } else { - composer.newReply(tid, pid, topicName, '[[modules:composer.user_said, ' + username + ']]' + quoted); + composer.newReply(tid, pid, topicName, '[[modules:composer.user_said, ' + username + ']]\n' + quoted); } }); } diff --git a/public/src/modules/composer.js b/public/src/modules/composer.js index 478c7738dc..1ca81906de 100644 --- a/public/src/modules/composer.js +++ b/public/src/modules/composer.js @@ -119,7 +119,7 @@ define('composer', dependencies, function(taskbar, controls, uploads, formatting var uuid = composer.active; if (uuid === undefined) { - composer.newReply(tid, pid, title, '[[modules:composer.user_said, ' + username + ']]' + text); + composer.newReply(tid, pid, title, '[[modules:composer.user_said, ' + username + ']]\n' + text); return; } var postContainer = $('#cmp-uuid-' + uuid); @@ -127,9 +127,9 @@ define('composer', dependencies, function(taskbar, controls, uploads, formatting var prevText = bodyEl.val(); if (parseInt(tid, 10) !== parseInt(composer.posts[uuid].tid, 10)) { var link = '[' + title + '](/topic/' + topicSlug + '/' + (parseInt(postIndex, 10) + 1) + ')'; - translator.translate('[[modules:composer.user_said_in, ' + username + ', ' + link + ']]', onTranslated); + translator.translate('[[modules:composer.user_said_in, ' + username + ', ' + link + ']]\n', onTranslated); } else { - translator.translate('[[modules:composer.user_said, ' + username + ']]', onTranslated); + translator.translate('[[modules:composer.user_said, ' + username + ']]\n', onTranslated); } function onTranslated(translated) { From b5cc852551e323b73b06744f00c3e80a3b215797 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sat, 9 Aug 2014 16:15:22 -0400 Subject: [PATCH 50/90] do a single filter after getting all unread tids --- src/topics/unread.js | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/topics/unread.js b/src/topics/unread.js index 8bdc8a04e2..2754fa9a88 100644 --- a/src/topics/unread.js +++ b/src/topics/unread.js @@ -23,48 +23,45 @@ module.exports = function(Topics) { done = false; uid = parseInt(uid, 10); - if(uid === 0) { + if (uid === 0) { return callback(null, unreadTids); } async.whilst(function() { return unreadTids.length < 21 && !done; - }, function(callback) { + }, function(next) { Topics.getLatestTids(start, stop, 'month', function(err, tids) { if (err) { - return callback(err); + return next(err); } if (tids && !tids.length) { done = true; - return callback(); + return next(); } Topics.hasReadTopics(tids, uid, function(err, read) { - if(err) { - return callback(err); + if (err) { + return next(err); } var newtids = tids.filter(function(tid, index) { return !read[index]; }); - privileges.topics.filter('read', newtids, uid, function(err, newtids) { - if(err) { - return callback(err); - } + unreadTids.push.apply(unreadTids, newtids); - unreadTids.push.apply(unreadTids, newtids); + start = stop + 1; + stop = start + 19; - start = stop + 1; - stop = start + 19; - - callback(); - }); + next(); }); }); }, function(err) { - callback(err, unreadTids); + if (err) { + return callback(err); + } + privileges.topics.filter('read', unreadTids, uid, callback); }); }; From 53d20cf058d70f58b8242346f7203a5f7ce9f9ae Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sat, 9 Aug 2014 21:05:59 -0400 Subject: [PATCH 51/90] parse variables before rendering widgets --- public/src/ajaxify.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index dc00cdbdb0..f2258fb823 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -96,12 +96,13 @@ var ajaxify = ajaxify || {}; translator.translate(template, function(translatedTemplate) { setTimeout(function() { $('#content').html(translatedTemplate); + + ajaxify.variables.parse(); + ajaxify.widgets.render(tpl_url, url, function() { $(window).trigger('action:ajaxify.end', {url: url}); }); - ajaxify.variables.parse(); - $(window).trigger('action:ajaxify.contentLoaded', {url: url}); ajaxify.loadScript(tpl_url); From 7642be3608310609a3de62cb3de77595997a178b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sun, 10 Aug 2014 14:52:23 -0400 Subject: [PATCH 52/90] closes #1939 --- src/user.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/user.js b/src/user.js index 3a6bcb4607..82201af070 100644 --- a/src/user.js +++ b/src/user.js @@ -68,8 +68,9 @@ var bcrypt = require('bcryptjs'), if (err) { return callback(err); } - - callback(null, modifyUserData(users, fieldsToRemove)); + plugins.fireHook('filter:user.removeFields', fieldsToRemove, function(err, fields) { + callback(err, modifyUserData(users, fields)); + }); }); }; @@ -94,7 +95,9 @@ var bcrypt = require('bcryptjs'), return callback(err); } - callback(null, modifyUserData(users, [])); + plugins.fireHook('filter:user.removeFields', [], function(err, fields) { + callback(err, modifyUserData(users, fields)); + }); }); }; From c991997552483269f76176606d1fcb909e0c83d4 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 11 Aug 2014 12:16:01 -0400 Subject: [PATCH 53/90] removed off from search button --- public/src/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/app.js b/public/src/app.js index eff176c266..d84d89e99a 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -441,7 +441,7 @@ var socket, searchButton.show(); } - searchButton.off().on('click', function(e) { + searchButton.on('click', function(e) { if (!config.loggedIn && !config.allowGuestSearching) { app.alert({ message:'[[error:search-requires-login]]', From e137baccd966afd57e31bb2e91c04e0e84848490 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 11 Aug 2014 13:47:24 -0400 Subject: [PATCH 54/90] fixed ip:recent weird --- src/database/redis/sorted.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/database/redis/sorted.js b/src/database/redis/sorted.js index 1ddc1fc6f4..59bffa685a 100644 --- a/src/database/redis/sorted.js +++ b/src/database/redis/sorted.js @@ -2,6 +2,7 @@ module.exports = function(redisClient, module) { module.sortedSetAdd = function(key, score, value, callback) { + callback = callback || function() {}; redisClient.zadd(key, score, value, callback); }; From 5e68e0b00962fd782063b179853d11354b733264 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 11 Aug 2014 15:41:45 -0400 Subject: [PATCH 55/90] same deal as previous commit --- src/database/redis/hash.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/database/redis/hash.js b/src/database/redis/hash.js index 86ed0027d9..63a85f77ec 100644 --- a/src/database/redis/hash.js +++ b/src/database/redis/hash.js @@ -7,6 +7,7 @@ module.exports = function(redisClient, module) { }; module.setObjectField = function(key, field, value, callback) { + callback = callback || function() {}; redisClient.hset(key, field, value, callback); }; From c8084e9b2e8496a176583c876c8be794f9cefa94 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 11 Aug 2014 16:26:20 -0400 Subject: [PATCH 56/90] closes #1978 --- src/routes/authentication.js | 3 -- src/user/create.js | 58 +++++++++++++++++------------------- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/routes/authentication.js b/src/routes/authentication.js index 99a7986c0b..42139e87c4 100644 --- a/src/routes/authentication.js +++ b/src/routes/authentication.js @@ -97,9 +97,6 @@ return res.redirect(nconf.get('relative_path') + '/register' + (err.message ? '?error=' + err.message : '')); } - delete userData['password-confirm']; - delete userData['_csrf']; - user.create(userData, function(err, uid) { if (err || !uid) { return res.redirect(nconf.get('relative_path') + '/register'); diff --git a/src/user/create.js b/src/user/create.js index b3b556edb7..ede0202b2b 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -13,18 +13,37 @@ var async = require('async'), module.exports = function(User) { User.create = function(userData, callback) { - userData = userData || {}; + var gravatar = User.createGravatarURLFromEmail(userData.email); + var timestamp = Date.now(); + var password = userData.password; + + userData = { + 'username': userData.username.trim(), + 'email': userData.email, + 'joindate': timestamp, + 'picture': gravatar, + 'gravatarpicture': gravatar, + 'fullname': '', + 'location': '', + 'birthday': '', + 'website': '', + 'signature': '', + 'uploadedpicture': '', + 'profileviews': 0, + 'reputation': 0, + 'postcount': 0, + 'lastposttime': 0, + 'banned': 0, + 'status': 'online' + }; + userData.userslug = utils.slugify(userData.username); - userData.username = userData.username.trim(); if (userData.email !== undefined) { userData.email = userData.email.trim(); userData.email = validator.escape(userData.email); } - var password = userData.password; - userData.password = null; - async.parallel({ emailValid: function(next) { if (userData.email) { @@ -104,37 +123,14 @@ module.exports = function(User) { } db.incrObjectField('global', 'nextUid', function(err, uid) { - if(err) { + if (err) { return callback(err); } - var gravatar = User.createGravatarURLFromEmail(userData.email); - var timestamp = Date.now(); - - userData = utils.merge({ - 'uid': uid, - 'username': userData.username, - 'userslug': userData.userslug, - 'fullname': '', - 'location': '', - 'birthday': '', - 'website': '', - 'email': userData.email || '', - 'signature': '', - 'joindate': timestamp, - 'picture': gravatar, - 'gravatarpicture': gravatar, - 'uploadedpicture': '', - 'profileviews': 0, - 'reputation': 0, - 'postcount': 0, - 'lastposttime': 0, - 'banned': 0, - 'status': 'online' - }, userData); + userData.uid = uid; db.setObject('user:' + uid, userData, function(err) { - if(err) { + if (err) { return callback(err); } From c4b083330c7d22edfc59e711b0f2d3c1bfc9c260 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 11 Aug 2014 18:07:56 -0400 Subject: [PATCH 57/90] closes #1978 --- src/user/create.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/user/create.js b/src/user/create.js index ede0202b2b..80a5877d7f 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -12,14 +12,14 @@ var async = require('async'), module.exports = function(User) { - User.create = function(userData, callback) { - var gravatar = User.createGravatarURLFromEmail(userData.email); + User.create = function(data, callback) { + var gravatar = User.createGravatarURLFromEmail(data.email); var timestamp = Date.now(); - var password = userData.password; + var password = data.password; - userData = { - 'username': userData.username.trim(), - 'email': userData.email, + var userData = { + 'username': data.username.trim(), + 'email': data.email, 'joindate': timestamp, 'picture': gravatar, 'gravatarpicture': gravatar, @@ -103,7 +103,7 @@ module.exports = function(User) { } }, customFields: function(next) { - plugins.fireHook('filter:user.custom_fields', userData, next); + plugins.fireHook('filter:user.custom_fields', [], next); }, userData: function(next) { plugins.fireHook('filter:user.create', userData, next); @@ -113,7 +113,14 @@ module.exports = function(User) { return callback(err); } - userData = utils.merge(results.userData, results.customFields); + var customData = {}; + results.customFields.forEach(function(customField) { + if (data[customField]) { + customData[customField] = data[customField]; + } + }); + + userData = utils.merge(results.userData, customData); var userNameChanged = !!results.renamedUsername; From 0e28b6f2d5bc9ca5af7b75b05fd7dff96a8f0c67 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 12 Aug 2014 09:17:41 -0400 Subject: [PATCH 58/90] fixed #1980 -- missing pass-through --- src/messaging.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/messaging.js b/src/messaging.js index 9b74bc4df4..dd72ae14d3 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -194,7 +194,11 @@ var db = require('./database'), } }, function(mids, next) { - db.getObjects(['message:' + mids[0], 'message:' + mids[1]], next); + if (typeof mids !== 'boolean') { + db.getObjects(['message:' + mids[0], 'message:' + mids[1]], next); + } else { + next(null, mids); + } }, function(messages, next) { if (typeof messages !== 'boolean') { From c818a37f0f6ce4e072f256ad14090d74680a02b4 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 12 Aug 2014 09:56:04 -0400 Subject: [PATCH 59/90] possible fix for #1981 --- public/src/forum/login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/forum/login.js b/public/src/forum/login.js index 75754b04ca..4f4c9b6061 100644 --- a/public/src/forum/login.js +++ b/public/src/forum/login.js @@ -28,7 +28,7 @@ define('forum/login', function() { if (previousUrl) { app.previousUrl = previousUrl; } else if (!app.previousUrl) { - app.previousUrl = '/'; + app.previousUrl = RELATIVE_PATH || '/'; } if(app.previousUrl.indexOf('/reset/') !== -1) { From c07d9121df575f0ae29d0509239b49cf06c27666 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 12 Aug 2014 11:19:17 -0400 Subject: [PATCH 60/90] small optimizations user.isOnline works with an array of uids do not make 2 trips to db to get main post and first 10 posts --- src/posts.js | 48 +++++++++++++++++++++---------------------- src/socket.io/user.js | 22 +++++++++----------- src/topics.js | 25 ++++++++++++++++------ src/user.js | 33 +++++++++++++++++------------ 4 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/posts.js b/src/posts.js index 7c7d5ff849..1392ac0372 100644 --- a/src/posts.js +++ b/src/posts.js @@ -93,7 +93,7 @@ var async = require('async'), }; Posts.getPostsByTid = function(tid, set, start, end, reverse, callback) { - db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, end, function(err, pids) { + Posts.getPidsFromSet(set, start, end, reverse, function(err, pids) { if(err) { return callback(err); } @@ -102,31 +102,15 @@ var async = require('async'), return callback(null, []); } - Posts.getPostsByPids(pids, function(err, posts) { - if(err) { - return callback(err); - } - - if(!Array.isArray(posts) || !posts.length) { - return callback(null, []); - } - - plugins.fireHook('filter:post.getPosts', {tid: tid, posts: posts}, function(err, data) { - if(err) { - return callback(err); - } - - if(!data || !Array.isArray(data.posts)) { - return callback(null, []); - } - - callback(null, data.posts); - }); - }); + Posts.getPostsByPids(pids, tid, callback); }); }; - Posts.getPostsByPids = function(pids, callback) { + Posts.getPidsFromSet = function(set, start, end, reverse, callback) { + db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, end, callback); + }; + + Posts.getPostsByPids = function(pids, tid, callback) { var keys = []; for(var x=0, numPids=pids.length; x Date: Tue, 12 Aug 2014 11:36:36 -0400 Subject: [PATCH 61/90] send uids to isOnline in messaging --- src/messaging.js | 33 ++++++++++++++------------------- src/user.js | 4 ++++ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/messaging.js b/src/messaging.js index dd72ae14d3..d6cd44be5a 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -221,32 +221,27 @@ var db = require('./database'), return callback(err); } - async.parallel({ - unreadUids: async.apply(db.isSortedSetMembers, 'uid:' + uid + ':chats:unread', uids), - users: async.apply(user.getMultipleUserFields, uids, ['username', 'picture', 'uid']) - }, function(err, results) { + db.isSortedSetMembers('uid:' + uid + ':chats:unread', uids, function(err, unreadUids) { if (err) { return callback(err); } - var users = results.users; - for (var i=0; i Date: Tue, 12 Aug 2014 11:41:18 -0400 Subject: [PATCH 62/90] crash fix --- src/socket.io/index.js | 8 ++++---- src/socket.io/user.js | 7 ++++--- src/user.js | 4 ---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 299aee3933..f0d9ea40e6 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -93,8 +93,8 @@ Sockets.init = function(server) { uid: uid }); - socketUser.isOnline(socket, uid, function(err, data) { - socket.broadcast.emit('user.isOnline', err, data); + socketUser.isOnline(socket, [uid], function(err, data) { + socket.broadcast.emit('user.isOnline', err, data[0]); }); }); }); @@ -114,8 +114,8 @@ Sockets.init = function(server) { if (uid && Sockets.getUserSockets(uid).length <= 1) { db.sortedSetRemove('users:online', uid, function(err) { - socketUser.isOnline(socket, uid, function(err, data) { - socket.broadcast.emit('user.isOnline', err, data); + socketUser.isOnline(socket, [uid], function(err, data) { + socket.broadcast.emit('user.isOnline', err, data[0]); }); }); } diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 06079dedaa..7501c9651b 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -227,6 +227,7 @@ SocketUser.getOnlineUsers = function(socket, uids, callback) { if (err) { return callback(err); } + userData.forEach(function(user) { if (user) { returnData[user.uid] = user; @@ -291,9 +292,9 @@ SocketUser.loadMore = function(socket, data, callback) { SocketUser.setStatus = function(socket, status, callback) { var server = require('./index'); user.setUserField(socket.uid, 'status', status, function(err) { - SocketUser.isOnline(socket, socket.uid, function(err, data) { - server.server.sockets.emit('user.isOnline', err, data); - callback(err, data); + SocketUser.isOnline(socket, [socket.uid], function(err, data) { + server.server.sockets.emit('user.isOnline', err, data[0]); + callback(err, data[0]); }); }); }; diff --git a/src/user.js b/src/user.js index 535bffa7b0..c0e96960c6 100644 --- a/src/user.js +++ b/src/user.js @@ -442,10 +442,6 @@ var bcrypt = require('bcryptjs'), return user; }); - if (uids.length === 1) { - userData = userData[0]; - } - callback(null, userData); }); }; From 8584da75f26425f35adfeda345788e9f440a5d02 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 12 Aug 2014 11:49:28 -0400 Subject: [PATCH 63/90] reverted main post change, breaks indices --- src/topics.js | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/topics.js b/src/topics.js index dc7929a6b7..ab3f4f6ffa 100644 --- a/src/topics.js +++ b/src/topics.js @@ -256,24 +256,11 @@ var async = require('async'), } async.parallel({ + mainPost: function(next) { + Topics.getMainPost(tid, uid, next); + }, posts: function(next) { - posts.getPidsFromSet(set, start, end, reverse, function(err, pids) { - if (err) { - return next(err); - } - - pids = [topicData.mainPid].concat(pids); - posts.getPostsByPids(pids, tid, function(err, posts) { - if (err) { - return next(err); - } - start = parseInt(start, 10); - for(var i=0; i Date: Tue, 12 Aug 2014 12:32:38 -0400 Subject: [PATCH 64/90] doing it properly this time mainPost always has index 0 --- public/src/forum/topic.js | 2 +- public/src/modules/navigator.js | 4 ++-- src/topics.js | 28 +++++++++++++++++++++------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 06d0167a53..3df4a2b1c3 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -76,7 +76,7 @@ define('forum/topic', dependencies, function(pagination, infinitescroll, threadT }; Topic.toTop = function() { - navigator.scrollTop(1); + navigator.scrollTop(0); }; Topic.toBottom = function() { diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index bc1bf3e2b8..88e3934128 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -110,7 +110,7 @@ define('navigator', ['forum/pagination'], function(pagination) { navigator.scrollTop = function(index) { if ($('li[data-index="' + index + '"]').length) { - navigator.scrollUp(); + navigator.scrollToPost(index, true); } else { ajaxify.go(generateUrl()); } @@ -118,7 +118,7 @@ define('navigator', ['forum/pagination'], function(pagination) { navigator.scrollBottom = function(index) { if ($('li[data-index="' + index + '"]').length) { - navigator.scrollDown(); + navigator.scrollToPost(index, true); } else { index = parseInt(index, 10) + 1; ajaxify.go(generateUrl(index)); diff --git a/src/topics.js b/src/topics.js index ab3f4f6ffa..926f8bb78b 100644 --- a/src/topics.js +++ b/src/topics.js @@ -256,12 +256,26 @@ var async = require('async'), } async.parallel({ - mainPost: function(next) { - Topics.getMainPost(tid, uid, next); - }, - posts: function(next) { - Topics.getTopicPosts(tid, set, start, end, uid, reverse, next); - }, + posts: function(next) { + posts.getPidsFromSet(set, start, end, reverse, function(err, pids) { + if (err) { + return next(err); + } + + pids = [topicData.mainPid].concat(pids); + posts.getPostsByPids(pids, tid, function(err, posts) { + if (err) { + return next(err); + } + start = parseInt(start, 10); + for(var i=0; i Date: Tue, 12 Aug 2014 13:57:30 -0400 Subject: [PATCH 65/90] further fix to #1957 --- public/src/ajaxify.js | 3 +-- src/routes/index.js | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index f2258fb823..06e5731983 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -204,7 +204,6 @@ var ajaxify = ajaxify || {}; } var location = document.location || window.location, - api_url = (url === RELATIVE_PATH || url === '/' + RELATIVE_PATH) ? 'home' : url, tpl_url = ajaxify.getCustomTemplateMapping(url.split('?')[0]); if (!tpl_url) { @@ -212,7 +211,7 @@ var ajaxify = ajaxify || {}; } apiXHR = $.ajax({ - url: RELATIVE_PATH + '/api/' + api_url, + url: RELATIVE_PATH + '/api/' + url, cache: false, success: function(data) { if (!data) { diff --git a/src/routes/index.js b/src/routes/index.js index 9fe56381f4..2df7114838 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -19,6 +19,7 @@ var nconf = require('nconf'), function mainRoutes(app, middleware, controllers) { app.get('/', middleware.buildHeader, controllers.home); + app.get('/api', controllers.home); app.get('/api/home', controllers.home); app.get('/login', middleware.redirectToAccountIfLoggedIn, middleware.buildHeader, controllers.login); From cf6acf6b4117748f1a1a1f69a4ebe330f1af3c21 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 12 Aug 2014 14:02:40 -0400 Subject: [PATCH 66/90] sacrificing a goat to ensure this doesn't come back to bite me --- src/routes/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/index.js b/src/routes/index.js index 2df7114838..e53ebbe275 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -20,7 +20,6 @@ var nconf = require('nconf'), function mainRoutes(app, middleware, controllers) { app.get('/', middleware.buildHeader, controllers.home); app.get('/api', controllers.home); - app.get('/api/home', controllers.home); app.get('/login', middleware.redirectToAccountIfLoggedIn, middleware.buildHeader, controllers.login); app.get('/api/login', middleware.redirectToAccountIfLoggedIn, controllers.login); From 4fa80263b02442b87255179607f7f23b8d8d103a Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 12 Aug 2014 14:15:01 -0400 Subject: [PATCH 67/90] fixed #1981 --- src/middleware/admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/admin.js b/src/middleware/admin.js index d9d36791ce..92ab6de9e2 100644 --- a/src/middleware/admin.js +++ b/src/middleware/admin.js @@ -16,7 +16,7 @@ var app, middleware.isAdmin = function(req, res, next) { if (!req.user) { - return res.redirect('/login?next=admin'); + return res.redirect(nconf.get('relative_path') + '/login?next=admin'); } user.isAdministrator((req.user && req.user.uid) ? req.user.uid : 0, function (err, isAdmin) { From c358ff3d83bf1c1577ed6bbcd256da8183fd3b59 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 12 Aug 2014 14:39:58 -0400 Subject: [PATCH 68/90] fix isSortedSetMembers on mongo --- src/database/mongo/sorted.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/database/mongo/sorted.js b/src/database/mongo/sorted.js index fbcaf3bb08..267446ae7e 100644 --- a/src/database/mongo/sorted.js +++ b/src/database/mongo/sorted.js @@ -151,13 +151,15 @@ module.exports = function(db, module) { if (err) { return callback(err); } + results = results.map(function(item) { return item.value; }); + values = values.map(function(value) { return results.indexOf(value) !== -1; }); - callback(err, results); + callback(null, values); }); }; From b16932a67635af8bcb9f3b7b7a0caadb18e4b6da Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 12 Aug 2014 15:08:42 -0400 Subject: [PATCH 69/90] check mainPid --- src/topics.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/topics.js b/src/topics.js index 926f8bb78b..34fe471163 100644 --- a/src/topics.js +++ b/src/topics.js @@ -262,7 +262,10 @@ var async = require('async'), return next(err); } - pids = [topicData.mainPid].concat(pids); + pids = topicData.mainPid ? [topicData.mainPid].concat(pids) : pids; + if (!pids.length) { + return next(null, []); + } posts.getPostsByPids(pids, tid, function(err, posts) { if (err) { return next(err); From 0847eb2c3de0c03917178980f3afef8cb43a3ae4 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 13 Aug 2014 15:32:31 -0400 Subject: [PATCH 70/90] added uid to filter:header.build --- src/middleware/middleware.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index 7db87f35c2..296a445ca4 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -208,6 +208,7 @@ middleware.renderHeader = function(req, res, callback) { var uid = req.user ? parseInt(req.user.uid, 10) : 0; var custom_header = { + uid: uid, 'navigation': [] }; From b48571ceb8fc052937f0a3d1d92636a7abcac68d Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 13 Aug 2014 16:03:33 -0400 Subject: [PATCH 71/90] fixed #1988 --- src/middleware/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/middleware/index.js b/src/middleware/index.js index 9fbaa0f97a..a90ea6d9a1 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -41,7 +41,7 @@ function routeThemeScreenshots(app, themes) { (function(id, path) { fs.exists(path, function(exists) { if (exists) { - app.get('/css/previews/' + id, function(req, res) { + app.get(relativePath + '/css/previews/' + id, function(req, res) { res.sendfile(path); }); } @@ -173,7 +173,7 @@ module.exports = function(app, data) { if(meta.config.cookieDomain) { cookie.domain = meta.config.cookieDomain; } - + app.use(session({ store: db.sessionStore, secret: nconf.get('secret'), From 1a97302d68357f13ad06552797539268a8b37435 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 13 Aug 2014 16:25:34 -0400 Subject: [PATCH 72/90] fix double anchors around images if the image is already inside an anchor dont wrap again --- public/src/forum/topic.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 3df4a2b1c3..0300d58121 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -351,7 +351,10 @@ define('forum/topic', dependencies, function(pagination, infinitescroll, threadT utils.makeNumbersHumanReadable(element.find('.human-readable-number')); element.find('span.timeago').timeago(); element.find('.post-content img:not(.emoji)').addClass('img-responsive').each(function() { - $(this).wrap(''); + var $this = $(this); + if (!$this.parent().is('a')) { + $this.wrap(''); + } }); postTools.updatePostCount(); showBottomPostBar(); From 544afd4e4c4a4c0b7c153a84ce29ba521992998c Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 13 Aug 2014 16:27:29 -0400 Subject: [PATCH 73/90] importing latest templates.js client-side --- public/src/templates.js | 58 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/public/src/templates.js b/public/src/templates.js index 5cf10aeb4b..fc81b14e29 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -36,7 +36,7 @@ Please use the npm module instead - require('templates.js') } callback(parse(loaded, obj, bind)); - }); + }); } else { callback(parse(templates.cache[template], obj, bind)); } @@ -58,14 +58,15 @@ Please use the npm module instead - require('templates.js') }; templates.getBlock = function(template, block) { - return template.replace(new RegExp('[\\s\\S]*([\r\n]*[\\s\\S]*?[\r\n]*)[\\s\\S]*', 'g'), '$1'); + return template.replace(new RegExp('[\\s\\S]*([\\s\\S]*?)[\\s\\S]*', 'g'), '$1'); }; function express(filename, options, fn) { - console.log(filename, options, fn); var fs = require('fs'), tpl = filename.replace(options.settings.views + '/', ''); + options['_locals'] = null; + if (!templates.cache[tpl]) { fs.readFile(filename, function(err, html) { templates.cache[tpl] = (html || '').toString(); @@ -82,11 +83,11 @@ Please use the npm module instead - require('templates.js') } function makeRegex(block) { - return new RegExp('[\\s\\S]*?'); + return new RegExp('[\\t ]*[\\s\\S]*?'); } function makeBlockRegex(block) { - return new RegExp('([\\n]?[\\n]?)|([\\n]?[\\n]?)', 'g'); + return new RegExp('([\\t ]*[\\r\\n?|\\n]?)|()', 'g'); } function makeConditionalRegex(block) { @@ -94,7 +95,7 @@ Please use the npm module instead - require('templates.js') } function makeStatementRegex(key) { - return new RegExp('([\\s]*)|([\\s]*)', 'gi'); + return new RegExp('([\\s]*)|([\\s]*)', 'g'); } function registerGlobals(obj) { @@ -113,23 +114,23 @@ Please use the npm module instead - require('templates.js') if (matches !== null) { for (var i = 0, ii = matches.length; i < ii; i++) { var statement = makeStatementRegex(key), - nestedConditionals = matches[i].match(/[\s|\S][\s|\S]/), - match = matches[i].replace(statement, '').replace(/[\s|\S][\s|\S]/gi, ''), - conditionalBlock = match.split(/\s*\s*/); + nestedConditionals = matches[i].match(/(?!^)(?!$)/), + match = matches[i].replace(statement, '').replace(/(?!^)/gi, ''), + conditionalBlock = match.split(/[\r\n?\n]*?[\r\n?\n]*?/); if (conditionalBlock[1]) { // there is an else statement - if (!value) { - template = template.replace(matches[i], conditionalBlock[1].replace(/(^[\r\n\t]*)|([\r\n\t]*$)/gi, '')); + if (!value) { // todo check second line break conditional, doesn't match. + template = template.replace(matches[i], conditionalBlock[1].replace(/(^[\r\n?|\n]*)|([\r\n\t]*$)/gi, '')); } else { - template = template.replace(matches[i], conditionalBlock[0].replace(/(^[\r\n\t]*)|([\r\n\t]*$)/gi, '')); + template = template.replace(matches[i], conditionalBlock[0].replace(/(^[\r\n?|\n]*)|([\r\n\t]*$)/gi, '')); } } else { // regular if statement if (!value) { template = template.replace(matches[i], ''); } else { - template = template.replace(matches[i], match.replace(/(^[\r\n\t]*)|([\r\n\t]*$)/gi, '')); + template = template.replace(matches[i], match.replace(/(^[\r\n?|\n]*)|([\r\n\t]*$)/gi, '')); } } @@ -181,40 +182,43 @@ Please use the npm module instead - require('templates.js') var regex = makeRegex(key), block; if (!array[key].length) { - return template; + return template.replace(regex, ''); } while (block = template.match(regex)) { block = block[0].replace(makeBlockRegex(key), ''); - + var numblocks = array[key].length - 1, iterator = 0, result = '', parsedBlock; do { - parsedBlock = parse(block, array[key][iterator], bind, namespace, {iterator: iterator, total: numblocks}) + ((iterator < numblocks) ? '\r\n':''); - + parsedBlock = parse(block, array[key][iterator], bind, namespace, {iterator: iterator, total: numblocks}); + result += (!bind) ? parsedBlock : setBindContainer(parsedBlock, bind + namespace + iterator); - result = parseFunctions(block, result, { - data: array[key][iterator], - iterator: iterator, - numblocks: numblocks - }); result = checkConditional(result, '@first', iterator === 0); result = checkConditional(result, '!@first', iterator !== 0); result = checkConditional(result, '@last', iterator === numblocks); result = checkConditional(result, '!@last', iterator !== numblocks); + result = result.replace(/^[\r\n?|\n|\t]*?|[\r\n?|\n|\t]*?$/g, ''); + + result = parseFunctions(block, result, { + data: array[key][iterator], + iterator: iterator, + numblocks: numblocks + }); + if (bind) { array[key][iterator].__template = block; } } while (iterator++ < numblocks); - template = template.replace(regex, result); + template = template.replace(regex, result.replace(/^[\r\n?|\n]|[\r\n?|\n]$/g, '')); } - + return template; } @@ -248,14 +252,14 @@ Please use the npm module instead - require('templates.js') this['__' + key] = value; var els = document.querySelectorAll('[data-binding="' + (this.__iterator !== false ? (bind + this.__namespace + this.__iterator) : bind) + '"]'); - + for (var el in els) { if (els.hasOwnProperty(el)) { if (this.__parent) { var parent = this.__parent(); els[el].innerHTML = parse(parent.template, parent.data, false); } else { - els[el].innerHTML = parse(this.__template, obj, false, this.__namespace); + els[el].innerHTML = parse(this.__template, obj, false, this.__namespace); } } } @@ -295,7 +299,7 @@ Please use the npm module instead - require('templates.js') template = parse(template, obj[key], bind, namespace + key + '.'); } else { template = parseValue(template, namespace + key, obj[key]); - + if (bind && obj[key]) { setupBindings({ obj: obj, From 5bf9c6db7be075bffe6572b9153c96a35404b3e5 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 13 Aug 2014 16:28:18 -0400 Subject: [PATCH 74/90] closes #1975 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04ee8c12c3..4d819ab281 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.9" + "templates.js": "0.0.10" }, "devDependencies": { "mocha": "~1.13.0" From a2fb4a66b05d8dadaf11fdaf891f9dfeb25303b5 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 13 Aug 2014 16:55:23 -0400 Subject: [PATCH 75/90] migrated ACP themes page from html rendered via js to template engine --- public/src/forum/admin/themes.js | 74 ++++++++++++-------------------- src/meta/themes.js | 9 ++++ 2 files changed, 37 insertions(+), 46 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index c76fea0c9a..6a1b3db477 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -1,5 +1,5 @@ "use strict"; -/*global define, socket, app, bootbox, tabIndent, config, RELATIVE_PATH*/ +/*global define, socket, app, bootbox, tabIndent, config, RELATIVE_PATH, templates */ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { var Themes = {}; @@ -71,17 +71,17 @@ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { if (confirm) { socket.emit('admin.themes.set', { type: 'local', - id: 'nodebb-theme-cerulean' + id: 'nodebb-theme-vanilla' }, function(err) { if (err) { return app.alertError(err.message); } - highlightSelectedTheme('nodebb-theme-cerulean'); + highlightSelectedTheme('nodebb-theme-vanilla'); app.alert({ alert_id: 'admin:theme', type: 'success', title: 'Theme Changed', - message: 'You have successfully reverted your NodeBB back to it\'s default theme. Restarting your NodeBB ', + message: 'You have successfully reverted your NodeBB back to it\'s default theme.', timeout: 3500 }); }); @@ -95,34 +95,19 @@ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { return app.alertError(err.message); } - var instListEl = $('#installed_themes').empty(), liEl; + var instListEl = $('#installed_themes'); if (!themes.length) { instListEl.append($('
  • ').addClass('no-themes').html('No installed themes found')); return; + } else { + templates.parse('partials/admin/theme_list', { + themes: themes + }, function(html) { + instListEl.html(html); + highlightSelectedTheme(config['theme:id']); + }); } - - for (var x = 0, numThemes = themes.length; x < numThemes; x++) { - liEl = $('
  • ').attr({ - 'data-type': 'local', - 'data-theme': themes[x].id - }).html('' + - '' + - '
    '); - - instListEl.append(liEl); - } - - highlightSelectedTheme(config['theme:id']); }); // Proper tabbing for "Custom CSS" field @@ -138,26 +123,23 @@ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { }; Themes.render = function(bootswatch) { - var themeContainer = $('#bootstrap_themes').empty(), - numThemes = bootswatch.themes.length, themeEl, theme; + var themeContainer = $('#bootstrap_themes'); - for (var x = 0; x < numThemes; x++) { - theme = bootswatch.themes[x]; - themeEl = $('
  • ').attr({ - 'data-type': 'bootswatch', - 'data-css': theme.cssCdn, - 'data-theme': theme.name - }).html('' + - '
    ' + - '
    ' + - ' ' + - '
    ' + - '

    ' + theme.name + '

    ' + - '

    ' + theme.description + '

    ' + - '
    ' + - '
    '); - themeContainer.append(themeEl); - } + templates.parse('partials/admin/theme_list', { + themes: bootswatch.themes.map(function(theme) { + return { + type: 'bootswatch', + id: theme.name, + name: theme.name, + description: theme.description, + screenshot_url: theme.thumbnail, + url: theme.preview, + css: theme.cssCdn + }; + }) + }, function(html) { + themeContainer.html(html); + }); }; Themes.prepareWidgets = function() { diff --git a/src/meta/themes.js b/src/meta/themes.js index b26253a495..f41620cc1b 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -39,6 +39,15 @@ module.exports = function(Meta) { return next(); } else { var configObj = JSON.parse(file.toString()); + + // Minor adjustments for API output + configObj.type = 'local'; + if (configObj.screenshot) { + configObj.screenshot_url = nconf.get('relative_path') + '/css/previews/' + configObj.id + } else { + configObj.screenshot_url = nconf.get('relative_path') + '/images/themes/default.png'; + } + next(err, configObj); } }); From dda032296881039d569d85b4a3bf77e6af1cd241 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 13 Aug 2014 18:44:40 -0400 Subject: [PATCH 76/90] getUsersInCategory --- src/socket.io/categories.js | 6 ++++++ src/socket.io/index.js | 25 +++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index dbbb606224..c594361589 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -5,6 +5,7 @@ var async = require('async'), categories = require('../categories'), privileges = require('../privileges'), user = require('../user'), + websockets = require('./index'), SocketCategories = {}; @@ -73,4 +74,9 @@ SocketCategories.lastTopicIndex = function(socket, cid, callback) { db.sortedSetCard('categories:' + cid + ':tid', callback); }; +SocketCategories.getUsersInCategory = function(socket, cid, callback) { + var uids = websockets.getUidsInRoom('category_' + cid); + user.getMultipleUserFields(uids, ['uid', 'userslug', 'username', 'picture'], callback); +}; + module.exports = SocketCategories; diff --git a/src/socket.io/index.js b/src/socket.io/index.js index f0d9ea40e6..64b1ae8f39 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -287,17 +287,6 @@ function updateRoomBrowsingText(roomName) { return; } - function getUidsInRoom() { - var uids = []; - var clients = io.sockets.clients(roomName); - for(var i=0; i Date: Thu, 14 Aug 2014 07:51:21 -0400 Subject: [PATCH 77/90] fix user online status on profile page --- src/socket.io/index.js | 8 ++++---- src/socket.io/user.js | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 64b1ae8f39..3457bd537f 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -93,8 +93,8 @@ Sockets.init = function(server) { uid: uid }); - socketUser.isOnline(socket, [uid], function(err, data) { - socket.broadcast.emit('user.isOnline', err, data[0]); + socketUser.isOnline(socket, uid, function(err, data) { + socket.broadcast.emit('user.isOnline', err, data); }); }); }); @@ -114,8 +114,8 @@ Sockets.init = function(server) { if (uid && Sockets.getUserSockets(uid).length <= 1) { db.sortedSetRemove('users:online', uid, function(err) { - socketUser.isOnline(socket, [uid], function(err, data) { - socket.broadcast.emit('user.isOnline', err, data[0]); + socketUser.isOnline(socket, uid, function(err, data) { + socket.broadcast.emit('user.isOnline', err, data); }); }); } diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 7501c9651b..844c2ac270 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -79,7 +79,9 @@ SocketUser.reset.commit = function(socket, data, callback) { }; SocketUser.isOnline = function(socket, uid, callback) { - user.isOnline(uid, callback); + user.isOnline([uid], function(err, data) { + callback(err, Array.isArray(data) ? data[0] : null); + }); }; SocketUser.changePassword = function(socket, data, callback) { @@ -223,7 +225,7 @@ SocketUser.getOnlineUsers = function(socket, uids, callback) { return callback(new Error('[[error:invalid-data]]')); } - SocketUser.isOnline(socket, uids, function(err, userData) { + user.isOnline(uids, function(err, userData) { if (err) { return callback(err); } @@ -292,9 +294,9 @@ SocketUser.loadMore = function(socket, data, callback) { SocketUser.setStatus = function(socket, status, callback) { var server = require('./index'); user.setUserField(socket.uid, 'status', status, function(err) { - SocketUser.isOnline(socket, [socket.uid], function(err, data) { - server.server.sockets.emit('user.isOnline', err, data[0]); - callback(err, data[0]); + SocketUser.isOnline(socket, socket.uid, function(err, data) { + server.server.sockets.emit('user.isOnline', err, data); + callback(err, data); }); }); }; From 1036ba463662ca7c7b4f11103b3e47195963530a Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 14 Aug 2014 17:46:58 -0400 Subject: [PATCH 78/90] removing timestamp from thread hooks... completely pointless --- src/threadTools.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/threadTools.js b/src/threadTools.js index 5e52d043c7..601ffc88ae 100644 --- a/src/threadTools.js +++ b/src/threadTools.js @@ -120,8 +120,7 @@ var winston = require('winston'), plugins.fireHook('action:topic.lock', { tid: tid, isLocked: lock, - uid: uid, - timestamp: Date.now() + uid: uid }); emitTo('topic_' + tid); @@ -165,8 +164,7 @@ var winston = require('winston'), plugins.fireHook('action:topic.pin', { tid: tid, isPinned: pin, - uid: uid, - timestamp: Date.now() + uid: uid }); emitTo('topic_' + tid); @@ -214,8 +212,7 @@ var winston = require('winston'), tid: tid, fromCid: oldCid, toCid: cid, - uid: uid, - timestamp: Date.now() + uid: uid }); }); }; From 0c17ee15f74dc548b61903e9f2cd0dbcecf05cd1 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 14 Aug 2014 17:52:17 -0400 Subject: [PATCH 79/90] action:user.follow and action:user.unfollow --- src/socket.io/user.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 844c2ac270..04a37313db 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -5,6 +5,7 @@ var async = require('async'), groups = require('../groups'), topics = require('../topics'), messaging = require('../messaging'), + plugins = require('../plugins'), utils = require('./../../public/src/utils'), meta = require('../meta'), SocketUser = {}; @@ -161,12 +162,22 @@ SocketUser.changePicture = function(socket, data, callback) { SocketUser.follow = function(socket, data, callback) { if (socket.uid && data) { + plugins.fireHook('action:user.follow', { + fromUid: socket.uid, + toUid: data.uid + }); + user.follow(socket.uid, data.uid, callback); } }; SocketUser.unfollow = function(socket, data, callback) { if (socket.uid && data) { + plugins.fireHook('action:user.unfollow', { + fromUid: socket.uid, + toUid: data.uid + }); + user.unfollow(socket.uid, data.uid, callback); } }; From b50b5e4787c988fed89b018d10064279311fffe7 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 14 Aug 2014 17:59:33 -0400 Subject: [PATCH 80/90] satifying my OCD fire hook after successful follow/unfollow --- src/socket.io/user.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 04a37313db..5597a03b3a 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -162,26 +162,29 @@ SocketUser.changePicture = function(socket, data, callback) { SocketUser.follow = function(socket, data, callback) { if (socket.uid && data) { - plugins.fireHook('action:user.follow', { - fromUid: socket.uid, - toUid: data.uid - }); - - user.follow(socket.uid, data.uid, callback); + toggleFollow('follow', socket.uid, data.uid, callback); } }; SocketUser.unfollow = function(socket, data, callback) { if (socket.uid && data) { - plugins.fireHook('action:user.unfollow', { - fromUid: socket.uid, - toUid: data.uid - }); - - user.unfollow(socket.uid, data.uid, callback); + toggleFollow('unfollow', socket.uid, data.uid, callback); } }; +function toggleFollow(method, uid, theiruid, callback) { + user[method](uid, theiruid, function(err) { + if (err) { + return callback(err); + } + + plugins.fireHook('action:user.' + method, { + fromUid: uid, + toUid: theiruid + }); + }); +} + SocketUser.getSettings = function(socket, data, callback) { if (socket.uid) { if (socket.uid === parseInt(data.uid, 10)) { From e097ac1fa7c7b5bdaa4edb63e6e14e3ca27c69a3 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 15 Aug 2014 17:26:49 -0400 Subject: [PATCH 81/90] latest templates.js --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d819ab281..9a9d9ba20f 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.10" + "templates.js": "0.0.12" }, "devDependencies": { "mocha": "~1.13.0" From a9ca035e1e3d54fc457569196116871bfc8c3ba5 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 15 Aug 2014 18:15:10 -0400 Subject: [PATCH 82/90] gotto check read after each pass --- src/topics/unread.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/topics/unread.js b/src/topics/unread.js index 2754fa9a88..871d2043e7 100644 --- a/src/topics/unread.js +++ b/src/topics/unread.js @@ -49,19 +49,21 @@ module.exports = function(Topics) { return !read[index]; }); - unreadTids.push.apply(unreadTids, newtids); + privileges.topics.filter('read', newtids, uid, function(err, newtids) { + if (err) { + return next(err); + } + unreadTids.push.apply(unreadTids, newtids); - start = stop + 1; - stop = start + 19; + start = stop + 1; + stop = start + 19; - next(); + next(); + }); }); }); }, function(err) { - if (err) { - return callback(err); - } - privileges.topics.filter('read', unreadTids, uid, callback); + callback(err, unreadTids); }); }; From 02889f2e705deef6ba67cdaf211504509983272a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sun, 17 Aug 2014 01:29:20 -0400 Subject: [PATCH 83/90] call callback on follow/unfollow --- src/socket.io/user.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 5597a03b3a..0f5e87c84e 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -182,6 +182,7 @@ function toggleFollow(method, uid, theiruid, callback) { fromUid: uid, toUid: theiruid }); + callback(); }); } From 01f5acea9bc2e0cc54550d64f892ff485370b30f Mon Sep 17 00:00:00 2001 From: nchase Date: Sun, 17 Aug 2014 23:34:08 -0400 Subject: [PATCH 84/90] fix link to travis-ci build in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 485922d449..b08b6c3a84 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # NodeBB -[![Build Status](https://travis-ci.org/NodeBB/NodeBB.svg?branch=master)](https://travis-ci.org/nodebb/nodebb) +[![Build Status](https://travis-ci.org/NodeBB/NodeBB.svg?branch=master)](https://travis-ci.org/NodeBB/NodeBB) [![Dependency Status](https://david-dm.org/nodebb/nodebb.svg)](https://david-dm.org/nodebb/nodebb) [![Code Climate](https://codeclimate.com/github/designcreateplay/NodeBB.png)](https://codeclimate.com/github/designcreateplay/NodeBB) From 4dd32e1024f35b4e9fed5bf55ab33a1b62542d26 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 18 Aug 2014 13:05:13 -0400 Subject: [PATCH 85/90] filter:category.get applies to all category-like API calls now @a5mith https://gist.github.com/psychobunny/572d867935469774c6e8#comment-1281883 --- src/controllers/categories.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/controllers/categories.js b/src/controllers/categories.js index 506747f741..d11567c4de 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -8,7 +8,8 @@ var categoriesController = {}, user = require('./../user'), categories = require('./../categories'), topics = require('./../topics'), - meta = require('./../meta'); + meta = require('./../meta'), + plugins = require('./../plugins'); categoriesController.recent = function(req, res, next) { var uid = req.user ? req.user.uid : 0; @@ -19,7 +20,9 @@ categoriesController.recent = function(req, res, next) { data['feeds:disableRSS'] = meta.config['feeds:disableRSS'] === '1' ? true : false; - res.render('recent', data); + plugins.fireHook('filter:category.get', data, uid, function(err, data) { + res.render('recent', data); + }); }); }; @@ -35,7 +38,9 @@ categoriesController.popular = function(req, res, next) { data['feeds:disableRSS'] = meta.config['feeds:disableRSS'] === '1' ? true : false; - res.render('popular', {topics: data}); + plugins.fireHook('filter:category.get', {topics: data}, uid, function(err, data) { + res.render('popular', data); + }); }); }; @@ -47,7 +52,9 @@ categoriesController.unread = function(req, res, next) { return next(err); } - res.render('unread', data); + plugins.fireHook('filter:category.get', data, uid, function(err, data) { + res.render('unread', data); + }); }); }; From 74e552449271b2665e2dcfc2fa64bc137dce1a32 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 18 Aug 2014 13:44:27 -0400 Subject: [PATCH 86/90] fixing request to /api not returning api result --- src/routes/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/index.js b/src/routes/index.js index e53ebbe275..e843175098 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -160,7 +160,7 @@ module.exports = function(app, middleware) { app.render.apply(app, arguments); }; - app.all(relativePath + '/api/*', middleware.updateLastOnlineTime, middleware.prepareAPI); + app.all(relativePath + '/api/?*', middleware.updateLastOnlineTime, middleware.prepareAPI); app.all(relativePath + '/api/admin/*', middleware.admin.isAdmin, middleware.prepareAPI); app.all(relativePath + '/admin/*', middleware.admin.isAdmin); app.get(relativePath + '/admin', middleware.admin.isAdmin); @@ -247,4 +247,4 @@ function catch404(req, res, next) { } else { res.type('txt').send('Not found'); } -} \ No newline at end of file +} From 6d580df8b1e48a0b4be90df0f2433807b2b5a728 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 19 Aug 2014 13:28:48 -0400 Subject: [PATCH 87/90] temporarily dropping templates.js to 0.0.8, closes #2001 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2716eb6888..9c596d0b3d 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.12" + "templates.js": "0.0.8" }, "devDependencies": { "mocha": "~1.13.0" From eed57603eff455960185c00a9d83be3e800e5421 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 19 Aug 2014 13:29:27 -0400 Subject: [PATCH 88/90] templates.js 0.0.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c596d0b3d..ad5ae44b90 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.8" + "templates.js": "0.0.10" }, "devDependencies": { "mocha": "~1.13.0" From 91e29d7bb21ea00bbd563b2f4edabdc961d3c476 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 20 Aug 2014 14:08:14 -0400 Subject: [PATCH 89/90] updated latest templates.js --- package.json | 2 +- public/src/templates.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ad5ae44b90..01592c9035 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.10" + "templates.js": "0.0.13" }, "devDependencies": { "mocha": "~1.13.0" diff --git a/public/src/templates.js b/public/src/templates.js index fc81b14e29..b629b03d0b 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -95,7 +95,7 @@ Please use the npm module instead - require('templates.js') } function makeStatementRegex(key) { - return new RegExp('([\\s]*)|([\\s]*)', 'g'); + return new RegExp('()|()', 'g'); } function registerGlobals(obj) { @@ -114,8 +114,8 @@ Please use the npm module instead - require('templates.js') if (matches !== null) { for (var i = 0, ii = matches.length; i < ii; i++) { var statement = makeStatementRegex(key), - nestedConditionals = matches[i].match(/(?!^)(?!$)/), - match = matches[i].replace(statement, '').replace(/(?!^)/gi, ''), + nestedConditionals = matches[i].match(/(?!^)(?!$)/gi), + match = matches[i].replace(statement, '').replace(/(?!^)(?!$)/gi, ''), conditionalBlock = match.split(/[\r\n?\n]*?[\r\n?\n]*?/); if (conditionalBlock[1]) { From 2ced285f89db44f243ce40285f34625b6ec28204 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 20 Aug 2014 14:21:23 -0400 Subject: [PATCH 90/90] closes #2004 --- public/src/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/app.js b/public/src/app.js index d84d89e99a..64e5e3e15c 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -413,8 +413,8 @@ var socket, if (utils.findBootstrapEnvironment() === 'xs') { return; } - $('#header-menu li i[title]').each(function() { - $(this).parents('a').tooltip({ + $('#header-menu li [title]').each(function() { + $(this).tooltip({ placement: 'bottom', title: $(this).attr('title') });