createOptimizerContext: function(options) {
        var writer = this.writer;
        var optimizerContext = new OptimizerContext();

        options = options || {};

        if (options.basePath) {
            optimizerContext.basePath = options.basePath;
        }

        if (options.data) {
            raptorUtil.extend(optimizerContext.data, options.data);
            delete options.data;
        }

        optimizerContext.dependencyRegistry = this.dependencies;
        optimizerContext.flags = this._resolveflags(options);
        optimizerContext.config = this.config;
        optimizerContext.writer = writer;
        optimizerContext.optimizer = this;
        optimizerContext.cache = this.getOptimizerCache(optimizerContext);
        optimizerContext.options = options;

        return optimizerContext;
    },
Пример #2
0
    createLassoContext: function(options) {
        var writer = this.writer;
        var lassoContext = new LassoContext();

        options = options || {};

        if (options.basePath) {
            lassoContext.basePath = options.basePath;
        }

        if (options.data) {
            raptorUtil.extend(lassoContext.data, options.data);
            delete options.data;
        }

        lassoContext.dependencyRegistry = this.dependencies;
        lassoContext.flags = this._resolveflags(options);
        lassoContext.config = this.config;
        lassoContext.writer = writer;
        lassoContext.lasso = this;
        lassoContext.cache = this.getLassoCache(lassoContext);
        lassoContext.options = options;

        return lassoContext;
    },
Пример #3
0
function Config(params) {
    this.configResource = null;

    this.bundlingEnabled = true;

    this.projectRoot = null;

    this.flags = flags.createFlagSet();
    this.params = {};
    this.bundleSetConfigsByName = {};
    this.fileWriterConfig = null;
    this.transforms = [];
    this.bundlingEnabled = true;
    this.basePath = null;
    this.writer = null;
    this.includeSlotNameForBundles = false;
    this._plugins = [];
    this.cacheProfiles = null;
    this.cacheProfile = null;
    this.cacheDir = null;
    this._requirePluginConfig = {};
    this._minifyJSPluginConfig = {};
    this._minifyCSSPluginConfig = {};
    this._imagePluginConfig = {};
    this.cspNonceProvider = null;
    this.fingerprintInlineCode = null;

    if (params) {
        extend(this.params, params);
    }

    this.addDefaultPlugins();

    this._configFingerprint = null;
}
Пример #4
0
    addTransform: function(transform) {
        if (!transform) {
            throw new Error('transform is required');
        }

        if (transform.enabled === false) {
            // Don't add transforms that are disabled
            return;
        }

        if (typeof transform === 'function') {
            transform = {
                transform: transform
            };
        }

        if (typeof transform.transform !== 'function') {
            throw new Error('Invalid transform: ' + require('util').inspect(transform));
        }

        transform.name = transform.name || transform.transform.name || '(anonymous)'; // Use the function name

        if (transform.contentType) {
            // Convert the contentType to a filter
            transform = extend({}, transform);
            transform.filter = createFilterFromContentType(transform.contentType);
            delete transform.contentType;
        }

        this.transforms.push(transform);
    },
    forEachDependency: function(options) {
         
        if (typeof options === 'function') {
            options = {
                callback: arguments[0],
                thisObj: arguments[1]
            };
            
            if (arguments[2]) {
                extend(options, arguments[2]);
            }
        }
        
        if (!options) {
            options = {};
        }

        var enabledExtensions = options.enabledExtensions;
        if (!enabledExtensions || !enabledExtensions.__ExtensionSet) {
            enabledExtensions = new ExtensionSet(enabledExtensions);
        }

        var callback = options.callback;
        var thisObj = options.thisObj;
    
        this.dependencies.forEach(function(dependency) {
            
            if (dependency._condition && !dependency._condition(enabledExtensions)) {
                return;
            }

            callback.call(thisObj, dependency.type, dependency);
        });
    }
Пример #6
0
function Command(stack, name, config) {
    this.stack = stack;
    this.name = name;
    extend(this, config);
    this.listed = config.listed !== false;
    this._options = undefined;
}
    registerRequireExtension: function(ext, options) {
        equal(typeof ext, 'string', '"ext" should be a string');

        if (typeof options === 'function') {
            options = {
                read: options,
                getLastModified: defaultGetLastModified
            };
        } else {
            options = extend({}, options);
            if (!options.getLastModified) {
                options.getLastModified = defaultGetLastModified;
            }

            ok(options.read, '"read" function is required when registering a require extension');
            ok(typeof options.read === 'function', '"read" should be a function when registering a require extension');
        }

        options.object = options.object === true;

        var read = options.read;

        options.readStream = function(path, optimizerContext) {
            return readStream(function(callback) {
                return read(path, optimizerContext, callback);
            });
        };

        this.requireExtensions[ext] = options;
    },
Пример #8
0
function Config(params) {
    this.configResource = null;
    
    this.bundlingEnabled = true;
    
    this.projectRoot = null;
    
    this.enabledExtensions = extensions.createExtensionSet();
    this.params = {};
    this.bundleSetConfigsByName = {};
    
    this.pages = {};
    this.fingerprintLength = 8;
    this.transforms = [];
    this.bundlingEnabled = true;
    this.basePath = null;
    this.writer = null;
    this.includeSlotNameForBundles = false;
    this.plugins = [];
    this.pages = {};
    this.cacheProfiles = null;
    this.cacheProfile = null;
    this.cacheDir = null;

    if (params) {
        extend(this.params, params);
    }

    this.addDefaultPlugins();
}
Пример #9
0
    lasso.dependencies.addNormalizer(function(dependency) {
        if (typeof dependency === 'string') {
            var matches;

            if ((matches = requireRegExp.exec(dependency))) {
                return {
                    type: 'require',
                    path: matches[1]
                };
            } else if ((matches = requireRunRegExp.exec(dependency))) {
                return {
                    type: 'require',
                    path: matches[1],
                    run: true
                };
            }
        }
        else if (!dependency.type) {
            if (dependency.require) {
                var reqDep = {
                    type: 'require',
                    path: dependency.require
                };

                extend(reqDep, dependency);
                delete reqDep.require;

                return reqDep;
            } else if (dependency['require-run']) {
                var reqRunDep = {
                    type: 'require',
                    run: true,
                    path: dependency['require-run']
                };

                extend(reqRunDep, dependency);
                delete reqRunDep['require-run'];

                return reqRunDep;
            }
        }
    });
Пример #10
0
        function onResourceWritten(writeResult) {
            ok(writeResult, 'writeResult expected');
            ok(writeResult.url, 'writeResult.url expected');

            var result = extend(writeResult || {}, {
                sourceFile: path
            });

            _this.emit('resourceWritten', result);
            return result;
        }
