|
|
|
@ -1,25 +1,22 @@
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var path = require('path');
|
|
|
|
|
var async = require('async');
|
|
|
|
|
var fs = require('fs');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const fs = require('fs');
|
|
|
|
|
const util = require('util');
|
|
|
|
|
var mkdirp = require('mkdirp');
|
|
|
|
|
var mkdirpCallback;
|
|
|
|
|
if (mkdirp.hasOwnProperty('native')) {
|
|
|
|
|
mkdirpCallback = util.callbackify(mkdirp);
|
|
|
|
|
} else {
|
|
|
|
|
mkdirpCallback = mkdirp;
|
|
|
|
|
let mkdirp = require('mkdirp');
|
|
|
|
|
// TODO: remove in 1.16.0
|
|
|
|
|
if (!mkdirp.hasOwnProperty('native')) {
|
|
|
|
|
mkdirp = util.promisify(mkdirp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var rimraf = require('rimraf');
|
|
|
|
|
const rimraf = require('rimraf');
|
|
|
|
|
const rimrafAsync = util.promisify(rimraf);
|
|
|
|
|
|
|
|
|
|
var file = require('../file');
|
|
|
|
|
var plugins = require('../plugins');
|
|
|
|
|
var minifier = require('./minifier');
|
|
|
|
|
const file = require('../file');
|
|
|
|
|
const plugins = require('../plugins');
|
|
|
|
|
const minifier = require('./minifier');
|
|
|
|
|
|
|
|
|
|
var JS = module.exports;
|
|
|
|
|
const JS = module.exports;
|
|
|
|
|
|
|
|
|
|
JS.scripts = {
|
|
|
|
|
base: [
|
|
|
|
@ -109,93 +106,74 @@ JS.scripts = {
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function linkIfLinux(srcPath, destPath, next) {
|
|
|
|
|
async function linkIfLinux(srcPath, destPath) {
|
|
|
|
|
if (process.platform === 'win32') {
|
|
|
|
|
fs.copyFile(srcPath, destPath, next);
|
|
|
|
|
await fs.promises.copyFile(srcPath, destPath);
|
|
|
|
|
} else {
|
|
|
|
|
file.link(srcPath, destPath, true, next);
|
|
|
|
|
await file.link(srcPath, destPath, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var basePath = path.resolve(__dirname, '../..');
|
|
|
|
|
const basePath = path.resolve(__dirname, '../..');
|
|
|
|
|
|
|
|
|
|
function minifyModules(modules, fork, callback) {
|
|
|
|
|
var moduleDirs = modules.reduce(function (prev, mod) {
|
|
|
|
|
var dir = path.resolve(path.dirname(mod.destPath));
|
|
|
|
|
async function minifyModules(modules, fork) {
|
|
|
|
|
const moduleDirs = modules.reduce(function (prev, mod) {
|
|
|
|
|
const dir = path.resolve(path.dirname(mod.destPath));
|
|
|
|
|
if (!prev.includes(dir)) {
|
|
|
|
|
prev.push(dir);
|
|
|
|
|
}
|
|
|
|
|
return prev;
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
async.each(moduleDirs, mkdirpCallback, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
await Promise.all(moduleDirs.map(dir => mkdirp(dir)));
|
|
|
|
|
|
|
|
|
|
var filtered = modules.reduce(function (prev, mod) {
|
|
|
|
|
if (mod.srcPath.endsWith('.min.js') || path.dirname(mod.srcPath).endsWith('min')) {
|
|
|
|
|
prev.skip.push(mod);
|
|
|
|
|
} else {
|
|
|
|
|
prev.minify.push(mod);
|
|
|
|
|
}
|
|
|
|
|
const filtered = modules.reduce(function (prev, mod) {
|
|
|
|
|
if (mod.srcPath.endsWith('.min.js') || path.dirname(mod.srcPath).endsWith('min')) {
|
|
|
|
|
prev.skip.push(mod);
|
|
|
|
|
} else {
|
|
|
|
|
prev.minify.push(mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return prev;
|
|
|
|
|
}, { minify: [], skip: [] });
|
|
|
|
|
return prev;
|
|
|
|
|
}, { minify: [], skip: [] });
|
|
|
|
|
|
|
|
|
|
async.parallel([
|
|
|
|
|
function (cb) {
|
|
|
|
|
minifier.js.minifyBatch(filtered.minify, fork, cb);
|
|
|
|
|
},
|
|
|
|
|
function (cb) {
|
|
|
|
|
async.each(filtered.skip, function (mod, next) {
|
|
|
|
|
linkIfLinux(mod.srcPath, mod.destPath, next);
|
|
|
|
|
}, cb);
|
|
|
|
|
},
|
|
|
|
|
], callback);
|
|
|
|
|
});
|
|
|
|
|
await Promise.all([
|
|
|
|
|
minifier.js.minifyBatch(filtered.minify, fork),
|
|
|
|
|
...filtered.skip.map(mod => linkIfLinux(mod.srcPath, mod.destPath)),
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function linkModules(callback) {
|
|
|
|
|
var modules = JS.scripts.modules;
|
|
|
|
|
async function linkModules() {
|
|
|
|
|
const modules = JS.scripts.modules;
|
|
|
|
|
|
|
|
|
|
async.each(Object.keys(modules), function (relPath, next) {
|
|
|
|
|
var srcPath = path.join(__dirname, '../../', modules[relPath]);
|
|
|
|
|
var destPath = path.join(__dirname, '../../build/public/src/modules', relPath);
|
|
|
|
|
await Promise.all(Object.keys(modules).map(async function (relPath) {
|
|
|
|
|
const srcPath = path.join(__dirname, '../../', modules[relPath]);
|
|
|
|
|
const destPath = path.join(__dirname, '../../build/public/src/modules', relPath);
|
|
|
|
|
const [stats] = await Promise.all([
|
|
|
|
|
fs.promises.stat(srcPath),
|
|
|
|
|
mkdirp(path.dirname(destPath)),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
async.parallel({
|
|
|
|
|
dir: function (cb) {
|
|
|
|
|
mkdirpCallback(path.dirname(destPath), function (err) {
|
|
|
|
|
cb(err);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
stats: function (cb) {
|
|
|
|
|
fs.stat(srcPath, cb);
|
|
|
|
|
},
|
|
|
|
|
}, function (err, res) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
if (res.stats.isDirectory()) {
|
|
|
|
|
return file.linkDirs(srcPath, destPath, true, next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linkIfLinux(srcPath, destPath, next);
|
|
|
|
|
});
|
|
|
|
|
}, callback);
|
|
|
|
|
if (stats.isDirectory()) {
|
|
|
|
|
await file.linkDirs(srcPath, destPath, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await linkIfLinux(srcPath, destPath);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var moduleDirs = ['modules', 'admin', 'client'];
|
|
|
|
|
const moduleDirs = ['modules', 'admin', 'client'];
|
|
|
|
|
|
|
|
|
|
function getModuleList(callback) {
|
|
|
|
|
var modules = Object.keys(JS.scripts.modules).map(function (relPath) {
|
|
|
|
|
async function getModuleList() {
|
|
|
|
|
let modules = Object.keys(JS.scripts.modules).map(function (relPath) {
|
|
|
|
|
return {
|
|
|
|
|
srcPath: path.join(__dirname, '../../', JS.scripts.modules[relPath]),
|
|
|
|
|
destPath: path.join(__dirname, '../../build/public/src/modules', relPath),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var coreDirs = moduleDirs.map(function (dir) {
|
|
|
|
|
const coreDirs = moduleDirs.map(function (dir) {
|
|
|
|
|
return {
|
|
|
|
|
srcPath: path.join(__dirname, '../../public/src', dir),
|
|
|
|
|
destPath: path.join(__dirname, '../../build/public/src', dir),
|
|
|
|
@ -204,75 +182,55 @@ function getModuleList(callback) {
|
|
|
|
|
|
|
|
|
|
modules = modules.concat(coreDirs);
|
|
|
|
|
|
|
|
|
|
var moduleFiles = [];
|
|
|
|
|
async.each(modules, function (module, next) {
|
|
|
|
|
var srcPath = module.srcPath;
|
|
|
|
|
var destPath = module.destPath;
|
|
|
|
|
|
|
|
|
|
fs.stat(srcPath, function (err, stats) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
if (!stats.isDirectory()) {
|
|
|
|
|
moduleFiles.push(module);
|
|
|
|
|
return next();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file.walk(srcPath, function (err, files) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mods = files.filter(function (filePath) {
|
|
|
|
|
return path.extname(filePath) === '.js';
|
|
|
|
|
}).map(function (filePath) {
|
|
|
|
|
return {
|
|
|
|
|
srcPath: path.normalize(filePath),
|
|
|
|
|
destPath: path.join(destPath, path.relative(srcPath, filePath)),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
moduleFiles = moduleFiles.concat(mods).map(function (mod) {
|
|
|
|
|
mod.filename = path.relative(basePath, mod.srcPath).replace(/\\/g, '/');
|
|
|
|
|
return mod;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
const moduleFiles = [];
|
|
|
|
|
await Promise.all(modules.map(async function (module) {
|
|
|
|
|
const srcPath = module.srcPath;
|
|
|
|
|
const destPath = module.destPath;
|
|
|
|
|
|
|
|
|
|
const stats = await fs.promises.stat(srcPath);
|
|
|
|
|
if (!stats.isDirectory()) {
|
|
|
|
|
moduleFiles.push(module);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const files = await file.walk(srcPath);
|
|
|
|
|
|
|
|
|
|
const mods = files.filter(
|
|
|
|
|
filePath => path.extname(filePath) === '.js'
|
|
|
|
|
).map(function (filePath) {
|
|
|
|
|
return {
|
|
|
|
|
srcPath: path.normalize(filePath),
|
|
|
|
|
destPath: path.join(destPath, path.relative(srcPath, filePath)),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}, function (err) {
|
|
|
|
|
callback(err, moduleFiles);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearModules(callback) {
|
|
|
|
|
var builtPaths = moduleDirs.map(function (p) {
|
|
|
|
|
return path.join(__dirname, '../../build/public/src', p);
|
|
|
|
|
});
|
|
|
|
|
async.each(builtPaths, function (builtPath, next) {
|
|
|
|
|
rimraf(builtPath, next);
|
|
|
|
|
}, function (err) {
|
|
|
|
|
callback(err);
|
|
|
|
|
});
|
|
|
|
|
moduleFiles.concat(mods).forEach(function (mod) {
|
|
|
|
|
mod.filename = path.relative(basePath, mod.srcPath).replace(/\\/g, '/');
|
|
|
|
|
});
|
|
|
|
|
}));
|
|
|
|
|
return moduleFiles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS.buildModules = function (fork, callback) {
|
|
|
|
|
async.waterfall([
|
|
|
|
|
clearModules,
|
|
|
|
|
function (next) {
|
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
|
|
|
return linkModules(callback);
|
|
|
|
|
}
|
|
|
|
|
async function clearModules() {
|
|
|
|
|
const builtPaths = moduleDirs.map(
|
|
|
|
|
p => path.join(__dirname, '../../build/public/src', p)
|
|
|
|
|
);
|
|
|
|
|
await Promise.all(
|
|
|
|
|
builtPaths.map(builtPath => rimrafAsync(builtPath))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getModuleList(next);
|
|
|
|
|
},
|
|
|
|
|
function (modules, next) {
|
|
|
|
|
minifyModules(modules, fork, next);
|
|
|
|
|
},
|
|
|
|
|
], callback);
|
|
|
|
|
JS.buildModules = async function (fork) {
|
|
|
|
|
await clearModules();
|
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
|
|
|
await linkModules();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const modules = await getModuleList();
|
|
|
|
|
await minifyModules(modules, fork);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function requirejsOptimize(target, callback) {
|
|
|
|
|
async function requirejsOptimize(target) {
|
|
|
|
|
const requirejs = require('requirejs');
|
|
|
|
|
let scriptText = '';
|
|
|
|
|
const sharedCfg = {
|
|
|
|
@ -305,52 +263,41 @@ function requirejsOptimize(target, callback) {
|
|
|
|
|
name: 'Sortable',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
client: [
|
|
|
|
|
|
|
|
|
|
],
|
|
|
|
|
client: [],
|
|
|
|
|
};
|
|
|
|
|
async.eachSeries(bundledModules.concat(targetModules[target]), function (moduleCfg, next) {
|
|
|
|
|
requirejs.optimize({ ...sharedCfg, ...moduleCfg }, function () {
|
|
|
|
|
next();
|
|
|
|
|
}, function (err) {
|
|
|
|
|
next(err);
|
|
|
|
|
});
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
const filePath = path.join(__dirname, '../../build/public/rjs-bundle-' + target + '.js');
|
|
|
|
|
fs.writeFile(filePath, scriptText, callback);
|
|
|
|
|
const optimizeAsync = util.promisify(function (config, cb) {
|
|
|
|
|
requirejs.optimize(config, () => cb(), err => cb(err));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const allModules = bundledModules.concat(targetModules[target]);
|
|
|
|
|
|
|
|
|
|
for (const moduleCfg of allModules) {
|
|
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
|
|
|
await optimizeAsync({ ...sharedCfg, ...moduleCfg });
|
|
|
|
|
}
|
|
|
|
|
const filePath = path.join(__dirname, '../../build/public/rjs-bundle-' + target + '.js');
|
|
|
|
|
await fs.promises.writeFile(filePath, scriptText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS.linkStatics = function (callback) {
|
|
|
|
|
rimraf(path.join(__dirname, '../../build/public/plugins'), function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
async.each(Object.keys(plugins.staticDirs), function (mappedPath, next) {
|
|
|
|
|
var sourceDir = plugins.staticDirs[mappedPath];
|
|
|
|
|
var destDir = path.join(__dirname, '../../build/public/plugins', mappedPath);
|
|
|
|
|
|
|
|
|
|
mkdirpCallback(path.dirname(destDir), function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file.linkDirs(sourceDir, destDir, true, next);
|
|
|
|
|
});
|
|
|
|
|
}, callback);
|
|
|
|
|
});
|
|
|
|
|
JS.linkStatics = async function () {
|
|
|
|
|
await rimrafAsync(path.join(__dirname, '../../build/public/plugins'));
|
|
|
|
|
|
|
|
|
|
await Promise.all(Object.keys(plugins.staticDirs).map(async function (mappedPath) {
|
|
|
|
|
const sourceDir = plugins.staticDirs[mappedPath];
|
|
|
|
|
const destDir = path.join(__dirname, '../../build/public/plugins', mappedPath);
|
|
|
|
|
|
|
|
|
|
await mkdirp(path.dirname(destDir));
|
|
|
|
|
await file.linkDirs(sourceDir, destDir, true);
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function getBundleScriptList(target, callback) {
|
|
|
|
|
var pluginDirectories = [];
|
|
|
|
|
async function getBundleScriptList(target) {
|
|
|
|
|
const pluginDirectories = [];
|
|
|
|
|
|
|
|
|
|
if (target === 'admin') {
|
|
|
|
|
target = 'acp';
|
|
|
|
|
}
|
|
|
|
|
var pluginScripts = plugins[target + 'Scripts'].filter(function (path) {
|
|
|
|
|
let pluginScripts = plugins[target + 'Scripts'].filter(function (path) {
|
|
|
|
|
if (path.endsWith('.js')) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -359,73 +306,51 @@ function getBundleScriptList(target, callback) {
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
async.each(pluginDirectories, function (directory, next) {
|
|
|
|
|
file.walk(directory, function (err, scripts) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
await Promise.all(pluginDirectories.map(async function (directory) {
|
|
|
|
|
const scripts = await file.walk(directory);
|
|
|
|
|
pluginScripts = pluginScripts.concat(scripts);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
pluginScripts = pluginScripts.concat(scripts);
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var scripts = JS.scripts.base;
|
|
|
|
|
|
|
|
|
|
if (target === 'client' && process.env.NODE_ENV !== 'development') {
|
|
|
|
|
scripts = scripts.concat(JS.scripts.rjs);
|
|
|
|
|
} else if (target === 'acp') {
|
|
|
|
|
scripts = scripts.concat(JS.scripts.admin);
|
|
|
|
|
}
|
|
|
|
|
let scripts = JS.scripts.base;
|
|
|
|
|
|
|
|
|
|
scripts = scripts.concat(pluginScripts).map(function (script) {
|
|
|
|
|
var srcPath = path.resolve(basePath, script).replace(/\\/g, '/');
|
|
|
|
|
return {
|
|
|
|
|
srcPath: srcPath,
|
|
|
|
|
filename: path.relative(basePath, srcPath).replace(/\\/g, '/'),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
if (target === 'client' && process.env.NODE_ENV !== 'development') {
|
|
|
|
|
scripts = scripts.concat(JS.scripts.rjs);
|
|
|
|
|
} else if (target === 'acp') {
|
|
|
|
|
scripts = scripts.concat(JS.scripts.admin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
callback(null, scripts);
|
|
|
|
|
scripts = scripts.concat(pluginScripts).map(function (script) {
|
|
|
|
|
const srcPath = path.resolve(basePath, script).replace(/\\/g, '/');
|
|
|
|
|
return {
|
|
|
|
|
srcPath: srcPath,
|
|
|
|
|
filename: path.relative(basePath, srcPath).replace(/\\/g, '/'),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return scripts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS.buildBundle = function (target, fork, callback) {
|
|
|
|
|
var fileNames = {
|
|
|
|
|
JS.buildBundle = async function (target, fork) {
|
|
|
|
|
const fileNames = {
|
|
|
|
|
client: 'nodebb.min.js',
|
|
|
|
|
admin: 'acp.min.js',
|
|
|
|
|
};
|
|
|
|
|
await requirejsOptimize(target);
|
|
|
|
|
const files = await getBundleScriptList(target);
|
|
|
|
|
await mkdirp(path.join(__dirname, '../../build/public'));
|
|
|
|
|
|
|
|
|
|
async.waterfall([
|
|
|
|
|
function (next) {
|
|
|
|
|
requirejsOptimize(target, next);
|
|
|
|
|
},
|
|
|
|
|
function (next) {
|
|
|
|
|
getBundleScriptList(target, next);
|
|
|
|
|
},
|
|
|
|
|
function (files, next) {
|
|
|
|
|
mkdirpCallback(path.join(__dirname, '../../build/public'), function (err) {
|
|
|
|
|
next(err, files);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
function (files, next) {
|
|
|
|
|
files.push({
|
|
|
|
|
srcPath: path.join(__dirname, '../../build/public/rjs-bundle-' + target + '.js'),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var minify = process.env.NODE_ENV !== 'development';
|
|
|
|
|
var filePath = path.join(__dirname, '../../build/public', fileNames[target]);
|
|
|
|
|
|
|
|
|
|
minifier.js.bundle({
|
|
|
|
|
files: files,
|
|
|
|
|
filename: fileNames[target],
|
|
|
|
|
destPath: filePath,
|
|
|
|
|
}, minify, fork, next);
|
|
|
|
|
},
|
|
|
|
|
], callback);
|
|
|
|
|
files.push({
|
|
|
|
|
srcPath: path.join(__dirname, '../../build/public/rjs-bundle-' + target + '.js'),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const minify = process.env.NODE_ENV !== 'development';
|
|
|
|
|
const filePath = path.join(__dirname, '../../build/public', fileNames[target]);
|
|
|
|
|
|
|
|
|
|
await minifier.js.bundle({
|
|
|
|
|
files: files,
|
|
|
|
|
filename: fileNames[target],
|
|
|
|
|
destPath: filePath,
|
|
|
|
|
}, minify, fork);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
JS.killMinifier = function () {
|
|
|
|
|