From 2669241c06be9c42f78ddf025efd68ab743b2f8e Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 10:26:10 -0400 Subject: [PATCH 01/32] closes #3656 --- package.json | 1 - public/language/en_GB/user.json | 1 + public/src/client/register.js | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c18d6468e..01abacedc3 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "express-session": "^1.8.2", "gravatar": "^1.1.0", "heapdump": "^0.3.0", - "jimp": "^0.2.5", "less": "^2.0.0", "logrotate-stream": "^0.2.3", "lru-cache": "^2.6.1", diff --git a/public/language/en_GB/user.json b/public/language/en_GB/user.json index 9a019791be..083e887a24 100644 --- a/public/language/en_GB/user.json +++ b/public/language/en_GB/user.json @@ -54,6 +54,7 @@ "confirm_password": "Confirm Password", "password": "Password", "username_taken_workaround": "The username you requested was already taken, so we have altered it slightly. You are now known as %1", + "password_same_as_username": "Your password is the same as your username, please select another password.", "upload_picture": "Upload picture", "upload_a_picture": "Upload a picture", diff --git a/public/src/client/register.js b/public/src/client/register.js index cca8617972..25d76a73fe 100644 --- a/public/src/client/register.js +++ b/public/src/client/register.js @@ -176,6 +176,8 @@ define('forum/register', ['csrf', 'translator'], function(csrf, translator) { showError(password_notify, '[[user:change_password_error_length]]'); } else if (!utils.isPasswordValid(password)) { showError(password_notify, '[[user:change_password_error]]'); + } else if (password === $('#username').val()) { + showError(password_notify, '[[user:password_same_as_username]]'); } else { showSuccess(password_notify, successIcon); } From 67c3f106fb2051b357b7a7b9d067645533fa2d94 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 10:29:15 -0400 Subject: [PATCH 02/32] tx for windows .gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 82ed213c66..e8fc8d5a13 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,7 @@ pidfile ## File-based project format: *.ipr -*.iws \ No newline at end of file +*.iws + +## Transifex for Windows +tx.exe \ No newline at end of file From be28d7db987fc7427c47de7d2222ca27b3f5bc81 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 10:30:23 -0400 Subject: [PATCH 03/32] changing bookmark alert to be more accurate to what it actually does --- public/language/en_GB/topic.json | 2 +- public/language/en_US/topic.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index eab097418b..a03ec807de 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -29,7 +29,7 @@ "flag": "Flag", "locked": "Locked", - "bookmark_instructions" : "Click here to return to your last position or close to discard.", + "bookmark_instructions" : "Click here to return to the last unread post in this thread.", "flag_title": "Flag this post for moderation", "flag_confirm": "Are you sure you want to flag this post?", diff --git a/public/language/en_US/topic.json b/public/language/en_US/topic.json index d9742f2eda..447376322b 100644 --- a/public/language/en_US/topic.json +++ b/public/language/en_US/topic.json @@ -25,7 +25,7 @@ "tools": "Tools", "flag": "Flag", "locked": "Locked", - "bookmark_instructions": "Click here to return to your last position or close to discard.", + "bookmark_instructions" : "Click here to return to the last unread post in this thread.", "flag_title": "Flag this post for moderation", "flag_confirm": "Are you sure you want to flag this post?", "flag_success": "This post has been flagged for moderation.", From bde6bc67b40e1968cee1697b0d9770f009b9e439 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 10:33:41 -0400 Subject: [PATCH 04/32] .transifexrc --- .gitignore | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e8fc8d5a13..783b71a23c 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,6 @@ pidfile *.ipr *.iws -## Transifex for Windows -tx.exe \ No newline at end of file +## Transifex +tx.exe +.transifexrc \ No newline at end of file From 5da445be859e427fac15f641ed469e757e4d2695 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 11:53:18 -0400 Subject: [PATCH 05/32] re-adding back jimp --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 01abacedc3..0c18d6468e 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "express-session": "^1.8.2", "gravatar": "^1.1.0", "heapdump": "^0.3.0", + "jimp": "^0.2.5", "less": "^2.0.0", "logrotate-stream": "^0.2.3", "lru-cache": "^2.6.1", From a80a21ea97f7f631c3a38cdbc3e70549dec9f93e Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 12:14:17 -0400 Subject: [PATCH 06/32] closes #3570 making a PR to our own repo ftw.... testing cla-assistant --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d6d64a04a9..5098d7d39a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ First of all, thank you! Please consider this [style guide](https://docs.nodebb. ## Contributor License Agreement -Thank you for considering contributing to NodeBB. **Before we can accept any pull requests, please take a moment to read and sign our [license agreement](https://www.clahub.com/agreements/NodeBB/NodeBB)**. In summary, signing this document means that 1) you own the code that you are contributing and 2) you give permission to NodeBB Inc. to license the code to others. This agreement applies to any repository under the NodeBB organization. +Thank you for considering contributing to NodeBB. **Before you are able to submit a pull request, please take a moment to read our [contributor license agreement](https://gist.github.com/psychobunny/65946d7aa8854b12fab9)** and agree to it on the pull request page on GitHub. In summary, signing this document means that 1) you own the code that you are contributing and 2) you give permission to NodeBB Inc. to license the code to others. This agreement applies to any repository under the NodeBB organization. If you are writing contributions as part of employment from another company / individual, then your employer will need to sign a separate agreement. Please [contact us](mailto:accounts@nodebb.org) so that we can send this additional agreement to your employer. From e9d3f4278dbb02bbd7432b9b85d8bda66ef35666 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 15:21:20 -0400 Subject: [PATCH 07/32] IS improvements * simplify calculation (scrollTop vs elementInView) * use post anchor rather than create big $ objs from post html * pressing f5 repeatedly now always takes you to the correct pid --- public/src/client/topic.js | 37 +++++++++++---------------------- public/src/modules/navigator.js | 33 +++++++---------------------- 2 files changed, 20 insertions(+), 50 deletions(-) diff --git a/public/src/client/topic.js b/public/src/client/topic.js index d85b079632..2ea69a9dfd 100644 --- a/public/src/client/topic.js +++ b/public/src/client/topic.js @@ -61,7 +61,7 @@ define('forum/topic', [ handleKeys(); - navigator.init('[component="post"]', ajaxify.data.postcount, Topic.toTop, Topic.toBottom, Topic.navigatorCallback, Topic.calculateIndex); + navigator.init('[component="post/anchor"]', ajaxify.data.postcount, Topic.toTop, Topic.toBottom, Topic.navigatorCallback, Topic.calculateIndex); $(window).on('scroll', updateTopicTitle); @@ -219,43 +219,30 @@ define('forum/topic', [ return index; }; - Topic.navigatorCallback = function(topPostIndex, bottomPostIndex, elementCount) { + Topic.navigatorCallback = function(index, elementCount) { var path = ajaxify.removeRelativePath(window.location.pathname.slice(1)); if (!path.startsWith('topic')) { return 1; } - var postIndex = topPostIndex; - var index = bottomPostIndex; - if (config.topicPostSort !== 'oldest_to_newest') { - if (bottomPostIndex === 0) { - index = 1; - } else { - index = Math.max(elementCount - bottomPostIndex + 2, 1); - } - } var bookmarkKey = 'topic:' + ajaxify.data.tid + ':bookmark'; var currentBookmark = ajaxify.data.bookmark || localStorage.getItem(bookmarkKey); - if (!currentBookmark || parseInt(postIndex, 10) > parseInt(currentBookmark, 10)) { + if (!currentBookmark || parseInt(index, 10) > parseInt(currentBookmark, 10)) { if (app.user.uid) { - var payload = { + socket.emit('topics.bookmark', { 'tid': ajaxify.data.tid, - 'index': postIndex - }; - socket.emit('topics.bookmark', payload, function(err) { - if (err) { - console.warn('Error saving bookmark:', err); - } - ajaxify.data.bookmark = postIndex; + 'index': index + }, function(err) { + ajaxify.data.bookmark = index; }); } else { - localStorage.setItem(bookmarkKey, postIndex); + localStorage.setItem(bookmarkKey, index); } } // removes the bookmark alert when we get to / past the bookmark - if (!currentBookmark || parseInt(postIndex, 10) >= parseInt(currentBookmark, 10)) { + if (!currentBookmark || parseInt(index, 10) >= parseInt(currentBookmark, 10)) { app.removeAlert('bookmark'); } @@ -264,14 +251,15 @@ define('forum/topic', [ var topicId = parts[1], slug = parts[2]; var newUrl = 'topic/' + topicId + '/' + (slug ? slug : ''); - if (postIndex > 1) { - newUrl += '/' + postIndex; + if (index > 1) { + newUrl += '/' + index; } if (newUrl !== currentUrl) { if (Topic.replaceURLTimeout) { clearTimeout(Topic.replaceURLTimeout); } + Topic.replaceURLTimeout = setTimeout(function() { Topic.replaceURLTimeout = 0; if (history.replaceState) { @@ -284,7 +272,6 @@ define('forum/topic', [ }, 500); } } - return index; }; diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index 5cc1092f37..174e4838c1 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -90,28 +90,21 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com navigator.update = function() { toggle(!!count); - var topIndex = 0; - var bottomIndex = 0; + var middleOfViewport = $(window).scrollTop() + $(window).height() / 2; + + index = 0; + $(navigator.selector).each(function() { var el = $(this); - if (elementInView(el)) { - if (!topIndex) { - topIndex = parseInt(el.attr('data-index'), 10) + 1; - } else { - bottomIndex = parseInt(el.attr('data-index'), 10) + 1; - } - } else if (topIndex && bottomIndex) { + index++; + if (el.offset().top > middleOfViewport) { return false; } }); - if (topIndex && !bottomIndex) { - bottomIndex = topIndex; - } - - if (typeof navigator.callback === 'function' && topIndex && bottomIndex) { - index = navigator.callback(topIndex, bottomIndex, count); + if (typeof navigator.callback === 'function') { + navigator.callback(index, count); navigator.updateTextAndProgressBar(); } }; @@ -155,16 +148,6 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com } }; - function elementInView(el) { - var scrollTop = $(window).scrollTop() + $('#header-menu').height(); - var scrollBottom = scrollTop + $(window).height(); - - var elTop = el.offset().top; - var elBottom = elTop + Math.floor(el.height()); - - return (elTop >= scrollTop && elBottom < scrollBottom) || (elTop < scrollTop && elBottom > scrollTop); - } - navigator.scrollToPost = function(postIndex, highlight, duration, offset) { if (!utils.isNumber(postIndex) || !components.get('topic').length) { return; From c72bb549573db9cf1456683858564cceca849f13 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 15:51:49 -0400 Subject: [PATCH 08/32] upping themes --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 0c18d6468e..a1fc7f6d67 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,9 @@ "nodebb-plugin-soundpack-default": "0.1.4", "nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-rewards-essentials": "0.0.5", - "nodebb-theme-lavender": "2.0.4", - "nodebb-theme-persona": "3.0.23", - "nodebb-theme-vanilla": "4.0.15", + "nodebb-theme-lavender": "2.0.5", + "nodebb-theme-persona": "3.0.24", + "nodebb-theme-vanilla": "4.0.16", "nodebb-widget-essentials": "2.0.1", "npm": "^2.1.4", "passport": "^0.3.0", From e7f87f4ffd8c188fe94204da0e710474463d4bbb Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 28 Sep 2015 16:09:33 -0400 Subject: [PATCH 09/32] closes #3686 --- public/src/admin/manage/categories.js | 10 ++-- src/categories/update.js | 73 +++++++++++++++------------ src/database/mongo/hash.js | 2 +- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/public/src/admin/manage/categories.js b/public/src/admin/manage/categories.js index c3e1dacab0..2d1cf08d5e 100644 --- a/public/src/admin/manage/categories.js +++ b/public/src/admin/manage/categories.js @@ -94,19 +94,18 @@ define('admin/manage/categories', ['vendor/jquery/serializeObject/jquery.ba-seri } }; - Categories.toggle = function(cid, state) { + Categories.toggle = function(cid, disabled) { var payload = {}; payload[cid] = { - disabled: !state | 0 + disabled: disabled ? 1 : 0 }; socket.emit('admin.categories.update', payload, function(err, result) { if (err) { return app.alertError(err.message); - } else { - ajaxify.refresh(); } + ajaxify.refresh(); }); }; @@ -114,8 +113,9 @@ define('admin/manage/categories', ['vendor/jquery/serializeObject/jquery.ba-seri newCategoryId = e.to.dataset.cid; } - function itemDragDidEnd(e){ + function itemDragDidEnd(e) { var isCategoryUpdate = (newCategoryId != -1); + //Update needed? if((e.newIndex != undefined && e.oldIndex != e.newIndex) || isCategoryUpdate){ var parentCategory = isCategoryUpdate ? sortables[newCategoryId] : sortables[e.from.dataset.cid], diff --git a/src/categories/update.js b/src/categories/update.js index 9ad8acf61e..4ebfda2f11 100644 --- a/src/categories/update.js +++ b/src/categories/update.js @@ -10,45 +10,52 @@ module.exports = function(Categories) { Categories.update = function(modified, callback) { - function updateCategory(cid, next) { - Categories.exists(cid, function(err, exists) { - if (err || !exists) { - return next(err); - } - - var modifiedFields = modified[cid]; - - if (modifiedFields.hasOwnProperty('name')) { - modifiedFields.slug = cid + '/' + utils.slugify(modifiedFields.name); - } - - plugins.fireHook('filter:category.update', {category: modifiedFields}, function(err, categoryData) { - if (err) { - return next(err); - } - - var category = categoryData.category; - var fields = Object.keys(category); - async.each(fields, function(key, next) { - updateCategoryField(cid, key, category[key], next); - }, function(err) { - if (err) { - return next(err); - } - plugins.fireHook('action:category.update', {cid: cid, modified: category}); - next(); - }); - }); - }); - } - var cids = Object.keys(modified); - async.each(cids, updateCategory, function(err) { + async.each(cids, function(cid, next) { + updateCategory(cid, modified[cid], next); + }, function(err) { callback(err, cids); }); }; + function updateCategory(cid, modifiedFields, callback) { + Categories.exists(cid, function(err, exists) { + if (err || !exists) { + return callback(err); + } + + + if (modifiedFields.hasOwnProperty('name')) { + modifiedFields.slug = cid + '/' + utils.slugify(modifiedFields.name); + } + + plugins.fireHook('filter:category.update', {category: modifiedFields}, function(err, categoryData) { + if (err) { + return callback(err); + } + + var category = categoryData.category; + var fields = Object.keys(category); + // move parent to front, so its updated first + var parentCidIndex = fields.indexOf('parentCid'); + if (parentCidIndex !== -1 && fields.length > 1) { + fields.splice(0, 0, fields.splice(parentCidIndex, 1)[0]); + } + + async.eachSeries(fields, function(key, next) { + updateCategoryField(cid, key, category[key], next); + }, function(err) { + if (err) { + return callback(err); + } + plugins.fireHook('action:category.update', {cid: cid, modified: category}); + callback(); + }); + }); + }); + } + function updateCategoryField(cid, key, value, callback) { if (key === 'parentCid') { return updateParent(cid, value, callback); diff --git a/src/database/mongo/hash.js b/src/database/mongo/hash.js index 8a833699f9..fe80afaaf4 100644 --- a/src/database/mongo/hash.js +++ b/src/database/mongo/hash.js @@ -68,7 +68,7 @@ module.exports = function(db, module) { return callback(err, null); } - callback(null, item[field] || null); + callback(null, item.hasOwnProperty(field) ? item[field] : null); }); }; From bcd8bdf0df55164fd70750282a4d8ad796510efb Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 28 Sep 2015 16:59:24 -0400 Subject: [PATCH 10/32] closes #3687 --- public/less/admin/manage/categories.less | 7 +++++++ public/src/admin/manage/categories.js | 4 +--- src/views/admin/partials/categories/category-rows.tpl | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/public/less/admin/manage/categories.less b/public/less/admin/manage/categories.less index 9b1e1fec3f..b9be869550 100644 --- a/public/less/admin/manage/categories.less +++ b/public/less/admin/manage/categories.less @@ -82,4 +82,11 @@ div.categories { .description { margin: 0; } + + .children-placeholder{ + border: 1px dashed #ddd; + min-height: 20px; + height: 20px; + } + } \ No newline at end of file diff --git a/public/src/admin/manage/categories.js b/public/src/admin/manage/categories.js index 2d1cf08d5e..1d346ccd8a 100644 --- a/public/src/admin/manage/categories.js +++ b/public/src/admin/manage/categories.js @@ -153,9 +153,7 @@ define('admin/manage/categories', ['vendor/jquery/serializeObject/jquery.ba-seri // Handle and children categories in this level have for(var x=0,numCategories=categories.length;x 0) { - renderList(categories[x].children, $('li[data-cid="' + categories[x].cid + '"]'), categories[x].cid); - } + renderList(categories[x].children, $('li[data-cid="' + categories[x].cid + '"]'), categories[x].cid); } // Make list sortable diff --git a/src/views/admin/partials/categories/category-rows.tpl b/src/views/admin/partials/categories/category-rows.tpl index 273d7e31b5..715427c34e 100644 --- a/src/views/admin/partials/categories/category-rows.tpl +++ b/src/views/admin/partials/categories/category-rows.tpl @@ -26,4 +26,7 @@ + +
  • + \ No newline at end of file From 9d0f681ebc0dc93fd5917cc7ecd0ab061196cd70 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 28 Sep 2015 17:01:36 -0400 Subject: [PATCH 11/32] fix component name --- public/src/client/topic/posts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index e13fc1a18c..d65f6c0407 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -152,7 +152,7 @@ define('forum/topic/posts', [ components.get('topic').append(html); } - infinitescroll.removeExtra(components.get('posts'), direction, 40); + infinitescroll.removeExtra(components.get('post'), direction, 40); html.hide().fadeIn('slow'); From 028a520bf05a3f20de72c1133ca26c207d97d554 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 17:05:50 -0400 Subject: [PATCH 12/32] remove hardcoded fadein --- public/src/client/topic/posts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index d65f6c0407..e19e1f9fa4 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -154,8 +154,6 @@ define('forum/topic/posts', [ infinitescroll.removeExtra(components.get('post'), direction, 40); - html.hide().fadeIn('slow'); - var pids = []; for(var i=0; i Date: Mon, 28 Sep 2015 17:17:47 -0400 Subject: [PATCH 13/32] fixed f5 from in the middle of a big topic --- public/src/modules/navigator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index 174e4838c1..78d17af053 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -92,7 +92,7 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com var middleOfViewport = $(window).scrollTop() + $(window).height() / 2; - index = 0; + index = parseInt($(navigator.selector).first().attr('data-index'), 10); $(navigator.selector).each(function() { var el = $(this); From 81b3ae2597897fbceb768dd55a8f44c4d30d7326 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 28 Sep 2015 17:20:55 -0400 Subject: [PATCH 14/32] cleanup --- public/src/modules/navigator.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index 78d17af053..078e562e67 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -95,18 +95,17 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com index = parseInt($(navigator.selector).first().attr('data-index'), 10); $(navigator.selector).each(function() { - var el = $(this); - index++; - if (el.offset().top > middleOfViewport) { + if ($(this).offset().top > middleOfViewport) { return false; } }); if (typeof navigator.callback === 'function') { navigator.callback(index, count); - navigator.updateTextAndProgressBar(); } + + navigator.updateTextAndProgressBar(); }; navigator.updateTextAndProgressBar = function() { From 09d23c3dd0332a5d8b5c05c364c221ad7f779ba1 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 29 Sep 2015 11:03:29 -0400 Subject: [PATCH 15/32] Added support for a theme to generate a link back to a parent post --- public/src/client/topic.js | 7 +++++++ src/topics/posts.js | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/public/src/client/topic.js b/public/src/client/topic.js index 2ea69a9dfd..18402c1f58 100644 --- a/public/src/client/topic.js +++ b/public/src/client/topic.js @@ -57,6 +57,8 @@ define('forum/topic', [ addBlockQuoteHandler(); + addParentHandler(); + handleBookmark(tid); handleKeys(); @@ -191,6 +193,11 @@ define('forum/topic', [ }); } + function addParentHandler() { + components.get('topic').on('click', '[component="post/parent"]', function() { + navigator.scrollToPost(parseInt(this.getAttribute('data-index'), 10), true); + }); + } function enableInfiniteLoadingOrPagination() { if (!config.usePagination) { diff --git a/src/topics/posts.js b/src/topics/posts.js index bf1e51ac4d..573c8b6ca8 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -112,6 +112,45 @@ module.exports = function(Topics) { }, privileges: function(next) { privileges.posts.get(pids, uid, next); + }, + parents: function(next) { + var parentPids = postData.map(function(postObj) { + return postObj.hasOwnProperty('toPid') ? parseInt(postObj.toPid, 10) : null + }).filter(Boolean), + parentUids; + + if (parentPids) { + async.waterfall([ + async.apply(posts.getPostsFields, parentPids, ['pid', 'tid', 'uid']), + function(postsArr, next) { + // To use Posts.getUserInfoForPosts would be overkill here... + parentUids = postsArr.map(function(postObj) { return parseInt(postObj.uid, 10); }).filter(function(uid, idx, users) { + return users.indexOf(uid) === idx; + }); + + user.getMultipleUserFields(parentUids, ['username'], function(err, userDataArr) { + var userData = {}; + userDataArr.forEach(function(user) { + userData[user.uid] = user; + }); + next(err, postsArr, userData); + }); + }, + function(postsArr, userData, next) { + var returnData = {}; + posts.getPostIndices(postsArr, uid, function(err, indices) { + postsArr.forEach(function(post, idx) { + var pid = parseInt(post.pid, 10); + returnData[pid] = _.clone(userData[parseInt(post.uid, 10)]); + returnData[pid].index = indices[idx]+0; + }); + next(err, returnData); + }); + } + ], next); + } else { + next(); + } } }, function(err, results) { if (err) { @@ -130,6 +169,7 @@ module.exports = function(Topics) { postObj.display_moderator_tools = results.privileges[i].editable; postObj.display_move_tools = results.privileges[i].move && postObj.index !== 0; postObj.selfPost = parseInt(uid, 10) === parseInt(postObj.uid, 10); + postObj.parent = results.parents[parseInt(postObj.toPid, 10)]; if(postObj.deleted && !results.privileges[i].view_deleted) { postObj.content = '[[topic:post_is_deleted]]'; From e400bb5a5250b5bd787ca335f344a00d9eea2670 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 29 Sep 2015 11:05:23 -0400 Subject: [PATCH 16/32] updated theme minver --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1fc7f6d67..476fb9ac97 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-rewards-essentials": "0.0.5", "nodebb-theme-lavender": "2.0.5", - "nodebb-theme-persona": "3.0.24", + "nodebb-theme-persona": "3.0.25", "nodebb-theme-vanilla": "4.0.16", "nodebb-widget-essentials": "2.0.1", "npm": "^2.1.4", From 018af5fa229e421322a056ddf10b4300d73f5a43 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 29 Sep 2015 11:15:08 -0400 Subject: [PATCH 17/32] accidentally used deprecated method, heh --- src/topics/posts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/topics/posts.js b/src/topics/posts.js index 573c8b6ca8..ba2a5eba13 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -128,7 +128,7 @@ module.exports = function(Topics) { return users.indexOf(uid) === idx; }); - user.getMultipleUserFields(parentUids, ['username'], function(err, userDataArr) { + user.getUsersFields(parentUids, ['username'], function(err, userDataArr) { var userData = {}; userDataArr.forEach(function(user) { userData[user.uid] = user; From 94d4e5eeebc301af3786ba7319eea0df8d242908 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 13:19:14 -0400 Subject: [PATCH 18/32] up widget essentials --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1fc7f6d67..138c337b0e 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "nodebb-theme-lavender": "2.0.5", "nodebb-theme-persona": "3.0.24", "nodebb-theme-vanilla": "4.0.16", - "nodebb-widget-essentials": "2.0.1", + "nodebb-widget-essentials": "2.0.2", "npm": "^2.1.4", "passport": "^0.3.0", "passport-local": "1.0.0", From b7ce4312a93c9c4a672b95be8aa339277dda6b29 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 14:35:28 -0400 Subject: [PATCH 19/32] show toPid inline --- public/src/client/topic.js | 16 +++++++++- src/socket.io/posts.js | 23 ++++++++++++++ src/topics/posts.js | 62 +++++++++++++++++--------------------- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/public/src/client/topic.js b/public/src/client/topic.js index 18402c1f58..9d8e878477 100644 --- a/public/src/client/topic.js +++ b/public/src/client/topic.js @@ -195,7 +195,21 @@ define('forum/topic', [ function addParentHandler() { components.get('topic').on('click', '[component="post/parent"]', function() { - navigator.scrollToPost(parseInt(this.getAttribute('data-index'), 10), true); + var toPid = $(this).attr('data-topid'); + var content = $(this).parents('[component="post"]').find('[component="post/parent/content"]'); + if (!content.hasClass('hidden')) { + return content.addClass('hidden'); + } else if (content.html().length) { + return content.removeClass('hidden'); + } + + socket.emit('posts.getPost', toPid, function(err, post) { + if (err) { + return app.alertError(err.message); + } + + content.html(post.content).removeClass('hidden'); + }); }); } diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 9e81c09993..c268f133fd 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -145,6 +145,29 @@ SocketPosts.getRawPost = function(socket, pid, callback) { ], callback); }; +SocketPosts.getPost = function(socket, pid, callback) { + async.waterfall([ + function(next) { + privileges.posts.can('read', pid, socket.uid, next); + }, + function(canRead, next) { + if (!canRead) { + return next(new Error('[[error:no-privileges]]')); + } + posts.getPostsByPids([pid], socket.uid, next); + }, + function(postData, next) { + if (!postData.length) { + return next(new Error('[[error:no-post]]')); + } + postData = postData[0]; + if (parseInt(postData.deleted, 10) === 1) { + return next(new Error('[[error:no-post]]')); + } + next(null, postData); + } + ], callback); +} SocketPosts.getPrivileges = function(socket, pids, callback) { privileges.posts.get(pids, socket.uid, function(err, privileges) { diff --git a/src/topics/posts.js b/src/topics/posts.js index ba2a5eba13..60f2dbe8ce 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -115,42 +115,36 @@ module.exports = function(Topics) { }, parents: function(next) { var parentPids = postData.map(function(postObj) { - return postObj.hasOwnProperty('toPid') ? parseInt(postObj.toPid, 10) : null - }).filter(Boolean), - parentUids; + return postObj.hasOwnProperty('toPid') ? parseInt(postObj.toPid, 10) : null; + }).filter(Boolean); + var parentUids; - if (parentPids) { - async.waterfall([ - async.apply(posts.getPostsFields, parentPids, ['pid', 'tid', 'uid']), - function(postsArr, next) { - // To use Posts.getUserInfoForPosts would be overkill here... - parentUids = postsArr.map(function(postObj) { return parseInt(postObj.uid, 10); }).filter(function(uid, idx, users) { - return users.indexOf(uid) === idx; - }); - - user.getUsersFields(parentUids, ['username'], function(err, userDataArr) { - var userData = {}; - userDataArr.forEach(function(user) { - userData[user.uid] = user; - }); - next(err, postsArr, userData); - }); - }, - function(postsArr, userData, next) { - var returnData = {}; - posts.getPostIndices(postsArr, uid, function(err, indices) { - postsArr.forEach(function(post, idx) { - var pid = parseInt(post.pid, 10); - returnData[pid] = _.clone(userData[parseInt(post.uid, 10)]); - returnData[pid].index = indices[idx]+0; - }); - next(err, returnData); - }); - } - ], next); - } else { - next(); + if (!parentPids.length) { + return next(null, []); } + var parentPosts; + async.waterfall([ + async.apply(posts.getPostsFields, parentPids, ['pid', 'uid']), + function(_parentPosts, next) { + parentPosts = _parentPosts; + parentUids = parentPosts.map(function(postObj) { return parseInt(postObj.uid, 10); }).filter(function(uid, idx, users) { + return users.indexOf(uid) === idx; + }); + + user.getUsersFields(parentUids, ['username'], next); + }, + function (userData, next) { + var usersMap = {}; + userData.forEach(function(user) { + usersMap[user.uid] = user.username; + }); + var parents = {}; + parentPosts.forEach(function(post, i) { + parents[parentPids[i]] = {username: usersMap[post.uid]}; + }); + next(null, parents); + } + ], next); } }, function(err, results) { if (err) { From 06acdcda6d0661d105736803fc5c5ee22b06dad2 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 14:37:00 -0400 Subject: [PATCH 20/32] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b383051d5..a3bf2897ee 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-rewards-essentials": "0.0.5", "nodebb-theme-lavender": "2.0.5", - "nodebb-theme-persona": "3.0.25", + "nodebb-theme-persona": "3.0.26", "nodebb-theme-vanilla": "4.0.16", "nodebb-widget-essentials": "2.0.2", "npm": "^2.1.4", From c88362a00f11215fb05336c239c25132d53492f0 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 14:43:58 -0400 Subject: [PATCH 21/32] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3bf2897ee..756af6a8eb 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-rewards-essentials": "0.0.5", "nodebb-theme-lavender": "2.0.5", - "nodebb-theme-persona": "3.0.26", + "nodebb-theme-persona": "3.0.27", "nodebb-theme-vanilla": "4.0.16", "nodebb-widget-essentials": "2.0.2", "npm": "^2.1.4", From 00bc9f51c9f3b7b7bffc2a535d8d77cac9218093 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 15:46:11 -0400 Subject: [PATCH 22/32] dont display post just scroll --- public/src/client/topic.js | 15 ++++++++------- src/socket.io/posts.js | 24 ------------------------ 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/public/src/client/topic.js b/public/src/client/topic.js index 9d8e878477..b8a60ceef3 100644 --- a/public/src/client/topic.js +++ b/public/src/client/topic.js @@ -196,19 +196,20 @@ define('forum/topic', [ function addParentHandler() { components.get('topic').on('click', '[component="post/parent"]', function() { var toPid = $(this).attr('data-topid'); - var content = $(this).parents('[component="post"]').find('[component="post/parent/content"]'); - if (!content.hasClass('hidden')) { - return content.addClass('hidden'); - } else if (content.html().length) { - return content.removeClass('hidden'); + + var toPost = $('[component="post"][data-pid="' + toPid + '"]'); + if (toPost.length) { + return navigator.scrollToPost(toPost.attr('data-index'), true); } - socket.emit('posts.getPost', toPid, function(err, post) { + socket.emit('posts.getPidIndex', {pid: toPid, tid: ajaxify.data.tid, topicPostSort: config.topicPostSort}, function(err, index) { if (err) { return app.alertError(err.message); } - content.html(post.content).removeClass('hidden'); + if (utils.isNumber(index)) { + navigator.scrollToPost(index, true); + } }); }); } diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index c268f133fd..ee2dc44420 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -145,30 +145,6 @@ SocketPosts.getRawPost = function(socket, pid, callback) { ], callback); }; -SocketPosts.getPost = function(socket, pid, callback) { - async.waterfall([ - function(next) { - privileges.posts.can('read', pid, socket.uid, next); - }, - function(canRead, next) { - if (!canRead) { - return next(new Error('[[error:no-privileges]]')); - } - posts.getPostsByPids([pid], socket.uid, next); - }, - function(postData, next) { - if (!postData.length) { - return next(new Error('[[error:no-post]]')); - } - postData = postData[0]; - if (parseInt(postData.deleted, 10) === 1) { - return next(new Error('[[error:no-post]]')); - } - next(null, postData); - } - ], callback); -} - SocketPosts.getPrivileges = function(socket, pids, callback) { privileges.posts.get(pids, socket.uid, function(err, privileges) { if (err) { From 9dda08bbdca718473673cc77b623690cc76ca309 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 15:47:31 -0400 Subject: [PATCH 23/32] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 756af6a8eb..09aa3ef677 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-rewards-essentials": "0.0.5", "nodebb-theme-lavender": "2.0.5", - "nodebb-theme-persona": "3.0.27", + "nodebb-theme-persona": "3.0.28", "nodebb-theme-vanilla": "4.0.16", "nodebb-widget-essentials": "2.0.2", "npm": "^2.1.4", From 75e2228989812a632253208f10e2ca27fd17610d Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 16:36:37 -0400 Subject: [PATCH 24/32] closes #3689 --- public/src/client/topic/posts.js | 50 ++++----------------- src/privileges/topics.js | 1 + src/socket.io/posts.js | 14 ------ src/topics/create.js | 3 ++ src/topics/posts.js | 75 +++++++++++++++++--------------- 5 files changed, 54 insertions(+), 89 deletions(-) diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index e19e1f9fa4..36df0b3d1f 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -22,6 +22,12 @@ define('forum/topic/posts', [ return; } + data.posts.forEach(function(post) { + post.selfPost = !!app.user.uid && parseInt(post.uid, 10) === parseInt(app.user.uid, 10); + post.display_moderator_tools = post.selfPost || ajaxify.data.isAdminOrMod; + post.display_move_tools = ajaxify.data.isAdminOrMod; + }); + updatePostCounts(data.posts); if (config.usePagination) { @@ -154,52 +160,14 @@ define('forum/topic/posts', [ infinitescroll.removeExtra(components.get('post'), direction, 40); - var pids = []; - for(var i=0; i Date: Tue, 29 Sep 2015 17:09:41 -0400 Subject: [PATCH 25/32] simpler check --- public/src/client/topic/posts.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index 36df0b3d1f..f17e8cbab5 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -13,12 +13,11 @@ define('forum/topic/posts', [ var Posts = {}; Posts.onNewPost = function(data) { - var tid = ajaxify.data.tid; - if (data && data.posts && data.posts.length && parseInt(data.posts[0].tid, 10) !== parseInt(tid, 10)) { + if (!data || !data.posts || !data.posts.length) { return; } - if (!data || !data.posts || !data.posts.length) { + if (parseInt(data.posts[0].tid, 10) !== parseInt(ajaxify.data.tid, 10)) { return; } From 714efd0d0e86471b01c42f1e01f2a1b325e5789f Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 29 Sep 2015 17:09:32 -0400 Subject: [PATCH 26/32] scrollToPost / scrollToPostIndex offset isn't used anymore --- public/src/modules/navigator.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index 078e562e67..b9ac5f6403 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -147,17 +147,16 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com } }; - navigator.scrollToPost = function(postIndex, highlight, duration, offset) { + navigator.scrollToPost = function(postIndex, highlight, duration) { if (!utils.isNumber(postIndex) || !components.get('topic').length) { return; } - offset = offset || 0; duration = duration !== undefined ? duration : 400; navigator.scrollActive = true; if (components.get('post/anchor', postIndex).length) { - return navigator.scrollToPostIndex(postIndex, highlight, duration, offset); + return navigator.scrollToPostIndex(postIndex, highlight, duration); } if (config.usePagination) { @@ -165,10 +164,10 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com if (parseInt(page, 10) !== pagination.currentPage) { pagination.loadPage(page, function() { - navigator.scrollToPostIndex(postIndex, highlight, duration, offset); + navigator.scrollToPostIndex(postIndex, highlight, duration); }); } else { - navigator.scrollToPostIndex(postIndex, highlight, duration, offset); + navigator.scrollToPostIndex(postIndex, highlight, duration); } } else { navigator.scrollActive = false; @@ -177,19 +176,20 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com } }; - navigator.scrollToPostIndex = function(postIndex, highlight, duration, offset) { + navigator.scrollToPostIndex = function(postIndex, highlight, duration) { var scrollTo = components.get('post/anchor', postIndex); if (!scrollTo.length) { navigator.scrollActive = false; return; } - offset = offset || 0; + duration = duration !== undefined ? duration : 400; navigator.scrollActive = true; var done = false; + function animateScroll() { - var scrollTop = (scrollTo.offset().top - ($(window).height() / 2) - offset) + 'px'; + var scrollTop = (scrollTo.offset().top - ($(window).height() / 2)) + 'px'; $('html, body').animate({ scrollTop: scrollTop From ca294fc6ecc5db424b892870c0a7fc619c40e98e Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 18:22:41 -0400 Subject: [PATCH 27/32] closes #3663 --- app.js | 6 ++-- loader.js | 4 +-- minifier.js | 17 ++++++------ public/src/modules/translator.js | 3 +- src/controllers/admin/themes.js | 22 +++++++-------- src/file.js | 19 ++++++++++++- src/logger.js | 3 +- src/meta/css.js | 40 ++++++++++++++------------- src/meta/js.js | 47 ++++++++++++++++---------------- src/meta/themes.js | 39 +++++++++++++------------- src/middleware/index.js | 3 +- src/plugins.js | 3 +- src/plugins/load.js | 3 +- src/routes/plugins.js | 31 ++++++--------------- src/webserver.js | 3 +- 15 files changed, 128 insertions(+), 115 deletions(-) diff --git a/app.js b/app.js index c6714a6425..4aa9371e18 100644 --- a/app.js +++ b/app.js @@ -23,14 +23,14 @@ var nconf = require('nconf'); nconf.argv().env('__'); -var fs = require('fs'), - url = require('url'), +var url = require('url'), async = require('async'), semver = require('semver'), winston = require('winston'), colors = require('colors'), path = require('path'), pkg = require('./package.json'), + file = require('./src/file'), utils = require('./public/src/utils.js'); global.env = process.env.NODE_ENV || 'production'; @@ -53,7 +53,7 @@ if (nconf.get('config')) { configFile = path.resolve(__dirname, nconf.get('config')); } -var configExists = fs.existsSync(configFile); +var configExists = file.existsSync(configFile); loadConfig(); diff --git a/loader.js b/loader.js index 96c78da4ee..20e8335a9a 100644 --- a/loader.js +++ b/loader.js @@ -8,7 +8,7 @@ var nconf = require('nconf'), async = require('async'), logrotate = require('logrotate-stream'), - + file = require('./src/file'), pkg = require('./package.json'); nconf.argv().env().file({ @@ -243,7 +243,7 @@ Loader.notifyWorkers = function(msg, worker_pid) { fs.open(path.join(__dirname, 'config.json'), 'r', function(err) { if (!err) { if (nconf.get('daemon') !== 'false' && nconf.get('daemon') !== false) { - if (fs.existsSync(pidFilePath)) { + if (file.existsSync(pidFilePath)) { try { var pid = fs.readFileSync(pidFilePath, { encoding: 'utf-8' }); process.kill(pid, 0); diff --git a/minifier.js b/minifier.js index 621d61fa08..c1df3930c1 100644 --- a/minifier.js +++ b/minifier.js @@ -4,6 +4,7 @@ var uglifyjs = require('uglify-js'), less = require('less'), async = require('async'), fs = require('fs'), + file = require('./src/file'), crypto = require('crypto'), utils = require('./public/src/utils'), @@ -14,16 +15,16 @@ var uglifyjs = require('uglify-js'), /* Javascript */ Minifier.js.minify = function (scripts, minify, callback) { scripts = scripts.filter(function(file) { - return fs.existsSync(file) && file.endsWith('.js'); + return file && file.endsWith('.js'); }); - if (minify) { - minifyScripts(scripts, function() { - callback.apply(this, arguments); - }); - } else { - concatenateScripts(scripts, callback); - } + async.filter(scripts, file.exists, function(scripts) { + if (minify) { + minifyScripts(scripts, callback); + } else { + concatenateScripts(scripts, callback); + } + }); }; process.on('message', function(payload) { diff --git a/public/src/modules/translator.js b/public/src/modules/translator.js index e2b70220f3..35429af587 100644 --- a/public/src/modules/translator.js +++ b/public/src/modules/translator.js @@ -264,11 +264,12 @@ var fs = require('fs'), path = require('path'), winston = require('winston'), + file = require('../../../src/file'), meta = require('../../../src/meta'); language = language || meta.config.defaultLang || 'en_GB'; - if (!fs.existsSync(path.join(__dirname, '../../language', language))) { + if (!file.existsSync(path.join(__dirname, '../../language', language))) { winston.warn('[translator] Language \'' + meta.config.defaultLang + '\' not found. Defaulting to \'en_GB\''); language = 'en_GB'; } diff --git a/src/controllers/admin/themes.js b/src/controllers/admin/themes.js index 0f87ecc83c..e5ef8a9343 100644 --- a/src/controllers/admin/themes.js +++ b/src/controllers/admin/themes.js @@ -1,24 +1,24 @@ 'use strict'; var path = require('path'); -var fs = require('fs'); +var file = require('../../file'); var themesController = {}; themesController.get = function(req, res, next) { var themeDir = path.join(__dirname, '../../../node_modules/' + req.params.theme); - fs.exists(themeDir, function(exists) { - if (exists) { - var themeConfig = require(path.join(themeDir, 'theme.json')), - screenshotPath = path.join(themeDir, themeConfig.screenshot); - if (themeConfig.screenshot && fs.existsSync(screenshotPath)) { - res.sendFile(screenshotPath); - } else { - res.sendFile(path.join(__dirname, '../../../public/images/themes/default.png')); - } - } else { + file.exists(themeDir, function(exists) { + if (!exists) { return next(); } + + var themeConfig = require(path.join(themeDir, 'theme.json')), + screenshotPath = path.join(themeDir, themeConfig.screenshot); + if (themeConfig.screenshot && file.existsSync(screenshotPath)) { + res.sendFile(screenshotPath); + } else { + res.sendFile(path.join(__dirname, '../../../public/images/themes/default.png')); + } }); }; diff --git a/src/file.js b/src/file.js index 94465b4ad7..2f503f0309 100644 --- a/src/file.js +++ b/src/file.js @@ -8,7 +8,6 @@ var fs = require('fs'), Magic = mmmagic.Magic, mime = require('mime'), - meta = require('./meta'), utils = require('../public/src/utils'); var file = {}; @@ -63,6 +62,7 @@ file.isFileTypeAllowed = function(path, allowedExtensions, callback) { }; file.allowedExtensions = function() { + var meta = require('./meta'); var allowedExtensions = (meta.config.allowedFileExtensions || '').trim(); if (!allowedExtensions) { return []; @@ -80,4 +80,21 @@ file.allowedExtensions = function() { return allowedExtensions; }; +file.exists = function(path, callback) { + fs.stat(path, function(err, stat) { + callback(!err && stat); + }); +}; + +file.existsSync = function(path) { + var exists = false; + try { + exists = fs.statSync(path); + } catch(err) { + exists = false; + } + + return !!exists; +}; + module.exports = file; \ No newline at end of file diff --git a/src/logger.js b/src/logger.js index cd437924be..5b15e90ad6 100644 --- a/src/logger.js +++ b/src/logger.js @@ -10,6 +10,7 @@ var fs = require('fs'), winston = require('winston'), util = require('util'), socketio = require('socket.io'), + file = require('./file'), meta = require('./meta'), morgan = require('morgan'); @@ -76,7 +77,7 @@ var opts = { /* Open the streams to log to: either a path or stdout */ var stream; if(value) { - if(fs.existsSync(value)) { + if(file.existsSync(value)) { var stats = fs.statSync(value); if(stats) { if(stats.isDirectory()) { diff --git a/src/meta/css.js b/src/meta/css.js index f3257e624f..46b54ccb18 100644 --- a/src/meta/css.js +++ b/src/meta/css.js @@ -11,6 +11,7 @@ var winston = require('winston'), plugins = require('../plugins'), emitter = require('../emitter'), db = require('../database'), + file = require('../file'), utils = require('../../public/src/utils'); module.exports = function(Meta) { @@ -149,24 +150,25 @@ module.exports = function(Meta) { Meta.css.getFromFile = function(callback) { var cachePath = path.join(__dirname, '../../public/stylesheet.css'), acpCachePath = path.join(__dirname, '../../public/admin.css'); - fs.exists(cachePath, function(exists) { - if (exists) { - if (nconf.get('isPrimary') === 'true') { - winston.verbose('[meta/css] Reading stylesheets from file'); - async.map([cachePath, acpCachePath], fs.readFile, function(err, files) { - Meta.css.cache = files[0]; - Meta.css.acpCache = files[1]; - - emitter.emit('meta:css.compiled'); - callback(); - }); - } else { - callback(); - } - } else { + file.exists(cachePath, function(exists) { + if (!exists) { winston.warn('[meta/css] No stylesheets found on disk, re-minifying'); - Meta.css.minify.apply(Meta.css, arguments); + Meta.css.minify(callback); + return; } + + if (nconf.get('isPrimary') !== 'true') { + return callback(); + } + + winston.verbose('[meta/css] Reading stylesheets from file'); + async.map([cachePath, acpCachePath], fs.readFile, function(err, files) { + Meta.css.cache = files[0]; + Meta.css.acpCache = files[1]; + + emitter.emit('meta:css.compiled'); + callback(); + }); }); }; @@ -197,10 +199,10 @@ module.exports = function(Meta) { } function filterMissingFiles(files) { - return files.filter(function(file) { - var exists = fs.existsSync(path.join(__dirname, '../../node_modules', file)); + return files.filter(function(filePath) { + var exists = file.existsSync(path.join(__dirname, '../../node_modules', filePath)); if (!exists) { - winston.warn('[meta/css] File not found! ' + file); + winston.warn('[meta/css] File not found! ' + filePath); } return exists; }); diff --git a/src/meta/js.js b/src/meta/js.js index 9bddbd58e9..dd8c364924 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -8,7 +8,7 @@ var winston = require('winston'), os = require('os'), nconf = require('nconf'), fs = require('fs'), - + file = require('../file'), plugins = require('../plugins'), emitter = require('../emitter'), utils = require('../../public/src/utils'); @@ -208,30 +208,31 @@ module.exports = function(Meta) { var scriptPath = path.join(__dirname, '../../public/nodebb.min.js'), mapPath = path.join(__dirname, '../../public/nodebb.min.js.map'), paths = [scriptPath]; - fs.exists(scriptPath, function(exists) { - if (exists) { - if (nconf.get('isPrimary') === 'true') { - fs.exists(mapPath, function(exists) { - if (exists) { - paths.push(mapPath); - } - - winston.verbose('[meta/js] Reading client-side scripts from file'); - async.map(paths, fs.readFile, function(err, files) { - Meta.js.cache = files[0]; - Meta.js.map = files[1] || ''; - - emitter.emit('meta:js.compiled'); - callback(); - }); - }); - } else { - callback(); - } - } else { + file.exists(scriptPath, function(exists) { + if (!exists) { winston.warn('[meta/js] No script file found on disk, re-minifying'); - Meta.js.minify.apply(Meta.js, arguments); + Meta.js.minify(minify, callback); + return; } + + if (nconf.get('isPrimary') !== 'true') { + return callback(); + } + + file.exists(mapPath, function(exists) { + if (exists) { + paths.push(mapPath); + } + + winston.verbose('[meta/js] Reading client-side scripts from file'); + async.map(paths, fs.readFile, function(err, files) { + Meta.js.cache = files[0]; + Meta.js.map = files[1] || ''; + + emitter.emit('meta:js.compiled'); + callback(); + }); + }); }); }; diff --git a/src/meta/themes.js b/src/meta/themes.js index e10194c9af..fedb1ff0d9 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -6,6 +6,8 @@ var nconf = require('nconf'), fs = require('fs'), path = require('path'), async = require('async'), + + file = require('../file'), db = require('../database'); module.exports = function(Meta) { @@ -34,27 +36,24 @@ module.exports = function(Meta) { async.map(themes, function (theme, next) { var config = path.join(themePath, theme, 'theme.json'); - if (fs.existsSync(config)) { - fs.readFile(config, function (err, file) { - if (err) { - return next(); - } else { - var configObj = JSON.parse(file.toString()); + fs.readFile(config, function (err, file) { + if (err) { + return next(); + } - // 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'; - } + 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(null, configObj); + }); - next(err, configObj); - } - }); - } else { - next(); - } }, function (err, themes) { themes = themes.filter(function (theme) { return (theme !== undefined); @@ -145,7 +144,7 @@ module.exports = function(Meta) { if (themeObj.templates) { themePath = path.join(nconf.get('themes_path'), themeObj.id, themeObj.templates); - } else if (fs.existsSync(fallback)) { + } else if (file.existsSync(fallback)) { themePath = fallback; } diff --git a/src/middleware/index.js b/src/middleware/index.js index fedb8b55cb..80b6677970 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -2,6 +2,7 @@ var meta = require('../meta'), db = require('../database'), + file = require('../file'), auth = require('../routes/authentication'), path = require('path'), @@ -21,7 +22,7 @@ var middleware = {}; function setupFavicon(app) { var faviconPath = path.join(__dirname, '../../', 'public', meta.config['brand:favicon'] ? meta.config['brand:favicon'] : 'favicon.ico'); - if (fs.existsSync(faviconPath)) { + if (file.existsSync(faviconPath)) { app.use(nconf.get('relative_path'), favicon(faviconPath)); } } diff --git a/src/plugins.js b/src/plugins.js index 7abf65dafa..f86251293a 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -14,6 +14,7 @@ var fs = require('fs'), translator = require('../public/src/modules/translator'), utils = require('../public/src/utils'), hotswap = require('./hotswap'), + file = require('./file'), controllers = require('./controllers'), app, middleware; @@ -103,7 +104,7 @@ var fs = require('fs'), return path.join(__dirname, '../node_modules/', plugin); }); - async.filter(plugins, fs.exists, function(plugins){ + async.filter(plugins, file.exists, function(plugins) { async.eachSeries(plugins, Plugins.loadPlugin, next); }); }, diff --git a/src/plugins/load.js b/src/plugins/load.js index ad441a2b97..f7d54cc6a8 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -6,6 +6,7 @@ var fs = require('fs'), async = require('async'), winston = require('winston'), nconf = require('nconf'), + file = require('../file'), utils = require('../../public/src/utils'); @@ -107,7 +108,7 @@ module.exports = function(Plugins) { var realPath = pluginData.staticDirs[mappedPath]; var staticDir = path.join(pluginPath, realPath); - fs.exists(staticDir, function(exists) { + file.exists(staticDir, function(exists) { if (exists) { Plugins.staticDirs[pluginData.id + '/' + mappedPath] = staticDir; } else { diff --git a/src/routes/plugins.js b/src/routes/plugins.js index ad1c0e84fa..72af49fbed 100644 --- a/src/routes/plugins.js +++ b/src/routes/plugins.js @@ -22,31 +22,18 @@ module.exports = function(app, middleware, controllers) { } else { return null; } - }).filter(function(a) { return a; }); + }).filter(Boolean); - if (matches) { - async.map(matches, function(mappedPath, next) { - var filePath = path.join(plugins.staticDirs[mappedPath], decodeURIComponent(relPath.slice(mappedPath.length))); + if (!matches) { + return next(); + } - fs.exists(filePath, function(exists) { - if (exists) { - next(null, filePath); - } else { - next(); - } - }); - }, function(err, matches) { - if (err) { - return next(err); - } - matches = matches.filter(Boolean); + matches = matches.map(function(mappedPath) { + return path.join(plugins.staticDirs[mappedPath], decodeURIComponent(relPath.slice(mappedPath.length))); + }); - if (matches.length) { - res.sendFile(matches[0]); - } else { - next(); - } - }); + if (matches.length) { + res.sendFile(matches[0]); } else { next(); } diff --git a/src/webserver.js b/src/webserver.js index 9b6fb24e8c..87b9f1a8cc 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -186,9 +186,10 @@ module.exports.testSocket = function(socketPath, callback) { return callback(new Error('invalid socket path : ' + socketPath)); } var net = require('net'); + var file = require('./file'); async.series([ function(next) { - fs.exists(socketPath, function(exists) { + file.exists(socketPath, function(exists) { if (exists) { next(); } else { From 22d67424224b148c8e46d725c0357ba62f1bbc83 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 18:38:18 -0400 Subject: [PATCH 28/32] closes #3569 --- public/src/ajaxify.js | 5 ++++- src/views/500.tpl | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index d1d7ecb4be..2ab64c65e8 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -307,6 +307,9 @@ $(document).ready(function() { } app.load(); - templates.cache['500'] = $('.tpl-500').html(); + + $('[data-template]').each(function() { + templates.cache[$(this).attr('data-template')] = $(this).html(); + }); }); \ No newline at end of file diff --git a/src/views/500.tpl b/src/views/500.tpl index 6408fbb79d..537cbac136 100644 --- a/src/views/500.tpl +++ b/src/views/500.tpl @@ -1,3 +1,4 @@ + \ No newline at end of file From 93dc3c2c347e92a6b3815abe5c6beb9af936aacb Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 18:41:52 -0400 Subject: [PATCH 29/32] up themes --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 09aa3ef677..a52e884f6f 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,8 @@ "nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-rewards-essentials": "0.0.5", "nodebb-theme-lavender": "2.0.5", - "nodebb-theme-persona": "3.0.28", - "nodebb-theme-vanilla": "4.0.16", + "nodebb-theme-persona": "3.0.29", + "nodebb-theme-vanilla": "4.0.17", "nodebb-widget-essentials": "2.0.2", "npm": "^2.1.4", "passport": "^0.3.0", From 5a3a627fcd4512e4ed064d3eeb0a607cb8f6e298 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 20:30:42 -0400 Subject: [PATCH 30/32] fix rel tag urls --- src/controllers/categories.js | 1 + src/controllers/topics.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/controllers/categories.js b/src/controllers/categories.js index ce1edc0532..2a045dc533 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -256,6 +256,7 @@ categoriesController.get = function(req, res, callback) { data.pagination = pagination.create(data.currentPage, data.pageCount); data.title = data.name; data.pagination.rel.forEach(function(rel) { + rel.href = nconf.get('url') + '/category/' + data.slug + rel.href; res.locals.linkTags.push(rel); }); diff --git a/src/controllers/topics.js b/src/controllers/topics.js index c4abfcbfbf..7632d26c5d 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -263,6 +263,7 @@ topicsController.get = function(req, res, callback) { data.rssFeedUrl = nconf.get('relative_path') + '/topic/' + data.tid + '.rss'; data.pagination = pagination.create(data.currentPage, data.pageCount); data.pagination.rel.forEach(function(rel) { + rel.href = nconf.get('url') + '/topic/' + data.slug + rel.href; res.locals.linkTags.push(rel); }); From df95d47c4ccfe354081cce54cae8646d66e3415a Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 20:31:40 -0400 Subject: [PATCH 31/32] ocd --- src/controllers/categories.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/categories.js b/src/controllers/categories.js index 2a045dc533..220779c524 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -253,8 +253,8 @@ categoriesController.get = function(req, res, callback) { data.pageCount = pageCount; data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; data.rssFeedUrl = nconf.get('relative_path') + '/category/' + data.cid + '.rss'; - data.pagination = pagination.create(data.currentPage, data.pageCount); data.title = data.name; + data.pagination = pagination.create(data.currentPage, data.pageCount); data.pagination.rel.forEach(function(rel) { rel.href = nconf.get('url') + '/category/' + data.slug + rel.href; res.locals.linkTags.push(rel); From 70b7535a27d2638a18eae9ceaff46b62bce37edc Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 29 Sep 2015 20:46:19 -0400 Subject: [PATCH 32/32] unused true --- .jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index f5b67ad0bc..1981c254c5 100644 --- a/.jshintrc +++ b/.jshintrc @@ -24,7 +24,7 @@ // "single" : require single quotes // "double" : require double quotes "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : false, // true: Require all defined variables be used TODO: Set this to true, update codebase. + "unused" : true, // true: Require all defined variables be used "strict" : true, // true: Requires all functions run in ES5 Strict Mode "trailing" : false, // true: Prohibit trailing whitespaces "maxparams" : false, // {int} Max number of formal params allowed per function