module.exports = function render(input, context) {
    var dependenciesParent = input.dependenciesParent;
    if (!dependenciesParent) {
        throw new Error('Expected property "dependenciesParent"');
    }

    delete input.dependenciesParent;

    var dependency = extend({}, input['*']);

    dependenciesParent.addDependency(dependency);
};
Пример #12
0
function renderSlot(attrs, lassoPageResult, out, lassoRenderContext) {
    var lassoConfig = lassoRenderContext.getLassoConfig();

    var cspNonceProvider = lassoConfig.cspNonceProvider;
    var slotName = attrs.name;
    var cspAttrs = null;
    var slotData = null;

    if (cspNonceProvider) {
        cspAttrs = {
            nonce: cspNonceProvider(out)
        };
    }
    if (isAttributePresent(attrs) || cspAttrs) {
        slotData = {
            inlineScriptAttrs: extend(extend({}, attrs.inlineScriptAttrs), cspAttrs),
            inlineStyleAttrs: extend(extend({}, attrs.inlineStyleAttrs), cspAttrs),
            externalScriptAttrs: extend({}, attrs.externalScriptAttrs),
            externalStyleAttrs: extend({}, attrs.externalStyleAttrs)
        };
    }

    var slotHtml = lassoPageResult.getSlotHtml(slotName, slotData);

    if (slotHtml) {
        out.write(slotHtml);
    }

    lassoRenderContext.emitAfterSlot(slotName, out);
}
function OptimizerManifest(options) {

    var dependencyRegistry = options.dependencyRegistry;
    var dirname = options.dirname;
    var filename = options.filename;

    ok(dependencyRegistry, '"dependencyRegistry" is required');
    ok(dirname, '"dirname" is required');
    ok(typeof dirname === 'string', '"dirname" must be a string');

    var async;

    if (options.manifest) {
        // save off the async property value
        async = options.manifest.async;

        extend(this, options.manifest);
    }
    
    this._uniqueId = nextId++;

    this.dirname = dirname;
    this.filename = filename;
    
    this.dependencies = new DependencyList(
        this.dependencies || [],
        dependencyRegistry,
        this.dirname,
        this.filename);

    this.async = null;

    if (async) {
        if (typeof async !== 'object') {
            throw new Error('async should be an object. (dirname=' + dirname + ', filename=' + filename + ')');
        }

        this.async = {};

        for (var asyncPackageName in async) {
            if (async.hasOwnProperty(asyncPackageName)) {
                var asyncDependencies = async[asyncPackageName];
                this.async[asyncPackageName] = new DependencyList(
                    asyncDependencies,
                    dependencyRegistry,
                    this.dirname,
                    this.filename);
            }
        }
    }
}
Пример #14
0
    createResourceTransformType: function(transformFunc) {
        var transformType = extend({}, dependencyResource);
        extend(transformType, {
            isExternalResource: function() {
                return false;
            },

            read: function(context, callback) {
                var stream = dependencyResource.read.call(this);
                var code = '';

                stream
                    .on('data', function(data) {
                        code += data;
                    })
                    .on('end', function() {
                        transformFunc(code, callback);
                    });
            }
        });

        return transformType;
    }
Пример #15
0
        function done(err, writeResult) {
            if (err) {
                return callback(createError('Error while writing resource "' + path + '": ' + (err.stack || err), err));
            }

            ok(writeResult, 'writeResult expected');
            ok(writeResult.url, 'writeResult.url expected');

            var result = extend(writeResult || {}, {
                sourceFile: path
            });

            _this.emit('resourceWritten', result);
            callback(null, result);
        }
Пример #16
0
        updateConfig: function(jsonFile, newProps) {
            if (arguments.length === 1) {
                newProps = arguments[0];
                jsonFile = rapido.findClosestConfigFile();
            }
            
            var config,
                updated = false;

            if (jsonFile.exists()) {
                updated = true;
                config = JSON.parse(jsonFile.readAsString());    
            }
            else {
                config = {};
            }
            
            var newPropsArray = [];

           forEachEntry(newProps, function(name, value) {
                if (config[name] !== value) {
                    newPropsArray.push('    ' + name + ': ' + value);
                }
            });

            var path = this.relativePath(jsonFile);

            if (newPropsArray.length) {
                extend(config, newProps);
                jsonFile.writeAsString(JSON.stringify(config, null, "    "));    
                rapido.log.info('update', 'Updated the following properties in "' + path + '":');
                newPropsArray.forEach(function(newPropStr) {
                    rapido.log.info('update', newPropStr);
                });
            }
            else {
                rapido.log.info('skip', 'No changes to "' + path + '"');
            }

            return {
                config: config,
                file: jsonFile,
                path: this.relativePath(jsonFile),
                updated: updated
            };
        },
Пример #17
0
function PackageInfo(path, pkg) {
    var pkgVersion = pkg.version;
    delete pkg.version;

    extend(this, pkg);

    var parsedVersion;

    Object.defineProperty(this, "path", {
        get: function() {
            return path;
        },
        set: function(value) {
            path = value;
        },
        enumerable: false,
        configurable: false
    });

    Object.defineProperty(this, "parsedVersion", {
        get: function() {
            return parsedVersion;
        },
        set: function(value) {
            parsedVersion = value;
        },
        enumerable: false,
        configurable: false
    });
    
    Object.defineProperty(this, "version", {
        get: function() {
            return parsedVersion.toString(); 
        },
        set: function(value) {
            parsedVersion = version.parse(value);
        },
        enumerable: true,
        configurable: true
    });

    this.version = pkgVersion;
}
Пример #18
0
    createOptimizerContext: function(options) {
        var writer = this.getWriter(options);
        var context = new OptimizerContext();


        if (options) {
            if (options.basePath) {
                context.basePath = options.basePath;
            }

            if (options.context) {
                raptorUtil.extend(context, options.context);
            }
        }

        writer.setContext(context);
        context.config = this.config;
        context.writer = writer;
        context.optimizer = this;
        context.cache = this.getCache(context);
        return context;
    },
