diff --git a/docs/upgrading/index.rst b/docs/upgrading/index.rst index 12c1b3d1e0..6563835e86 100644 --- a/docs/upgrading/index.rst +++ b/docs/upgrading/index.rst @@ -78,7 +78,13 @@ All of the textual data stored in NodeBB is found in a ``.rdb`` file. On typical Backing up MongoDB ~~~~~~~~~~~~~~ -TBA +To run a backup of your complete MongoDB you can simply run + + mongodump + +which will create a directory structure that can be restored with the `mongorestore` command. + +It is recommended that you first shut down your database. On Debian / Ubuntu it's likely to be: `sudo service mongodb stop` Backing up LevelDB ~~~~~~~~~~~~~~ diff --git a/minifier.js b/minifier.js index b4354db0ba..3bbfcff2e1 100644 --- a/minifier.js +++ b/minifier.js @@ -1,3 +1,5 @@ +"use strict"; + var uglifyjs = require('uglify-js'), less = require('less'), async = require('async'), @@ -9,10 +11,23 @@ var uglifyjs = require('uglify-js'), }; /* Javascript */ -Minifier.js.minify = function (scripts, callback) { +Minifier.js.minify = function (scripts, minify, callback) { + var options = {}; + + if (!minify) { + options.sourceMapURL = '/nodebb.min.js.map'; + options.outSourceMap = 'nodebb.min.js.map'; + options.mangle = false; + options.compress = false; + options.prefix = 6; + } + try { - var minified = uglifyjs.minify(scripts); - callback(minified.code); + var minified = uglifyjs.minify(scripts, options); + callback({ + js: minified.code, + map: minified.map + }); } catch(err) { process.send({ action: 'error', @@ -21,22 +36,22 @@ Minifier.js.minify = function (scripts, callback) { } }; -Minifier.js.concatenate = function(scripts, callback) { - async.map(scripts, function(path, next) { - fs.readFile(path, { encoding: 'utf-8' }, next); - }, function(err, contents) { - if (err) { - process.send({ - action: 'error', - error: err - }); - } else { - callback(contents.reduce(function(output, src) { - return output.length ? output + ';\n' + src : src; - }, '')); - } - }); -}; +// Minifier.js.concatenate = function(scripts, callback) { +// async.map(scripts, function(path, next) { +// fs.readFile(path, { encoding: 'utf-8' }, next); +// }, function(err, contents) { +// if (err) { +// process.send({ +// action: 'error', +// error: err +// }); +// } else { +// callback(contents.reduce(function(output, src) { +// return output.length ? output + ';\n' + src : src; +// }, '')); +// } +// }); +// }; process.on('message', function(payload) { var executeCallback = function(data) { @@ -47,12 +62,8 @@ process.on('message', function(payload) { }; switch(payload.action) { - case 'js.minify': - Minifier.js.minify(payload.scripts, executeCallback); - break; - - case 'js.concatenate': - Minifier.js.concatenate(payload.scripts, executeCallback); + case 'js': + Minifier.js.minify(payload.scripts, payload.minify, executeCallback); break; } -}) +}); diff --git a/package.json b/package.json index 6deb214229..286eadfd3a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "rss": "~0.2.0", "request": "~2.34.0", "prompt": "~0.2.11", - "uglify-js": "~2.4.0", + "uglify-js": "git+https://github.com/julianlam/UglifyJS2.git", "validator": "~3.4.0", "cron": "~1.0.4", "semver": "~2.2.1", diff --git a/public/src/translator.js b/public/src/translator.js index 20d8db2129..d6b753f0ef 100644 --- a/public/src/translator.js +++ b/public/src/translator.js @@ -22,7 +22,7 @@ translator.prepareDOM = function() { // Load the appropriate timeago locale file - if (config.defaultLang !== 'en_GB') { + if (config.defaultLang !== 'en_GB' && config.defaultLang !== 'en_US') { // Correct NodeBB language codes to timeago codes, if necessary var languageCode; switch(config.defaultLang) { diff --git a/src/meta.js b/src/meta.js index 322180c647..9a94046da8 100644 --- a/src/meta.js +++ b/src/meta.js @@ -323,7 +323,8 @@ var fs = require('fs'), minifier.on('message', function(payload) { if (payload.action !== 'error') { winston.info('[meta/js] Compilation complete'); - Meta.js.cache = payload.data; + Meta.js.cache = payload.data.js; + Meta.js.map = payload.data.map; minifier.kill(); } else { winston.error('[meta/js] Could not compile client-side scripts!'); @@ -336,7 +337,8 @@ var fs = require('fs'), Meta.js.loadRJS(function() { Meta.js.prepare(function() { minifier.send({ - action: minify ? 'js.minify' : 'js.concatenate', + action: 'js', + minify: minify, scripts: Meta.js.scripts }); }); diff --git a/src/routes/meta.js b/src/routes/meta.js index 79e757c3af..cfe258022a 100644 --- a/src/routes/meta.js +++ b/src/routes/meta.js @@ -11,18 +11,47 @@ var path = require('path'), function sendMinifiedJS(req, res, next) { + if (!minificationEnabled) { + res.set('X-SourceMap', '/nodebb.min.js.map'); + } + return res.type('text/javascript').send(meta.js.cache); } +function sendSourceMap(req, res) { + return res.type('application/json').send(meta.js.map); +} + function sendStylesheet(req, res, next) { res.type('text/css').send(200, meta.css.cache); } -module.exports = function(app, middleware, controllers) { - minificationEnabled = app.enabled('minification'); +function setupPluginSourceMapping(app) { + /* + These mappings are utilised by the source map file, as client-side + scripts defined in `scripts` in plugin.json are not normally + served to the end-user. These mappings are only accessible via + development mode (`./nodebb dev`) + */ + var routes = plugins.clientScripts, + mapping; + + routes.forEach(function(route) { + mapping = '/' + route.split('/').slice(7).join('/'); + app.get(mapping, function(req, res) { + res.type('text/javascript').sendfile(route); + }); + }); +} +module.exports = function(app, middleware, controllers) { app.get('/stylesheet.css', sendStylesheet); app.get('/nodebb.min.js', sendMinifiedJS); app.get('/sitemap.xml', controllers.sitemap); app.get('/robots.txt', controllers.robots); + + if (!minificationEnabled) { + app.get('/nodebb.min.js.map', sendSourceMap); + setupPluginSourceMapping(app); + } };