UNPKG

cram

Version:

An AMD-compatible build tool.

198 lines (161 loc) 4.67 kB
/** MIT License (c) copyright 2010-2014 B Cavalier & J Hann */ define(function (require) { var when = require('when'); var sequence = require('when/sequence'); var getCtx = require('./ctx'); var scan = require('./compile/scan'); var getPlugin = require('./compile/getPlugin'); var locate = require('./compile/locate'); var amdFromPlugin = require('./transform/amdFromPlugin'); var pseudoModules; pseudoModules = { require: 1, exports: 1, module: 1 }; function configure (status, readFromSource, readFile, writeToCache, collect) { var parse; parse = partial(parseModules, status); return compile; function compile (parentCtx, ids, isExcluded) { var toAmd, fetch, compileDeps; toAmd = amdFromPlugin(readFile, parentCtx); fetch = partial(fetchSource, readFromSource, compile, toAmd, isExcluded); compileDeps = partial(processDeps, compile, isExcluded); return when.map(ids, function (id) { var ctx, absId; // normalize absId = parentCtx.toAbsId(id); if (id in pseudoModules) return { absId: absId }; ctx = getCtx(absId, parentCtx.config); // check if this module is excluded if (isExcluded(absId)) { ctx.source = ''; status.info('Excluded ' + absId); return ctx; } status.info('Compiling ' + absId); return getPlugin(parentCtx, ctx, getCtx) .then(locate) .then(fetch) .then(parse) .then(deanonymize) .then(compileDeps) .then(notify) .then(writeToCache) .yield(ctx); }); } function notify (fileCtx) { collect(fileCtx.absId, fileCtx); return fileCtx; } } function processDeps (compile, isExcluded, ctx) { var deps = collectDeps(ctx); if (deps.length) { return compile(ctx, deps, isExcluded) .then(function (depCtxs) { fixDepIds(depCtxs, ctx); }) .yield(ctx); } else { return ctx; } } function fetchSource (readSource, compile, toAmd, isExcluded, ctx) { if (ctx.plugin) { return toAmd(ctx).then(function (source) { if (source) { ctx.source = source; } else { // run-time plugin, just include plugin and deps ctx.source = ''; ctx.modules = compile(ctx, [ctx.pluginId], isExcluded); } return ctx; }); } else { return readSource(ctx); } } function deanonymize (fileCtx) { // assign id to first anonymous module fileCtx.modules.every(function (module) { if (!module.id) module.id = fileCtx.absId; else return true; }); return fileCtx; } return configure; function parseModules (status, fileCtx) { var prettifier, results; prettifier = prettifyMessage.bind(null, fileCtx); try { results = scan(fileCtx.source); } catch (ex) { throw prettifyErrorMessage(fileCtx, ex); } // scan for AMD meta data return when(results, function (modules) { //if (modules.errors) modules.errors.forEach(io.error); if (modules.warnings) { modules.warnings.forEach(chain(prettifier, status.warn)); } if (modules.infos) { modules.infos.forEach(chain(prettifier, status.info)); } fileCtx.modules = modules || []; return fileCtx; }); } function prettifyMessage (moduleCtx, msg) { return '[' + moduleCtx.absId + '] ' + msg; } function prettifyErrorMessage (moduleCtx, ex) { ex.message = prettifyMessage(moduleCtx, ex.message); return ex; } function chain (func1, func2) { return function () { return func2(func1.apply(this, arguments)); } } function collectDeps (fileCtx) { // iterate through modules found in AMD meta data return fileCtx.modules.reduce(function (deps, module) { if (module.depList) { deps = deps.concat(module.depList); } if (module.requires) { deps = deps.concat( module.requires.map(function (req) { return req.id; }) ); } return deps; }, []); } function fixDepIds (depCtxs, parentCtx) { var parentModule, depCount, reqCount; // correct the dependency ids since some may have been normalized // by plugins. // TODO: support more than one module per file parentModule = parentCtx.modules[0]; depCount = parentModule.depList ? parentModule.depList.length : 0; reqCount = parentModule.requires ? parentModule.requires.length : 0; if (depCount) { depCtxs.forEach(function (depCtx, i) { if (i < depCount) { parentModule.depList[i] = depCtx.absId; } // this can happen if the plugin-generated output has multiple define()s else if (i - depCount < reqCount) { parentModule.requires[i - depCount].id = depCtx.absId; } }); } } function partial (func /* ...params */) { return Function.prototype.bind.apply(func, arguments); } });