IncludeNode.convertNode = function (node, template) {
    extend(node, IncludeNode.prototype);
    IncludeNode.call(node);
    node.setProperty('template', template);
};
Пример #20
0
exports.create = function(options) {
    var _exclusiveStackCommands = [];
    var _hiddenCommands = {};

    var rapido = {

        initialized: false,

        config: null,

        commands: new CommandRegistry(),

        optimist: optimist,

        globalNodeModulesDir: null,

        log: function(message) {
            var args = Array.prototype.slice.call(arguments, 0);

            for (var i=0, len=args.length; i<len; i++) {
                var arg = arguments[i];
                if (typeof arg === 'string') {
                    args[i] = arg.replace(/\$0/g, $0);
                }
                
            }
            console.log.apply(console, args);
        },

        scaffold: function(config) {
            require('./scaffolding').generate(config, rapido);
        },
        $0: $0,
        configFilename: 'rapido.json',
        stackConfigFilename: 'rapido-stack.json',
        stackDirs: null,
        additionalStackDirs: [],
        additionalNodeModulesDirs: [],
        additionalEnabledStacks: [],

        exclusiveStackCommands: function(stackName) {
            _exclusiveStackCommands.push(stackName);
        },

        hideCommand: function(stackName, commandName) {
            _hiddenCommands[stackName + ':' + commandName] = {
                stackName: stackName,
                commandName: commandName
            };
        },

        init: function() {
            if (this.initialized) {
                return;
            }

            this.initialized = true;

            var startTime = Date.now();
            var configFilename = rapido.configFilename;
            var stackConfigFilename = rapido.stackConfigFilename;

            var config = rapido.config;

            if (!config) {
                config = rapido.config = {};
                
                require('./config-loader').loadConfigs(
                    config,
                    buildDefaultUserConfigPaths(rapido), 
                    configFilename, 
                    rapido);

                var stacks = require('./config-loader').loadStackConfigs(
                    config,
                    buildStackConfigPaths(rapido), 
                    stackConfigFilename, 
                    rapido); 

                if (_exclusiveStackCommands) {
                    _exclusiveStackCommands.forEach(function(stackName) {
                        var stack = stacks[stackName];
                        if (stack) {
                            if (stack.commands) {
                               forEachEntry(stack.commands, function(commandName, commandConfig) {
                                    rapido.commands.exclusiveStackCommand(stackName, commandName);
                                });
                            }
                            
                        }
                    });
                }


                
               forEachEntry(stacks, function(stackName, stackConfig) {
                    rapido.registerStack(stackConfig);
                });

               forEachEntry(_hiddenCommands, function(name, value) {
                    var stackName = value.stackName;
                    var commandName = value.commandName;
                    var stack = rapido.getStack(stackName);
                    if (!stack) {
                        throw new Error('Stack not found with name "' + stackName + '"');
                    }
                    rapido.getStack(stackName).hideCommand(commandName);
                });
            }

            var enabledStackNames = rapido.config['use'] || [];

            this.disableAllStacks();

            
            enabledStackNames = enabledStackNames.concat(rapido.additionalEnabledStacks);
            enabledStackNames.push('default'); // Always enable the default stack

            enabledStackNames.forEach(function(enabledStackName) {
                if (!rapido.stackExists(enabledStackName)) {
                    rapido.log.warn('WARN', "Enabled stack not found: " + enabledStackName);
                }
                else {
                    this.enableStack(enabledStackName);    
                }
                
            }, this);

            logger.debug('rapido configuration loaded in ' + (Date.now() - startTime) + 'ms');
        },

        disableAllStacks: function() {
            this.commands.disableAllStacks();
        },

        getStack: function(stackName) {
            return this.commands.getStack(stackName);
        },

        enableStack: function(stackName) {
            if (!this.initialized) {
                rapido.additionalEnabledStacks.push(stackName);
                return;
            }
            
            var stack = this.commands.getStack(stackName);
            if (!stack) {
                throw new Error("Unable to enable stack. Invalid stack: " + stackName);
            }

            this.commands.enableStack(stackName);
        },
        
        isStackEnabled: function(stackName) {
            return this.commands.isStackEnabled(stackName);
        },

        getStacks: function() {
            return this.commands.getStacks();
        },

        stackExists: function(stackName) {
            return this.commands.getStack(stackName) != null;
        },

        getEnabledStacks: function(stackName) {
            return this.commands.getEnabledStacks();
        },

        registerStack: function(stackConfig) {
            this.commands.registerStack(stackConfig);
        },

        registerCommand: function(stackName, commandName, commandConfig) {
            this.commands.registerCommand(stackName, commandName, commandConfig);
        },

        getCommandModule: function(stackName, commandName) {
            var command = rapido.commands.getCommand(stackName, commandName);
            return command.getModule();
        },

        runCommand: function(stackName, commandName, options) {
            var command;

            if (typeof arguments[0] !== 'string') {
                options = arguments[1];
                command = arguments[0];
                commandName = command.name;
                stackName = command.stack.name;
            }

            if (!stackName) {
                stackName = "default";
            }

            if (typeof stackName !== 'string') {
                throw new Error('Unable to run command. Invalid stack name: ' + stackName);
            }

            if (typeof commandName !== 'string') {
                throw new Error('Unable to run command. Invalid command name: ' + commandName);
            }

            command = rapido.getCommandModule(stackName, commandName);

            try
            {
                return command.run(options || {}, rapido.config, rapido);    
            }
            catch(e) {
                if (e === '') {
                    throw e;
                }

                throw createError(
                    new Error('Error while executing command "' + commandName + '" (' + stackName + '). Error: ' + (e.stack || e)), 
                    e);
            }
        },

        padding: function(str, targetLen) {
            var padding = '';
            for (var i=0, len=targetLen-str.length; i<len; i++) {
                padding += ' ';
            }
            return padding;
        },

        rightPad: function(str, len) {
            while(str.length<len) {
                str += ' ';
            }
            return str;
        },

        leftPad: function(str, len) {
            while(str.length<len) {
                str = ' ' + str;
            }
            return str;
        },

        writeConfig: function(jsonFile, config) {
            if (typeof jsonFile === 'string') {
                jsonFile = new File(jsonFile);
            }

            jsonFile.writeAsString(JSON.stringify(config, null, "    "));
        },

        findClosestConfigFile: function(paths, configFilename) {
            if (!paths) {
                paths = buildDefaultUserConfigPaths();
            }

            if (!configFilename) {
                configFilename = rapido.configFilename;
            }

            for (var i=0, len=paths.length; i<len; i++) {
                var configFile = new File(paths[i], configFilename);
                if (configFile.exists()) {
                    return configFile;
                }
            }

            // Config file not found... create it as a child of the first path
            return new File(paths[0], configFilename);
        },

        findClosestConfig: function(paths, configFilename) {
            var file = rapido.findClosestConfigFile(paths, configFilename);
            var config;

            if (file.exists()) {
                config = JSON.parse(file.readAsString());
            }
            else {
                config = {};
            }

            return {
                file: file,
                exists: file.exists(),
                config: config,
                path: this.relativePath(file)
            };
        },

        updateConfig: function(jsonFile, newProps) {
            if (arguments.length === 1) {
                newProps = arguments[0];
                jsonFile = rapido.findClosestConfigFile();
            }
            
            var config,
                updated = false;

            if (jsonFile.exists()) {
                updated = true;
                config = JSON.parse(jsonFile.readAsString());    
            }
            else {
                config = {};
            }
            
            var newPropsArray = [];

           forEachEntry(newProps, function(name, value) {
                if (config[name] !== value) {
                    newPropsArray.push('    ' + name + ': ' + value);
                }
            });

            var path = this.relativePath(jsonFile);

            if (newPropsArray.length) {
                extend(config, newProps);
                jsonFile.writeAsString(JSON.stringify(config, null, "    "));    
                rapido.log.info('update', 'Updated the following properties in "' + path + '":');
                newPropsArray.forEach(function(newPropStr) {
                    rapido.log.info('update', newPropStr);
                });
            }
            else {
                rapido.log.info('skip', 'No changes to "' + path + '"');
            }

            return {
                config: config,
                file: jsonFile,
                path: this.relativePath(jsonFile),
                updated: updated
            };
        },

        isCommandEnabled: function(stackName, commandName) {
            return this.commands.isCommandEnabled(stackName, commandName);
        },

        _parseArgs: function(args) {
            this.init();

            var commandParts = [], 
                optionArgs = [],
                matchingCommands = [],
                optionsStarted = false;

            //console.error('CONFIG: ', config);
            /*
             * Separate out option args from the command
             */
            args.forEach(function(arg) {
                if (arg.startsWith('-') || optionsStarted) {
                    optionsStarted = true;
                    optionArgs.push(arg);
                }
                else {
                    commandParts.push(arg);
                }
            });

            if (commandParts.length === 0) {
                commandParts = ['default'];
            }

            var enabledStacks = this.getEnabledStacks();

            var commandName;

            for (var i=commandParts.length-1; i>=0; i--) {
                commandName = commandParts.slice(0, i+1).join(' ');

                enabledStacks.forEach(function(stack) {
                    var command = stack.getCommand(commandName);
                    if (command && this.commands.isCommandEnabled(stack.name, commandName)) {
                        matchingCommands.push(command);
                    } 
                }, this);

                if (matchingCommands.length) {
                    if (i<commandParts.length-1) {
                        optionArgs = commandParts.slice(i+1).concat(optionArgs);
                    }
                    break;
                }
            }

            if (!matchingCommands.length) {
                commandName = commandParts.join(' ');
            }

            function forEachCommand(callback, thisObj) {
                matchingCommands.forEach(callback, thisObj);
            }

            return {
                matchingCommands: matchingCommands,
                optionArgs: optionArgs,
                commandName: commandName,
                hasMatchingCommands: matchingCommands.length > 0,
                forEachCommand: forEachCommand
            };
        },


        /**
         * This method is used by the Bash shell to support
         * command line auto-completion for command names
         * and command options.
         *
         * See:
         * http://www.gnu.org/software/bash/manual/bash.html#Programmable-Completion-Builtins
         * 
         * @param  {String} line      The auto-completion line (i.e. COMP_LINE)
         * @param  {int} cursorPos    The index into the line where the cursor is
         * @return {void}
         */
        outputCompletions: function(line, cursorPos) {
            this.init();

            if (cursorPos == null) {
                cursorPos = line.length;
            }

            /*
            Use cases:
    
            1) Completion on option value:
            rap some command --options opt

            Expected: (no completions)

            2) Completion on option name
            rap some comm

            Expected: Complete last words of any matching commands

            3) Completion on rap
            rap

            Expected: Output first word for all enabled commends
            */

            // We only care about the string up to the cursor
            line = line.substring(0, cursorPos);
            
            // Chop off the shell command name used to invoke Rapido
            var firstWordRegExp = /^([^\s]+)\s*/g;
            var firstWordMatches = firstWordRegExp.exec(line);
            if (firstWordMatches) {
                line = line.substring(firstWordRegExp.lastIndex);
            }

            // First find where the options start:
            var optionsStartMatches = /\s-/.exec(line);
            var optionsStart = -1;
            
            if (optionsStartMatches) {
                optionsStart = optionsStartMatches.index;
            }

            // Find where the current word is based on the cursor position
            var currentWord;
            var currentWordStart = -1;
            var currentWordRegExp = /([^\s^]+)$/g;

            var currentWordMatches = currentWordRegExp.exec(line);
            if (currentWordMatches) {
                currentWord = currentWordMatches[1];
                currentWordStart = currentWordMatches.index;
            }
            else {
                currentWord = '';
                currentWordStart = line.length;
            }

            var completions = [];
            var foundCompletions = {};

            function add(completion) {
                if (!foundCompletions[completion]) {
                    foundCompletions[completion] = true;
                    completions.push(completion);
                }
            }

            if (optionsStart !== -1) {

                if (/^--?.*$/.test(currentWord)) {
                    // The current word is an option name so we are expected to
                    // have a complete command
                    var parseInfo = this._parseArgs(line.split(/\s+/));
                    if (!parseInfo.hasMatchingCommands) {
                        // Invalid command...we cannot complete the option names
                        return;
                    }

                    // Loop over all the matching commands to look for matching options
                    parseInfo.forEachCommand(function(command) {
                        
                        // Get a list of allowed options for the current command as an array
                        // NOTE: The "-" and "--" prefixes will be included for each option
                        var allowedOptions = command.getAllowedOptions();
                        allowedOptions.forEach(function(allowedOption) {
                            if (allowedOption.startsWith(currentWord)) {
                                add(allowedOption);
                            }
                        });
                    }, this);
                }
                else {
                    // We are after the options, but the current word is not an option
                    // name so we can't auto-complete the current word
                    return;
                }
                    
            }
            else {
                var enabledStacks = this.getEnabledStacks();

                enabledStacks.forEach(function(stack) {
                    stack.forEachCommand(function(command) {

                        if (!this.isCommandEnabled(stack.name, command.name)) {
                            return;
                        }

                        if (!command.listed) {
                            return;
                        }

                        // Find the start of the last word
                        if (command.name.startsWith(line)) {
                            add(command.name.substring(currentWordStart));
                        }
                    }, this);
                }, this);
                    
            }

            if (completions.length) {
                completions.sort(function(a, b) {
                    a = a.toLowerCase();
                    b = b.toLowerCase();
                    return a < b ? -1 : (a === b ? 0 : 1);
                });

                require('util').print(completions.join('\n'));    
            }
        },

        _doRun: function(args) {
            this.init();

            if (process.env.COMP_LINE) {
                this.outputCompletions(process.env.COMP_LINE, process.env.COMP_POINT);
                return;
            }

            args = args.slice(2);

            function onError(err) {
                if (err.message === 'canceled') {
                    rapido.log.error('ABORT', 'Command canceled');
                    return;
                }
                rapido.log.error('ERROR', '' + (err.stack || err));
                process.exit(1);
            }
            
            var parseInfo = this._parseArgs(args);
            var commandName = parseInfo.commandName;
            var matchingCommands = parseInfo.matchingCommands;
            var optionArgs = parseInfo.optionArgs;

            if (!matchingCommands.length) {
                rapido.log.error('Command not found: ' + commandName);
                return process.exit(1);
            }
            
            function invokeCommand(command) {
                // console.log('Running command "' + command.name + '" (stack: ' + command.stack.name + ')...\n');    
                
                try
                {
                    var commandFilePath = command.file.getAbsolutePath();
                    var commandModule = require(commandFilePath);
                    var commandArgs;
                    var options = command.getOptions();

                    if (options) {
                        
                        var optimistCommand = optimist(optionArgs);

                        if (commandModule.usage) {
                            optimistCommand.usage(commandModule.usage.replace(/\$0/g, $0));
                        }

                        optimistCommand.options(options);

                        commandArgs = optimistCommand.argv;

                        if (commandArgs.help) {
                            command.showHelp(null, optimistCommand);
                            return;
                        }

                        if (commandModule.validate) {
                            try
                            {
                                var newCommandArgs = commandModule.validate(commandArgs, rapido);
                                if (newCommandArgs) {
                                    commandArgs = newCommandArgs;
                                }
                            }
                            catch(e) {
                                optimistCommand.showHelp(console.log);
                                rapido.log('Invalid args: ' + (e.message || e));
                                return;
                            }
                        }

                    }
                    else if (commandModule.parseOptions) {
                        commandArgs = commandModule.parseOptions(optionArgs, rapido);
                    }

                    var output = rapido.runCommand(command, commandArgs);
                    if (output && typeof output.fail === 'function') {
                        output.fail(function(err) {
                            if (err.message === 'canceled') {
                                rapido.log.error('ABORT', 'Command canceled');
                                return;
                            }

                            onError(err);
                        });
                    }
                    // Time not valid for async commands...
                    // logger.debug('Command completed in ' + (Date.now() - startTime) + 'ms');
                }
                catch(e) {
                    if (e !== '') {
                        onError(e);
                    }
                }
            }

            if (matchingCommands.length > 1) {

                console.log('Multiple matching commands found. Choose a command:');
                matchingCommands.forEach(function(command, i) {
                    console.log('[' + (i+1) + '] ' + command.name + ' (' + command.stack.name + ')');
                });

                var prompt = rapido.prompt;
                prompt.start();
                prompt.get(
                    {
                        name: "index",
                        description: 'Command number [default: 1]',     // Prompt displayed to the user. If not supplied name will be used.
                        //type: 'number',                 // Specify the type of input to expect.
                        pattern: /^[0-9]+$/,                  // Regular expression that input must be valid against.
                        message: 'Choose a valid command', // Warning message to display if validation fails.
                        conform: function(value) {
                            var index = parseInt(value, 10);
                            return index >= 1 && index <= matchingCommands.length;
                        },
                        before: function(value) {
                            return value === '' ? '1' : value;
                        }
                    },
                    function (err, result) {
                        if (err) { return onError(err); }
                        var index = parseInt(result.index, 10)-1;
                        invokeCommand(matchingCommands[index]);
                    });
            }
            else {
                invokeCommand(matchingCommands[0]);
            }
        },

        run: function(args) {
            exports.instance = rapido;

            var globalNodeModulesDir = new File(path.dirname(process.execPath), '../lib/node_modules');

            if (globalNodeModulesDir.exists()) {
                rapido.globalNodeModulesDir = globalNodeModulesDir;
                rapido._doRun(args);
            }
            else {
                var npm = require("npm");
                npm.load({}, function (er) {
                    rapido.globalNodeModulesDir = new File(npm.globalDir);
                    rapido._doRun(args);
                });
            }
        },

        relativePath: function(filePath) {
            if (filePath instanceof File) {
                filePath = filePath.getAbsolutePath();
            }
            return path.relative(process.cwd(), filePath);
        },
        
        addNodeModulesDir: function(path) {
            rapido.additionalNodeModulesDirs.push(path);
        },
        
        addStackDir: function(path) {
            rapido.additionalStackDirs.push(path);
        },

        prompt: require('./prompt')
    };

    Object.defineProperty(rapido, 'util', {
        get: function() {
            return require('./util/util');
        }
    });

    Object.defineProperty(rapido, 'projectManager', {
        get: function() {
            return require('./util/project-manager');
        }
    });

    function logColor(color, args) {
        if (args.length === 2) {
            var label = '[' + args[0] + ']',
                message = args[1];

            rapido.log((label[color]) + ' ' + message);    
        }
        else {
            var output = args[0] ? args[0][color] : null;
            rapido.log(output);
        }
        
    }

    function logSuccess(message) {
        logColor('green', arguments);
    }

    function logDebug(message) {
        logColor('cyan', arguments);
    }

    function logInfo(message) {
        logColor('cyan', arguments);
    }

    function logError(message) {
        logColor('red', arguments);
    }

    function logWarn(message) {
        logColor('yellow', arguments);
    }

    extend(rapido.log, {
        success: logSuccess,
        debug: logDebug,
        info: logInfo,
        error: logError,
        warn: logWarn
    });

    if (options) {
        require('./options-loader').load(rapido, options);
    }
    
    return rapido;
};
Пример #21
0
module.exports = exports = function plugin(lasso, config) {
    config = extend({}, config || {});

    config.rootDir = config.rootDir || lasso.config.getProjectRoot();
    config.runImmediately = config.runImmediately === true;
    config.builtins = builtins.getBuiltins(config.builtins);
    config.resolver = resolve.createResolver(config.builtins);

    var transforms;
    if (config.transforms) {
        if (config.transforms.length > 0) {
            config.transforms = transforms = new Transforms(config.transforms);
        } else {
            config.transforms = undefined;
        }
    }

    var globals = extend({}, defaultGlobals);
    if (config.globals) {
        extend(globals, config.globals);
    }

    Object.keys(globals).forEach(function(moduleName) {
        var varName = globals[moduleName];
        var resolved;

        try {
            resolved = resolveRequire(moduleName, config.rootDir);
        } catch(e) {
            if (e.moduleNotFound) {
                if (config.globals && config.globals.hasOwnProperty(moduleName)) {
                    throw e;
                }
            } else {
                throw e;
            }
        }

        delete globals[moduleName];

        if (resolved) {
            resolved = resolved.main ? resolved.main.filePath : resolved.filePath;
            globals[resolved] = varName;
        }

    });

    config.globals = globals;

    lasso.on('lassoCacheCreated', function(cacheInfo) {
        var lassoCache = cacheInfo.lassoCache;

        lassoCache.configureCacheDefaults({
            '*': { // Any profile
                'lasso-require/inspect': {
                    store: 'disk',
                    encoding: 'utf8',
                    valueType: 'json'
                },
                'lasso-require/transformed': {
                    store: 'disk',
                    singleFile: false,
                    encoding: 'utf8'
                }
            }
        });
    });

    lasso.dependencies.registerRequireExtension('js', {
            read: function(path) {
                return fs.createReadStream(path, {encoding: 'utf8'});
            },

            getLastModified: function(path, lassoContext, callback) {
                lassoContext.getFileLastModified(path, callback);
            }
        });

    lasso.dependencies.registerRequireExtension('json', {
            object: true,

            read: function(path) {
                return fs.createReadStream(path, {encoding: 'utf8'});
            },

            getLastModified: function(path, lassoContext, callback) {
                lassoContext.getFileLastModified(path, callback);
            }
        });

    lasso.dependencies.registerJavaScriptType('commonjs-def', dependency_commonjs_def);
    lasso.dependencies.registerJavaScriptType('commonjs-run', dependency_commonjs_run);
    lasso.dependencies.registerJavaScriptType('commonjs-dep', depednency_commonjs_dep);
    lasso.dependencies.registerJavaScriptType('commonjs-main', dependency_commonjs_main);
    lasso.dependencies.registerJavaScriptType('commonjs-remap', dependency_commonjs_remap);
    lasso.dependencies.registerJavaScriptType('commonjs-resolved', dependency_commonjs_resolved);
    lasso.dependencies.registerJavaScriptType('commonjs-ready', dependency_commonjs_ready);
    lasso.dependencies.registerJavaScriptType('commonjs-search-path', dependency_commonjs_search_path);

    lasso.dependencies.registerPackageType('require', dependency_require.create(config, lasso));

    lasso.dependencies.addNormalizer(function(dependency) {
        if (typeof dependency === 'string') {
            var matches;

            if ((matches = requireRegExp.exec(dependency))) {
                return {
                    type: 'require',
                    path: matches[1]
                };
            } else if ((matches = requireRunRegExp.exec(dependency))) {
                return {
                    type: 'require',
                    path: matches[1],
                    run: true
                };
            }
        }
        else if (!dependency.type) {
            if (dependency.require) {
                var reqDep = {
                    type: 'require',
                    path: dependency.require
                };

                extend(reqDep, dependency);
                delete reqDep.require;

                return reqDep;
            } else if (dependency['require-run']) {
                var reqRunDep = {
                    type: 'require',
                    run: true,
                    path: dependency['require-run']
                };

                extend(reqRunDep, dependency);
                delete reqRunDep['require-run'];

                return reqRunDep;
            }
        }
    });
};
    registerType: function(type, mixins) {
        equal(typeof type, 'string', '"type" should be a string');
        equal(typeof mixins, 'object', '"mixins" should be a object');

        var isPackageDependency = mixins._packageDependency === true;

        var hasReadFunc = mixins.read;

        if (isPackageDependency && hasReadFunc) {
            throw new Error('Manifest dependency of type "' + type + '" is not expected to have a read() method.');
        }

        if (mixins.init) {
            mixins.doInit = mixins.init;
            delete mixins.init;
        }

        mixins = extend({}, mixins);

        var properties = mixins.properties || {};
        var childProperties = Object.create(Dependency.prototype.properties);
        extend(childProperties, properties);
        mixins.properties = childProperties;

        var calculateKey = mixins.calculateKey;
        if (calculateKey) {
            mixins.doCalculateKey = calculateKey;
            delete mixins.calculateKey;
        }

        var getLastModified = mixins.getLastModified || mixins.lastModified /* legacy */;
        if (getLastModified) {
            mixins.doGetLastModified = getLastModified;
            delete mixins.getLastModified;
            delete mixins.lastModified;
        }

        if (!isPackageDependency && mixins.read) {
            // Wrap the read method to ensure that it always returns a stream
            // instead of possibly using a callback
            var oldRead = mixins.read;
            delete mixins.read;

            mixins.doRead = function(optimizerContext) {
                var _this = this;
                return readStream(function(callback) {
                    return oldRead.call(_this, optimizerContext, callback);
                });
            };
        }


        var _this = this;

        function Ctor(dependencyConfig, dirname, filename) {
            this.__dependencyRegistry = _this;
            Dependency.call(this, dependencyConfig, dirname, filename);
        }

        inherit(Ctor, Dependency);

        extend(Ctor.prototype, mixins);

        this.registeredTypes[type] = Ctor;
    },
