mmir-tooling
Version:
Build tools for MMIR projects
263 lines (262 loc) • 11.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const filepath_utils_1 = __importDefault(require("../utils/filepath-utils"));
const module_config_init_1 = __importDefault(require("../utils/module-config-init"));
const directories_utils_1 = __importDefault(require("../tools/directories-utils"));
const option_utils_1 = __importDefault(require("../tools/option-utils"));
const log_utils_1 = __importDefault(require("../utils/log-utils"));
const type_utils_1 = require("../tools/type-utils");
const log = log_utils_1.default.log;
const warn = log_utils_1.default.warn;
var VirtualModulePlugin;
function initVirtualModulePlugin() {
if (!VirtualModulePlugin) {
try {
VirtualModulePlugin = require('webpack-virtual-modules');
}
catch (err) {
warn('view-utils: failed to initialize webpack-virtual-modules ', err);
}
}
return !!VirtualModulePlugin;
}
function isPartialView(name) {
return name.charAt(0) == '~';
}
;
var regExprFileExt = /\.ehtml$/i;
function readDir(dir, list, options) {
const files = fs_extra_1.default.readdirSync(dir);
const dirs = [];
// log('read dir "'+dir+'" -> ', files);
files.forEach(function (p) {
var absPath = path_1.default.join(dir, p);
if (filepath_utils_1.default.isDirectory(absPath)) {
var name = path_1.default.basename(absPath);
var isLayout = /layouts/i.test(name);
if (!isLayout && name) {
name = name[0].toUpperCase() + name.substring(1);
}
dirs.push({ dir: absPath, ctrlName: name, isLayout: isLayout });
}
else {
warn('view-utils.addFromDirectory(): unknow file in view root path: ', absPath);
}
});
// log('read sub-dirs -> ', dirs);
var size = dirs.length;
if (size > 0) {
for (var i = 0; i < size; ++i) {
readSubDir(dirs[i], list, options);
}
}
}
function readSubDir(dirs, list, options) {
var dir = dirs.dir;
var files = fs_extra_1.default.readdirSync(dir);
// log('read dir "'+dir+'" -> ', files);
files.forEach(function (p) {
var absPath = path_1.default.join(dir, p);
if (filepath_utils_1.default.isDirectory(absPath)) {
warn('view-utils.addFromDirectory(): invalid sub-directory in view-directory: ', absPath);
}
else if (regExprFileExt.test(absPath)) {
var normalized = filepath_utils_1.default.normalizePath(absPath);
var fileName = path_1.default.basename(normalized).replace(/\.ehtml/i, '');
var isLayout = dirs.isLayout;
var isPartial = false;
let ctrlName, viewName;
if (isLayout && fileName) {
ctrlName = fileName[0].toUpperCase() + fileName.substring(1);
viewName = ctrlName;
}
else {
ctrlName = dirs.ctrlName;
viewName = fileName;
isPartial = isPartialView(viewName);
if (isPartial) {
viewName = viewName.substring(1);
}
}
var id = dirs.ctrlName.toLowerCase() + '/' + fileName;
var opt = options && options[id];
list.push({
id: id,
ctrlName: ctrlName,
viewName: viewName,
file: normalized,
viewImpl: isLayout ? 'mmirf/layout' : isPartial ? 'mmirf/partial' : 'mmirf/view',
isLayout: isLayout,
isPartial: isPartial,
strict: opt && typeof opt.strict === 'boolean' ? opt.strict : void (0)
});
}
else {
warn('view-utils.addFromDirectory(): unknown view template file: ', absPath);
}
});
// log('results for dir "'+dir+'" -> ', ids, views);
}
function toAliasPath(view) {
return path_1.default.normalize(view.file); //.replace(/\.ehtml$/i, '')
}
function toAliasId(view) {
return 'mmirf/view/' + view.id; //FIXME formalize IDs for loading views in webpack (?)
}
function containsCtrl(ctrlName, ctrlList) {
return ctrlList.findIndex(function (c) {
return c.name === ctrlName;
}) !== -1;
}
function addCtrlStub(view, ctrlList, ctrlMap) {
if (view.isLayout) {
return;
}
if (containsCtrl(view.ctrlName, ctrlList)) {
return;
}
var ctrl = ctrlMap.get(view.ctrlName);
var isDebug = true; //DEBUG TODO make configurable/settable via options
if (!ctrl) {
ctrl = {
moduleName: 'mmirf/controller/' + view.ctrlName[0].toLowerCase() + view.ctrlName.substring(1),
contents: 'function ' + view.ctrlName + '(){' + (isDebug ? 'console.log("created stub controller ' + view.ctrlName + '");' : '') + '}; ' +
view.ctrlName + '.prototype.on_page_load = function(){' + (isDebug ? 'console.log("invoked on_page_load() on stub controller ' + view.ctrlName + '");' : '') + '};' +
// 'window.'+view.ctrlName+' = '+view.ctrlName+';' +
'module.exports = ' + view.ctrlName + ';'
};
ctrlMap.set(view.ctrlName, ctrl);
}
}
module.exports = {
/**
* add views from a base-directory that adheres to the structure:
* <pre>
* <dir>/<controller name 1>/view1.ehtml
* /view2.ehtml
* ...
* <dir>/<controller name 2>/view1.ehtml
* /view2.ehtml
* ...
* ...
* <dir>/layouts/default.ehtml
* /<controller name 1>.ehtml
* ...
* </pre>
* @param {String} dir the direcotry from which to parse/collect the views
* @param {String} appRootDir the root directory of the app (against which relative paths will be resolved)
* @param {ViewOptionMap} [options] OPTIONAL
* unsupported TODO
* @return {Array<ViewEntry>} a list of ViewEntry objects:
* {
* id: String
* ctrlName: String,
* viewName: String,
* file: String,
* viewImpl: 'mmirf/layout' | 'mmirf/partial' | 'mmirf/view',
* isLayout: Boolean
* isPartial: Boolean
* }
*/
viewTemplatesFromDir: function (dir, appRootDir, options) {
if (!path_1.default.isAbsolute(dir)) {
dir = path_1.default.resolve(appRootDir, dir);
}
var list = [];
readDir(dir, list, options);
return list;
},
/**
* apply the "global" options from `options` or default values to the entries
* from `viewList` if its corresponding options-field is not explicitly specified.
*
* @param {ViewOptions} options the view options
* @param {{Array<ViewEntry>}} viewList
* @return {{Array<ViewEntry>}}
*/
applyDefaultOptions: function (options, viewList) {
//TODO impl. if/when addFromOpitions is implemented...
viewList.forEach(function (v) {
[
// {name: 'ignoreErrors', defaultValue: false}, //TODO impl. if/when addFromOpitions is implemented...
// {name: 'force', defaultValue: false}, //TODO impl. if/when addFromOpitions is implemented...
{ name: 'strict', defaultValue: true }
].forEach(function (fieldInfo) {
option_utils_1.default.applySetting(fieldInfo.name, v, options, fieldInfo.defaultValue);
});
});
return viewList;
},
/**
* add views to (webpack) app build configuration
*
* @param {Array<ViewEntry>} view list of ViewEntry objects:
* view.id {String}: the view id
* view.file {String}: the path to the eHTML view template (from which the executable view will be created)
* @param {Array<ControllerEntry>} ctrls list of ControllerEntry objects:
* ctrl.id {String}: the controller id
* @param {[type]} appConfig the app configuration to which the views will be added
* @param {[type]} directories the directories.json representation
* @param {ResourcesConfig} resources the resources configuration
* @param {[type]} runtimeConfiguration the configuration.json representation
*/
addViewsToAppConfig: function (views, ctrls, appConfig, directories, resources, _runtimeConfiguration) {
if (!views || views.length < 1) {
return;
}
var stubCtrlMap = new Map();
views.forEach(function (v) {
var aliasId = toAliasId(v);
if ((0, type_utils_1.isWebpackConfig)(appConfig)) {
module_config_init_1.default.addIncludeModule(appConfig, aliasId, toAliasPath(v));
}
directories_utils_1.default.addView(directories, aliasId);
if (appConfig.includeViewTemplates) {
directories_utils_1.default.addViewTemplate(directories, aliasId);
}
addCtrlStub(v, ctrls, stubCtrlMap);
});
//FIXME set simpleViewEngine TODO support setting engine via appConfig
resources.paths['mmirf/simpleViewEngine'] = 'env/view/simpleViewEngine';
if (!(0, type_utils_1.isWebpackConfig)(appConfig)) {
return;
}
// include dependencies for loading & rendering views:
appConfig.includeModules.push('mmirf/storageUtils', 'mmirf/renderUtils');
appConfig.includeModules.push('mmirf/yield', 'mmirf/layout', 'mmirf/view', 'mmirf/partial'); //TODO only include types that were actually parsed
if (!appConfig.paths) {
appConfig.paths = {};
}
// replace default viewLoader with webpack-viewLoader:
appConfig.paths['mmirf/viewLoader'] = path_1.default.resolve(__dirname, '..', 'runtime', 'webpackViewLoader.js');
//add generated stub controllers if necessary:
if (stubCtrlMap.size > 0 && appConfig.controllers !== false) {
if (initVirtualModulePlugin()) {
if (!appConfig.webpackPlugins) {
appConfig.webpackPlugins = [];
}
var virtualModules = {};
stubCtrlMap.forEach(function (ctrl, name) {
var id = ctrl.moduleName;
log('view-utils: adding view controller stub "' + name + '": ', id, ' -> ', ctrl); //DEBUG
// appConfig.paths[id] = id;// path.resolve('./viewParser/webpackGenCtrl.js');
// appConfig.includeModules.push(id);
module_config_init_1.default.addIncludeModule(appConfig, id, id);
directories_utils_1.default.addCtrl(directories, ctrl.moduleName);
virtualModules[ctrl.moduleName] = ctrl.contents;
});
appConfig.webpackPlugins.push(new VirtualModulePlugin(virtualModules));
}
else {
warn('view-utils: cannot add stub controllers, because of misssing package virtual-module-webpack-plugin');
}
}
},
// getCtrlImpl: function(){
// return controllers.slice();
// }
};