Merge commit 'f7ac1d89ffad60d810d639f53ca4303d9574021c' into weekly

This commit is contained in:
NodeBB Misty
2016-04-11 16:00:15 -04:00
38 changed files with 196 additions and 128 deletions

4
app.js
View File

@@ -207,6 +207,10 @@ function start() {
winston.warn('One or more of NodeBB\'s dependent packages are out-of-date. Please run the following command to update them:');
winston.warn(' ./nodebb upgrade');
break;
case 'dependencies-missing':
winston.warn('One or more of NodeBB\'s dependent packages are missing. Please run the following command to update them:');
winston.warn(' ./nodebb upgrade');
break;
default:
if (err.stacktrace !== false) {
winston.error(err.stack);

View File

@@ -18,6 +18,7 @@
"autoprefixer": "^6.2.3",
"bcryptjs": "~2.3.0",
"body-parser": "^1.9.0",
"chart.js": "^1.0.2",
"colors": "^1.1.0",
"compression": "^1.1.0",
"connect-ensure-login": "^0.1.1",
@@ -43,18 +44,20 @@
"mkdirp": "~0.5.0",
"mongodb": "~2.1.3",
"morgan": "^1.3.2",
"mousetrap": "^1.5.3",
"nconf": "~0.8.2",
"nodebb-plugin-composer-default": "3.0.18",
"nodebb-plugin-composer-default": "3.0.21",
"nodebb-plugin-dbsearch": "1.0.1",
"nodebb-plugin-emoji-extended": "1.0.3",
"nodebb-plugin-emoji-one": "1.1.0",
"nodebb-plugin-emoji-extended": "1.1.0",
"nodebb-plugin-markdown": "5.0.1",
"nodebb-plugin-mentions": "1.0.21",
"nodebb-plugin-soundpack-default": "0.1.6",
"nodebb-plugin-spam-be-gone": "0.4.6",
"nodebb-rewards-essentials": "0.0.8",
"nodebb-theme-lavender": "3.0.9",
"nodebb-theme-persona": "4.0.115",
"nodebb-theme-vanilla": "5.0.61",
"nodebb-theme-persona": "4.0.118",
"nodebb-theme-vanilla": "5.0.63",
"nodebb-widget-essentials": "2.0.9",
"nodemailer": "2.0.0",
"nodemailer-sendmail-transport": "1.0.0",
@@ -67,7 +70,7 @@
"request": "^2.44.0",
"rimraf": "~2.5.0",
"rss": "^1.0.0",
"semver": "^5.0.1",
"semver": "^5.1.0",
"serve-favicon": "^2.1.5",
"sitemap": "^1.4.0",
"socket.io": "^1.4.0",
@@ -112,4 +115,4 @@
"url": "https://github.com/barisusakli"
}
]
}
}

View File

@@ -104,6 +104,9 @@
"enable_topic_searching": "Enable In-Topic Searching",
"topic_search_help": "If enabled, in-topic searching will override the browser's default page search behaviour and allow you to search through the entire topic, instead of what is only shown on screen",
"delay_image_loading": "Delay Image Loading",
"image_load_delay_help": "If enabled, images in topics will not load until they are scrolled into view",
"scroll_to_my_post": "After posting a reply, show the new post",
"follow_topics_you_reply_to": "Follow topics that you reply to",

View File