extend(exports, {
    isPromise: isPromise,

    valueOfPromise: function(p) {
        if (!p) {
            return p;
        }

        if (typeof p.then !== 'function') {
            return p; //It is not a promise, just return it
        }
        
        if (p && typeof p.inspect === 'function') {
            var inspected = p.inspect();
            if (inspected.state === 'fulfilled') {
                return inspected.value;
            }
            else {
                return undefined;
            }
        }
        else {
            return undefined;
        }
    },

    immediateThen: function(p, resolvedCallback, rejectedCallback) {
        var result;

        if (!isPromise(p)) {
            result = resolvedCallback(p);
            return makePromise(result);
        }
        else if (isPromise(p) && typeof p.inspect === 'function') {
            var inspected = p.inspect();
            if (inspected.state === 'fulfilled') {
                result = resolvedCallback(inspected.value);
                return makePromise(result); // Make sure it is a promise
            }
            else if (inspected.state === 'rejected') {
                result = rejectedCallback(inspected.reason);
                return makePromise(result); // Make sure it is a promise
            }
        }

        // Fall-through for the pending state or lack of "inspect"
        return p.then(resolvedCallback, rejectedCallback);
    }
});
    registerRequireType: function(type, mixins) {
        equal(typeof type, 'string', '"type" should be a string');
        equal(typeof mixins, 'object', '"mixins" should be a object');

        mixins = extend({}, mixins);

        var requireRead = mixins.read;
        var requireGetLastModified = mixins.getLastModified;
        var object = mixins.object === true;

        delete mixins.read;
        delete mixins.getLastModified;
        delete mixins.object;

        if (!mixins.getSourceFile) {
            mixins.getSourceFile = function() {
                return this.path;
            };
        }
        mixins.getDependencies = function(optimizerContext, callback) {
            /*
            We use the require dependency type since we are compiling Dust templates
            to CommonJS modules and they need to be wrapped for transport to the browser.
             */

            var _this = this;
            var path = this.path;

            callback(null, [
                {
                    type: 'require',
                    resolvedPath: path,
                    _requireIsObject: object,

                    _requireReader: function() {
                        return readStream(function(callback) {
                            return requireRead.call(_this, optimizerContext, callback);
                        });
                    },
                    _requireGetLastModified: function(callback) {
                        if (requireGetLastModified) {
                            callback(null, -1);
                        } else {
                            requireGetLastModified.call(_this, optimizerContext, callback);
                        }
                    }
                }
            ]);
        };

        this.registerPackageType(type, mixins);

        this.registerRequireExtension(type, {
            object: object,

            read: function(path, optimizerContext) {
                var _this = {
                    path: path
                };

                return readStream(function(callback) {
                    return requireRead.call(_this, optimizerContext, callback);
                });
            },
            getLastModified: function(path, optimizerContext, callback) {
                var _this = {
                    path: path
                };

                return requireGetLastModified.call(_this, optimizerContext, callback);
            }
        });
    },
