diff --git a/src/cli/index.js b/src/cli/index.js index 07efaadf5e..76ceb5b071 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -50,6 +50,7 @@ try { console.warn('Dependencies outdated or not yet installed.'); console.log('Installing them now...\n'); + packageInstall.updatePackageFile(); packageInstall.installAll(); require('colors'); @@ -292,16 +293,12 @@ program } }); -program - .command('*', {}, { - noHelp: true, - }) - .action(function () { - program.help(); - }); - require('./colors'); +if (process.argv.length === 2) { + program.help(); +} + program.executables = false; program.parse(process.argv); diff --git a/src/emailer.js b/src/emailer.js index 10163cc512..a841eb1f91 100644 --- a/src/emailer.js +++ b/src/emailer.js @@ -10,6 +10,7 @@ var htmlToText = require('html-to-text'); var url = require('url'); var path = require('path'); var fs = require('fs'); +var _ = require('lodash'); var User = require('./user'); var Plugins = require('./plugins'); @@ -289,11 +290,10 @@ function buildCustomTemplates(config) { file.walk(viewsDir, next); }, function (paths, next) { - paths = paths.reduce(function (obj, p) { - var relative = path.relative(viewsDir, p); - obj['/' + relative] = p; - return obj; - }, {}); + paths = _.fromPairs(paths.map(function (p) { + var relative = path.relative(viewsDir, p).replace(/\\/g, '/'); + return [relative, p]; + })); meta.templates.processImports(paths, template.path, template.text, next); }, function (source, next) { diff --git a/src/meta/js.js b/src/meta/js.js index ada16d56be..fb3d12f683 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -343,6 +343,11 @@ JS.buildBundle = function (target, fork, callback) { function (next) { getBundleScriptList(target, next); }, + function (files, next) { + mkdirp(path.join(__dirname, '../../build/public'), function (err) { + next(err, files); + }); + }, function (files, next) { var minify = global.env !== 'development'; var filePath = path.join(__dirname, '../../build/public', fileNames[target]); diff --git a/src/meta/templates.js b/src/meta/templates.js index 943978ff56..f8b63d41fa 100644 --- a/src/meta/templates.js +++ b/src/meta/templates.js @@ -7,6 +7,7 @@ var async = require('async'); var path = require('path'); var fs = require('fs'); var nconf = require('nconf'); +var _ = require('lodash'); var plugins = require('../plugins'); var file = require('../file'); @@ -24,7 +25,7 @@ function processImports(paths, templatePath, source, callback) { return callback(null, source); } - var partial = '/' + matches[1]; + var partial = matches[1]; if (paths[partial] && templatePath !== partial) { fs.readFile(paths[partial], 'utf8', function (err, partialSource) { if (err) { @@ -43,124 +44,108 @@ function processImports(paths, templatePath, source, callback) { } Templates.processImports = processImports; -Templates.compile = function (callback) { - callback = callback || function () {}; +function getTemplateDirs(callback) { + var pluginTemplates = _.values(plugins.pluginsData) + .filter(function (pluginData) { + return !pluginData.id.startsWith('nodebb-theme-'); + }) + .map(function (pluginData) { + return path.join(__dirname, '../../node_modules/', pluginData.id, pluginData.templates || 'templates'); + }); var themeConfig = require(nconf.get('theme_config')); - var baseTemplatesPaths = themeConfig.baseTheme ? getBaseTemplates(themeConfig.baseTheme) : [nconf.get('base_templates_path')]; + var theme = themeConfig.baseTheme; + + var themePath; + var themeTemplates = [nconf.get('theme_templates_path')]; + while (theme) { + themePath = path.join(nconf.get('themes_path'), theme); + themeConfig = require(path.join(themePath, 'theme.json')); + + themeTemplates.push(path.join(themePath, themeConfig.templates || 'templates')); + theme = themeConfig.baseTheme; + } + + themeTemplates.push(nconf.get('base_templates_path')); + themeTemplates = _.uniq(themeTemplates.reverse()); + + var coreTemplatesPath = nconf.get('core_templates_path'); + + var templateDirs = _.uniq([coreTemplatesPath].concat(themeTemplates, pluginTemplates)); + + async.filter(templateDirs, file.exists, callback); +} + +function getTemplateFiles(dirs, callback) { + async.waterfall([ + function (cb) { + async.map(dirs, function (dir, next) { + file.walk(dir, function (err, files) { + if (err) { return next(err); } + + files = files.filter(function (path) { + return path.endsWith('.tpl'); + }).map(function (file) { + return { + name: path.relative(dir, file).replace(/\\/g, '/'), + path: file, + }; + }); + next(null, files); + }); + }, cb); + }, + function (buckets, cb) { + var dict = {}; + buckets.forEach(function (files) { + files.forEach(function (file) { + dict[file.name] = file.path; + }); + }); + + cb(null, dict); + }, + ], callback); +} + +function compile(callback) { + callback = callback || function () {}; async.waterfall([ function (next) { - preparePaths(baseTemplatesPaths, next); + rimraf(viewsPath, function (err) { next(err); }); + }, + function (next) { + mkdirp(viewsPath, function (err) { next(err); }); }, - function (paths, next) { - async.each(Object.keys(paths), function (relativePath, next) { + getTemplateDirs, + getTemplateFiles, + function (files, next) { + async.each(Object.keys(files), function (name, next) { + var filePath = files[name]; + async.waterfall([ function (next) { - fs.readFile(paths[relativePath], 'utf8', next); + fs.readFile(filePath, 'utf8', next); }, function (source, next) { - processImports(paths, relativePath, source, next); + processImports(files, name, source, next); }, function (source, next) { - mkdirp(path.join(viewsPath, path.dirname(relativePath)), function (err) { + mkdirp(path.join(viewsPath, path.dirname(name)), function (err) { next(err, source); }); }, function (compiled, next) { - fs.writeFile(path.join(viewsPath, relativePath), compiled, next); + fs.writeFile(path.join(viewsPath, name), compiled, next); }, ], next); }, next); }, - function (next) { - rimraf(path.join(viewsPath, '*.js'), next); - }, function (next) { winston.verbose('[meta/templates] Successfully compiled templates.'); next(); }, ], callback); -}; - -function getBaseTemplates(theme) { - var baseTemplatesPaths = []; - var baseThemePath; - var baseThemeConfig; - - while (theme) { - baseThemePath = path.join(nconf.get('themes_path'), theme); - baseThemeConfig = require(path.join(baseThemePath, 'theme.json')); - - baseTemplatesPaths.push(path.join(baseThemePath, baseThemeConfig.templates || 'templates')); - theme = baseThemeConfig.baseTheme; - } - - return baseTemplatesPaths.reverse(); -} - -function preparePaths(baseTemplatesPaths, callback) { - var coreTemplatesPath = nconf.get('core_templates_path'); - var pluginTemplates; - async.waterfall([ - function (next) { - rimraf(viewsPath, next); - }, - function (next) { - mkdirp(viewsPath, next); - }, - function (viewsPath, next) { - plugins.fireHook('static:templates.precompile', {}, next); - }, - function (next) { - plugins.getTemplates(next); - }, - function (_pluginTemplates, next) { - pluginTemplates = _pluginTemplates; - winston.verbose('[meta/templates] Compiling templates'); - - async.parallel({ - coreTpls: function (next) { - file.walk(coreTemplatesPath, next); - }, - baseThemes: function (next) { - async.map(baseTemplatesPaths, function (baseTemplatePath, next) { - file.walk(baseTemplatePath, function (err, paths) { - paths = paths.map(function (tpl) { - return { - base: baseTemplatePath, - path: tpl.replace(baseTemplatePath, ''), - }; - }); - - next(err, paths); - }); - }, next); - }, - }, next); - }, - function (data, next) { - var baseThemes = data.baseThemes; - var coreTpls = data.coreTpls; - var paths = {}; - - coreTpls.forEach(function (el, i) { - paths[coreTpls[i].replace(coreTemplatesPath, '')] = coreTpls[i]; - }); - - baseThemes.forEach(function (baseTpls) { - baseTpls.forEach(function (el, i) { - paths[baseTpls[i].path] = path.join(baseTpls[i].base, baseTpls[i].path); - }); - }); - - for (var tpl in pluginTemplates) { - if (pluginTemplates.hasOwnProperty(tpl)) { - paths[tpl] = pluginTemplates[tpl]; - } - } - - next(null, paths); - }, - ], callback); } +Templates.compile = compile; diff --git a/src/plugins.js b/src/plugins.js index f11ed63494..a1193125e8 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -138,10 +138,13 @@ Plugins.reloadRoutes = function (callback) { }); }; +// DEPRECATED: remove in v1.8.0 Plugins.getTemplates = function (callback) { var templates = {}; var tplName; + winston.warn('[deprecated] Plugins.getTemplates is DEPRECATED to be removed in v1.8.0'); + Plugins.data.getActive(function (err, plugins) { if (err) { return callback(err);