@@ -13,15 +13,15 @@
"new_message_from": "Pesanan baru daripada <strong>%1</strong>",
"upvoted_your_post_in": "<strong>%1</strong> telah mengundi naik kiriman and di <strong>%2</strong>.",
"upvoted_your_post_in_dual": "<strong>%1</strong>dan <strong>%2</strong> telah menambah undi pada kiriman anda di <strong>%3</strong>.",
"upvoted_your_post_in_multiple": "<strong>%1</strong> dan %2 lagi telah menambah undi pada kiriman anda di <strong>%3</strong>. ",
"upvoted_your_post_in_multiple": "<strong>%1</strong> dan %2 lagi telah menambah undi pada kiriman anda di <strong>%3</strong>.",
"moved_your_post": "<strong>%1</strong> telah memindahkan kiriman anda ke <strong>%2</strong>",
"moved_your_topic": "<strong>%1</strong> telah memindahkan <strong>%2</strong>",
"favourited_your_post_in": "<strong>%1</strong> has bookmarked your post in <strong>%2</strong>.",
"favourited_your_post_in_dual": "<strong>%1</strong> and <strong>%2</strong> have bookmarked your post in <strong>%3</strong>.",
"favourited_your_post_in_multiple": "<strong>%1</strong> and %2 others have bookmarked your post in <strong>%3</strong>.",
"favourited_your_post_in": "<strong>%1</strong> telah menyukai kiriman anda di <strong>%2</strong>.",
"favourited_your_post_in_dual": "<strong>%1</strong> dan <strong>%2</strong> telah menyukai kiriman anda di <strong>%3</strong>.",
"favourited_your_post_in_multiple": "<strong>%1</strong> dan %2 yang lain, telah menyukai kiriman anda di <strong>%3</strong>.",
"user_flagged_post_in": "<strong>%1</strong> menanda kiriman anda di <strong>%2</strong>",
"user_flagged_post_in_dual": "<strong>%1</strong> dan <strong>%2</strong> telah menanda kiriman anda pada <strong>%3</strong>",
"user_flagged_post_in_multiple": "<strong>%1</strong> dan %2 lagi telah mendanda kiriman anda pada <strong>%3</strong>",
"user_flagged_post_in_multiple": "<strong>%1</strong> dan %2 lagi telah menanda kiriman anda pada <strong>%3</strong>",
"user_posted_to": "<strong>%1</strong> telah membalas kiriman kepada: <strong>%2</strong>",
"user_posted_to_dual": "<strong>%1</strong> dan <strong>%2</strong> membalas kiriman : <strong>%3</strong>",
"user_posted_to_multiple": "<strong>%1</strong> dan %2 lagu membalas kiriman: <strong>%3</strong>",
@@ -30,7 +30,7 @@
"user_started_following_you_dual": "<strong>%1</strong> dan <strong>%2</strong> mula mengikuti anda.",
"user_started_following_you_multiple": "<strong>%1</strong> dan %2 lagi mula mengikuti anda.",
"new_register": "<strong>%1</strong> menghantar jemputan pendaftaran.",
"new_register_multiple": "There are <strong>%1</strong> registration requests awaiting review.",
"new_register_multiple": "Ada <strong>%1</strong> permohonan ingin daftar yang sedang menunggu pengesahan.",
"email-confirmed": "Emel Disahkan",
"email-confirmed-message": "Terima kasih kerana mengesahkan emel anda. Akaun anda telah diaktifkan sepenuhnya.",
"email-confirm-error-message": "Berlaku masalah semasa mengesahkan emel anda. Mungkin kod tidak sah atau tamat tempoh.",

View File

@@ -1,6 +1,6 @@
{
"uploading-file": "Uploading the file...",
"select-file-to-upload": "Select a file to upload!",
"upload-success": "File uploaded successfully!",
"maximum-file-size": "Maximum %1 kb"
"uploading-file": "Sedang memuatnaik fail...",
"select-file-to-upload": "Pilih fail yang hendak dimuatnaik!",
"upload-success": "Muatnaik fail berjaya!",
"maximum-file-size": "Maksima %1 kb"
}

View File