Пример #25
0
module.exports = function transform(node, compiler, template) {
    //Find and handle nested <attrs> elements
    findNestedAttrs(node, compiler, template);

    var tag;
    tag = node.tag || compiler.taglibs.getTag(node);

    var transformer = new Transformer(template, compiler, tag);
    node = transformer.transformNode(node);
    var inputAttr = transformer.inputAttr;
    var shouldRemoveAttr = true;

    if (tag) {
        if (tag.renderer || tag.template) {
            node.tag = tag;
        }

        if (tag.preserveWhitespace) {
            node.setPreserveWhitespace(true);
        }

        if (tag.escapeXmlBody === false) {
            node.setEscapeXmlBodyText(false);
        }

        if (tag.renderer || tag.isNestedTag) {
            shouldRemoveAttr = false;

            //Instead of compiling as a static XML element, we'll
            //make the node render as a tag handler node so that
            //writes code that invokes the handler
            TagHandlerNode.convertNode(node, tag);
            if (inputAttr) {
                node.setInputExpression(template.makeExpression(inputAttr));
            }
        } else if (tag.template) {
            shouldRemoveAttr = false;
            var templatePath = compiler.getRequirePath(tag.template);
            // The tag is mapped to a template that will be used to perform
            // the rendering so convert the node into a "IncludeNode" that can
            // be used to include the output of rendering a template
            IncludeNode.convertNode(node, templatePath);
        } else if (tag.nodeClass) {
            shouldRemoveAttr = false;

            var NodeCompilerClass = require(tag.nodeClass);
            compiler.inheritNode(NodeCompilerClass);
            extend(node, NodeCompilerClass.prototype);
            NodeCompilerClass.call(node);
            node.setNodeClass(NodeCompilerClass);
        }
    }

    function handleProp(name, value, attrDef, attr) {
        if (attrDef.setFlag) {
            node.setFlag(attrDef.setFlag);
        }

        if (shouldRemoveAttr && attr) {
            // When an attribute is converted to a property we remove
            // the old attribute and only keep the resulting
            // property in the property map.
            node.removeAttributeNS(attr.namespace, attr.localName);
        }

        if (attrDef.dynamicAttribute) {
            if (attrDef.removeDashes === true) {
                name = removeDashes(name);
            }
            if (node.addDynamicAttribute && attrDef.targetProperty) {
                node.addDynamicAttribute(name, value);
                node.setDynamicAttributesProperty(attrDef.targetProperty);
            } else {
                node.setProperty(name, value);
            }
        } else {
            node.setProperty(name, value);
        }
    }

    function handleAttrs() {
        // Convert tag attributes to JavaScript expressions based on loaded
        // taglibs. Attributes are converted to properties and applied
        // to either the runtime render tag or a compile-time AST Node.

        function convertAttrValue(attr, type, attrDef) {
            type = type || (attrDef ? attrDef.type : 'string') || 'string';

            try {
                return compiler.convertType(attr.value, type, attrDef ? attrDef.allowExpressions !== false : true);
            } catch (e) {
                node.addError('Invalid attribute value of "' + attr.value + '" for attribute "' + attr.name + '": ' + e.message);
                return attr.value;
            }
        }

        var foundProps = {};

        node.forEachAttributeAnyNS(function (attr) {
            var attrDef = compiler.taglibs.getAttribute(node, attr);
            if (!attrDef) {
                if (tag) {
                    // var isAttrForTaglib = compiler.taglibs.isTaglib(attrUri);
                    //Tag doesn't allow dynamic attributes
                    node.addError('The tag "' + tag.name + '" in taglib "' + getTaglibPath(tag.taglibId) + '" does not support attribute "' + attr + '"');
                }
                return;
            }

            if (attrDef.ignore) {
                // Skip attributes that are marked as "ignore" by the
                // taglib author. They'll handle the attribute themselves
                // and we don't need to bother copying it into
                // the properties map
                return;
            }

            var type = attrDef.type || 'string';

            var value;

            if (compiler.isExpression(attr.value)) {
                value = attr.value;
            } else {
                if (type === 'path') {
                    var pathVar;
                    if (compiler.hasExpression(attr.value)) {
                        value = convertAttrValue(
                            attr,
                            'string',
                            attrDef);

                    } else {
                        // Resolve the static string to a full path only once
                        pathVar = template.addStaticVar(attr.value, 'require.resolve(' + compiler.convertType(attr.value, 'string', true) + ')');
                        value = compiler.makeExpression(pathVar);
                    }
                } else if (type === 'template') {
                    template.addStaticVar('__loadTemplate', '__helpers.l');
                    var templateVar;
                    if (compiler.hasExpression(attr.value)) {
                        value = compiler.makeExpression('__loadTemplate(' +
                            convertAttrValue(
                                attr,
                                'string',
                                attrDef) +
                                ', require' + // Include the "require" variable to allow relative paths to be resolved
                            ')');
                    } else {
                        // Resolve the static string to a full path only once
                        templateVar = template.addStaticVar(attr.value, '__loadTemplate(require.resolve(' + compiler.convertType(attr.value, 'string', true) + '), require)');
                        value = compiler.makeExpression(templateVar);
                    }
                } else {
                    value = convertAttrValue(attr, type, attrDef);
                }
            }
            var propName;
            if (attrDef.dynamicAttribute) {
                // Dynamic attributes are allowed attributes
                // that are not declared (i.e. "*" attributes)
                //
                if (attrDef.preserveName === false) {
                    propName = removeDashes(attr.localName);
                } else {
                    propName = attr.qName;
                }



            } else {
                // Attributes map to properties and we allow the taglib
                // author to control how an attribute name resolves
                // to a property name.
                if (attrDef.targetProperty) {
                    propName = attrDef.targetProperty;
                } else if (attrDef.preserveName) {
                    propName = attr.localName;
                } else {
                    propName = removeDashes(attr.localName);
                }
            }

            foundProps[propName] = true;
            handleProp(propName, value, attrDef, attr);
        });

        if (tag) {
            // Add default values for any attributes. If an attribute has a declared
            // default value and the attribute was not found on the element
            // then add the property with the specified default value
            tag.forEachAttribute(function (attrDef) {
                if (attrDef.hasOwnProperty('defaultValue') && !foundProps[attrDef.name]) {
                    handleProp(
                        attrDef.name,
                        template.makeExpression(JSON.stringify(attrDef.defaultValue)),
                        attrDef,
                        null);
                }
            });
        }
    }

    handleAttrs();
};
Пример #26
0
 setProperties: function (props) {
     if (!props) {
         return;
     }
     extend(this.properties, props);
 },
