diff --git a/.gitignore b/.gitignore
index 783b71a23c..ca99d725e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,8 @@ pidfile
/public/admin.css
/public/nodebb.min.js
/public/nodebb.min.js.map
+/public/acp.min.js
+/public/acp.min.js.map
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
diff --git a/src/meta.js b/src/meta.js
index fef6f5def7..7a054b1836 100644
--- a/src/meta.js
+++ b/src/meta.js
@@ -62,7 +62,8 @@ var async = require('async'),
async.apply(plugins.reloadRoutes),
function(next) {
async.parallel([
- async.apply(Meta.js.minify),
+ async.apply(Meta.js.minify, 'nodebb.min.js'),
+ async.apply(Meta.js.minify, 'acp.min.js'),
async.apply(Meta.css.minify),
async.apply(Meta.sounds.init),
async.apply(Meta.templates.compile),
diff --git a/src/meta/js.js b/src/meta/js.js
index 421d14b096..766f65419a 100644
--- a/src/meta/js.js
+++ b/src/meta/js.js
@@ -15,8 +15,7 @@ var winston = require('winston'),
module.exports = function(Meta) {
Meta.js = {
- cache: '',
- map: '',
+ target: {},
scripts: {
base: [
'public/vendor/jquery/js/jquery.js',
@@ -82,7 +81,7 @@ module.exports = function(Meta) {
}
};
- Meta.js.minify = function(callback) {
+ Meta.js.minify = function(target, callback) {
if (nconf.get('isPrimary') !== 'true') {
if (typeof callback === 'function') {
callback();
@@ -94,31 +93,33 @@ module.exports = function(Meta) {
var forkProcessParams = setupDebugging();
var minifier = Meta.js.minifierProc = fork('minifier.js', [], forkProcessParams);
- Meta.js.prepare(function() {
+ Meta.js.target[target] = {};
+
+ Meta.js.prepare(target, function() {
minifier.send({
action: 'js',
minify: global.env !== 'development',
- scripts: Meta.js.scripts.all
+ scripts: Meta.js.target[target].scripts
});
});
minifier.on('message', function(message) {
switch(message.type) {
case 'end':
- Meta.js.cache = message.minified;
- Meta.js.map = message.sourceMap;
+ Meta.js.target[target].cache = message.minified;
+ Meta.js.target[target].map = message.sourceMap;
winston.verbose('[meta/js] Minification complete');
minifier.kill();
if (process.send) {
process.send({
action: 'js-propagate',
- cache: Meta.js.cache,
- map: Meta.js.map
+ cache: Meta.js.target[target].cache,
+ map: Meta.js.target[target].map
});
}
- Meta.js.commitToFile();
+ Meta.js.commitToFile(target);
if (typeof callback === 'function') {
callback();
@@ -137,14 +138,22 @@ module.exports = function(Meta) {
});
};
- Meta.js.prepare = function(callback) {
- async.parallel([
- async.apply(getPluginScripts), // plugin scripts via filter:scripts.get
- function(next) { // client scripts via "scripts" config in plugin.json
- var pluginsScripts = [],
- pluginDirectories = [];
+ Meta.js.prepare = function(target, callback) {
+ var pluginsScripts = [];
- pluginsScripts = plugins.clientScripts.filter(function(path) {
+ async.parallel([
+ function(next) {
+ if (target === 'nodebb.min.js') {
+ getPluginScripts(next);
+ } else {
+ next();
+ }
+ },
+ function(next) {
+ // client scripts via "scripts" config in plugin.json
+ var pluginDirectories = [];
+
+ pluginsScripts = plugins[target === 'nodebb.min.js' ? 'clientScripts' : 'acpScripts'].filter(function(path) {
if (path.endsWith('.js')) {
return true;
} else {
@@ -153,13 +162,9 @@ module.exports = function(Meta) {
}
});
- // Add plugin scripts
- Meta.js.scripts.client = pluginsScripts;
-
- // Add plugin script directories
async.each(pluginDirectories, function(directory, next) {
utils.walk(directory, function(err, scripts) {
- Meta.js.scripts.client = Meta.js.scripts.client.concat(scripts);
+ pluginsScripts = pluginsScripts.concat(scripts);
next(err);
});
}, next);
@@ -171,9 +176,17 @@ module.exports = function(Meta) {
// Convert all scripts to paths relative to the NodeBB base directory
var basePath = path.resolve(__dirname, '../..');
- Meta.js.scripts.all = Meta.js.scripts.base.concat(Meta.js.scripts.rjs, Meta.js.scripts.plugin, Meta.js.scripts.client).map(function(script) {
+
+ if (target === 'nodebb.min.js') {
+ Meta.js.target[target].scripts = Meta.js.scripts.base.concat(pluginsScripts, Meta.js.scripts.rjs, Meta.js.scripts.plugin);
+ } else {
+ Meta.js.target[target].scripts = pluginsScripts;
+ }
+
+ Meta.js.target[target].scripts = Meta.js.target[target].scripts.map(function(script) {
return path.relative(basePath, script).replace(/\\/g, '/');
});
+
callback();
});
};
@@ -184,8 +197,8 @@ module.exports = function(Meta) {
}
};
- Meta.js.commitToFile = function() {
- fs.writeFile(path.join(__dirname, '../../public/nodebb.min.js'), Meta.js.cache, function (err) {
+ Meta.js.commitToFile = function(target) {
+ fs.writeFile(path.join(__dirname, '../../public/' + target), Meta.js.target[target].cache, function (err) {
if (err) {
winston.error('[meta/js] ' + err.message);
process.exit(0);
@@ -196,14 +209,15 @@ module.exports = function(Meta) {
});
};
- Meta.js.getFromFile = function(callback) {
- var scriptPath = path.join(__dirname, '../../public/nodebb.min.js'),
- mapPath = path.join(__dirname, '../../public/nodebb.min.js.map'),
+ Meta.js.getFromFile = function(target, callback) {
+ var scriptPath = path.join(__dirname, '../../public/' + target),
+ mapPath = path.join(__dirname, '../../public/' + target + '.map'),
paths = [scriptPath];
+
file.exists(scriptPath, function(exists) {
if (!exists) {
winston.warn('[meta/js] No script file found on disk, re-minifying');
- Meta.js.minify(callback);
+ Meta.js.minify(target, callback);
return;
}
@@ -218,8 +232,10 @@ module.exports = function(Meta) {
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] || '';
+ Meta.js.target[target] = {
+ cache: files[0],
+ map: files[1] || ''
+ };
emitter.emit('meta:js.compiled');
callback();
diff --git a/src/plugins.js b/src/plugins.js
index 61cbc65532..3e8669b08b 100644
--- a/src/plugins.js
+++ b/src/plugins.js
@@ -30,6 +30,7 @@ var fs = require('fs'),
Plugins.cssFiles = [];
Plugins.lessFiles = [];
Plugins.clientScripts = [];
+ Plugins.acpScripts = [];
Plugins.customLanguages = [];
Plugins.customLanguageFallbacks = {};
Plugins.libraryPaths = [];
@@ -81,6 +82,7 @@ var fs = require('fs'),
Plugins.cssFiles.length = 0;
Plugins.lessFiles.length = 0;
Plugins.clientScripts.length = 0;
+ Plugins.acpScripts.length = 0;
Plugins.libraryPaths.length = 0;
Plugins.registerHook('core', {
diff --git a/src/plugins/load.js b/src/plugins/load.js
index 90775c64d8..cf1ff27d9a 100644
--- a/src/plugins/load.js
+++ b/src/plugins/load.js
@@ -152,6 +152,16 @@ module.exports = function(Plugins) {
}));
}
+ if (Array.isArray(pluginData.acpScripts)) {
+ if (global.env === 'development') {
+ winston.verbose('[plugins] Found ' + pluginData.acpScripts.length + ' js file(s) for plugin ' + pluginData.id);
+ }
+
+ Plugins.acpScripts = Plugins.acpScripts.concat(pluginData.acpScripts.map(function(file) {
+ return path.join(__dirname, '../../node_modules/', pluginData.id, file);
+ }));
+ }
+
callback();
}
diff --git a/src/routes/meta.js b/src/routes/meta.js
index 61e22e2be0..5fe767ce21 100644
--- a/src/routes/meta.js
+++ b/src/routes/meta.js
@@ -5,7 +5,7 @@ var meta = require('../meta'),
function sendMinifiedJS(req, res, next) {
- res.type('text/javascript').send(meta.js.cache);
+ res.type('text/javascript').send(meta.js.target['nodebb.min.js'].cache);
}
// The portions of code involving the source map are commented out as they're broken in UglifyJS2
diff --git a/src/views/admin/header.tpl b/src/views/admin/header.tpl
index 9ac8762a5e..bdcdf14ee4 100644
--- a/src/views/admin/header.tpl
+++ b/src/views/admin/header.tpl
@@ -31,6 +31,7 @@
+