@@ -1,5 +1,5 @@
"use strict";
/*global config, translator, componentHandler, define, socket, app, ajaxify, utils, bootbox, Mousetrap, Hammer, Slideout, RELATIVE_PATH*/
/*global config, translator, componentHandler, define, socket, app, ajaxify, utils, bootbox, Slideout, RELATIVE_PATH*/
(function() {
$(document).ready(function() {
@@ -32,20 +32,22 @@
});
function setupKeybindings() {
Mousetrap.bind('ctrl+shift+a r', function() {
require(['admin/modules/instance'], function(instance) {
instance.reload();
require(['mousetrap'], function(mousetrap) {
mousetrap.bind('ctrl+shift+a r', function() {
require(['admin/modules/instance'], function(instance) {
instance.reload();
});
});
});
Mousetrap.bind('ctrl+shift+a R', function() {
socket.emit('admin.restart');
});
mousetrap.bind('ctrl+shift+a R', function() {
socket.emit('admin.restart');
});
Mousetrap.bind('/', function(e) {
$('#acp-search input').focus();
mousetrap.bind('/', function(e) {
$('#acp-search input').focus();
return false;
return false;
});
});
}

View File

@@ -1,7 +1,7 @@
"use strict";
/*global define, ajaxify, app, socket, utils, bootbox, Chart, RELATIVE_PATH*/
/*global define, ajaxify, app, socket, utils, bootbox, RELATIVE_PATH*/
define('admin/general/dashboard', ['semver'], function(semver) {
define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
var Admin = {},
intervals = {
rooms: false,

View File

@@ -1,12 +1,13 @@
"use strict";
/*global config, define, app, socket, ajaxify, bootbox, templates, Chart, utils */
/*global config, define, app, socket, ajaxify, bootbox, templates */
define('admin/manage/category', [
'uploader',
'iconSelect',
'admin/modules/colorpicker',
'autocomplete'
], function(uploader, iconSelect, colorpicker, autocomplete) {
'autocomplete',
'Chart'
], function(uploader, iconSelect, colorpicker, autocomplete, Chart) {
var Category = {};
Category.init = function() {

View File

@@ -1,8 +1,8 @@
'use strict';
/* globals define, config, app, ajaxify, utils, socket, templates, Mousetrap, bootbox */
/* globals define, config, app, ajaxify, utils, socket, templates, bootbox */
define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', 'translator'], function(components, S, sounds, infinitescroll, translator) {
define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', 'translator', 'mousetrap'], function(components, S, sounds, infinitescroll, translator, mousetrap) {
var Chats = {
initialised: false
};
@@ -92,7 +92,7 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll',
};
Chats.addHotkeys = function() {
Mousetrap.bind('ctrl+up', function() {
mousetrap.bind('ctrl+up', function() {
var activeContact = $('.chats-list .bg-primary'),
prev = activeContact.prev();
@@ -100,7 +100,7 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll',
Chats.switchChat(prev.attr('data-roomid'));
}
});
Mousetrap.bind('ctrl+down', function() {
mousetrap.bind('ctrl+down', function() {
var activeContact = $('.chats-list .bg-primary'),
next = activeContact.next();
@@ -108,7 +108,7 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll',
Chats.switchChat(next.attr('data-roomid'));
}
});
Mousetrap.bind('up', function(e) {
mousetrap.bind('up', function(e) {
if (e.target === components.get('chat/input').get(0)) {
// Retrieve message id from messages list
var message = components.get('chat/messages').find('.chat-message[data-self="1"]').last();

View File

@@ -96,7 +96,7 @@ define('forum/topic', [
}
function handleTopicSearch() {
require(['search', 'mousetrap'], function(search, Mousetrap) {
require(['search', 'mousetrap'], function(search, mousetrap) {
$('.topic-search')
.on('click', '.prev', function() {
search.topicDOM.prev();
@@ -105,7 +105,7 @@ define('forum/topic', [
search.topicDOM.next();
});
Mousetrap.bind('ctrl+f', function(e) {
mousetrap.bind('ctrl+f', function(e) {
if (config.topicSearchEnabled) {
// If in topic, open search window and populate, otherwise regular behaviour
var match = ajaxify.currentPage.match(/^topic\/([\d]+)/),

View File

@@ -263,7 +263,7 @@ define('forum/topic/posts', [
var images = components.get('post/content').find('img[data-state="unloaded"]'),
visible = images.filter(function() {
return utils.isElementInViewport(this);
return config.delayImageLoading ? utils.isElementInViewport(this) : true;
}),
scrollTop = $(window).scrollTop(),
adjusting = false,
@@ -304,7 +304,7 @@ define('forum/topic/posts', [
});
image.attr('src', image.attr('data-src'));
if (image.parent().attr('href')) {
if (image.parent().attr('href') === 'about:blank') {
image.parent().attr('href', image.attr('data-src'));
}
image.removeAttr('data-src');

View File

@@ -131,7 +131,7 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com
}
// If a threshold is undefined, try to determine one based on new index
if (threshold === undefined) {
if (threshold === undefined && ajaxify.data.template.topic === true) {
if (atTop) {
threshold = 0;
} else {

View File

@@ -150,8 +150,8 @@ define('search', ['navigator', 'translator'], function(nav, translator) {
Search.topicDOM.active = true;
// Bind to esc
require(['mousetrap'], function(Mousetrap) {
Mousetrap.bind('esc', Search.topicDOM.end);
require(['mousetrap'], function(mousetrap) {
mousetrap.bind('esc', Search.topicDOM.end);
});
}
};
@@ -161,8 +161,8 @@ define('search', ['navigator', 'translator'], function(nav, translator) {
Search.topicDOM.active = false;
// Unbind esc
require(['mousetrap'], function(Mousetrap) {
Mousetrap.unbind('esc', Search.topicDOM.end);
require(['mousetrap'], function(mousetrap) {
mousetrap.unbind('esc', Search.topicDOM.end);
});
};

11
public/vendor/buzz/buzz.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +0,0 @@
/* mousetrap v1.4.6 craig.is/killing/mice */
(function(J,r,f){function s(a,b,d){a.addEventListener?a.addEventListener(b,d,!1):a.attachEvent("on"+b,d)}function A(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return h[a.which]?h[a.which]:B[a.which]?B[a.which]:String.fromCharCode(a.which).toLowerCase()}function t(a){a=a||{};var b=!1,d;for(d in n)a[d]?b=!0:n[d]=0;b||(u=!1)}function C(a,b,d,c,e,v){var g,k,f=[],h=d.type;if(!l[a])return[];"keyup"==h&&w(a)&&(b=[a]);for(g=0;g<l[a].length;++g)if(k=
l[a][g],!(!c&&k.seq&&n[k.seq]!=k.level||h!=k.action||("keypress"!=h||d.metaKey||d.ctrlKey)&&b.sort().join(",")!==k.modifiers.sort().join(","))){var m=c&&k.seq==c&&k.level==v;(!c&&k.combo==e||m)&&l[a].splice(g,1);f.push(k)}return f}function K(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function x(a,b,d,c){m.stopCallback(b,b.target||b.srcElement,d,c)||!1!==a(b,d)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?
b.stopPropagation():b.cancelBubble=!0)}function y(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=A(a);b&&("keyup"==a.type&&z===b?z=!1:m.handleKey(b,K(a),a))}function w(a){return"shift"==a||"ctrl"==a||"alt"==a||"meta"==a}function L(a,b,d,c){function e(b){return function(){u=b;++n[a];clearTimeout(D);D=setTimeout(t,1E3)}}function v(b){x(d,b,a);"keyup"!==c&&(z=A(b));setTimeout(t,10)}for(var g=n[a]=0;g<b.length;++g){var f=g+1===b.length?v:e(c||E(b[g+1]).action);F(b[g],f,c,a,g)}}function E(a,b){var d,
c,e,f=[];d="+"===a?["+"]:a.split("+");for(e=0;e<d.length;++e)c=d[e],G[c]&&(c=G[c]),b&&"keypress"!=b&&H[c]&&(c=H[c],f.push("shift")),w(c)&&f.push(c);d=c;e=b;if(!e){if(!p){p={};for(var g in h)95<g&&112>g||h.hasOwnProperty(g)&&(p[h[g]]=g)}e=p[d]?"keydown":"keypress"}"keypress"==e&&f.length&&(e="keydown");return{key:c,modifiers:f,action:e}}function F(a,b,d,c,e){q[a+":"+d]=b;a=a.replace(/\s+/g," ");var f=a.split(" ");1<f.length?L(a,f,b,d):(d=E(a,d),l[d.key]=l[d.key]||[],C(d.key,d.modifiers,{type:d.action},
c,a,e),l[d.key][c?"unshift":"push"]({callback:b,modifiers:d.modifiers,action:d.action,seq:c,level:e,combo:a}))}var h={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},B={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},H={"~":"`","!":"1",
"@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},G={option:"alt",command:"meta","return":"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},p,l={},q={},n={},D,z=!1,I=!1,u=!1;for(f=1;20>f;++f)h[111+f]="f"+f;for(f=0;9>=f;++f)h[f+96]=f;s(r,"keypress",y);s(r,"keydown",y);s(r,"keyup",y);var m={bind:function(a,b,d){a=a instanceof Array?a:[a];for(var c=0;c<a.length;++c)F(a[c],b,d);return this},
unbind:function(a,b){return m.bind(a,function(){},b)},trigger:function(a,b){if(q[a+":"+b])q[a+":"+b]({},a);return this},reset:function(){l={};q={};return this},stopCallback:function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable},handleKey:function(a,b,d){var c=C(a,b,d),e;b={};var f=0,g=!1;for(e=0;e<c.length;++e)c[e].seq&&(f=Math.max(f,c[e].level));for(e=0;e<c.length;++e)c[e].seq?c[e].level==f&&(g=!0,
b[c[e].seq]=1,x(c[e].callback,d,c[e].combo,c[e].seq)):g||x(c[e].callback,d,c[e].combo);c="keypress"==d.type&&I;d.type!=u||w(a)||c||t(b);I=g&&"keydown"==d.type}};J.Mousetrap=m;"function"===typeof define&&define.amd&&define('mousetrap', m)})(window,document);

View File

@@ -126,7 +126,9 @@ editController.uploadPicture = function (req, res, next) {
}
], function(err, image) {
fs.unlink(userPhoto.path, function(err) {
winston.error('unable to delete picture ' + userPhoto.path, err);
if (err) {
winston.warn('[user/picture] Unable to delete picture ' + userPhoto.path, err);
}
});
if (err) {
return next(err);

View File

@@ -6,7 +6,7 @@ var categories = require('../../categories');
var privileges = require('../../privileges');
var analytics = require('../../analytics');
var plugins = require('../../plugins');
var translator = require('../../../public/src/modules/translator')
var translator = require('../../../public/src/modules/translator');
var categoriesController = {};
@@ -19,12 +19,17 @@ categoriesController.get = function(req, res, next) {
if (err) {
return next(err);
}
var category = data.category[0];
plugins.fireHook('filter:admin.category.get', { req: req, res: res, category: data.category[0], privileges: data.privileges }, function(err, data) {
if (!category) {
return next();
}
plugins.fireHook('filter:admin.category.get', { req: req, res: res, category: category, privileges: data.privileges }, function(err, data) {
if (err) {
return next(err);
}
data.category.name = translator.escape(data.category.name);
data.category.name = translator.escape(String(data.category.name));
res.render('admin/manage/category', {
category: data.category,
privileges: data.privileges

View File

@@ -79,6 +79,7 @@ apiController.getConfig = function(req, res, next) {
config.topicPostSort = settings.topicPostSort || config.topicPostSort;
config.categoryTopicSort = settings.categoryTopicSort || config.categoryTopicSort;
config.topicSearchEnabled = settings.topicSearchEnabled || false;
config.delayImageLoading = settings.delayImageLoading !== undefined ? settings.delayImageLoading : true;
config.bootswatchSkin = settings.bootswatchSkin || config.bootswatchSkin;
next(null, config);
});

View File

@@ -66,7 +66,8 @@ categoriesController.list = function(req, res, next) {
if (category && Array.isArray(category.posts) && category.posts.length) {
category.teaser = {
url: nconf.get('relative_path') + '/topic/' + category.posts[0].topic.slug + '/' + category.posts[0].index,
timestampISO: category.posts[0].timestampISO
timestampISO: category.posts[0].timestampISO,
pid: category.posts[0].pid
};
}
});

View File

@@ -440,7 +440,8 @@ function enableDefaultPlugins(next) {
'nodebb-widget-essentials',
'nodebb-rewards-essentials',
'nodebb-plugin-soundpack-default',
'nodebb-plugin-emoji-extended'
'nodebb-plugin-emoji-extended',
'nodebb-plugin-emoji-one'
],
customDefaults = nconf.get('defaultPlugins');

View File

@@ -96,7 +96,7 @@ module.exports = function(Messaging) {
message: messageObj,
site_title: meta.config.title || 'NodeBB',
url: nconf.get('url'),
fromUserslug: utils.slugify(messageObj.fromUser.username)
roomId: messageObj.roomId
}, next);
}, callback);
});

View File

@@ -68,6 +68,7 @@ module.exports = function(Meta) {
source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/css/smoothness/jquery-ui-1.10.4.custom.min.css";';
source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";';
source += '\n@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";';
source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/flags.less";';
source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/blacklist.less";';
source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/generics.less";';

View File

@@ -12,7 +12,9 @@ module.exports = function(Meta) {
Meta.dependencies = {};
Meta.dependencies.check = function(callback) {
var modules = Object.keys(pkg.dependencies);
var modules = Object.keys(pkg.dependencies),
depsOutdated = false,
depsMissing = false;
winston.verbose('Checking dependencies for outdated modules');
async.every(modules, function(module, next) {
@@ -33,15 +35,23 @@ module.exports = function(Meta) {
next(true);
} else {
process.stdout.write('[' + 'outdated'.yellow + '] ' + module.bold + ' installed v' + pkgData.version + ', package.json requires ' + pkg.dependencies[module] + '\n');
next(false);
depsOutdated = true;
next(true);
}
} catch(e) {
winston.error('[meta/dependencies] Could not read: ' + module);
process.exit();
process.stdout.write('[' + 'missing'.red + '] ' + module.bold + ' is a required dependency but could not be found\n');
depsMissing = true;
next(true);
}
});
}, function(ok) {
callback(!ok && global.env !== 'development' ? new Error('dependencies-out-of-date') : null);
if (depsMissing) {
callback(new Error('dependencies-missing'));
} else if (depsOutdated) {
callback(global.env !== 'development' ? new Error('dependencies-out-of-date') : null);
} else {
callback(null);
}
});
};
};

View File

@@ -30,8 +30,6 @@ module.exports = function(Meta) {
'public/vendor/tinycon/tinycon.js',
'public/vendor/xregexp/xregexp.js',
'public/vendor/xregexp/unicode/unicode-base.js',
'public/vendor/buzz/buzz.min.js',
'public/vendor/mousetrap/mousetrap.js',
'public/vendor/autosize.js',
'./node_modules/templates.js/lib/templates.js',
'public/src/utils.js',
@@ -42,6 +40,8 @@ module.exports = function(Meta) {
'public/src/variables.js',
'public/src/widgets.js'
],
// files listed below are only available client-side, or are bundled in to reduce # of network requests on cold load
rjs: [
'public/src/client/footer.js',
'public/src/client/chats.js',
@@ -76,10 +76,45 @@ module.exports = function(Meta) {
'public/src/modules/helpers.js',
'public/src/modules/sounds.js',
'public/src/modules/string.js'
],
// modules listed below are routed through express (/src/modules) so they can be defined anonymously
modules: [
'./node_modules/chart.js/Chart.js',
'./node_modules/mousetrap/mousetrap.js',
'public/vendor/buzz/buzz.js'
]
}
};
Meta.js.bridgeModules = function(app, callback) {
// Add routes for AMD-type modules to serve those files
var numBridged = 0;
async.series([
function(next) {
async.each(Meta.js.scripts.modules, function(localPath, next) {
app.get(path.join('/src/modules/', path.basename(localPath)), function(req, res) {
return res.sendFile(path.join(__dirname, '../../', localPath), {
maxAge: app.enabled('cache') ? 5184000000 : 0
});
});
++numBridged;
next();
}, next);
}
], function(err) {
if (err) {
winston.error('[meta/js] Encountered error while bridging modules:' + err.message);
}
winston.verbose('[meta/js] ' + numBridged + ' of ' + Meta.js.scripts.modules.length + ' modules bridged');
callback(err);
});
};
Meta.js.minify = function(target, callback) {
if (nconf.get('isPrimary') !== 'true') {
if (typeof callback === 'function') {

View File

@@ -7,8 +7,10 @@ var fs = require('fs'),
winston = require('winston'),
nconf = require('nconf'),
_ = require('underscore'),
file = require('../file'),
utils = require('../../public/src/utils');
file = require('../file');
var utils = require('../../public/src/utils'),
meta = require('../meta');
module.exports = function(Plugins) {
@@ -40,6 +42,9 @@ module.exports = function(Plugins) {
function(next) {
mapClientSideScripts(pluginData, next);
},
function(next) {
mapClientModules(pluginData, next);
},
function(next) {
loadLanguages(pluginData, next);
}
@@ -163,7 +168,21 @@ module.exports = function(Plugins) {
}
callback();
}
};
function mapClientModules(pluginData, callback) {
if (Array.isArray(pluginData.modules)) {
if (global.env === 'development') {
winston.verbose('[plugins] Found ' + pluginData.modules.length + ' AMD-style module(s) for plugin ' + pluginData.id);
}
meta.js.scripts.modules = meta.js.scripts.modules.concat(pluginData.modules.map(function(file) {
return path.join('./node_modules/', pluginData.id, file);
}));
}
callback();
};
function loadLanguages(pluginData, callback) {
if (typeof pluginData.languages !== 'string') {

View File

@@ -107,7 +107,7 @@ function generateForUserTopics(req, res, callback) {
}
], function(err, userData) {
if (err) {
return next(err);
return callback(err);
}
generateForTopics({
@@ -116,7 +116,7 @@ function generateForUserTopics(req, res, callback) {
description: 'A list of topics that are posted by ' + userData.username,
feed_url: '/user/' + userslug + '/topics.rss',
site_url: '/user/' + userslug + '/topics'
}, 'uid:' + userData.uid + ':topics', req, res, next);
}, 'uid:' + userData.uid + ':topics', req, res, callback);
});
}

View File

@@ -1,16 +1,15 @@
'use strict';
var path = require('path'),
async = require('async'),
sm = require('sitemap'),
url = require('url'),
nconf = require('nconf'),
db = require('./database'),
categories = require('./categories'),
topics = require('./topics'),
privileges = require('./privileges'),
meta = require('./meta'),
utils = require('../public/src/utils');
var async = require('async');
var sm = require('sitemap');
var nconf = require('nconf');
var db = require('./database');
var categories = require('./categories');
var topics = require('./topics');
var privileges = require('./privileges');
var meta = require('./meta');
var utils = require('../public/src/utils');
var sitemap = {
maps: {
@@ -88,7 +87,7 @@ sitemap.getPages = function(callback) {
changefreq: 'daily',
priority: '0.4'
}];
sitemap.maps.pages = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours

View File

@@ -80,7 +80,7 @@ SocketHelpers.sendNotificationToPostOwner = function(pid, fromuid, notification)
pid: pid,
nid: 'post:' + pid + ':uid:' + fromuid,
from: fromuid,
mergeId: notification + '|' + postData.tid,
mergeId: notification + '|' + pid,
topicTitle: results.topicTitle
}, function(err, notification) {
if (!err && notification) {

View File

@@ -124,11 +124,11 @@ module.exports = function(SocketPosts) {
/*
hooks:
filter.post.upvote
filter.post.downvote
filter.post.unvote
filter.post.favourite
filter.post.unfavourite
filter:post.upvote
filter:post.downvote
filter:post.unvote
filter:post.favourite
filter:post.unfavourite
*/
plugins.fireHook('filter:post.' + command, {data: data, uid: socket.uid}, function(err, filteredData) {
if (err) {

View File

@@ -75,6 +75,7 @@ module.exports = function(User) {
settings.sendPostNotifications = parseInt(getSetting(settings, 'sendPostNotifications', 0), 10) === 1;
settings.restrictChat = parseInt(getSetting(settings, 'restrictChat', 0), 10) === 1;
settings.topicSearchEnabled = parseInt(getSetting(settings, 'topicSearchEnabled', 0), 10) === 1;
settings.delayImageLoading = parseInt(getSetting(settings, 'delayImageLoading', 1), 10) === 1;
settings.bootswatchSkin = settings.bootswatchSkin || 'default';
settings.scrollToMyPost = parseInt(getSetting(settings, 'scrollToMyPost', 1), 10) === 1;
@@ -120,6 +121,7 @@ module.exports = function(User) {
sendPostNotifications: data.sendPostNotifications,
restrictChat: data.restrictChat,
topicSearchEnabled: data.topicSearchEnabled,
delayImageLoading: data.delayImageLoading,
groupTitle: data.groupTitle,
homePageRoute: data.homePageCustom || data.homePageRoute,
scrollToMyPost: data.scrollToMyPost

View File

@@ -27,8 +27,6 @@
<![endif]-->
<script src="https://storage.googleapis.com/code.getmdl.io/1.0.3/material.min.js"></script>
<script type="text/javascript" src="{relative_path}/vendor/chart.js/chart.min.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/hammer/hammer.min.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/jquery/sortable/Sortable.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/acp.min.js?{cache-buster}"></script>
<script>
@@ -39,8 +37,7 @@
paths: {
'forum': '../client',
'admin': '../admin',
'vendor': '../../vendor',
'buzz': '../../vendor/buzz/buzz.min'
'vendor': '../../vendor'
}
});
@@ -54,7 +51,6 @@
<script type="text/javascript" src="{relative_path}/vendor/semver/semver.browser.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/jquery/serializeObject/jquery.ba-serializeobject.min.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/jquery/deserialize/jquery.deserialize.min.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/mousetrap/mousetrap.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/jquery/js/jquery-ui-1.10.4.custom.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/snackbar/snackbar.min.js?{cache-buster}"></script>
<script type="text/javascript" src="{relative_path}/vendor/slideout/slideout.min.js?{cache-buster}"></script>

View File

@@ -91,16 +91,25 @@
<div class="form-group">
<label for="profileImageDimension">Profile Image Dimension</label>
<input id="profileImageDimension" type="text" class="form-control" data-field="profileImageDimension" placeholder="128" />
<p class="help-block">
(in pixels, default: 128 pixels)
</p>
</div>
<div class="form-group">
<label>Maximum Profile Image File Size</label>
<input type="text" class="form-control" placeholder="Maximum size of uploaded user images in kilobytes" data-field="maximumProfileImageSize" />
<p class="help-block">
(in kilobytes, default: 256 KiB)
</p>
</div>
<div class="form-group">
<label>Maximum Cover Image File Size</label>
<input type="text" class="form-control" placeholder="Maximum size of uploaded cover images in kilobytes" data-field="maximumCoverImageSize" />
<p class="help-block">
(in kilobytes, default: 2,048 KiB)
</p>
</div>
</form>
</div>

View File

@@ -3,7 +3,7 @@
<p>{summary}:</p>
<blockquote>{message.content}</blockquote>
<a href="{url}/chats/{fromUserslug}">[[email:notif.chat.cta]]</a>
<a href="{url}/chats/{roomId}">[[email:notif.chat.cta]]</a>
<!-- IMPORT emails/partials/footer.tpl -->

View File

@@ -6,8 +6,7 @@
paths: {
'forum': '../client',
'admin': '../admin',
'vendor': '../../vendor',
'mousetrap': '../../bower/mousetrap/mousetrap'
'vendor': '../../vendor'
}
});
</script>

View File

@@ -84,6 +84,7 @@ function initializeNodeBB(callback) {
function(next) {
plugins.init(app, middleware, next);
},
async.apply(meta.js.bridgeModules, app),
function(next) {
async.series([
async.apply(meta.templates.compile),