Пример #27
0
TagHandlerNode.convertNode = function (node, tag) {
    extend(node, TagHandlerNode.prototype);
    TagHandlerNode.call(node, tag);
};
Пример #28
0
function LassoManifest(options) {

    var dependencyRegistry = options.dependencyRegistry;


    var async;

    if (options.manifest) {
        // save off the async property value
        async = options.manifest.async;

        extend(this, options.manifest);
    }

    ok(dependencyRegistry, '"dependencyRegistry" is required');

    this._uniqueId = nextId++;

    if (options.dirname) {
        this.dirname = options.dirname;
    }

    if (options.filename) {
        this.filename = options.filename;
    }

    var dirname = this.dirname;
    var filename = this.filename;

    ok(dirname, '"dirname" is required');
    ok(typeof dirname === 'string', '"dirname" must be a string');

    this.dependencies = new DependencyList(
        this.dependencies || [],
        dependencyRegistry,
        dirname,
        filename);

    this.async = null;

    if (async) {
        if (typeof async !== 'object') {
            throw new Error('async should be an object. (dirname=' + dirname + ', filename=' + filename + ')');
        }

        this.async = {};

        for (var asyncPackageName in async) {
            if (async.hasOwnProperty(asyncPackageName)) {
                var asyncDependencies = async[asyncPackageName];
                this.async[asyncPackageName] = new DependencyList(
                    asyncDependencies,
                    dependencyRegistry,
                    dirname,
                    filename);
            }
        }
    }

    var requireRemap = this.requireRemap;
    if (requireRemap && Array.isArray(requireRemap)) {
        requireRemap.forEach(function(requireRemap) {

            var from = requireRemap.from;
            var to = requireRemap.to;

            from = nodePath.resolve(dirname || process.cwd(), from);

            if (to.charAt(0) === '.') {
                to = nodePath.resolve(dirname || process.cwd(), to);
            }

            requireRemap.from = from;
            requireRemap.to = to;
            requireRemap.condition = condition.fromObject(this);
        });
    }
}
module.exports = function transform(node, compiler, template) {

    //Find and handle nested <attrs> elements
    findNestedAttrs(node, compiler, template);

    var tag;


    function convertAttrValue(attr, type, attrDef) {
        type = type || (attrDef ? attrDef.type : 'string') || 'string';

        try {
            return compiler.convertType(attr.value, type, attrDef ? attrDef.allowExpressions !== false : true);
        } catch (e) {
            node.addError('Invalid attribute value of "' + attr.value + '" for attribute "' + attr.name + '": ' + e.message);
            return attr.value;
        }
    }

    function forEachProp(callback, thisObj) {
        var foundProps = {};

        node.forEachAttributeAnyNS(function (attr) {
            var attrDef = compiler.taglibs.getAttribute(node, attr);
            if (!attrDef) {
                // var isAttrForTaglib = compiler.taglibs.isTaglib(attrUri);
                //Tag doesn't allow dynamic attributes
                node.addError('The tag "' + tag.name + '" in taglib "' + tag.taglibId + '" does not support attribute "' + attr + '"');
                return;
            }

            var type = attrDef.type || 'string';

            var value;

            if (compiler.isExpression(attr.value)) {
                value = attr.value;
            } else {
                if (type === 'path') {
                    var pathVar;
                    if (compiler.hasExpression(attr.value)) {
                        value = convertAttrValue(attr, 'string', attrDef);
                    } else {
                        // Resolve the static string to a full path only once
                        pathVar = template.addStaticVar(attr.value, 'require.resolve(' + compiler.convertType(attr.value, 'string', true) + ')');
                        value = compiler.makeExpression(pathVar);
                    }
                } else if (type === 'template') {
                    var templateVar;
                    if (compiler.hasExpression(attr.value)) {
                        value = compiler.makeExpression('__helpers.l(' + convertAttrValue(attr, 'string', attrDef) + ')');
                    } else {
                        // Resolve the static string to a full path only once
                        templateVar = template.addStaticVar(attr.value, '__helpers.l(require.resolve(' + compiler.convertType(attr.value, 'string', true) + '))');
                        value = compiler.makeExpression(templateVar);
                    }
                } else {
                    value = convertAttrValue(attr, type, attrDef);
                }
            }
            var propName;
            if (attrDef.dynamicAttribute) {
                propName = attr.qName;
            } else {
                if (attrDef.targetProperty) {
                    propName = attrDef.targetProperty;
                } else if (attrDef.preserveName) {
                    propName = attr.localName;
                } else {
                    propName = removeDashes(attr.localName);
                }
            }

            foundProps[propName] = true;
            callback.call(thisObj, propName, value, attrDef);
        });

        tag.forEachAttribute(function (attr) {
            if (attr.hasOwnProperty('defaultValue') && !foundProps[attr.name]) {
                callback.call(thisObj, attr.name, template.makeExpression(JSON.stringify(attr.defaultValue)), '', attr);
            }
        });
    }

    tag = node.tag || compiler.taglibs.getTag(node);

    var transformer = new Transformer(template, compiler);
    node = transformer.transformNode(node);
    var inputAttr = transformer.inputAttr;

    if (tag) {
        if (tag.preserveWhitespace) {
            node.setPreserveWhitespace(true);
        }
        if (tag.renderer || tag.template) {
            if (tag.renderer) {
                //Instead of compiling as a static XML element, we'll
                //make the node render as a tag handler node so that
                //writes code that invokes the handler
                TagHandlerNode.convertNode(node, tag);
                if (inputAttr) {
                    node.setInputExpression(template.makeExpression(inputAttr));
                }
            } else {
                var templatePath = resolver.deresolve(tag.template, compiler.dirname);
                // The tag is mapped to a template that will be used to perform
                // the rendering so convert the node into a "IncludeNode" that can
                // be used to include the output of rendering a template
                IncludeNode.convertNode(node, templatePath);
            }

            forEachProp(function (name, value, attrDef) {
                if (attrDef.dynamicAttribute && attrDef.targetProperty) {
                    if (attrDef.removeDashes === true) {
                        name = removeDashes(name);
                    }
                    if (node.addDynamicAttribute) {
                        node.addDynamicAttribute(name, value);
                        node.setDynamicAttributesProperty(attrDef.targetProperty);
                    } else {
                        node.setProperty(name, value);
                    }
                } else {
                    node.setProperty(name, value);
                }
            });

        } else if (tag.nodeClass) {
            var NodeCompilerClass = require(tag.nodeClass);
            compiler.inheritNode(NodeCompilerClass);
            extend(node, NodeCompilerClass.prototype);
            NodeCompilerClass.call(node);
            node.setNodeClass(NodeCompilerClass);
            forEachProp(function (name, value) {
                node.setProperty(name, value);
            });
        }
    }
};
Пример #30
0
    registerRequireType: function(type, mixins) {
        equal(typeof type, 'string', '"type" should be a string');
        equal(typeof mixins, 'object', '"mixins" should be a object');

        mixins = extend({}, mixins);

        var userRead = mixins.read;
        var userCreateReadStream = mixins.createReadStream;

        var getLastModified = mixins.getLastModified;

        var object = mixins.object === true;

        delete mixins.read;
        delete mixins.createReadStream;
        delete mixins.getLastModified;
        delete mixins.object;

        let createReadStream = function(dependency, lassoContext) {
            return lassoContext.createReadStream(function(callback) {
                if (userCreateReadStream) {
                    return userCreateReadStream.call(dependency, lassoContext);
                } else {
                    return userRead.call(dependency, lassoContext, callback);
                }
            });
        };

        if (!mixins.getSourceFile) {
            mixins.getSourceFile = function() {
                return this.path;
            };
        }

        mixins.getDependencies = function(lassoContext, callback) {
            var path = this.path;
            var self = this;
            var lastModifiedAsyncValue = null;
            callback(null, [
                {
                    type: 'require',
                    path: path,
                    requireHandler: {
                        createReadStream: () => {
                            return createReadStream(self, lassoContext);
                        },
                        getLastModified: (callback) => {
                            var promise;

                            if (!callback) {
                                promise = new Promise((resolve, reject) => {
                                    callback = function(err, lastModified) {
                                        if (err) {
                                            return reject(err);
                                        }

                                        resolve(lastModified);
                                    };
                                });
                            }

                            if (!lastModifiedAsyncValue) {
                                lastModifiedAsyncValue = new AsyncValue();
                                if (getLastModified) {
                                    getLastModified.call(self, lassoContext, function(err, lastModified) {
                                        if (err) {
                                            return lastModifiedAsyncValue.reject(err);
                                        }

                                        lastModifiedAsyncValue.resolve(lastModified);
                                    });
                                } else {
                                    lastModifiedAsyncValue.resolve(-1);
                                }
                            }

                            lastModifiedAsyncValue.done(callback);

                            return promise;
                        },
                        object: object
                    }
                }
            ]);
        };

        this.registerPackageType(type, mixins);

        this.registerRequireExtension(type, {
            object: object,

            read: function(path, lassoContext) {
                var self = {
                    path: path
                };

                return createReadStream(self, lassoContext);
            },
            getLastModified: function(path, lassoContext, callback) {
                if (getLastModified) {
                    var self = {
                        path: path
                    };
                    return getLastModified.call(self, lassoContext, callback);
                } else {
                    return callback(null, -1);
                }
            }
        });
    },