toloframework
Version: 
Javascript/HTML/CSS compiler for Firefox OS or nodewebkit apps using modules in the nodejs style.
153 lines (140 loc) • 4.89 kB
JavaScript
var FS = require("fs");
var Libs = require("./compiler-com-libs");
var Path = require("path");
var Tree = require("./htmltree");
var Fatal = require("./fatal");
var Utils = require("./pathutils");
var Source = require("./source");
var Components = [];
var TagRegExps = [];
/**
 * Loading and sorting all components.
 */
exports.loadComponents = function(prj) {
    var pathes = [prj.srcPath("com")];
    prj.getExtraModulesPath().forEach(
        function(extraModulePath) {
            pathes.push(Path.join(extraModulePath, "com"));
        }
    );
    pathes.push(prj.libPath("com"));
    Components = [];
    TagRegExps = [];
    // Store  here all  found components  to prevent  from loading  them
    // twice  if there  are in  several folders.   The first  folder has
    // priority.
    var foundComponents = [];
    
    pathes.forEach(function (path) {
        var components = [];
        Utils.findFilesByExtension(path, ".com.js").forEach(function (comPath) {
            var name = Path.relative(path, comPath);
            var id = Path.basename(comPath);
            id = id.substr(0, id.length - 7);
            
            if (foundComponents.indexOf(name) > -1) {
                // Already loaded.
                return;
            }
            foundComponents.push(name);
            //console.log("com> ", comPath.bold);
            var com;
            try {
                com = require(comPath);
            }
            catch (ex) {
                Fatal.bubble(ex, comPath);
            }
            com.$ = { path: comPath, name: name, id: id };
            // Look for relative CSS file.
            var cssName = com.$.name.substr(0, com.$.name.length - 3) + ".css";
            var cssPath = prj.srcOrLibPath(Path.join("com", cssName));            
            if (FS.existsSync(cssPath)) {
                com.$.css = FS.readFileSync(cssPath).toString();
                //console.info("Component CSS: ", cssPath);
            }
            // Look for resource. In a folder with the name of the component.
            var resPath = comPath.substr(0, comPath.length - 3);
            if (FS.existsSync(resPath)) {
                com.$.res = Path.join('com', Path.relative(path, resPath));
            }
            if (typeof com.tags === 'undefined') {
                Fatal.fire(
                    "Missing the mandatory attribute \"tags\"!",
                    "Bad Component Definition",
                    comPath
                );
            }
            if (typeof com.priotity !== 'number') com.priotity = 0;
            if (typeof com.compile !== 'function') {
                Fatal.fire(
                    "Missing the mandatory function \"compile(root libs)\"!",
                    "Bad Component Definition",
                    comPath
                );
            }
            components.push(com);
        });
        components.sort(function(a, b) {
            return b.priotity - a.priotity;
        });
        components.forEach(function(item) {
            Components.push(item);
        });
    });
    // Precompile all regular expressions used to match the tag.
    Components.forEach(function (com) {
        var filters = com.tags;
        if (!Array.isArray(filters)) {
            filters = [filters];
        }
        var regexps = [];
        filters.forEach(function (filter) {
            try {
                var rx = new RegExp("^" + filter + "$", "i");
                regexps.push(rx);
            }
            catch (ex) {
                Fatal.fire(
                    "Bad regexp for component " + com.$.path + "\n" + ex,
                    "Tags was defined as " + JSON.stringify(com.tags)
                );
            }
        });
        TagRegExps.push(regexps);
    });
};
/**
 * @param {string} tagName Name of the HTML tag element.
 * @return {object|null} First component registered for this `tagName`.
 */
exports.getCompilerForTag = function(tagName) {
    var i, k, rx, regexps, component, cssFile;
    for (i = 0; i < Components.length; i++) {
        regexps = TagRegExps[i];
        for (k = 0; k < regexps.length; k++) {
            rx = regexps[k];
            if (rx.test(tagName)) {
                component = Components[i];
                return component;
            }
        }
    }
    return null;
};
/**
 * To be uptodate, an HTML page must be more recent that all its dependencies.
 */
function isHtmlFileUptodate(source) {
    var dependencies = source.tag("dependencies") || [];
    var i, dep, file, prj = source.prj(),
    stat,
    mtime = source.modificationTime();
    for (i = 0 ; i < dependencies.length ; i++) {
        dep = dependencies[i];
        file = prj.srcOrLibPath(dep);
        if (file) {
            stat = FS.statSync(file);
            if (stat.mtime > mtime) return false;
        }
    }
    return source.isUptodate();
}