Example #1
0
module.exports = inherit(require('enb/lib/tech/base-tech.js'), {
    getName: function () {
        return 'files';
    },

    configure: function () {
        var logger = this.node.getLogger();

        this._filesTarget = this.node.unmaskTargetName(this.getOption('filesTarget', '?.files'));
        this._dirsTarget = this.node.unmaskTargetName(this.getOption('dirsTarget', '?.dirs'));
        this._levelsTarget = this.node.unmaskTargetName(this.getOption('levelsTarget', '?.levels'));

        this._depsFile = this.getOption('depsTarget');
        if (this._depsFile) {
            logger.logOptionIsDeprecated(this._filesTarget, 'enb-bem', this.getName(), 'depsTarget', 'depsFile');
            logger.logOptionIsDeprecated(this._dirsTarget, 'enb-bem', this.getName(), 'depsTarget', 'depsFile');
        } else {
            this._depsFile = this.getOption('depsFile', '?.deps.js');
        }
        this._depsFile = this.node.unmaskTargetName(this._depsFile);
    },

    getTargets: function () {
        return [
            this._filesTarget,
            this._dirsTarget
        ];
    },

    build: function () {
        var _this = this,
            depsFilename = this.node.resolvePath(this._depsFile),
            filesTarget = this._filesTarget,
            dirsTarget = this._dirsTarget;

        return this.node.requireSources([this._depsFile, this._levelsTarget])
            .spread(function (data, levels) {
                return requireSourceDeps(data, depsFilename)
                    .then(function (sourceDeps) {
                        var fileList = new FileList(),
                            dirList = new FileList(),
                            files = {},
                            dirs = {};

                        for (var i = 0, l = sourceDeps.length; i < l; i++) {
                            var dep = sourceDeps[i],
                                entities;
                            if (dep.elem) {
                                entities = levels.getElemEntities(dep.block, dep.elem, dep.mod, dep.val);
                            } else {
                                entities = levels.getBlockEntities(dep.block, dep.mod, dep.val);
                            }

                            addEntityFiles(entities);
                        }

                        fileList.addFiles(Object.keys(files).map(function (filename) {
                            return files[filename];
                        }));

                        dirList.addFiles(Object.keys(dirs).map(function (dirname) {
                            return dirs[dirname];
                        }));

                        function addEntityFiles(entities) {
                            entities.files.forEach(function (file) {
                                files[file.fullname] = file;
                            });

                            entities.dirs.forEach(function (dir) {
                                dirs[dir.fullname] = dir;
                            });
                        }

                        _this.node.resolveTarget(filesTarget, fileList);
                        _this.node.resolveTarget(dirsTarget, dirList);
                    });
            });
    },

    clean: function () {}
});
Example #2
0
var User = require(global.MODEL_PATH + '/user');
var inherit = require('inherit');


module.exports = inherit({}, {

    'all /index' : function (req, res) {
        var params = '\n';

        for (var key in  req.headers) {
            params += (key + ' : ' + req.headers[key] + '\n');
        }


        res.render('post', {
            content : params
        });
    }
});
Example #3
0
File: make.js Project: Yeti-or/enb
module.exports = inherit(/** @lends MakePlatform.prototype */ {

    /**
     * Конструктор.
     */
    __constructor: function () {
        this._nodes = {};
        this._nodeInitPromises = {};
        this._cacheStorage = null;
        this._cache = null;
        this._projectConfig = null;
        this._cdir = null;
        this._languages = null;
        this._env = {};
        this._mode = null;
        this._makefiles = [];
        this._graph = null;
        this._profiler = null;
        this._levelNamingSchemes = {};
        this._sharedResources = new SharedResources();
    },

    /**
     * Инициализация make-платформы.
     * Создает директорию для хранения временных файлов, загружает конфиг для сборки.
     * @param {String} cdir Путь к директории с проектом.
     * @param {String} [mode] Режим сборки. Например, development.
     * @param {Function} [config] Функция, которая инициирует конфиг сборки. По умолчанию загружается из `.enb/make.js`.
     * @param {Object} [opts]
     * @param {Boolean} [opts.graph=false]
     * @returns {Promise}
     */
    init: function (cdir, mode, config, opts) {
        opts = opts || {};

        this._mode = mode = mode || process.env.YENV || 'development';

        this._cdir = cdir;

        var _this = this,
            projectName = path.basename(cdir),
            configDir = this._getConfigDir(),
            projectConfig = this._projectConfig = new ProjectConfig(cdir);

        this._projectName = projectName;
        this._logger = new Logger();
        this._buildState = {};

        if (opts.graph || opts.profiler) {
            this._graph = new BuildGraph(projectName);
        }

        if (opts.profiler) {
            this._profiler = new BuildProfiler();
        }

        try {
            if (config) {
                config(projectConfig);
            } else {
                var makefilePath = this._getMakeFile('make'),
                    personalMakefilePath = this._getMakeFile('make.personal');

                if (!makefilePath) {
                    throw new Error('Cannot find make configuration file.');
                }

                this._makefiles = [makefilePath, personalMakefilePath];

                clearRequire(makefilePath);
                require(makefilePath)(projectConfig);

                if (personalMakefilePath) {
                    clearRequire(personalMakefilePath);
                    require(personalMakefilePath)(projectConfig);
                }
            }
        } catch (err) {
            return vow.reject(err);
        }

        this._makefiles = this._makefiles.concat(projectConfig.getIncludedConfigFilenames());

        var modeConfig = projectConfig.getModeConfig(mode);
        if (modeConfig) {
            modeConfig.exec(null, projectConfig);
        }

        this._languages = projectConfig.getLanguages();
        this._env = projectConfig.getEnvValues();
        this._levelNamingSchemes = projectConfig.getLevelNamingSchemes();

        projectConfig.task('clean', function (task) {
            return task.cleanTargets([].slice.call(arguments, 1));
        });

        var tmpDir = path.join(configDir, 'tmp');

        return vowFs.makeDir(tmpDir).then(function () {
            _this._cacheStorage = new CacheStorage(path.join(tmpDir, 'cache.json'));
            _this._nodes = {};
        });
    },

    /**
     * Возвращает профайлер для указанной ноды
     * @param {String} nodeName
     * @returns {{setStartTime: function, setEndTime: function}}
     */
    getNodeProfiler: function (nodeName) {
        var profiler = this._profiler;

        return {
            setStartTime: function (target) {
                var filename = path.join(nodeName, target);

                return profiler.setStartTime(filename);
            },
            setEndTime: function (target) {
                var filename = path.join(nodeName, target);

                return profiler.setEndTime(filename);
            }
        };
    },

    /**
     * @returns {SharedResources}
     */
    getSharedResources: function () {
        return this._sharedResources;
    },

    /**
     * Возвращает абсолютный путь к директории с проектом.
     * @returns {String}
     */
    getDir: function () {
        return this._cdir;
    },

    /**
     * Возвращает абсолютный путь к директории с конфигурационными файлами.
     * В качестве директории ожидается либо .enb/, либо .bem/.
     * @returns {string}
     * @private
     */
    _getConfigDir: function () {
        var cdir = this.getDir(),
            possibleDirs = ['.enb', '.bem'],
            configDir,
            isConfigDirExists = possibleDirs.some(function (dir) {
                configDir = path.join(cdir, dir);
                return fs.existsSync(configDir);
            });

        if (isConfigDirExists) {
            return configDir;
        } else {
            throw new Error('Cannot find enb config directory. Should be either .enb/ or .bem/.');
        }
    },

    /**
     * Возвращает путь к указанному конфигу сборки.
     * Если файлов make.js и make.personal.js не существует, то пробуем искать файлы с префиксом enb-.
     * @param {String} file Название конфига (основной или персональный).
     * @returns {String}
     * @private
     */
    _getMakeFile: function (file) {
        var configDir = this._getConfigDir(),
            possiblePrefixes = ['enb-', ''],
            makeFile,
            isMakeFileExists = possiblePrefixes.some(function (prefix) {
                makeFile = path.join(configDir, prefix + file + '.js');
                return fs.existsSync(makeFile);
            });

        if (isMakeFileExists) {
            return makeFile;
        }
    },

    /**
     * Возвращает построитель графа сборки.
     * @returns {BuildGraph}
     */
    getBuildGraph: function () {
        return this._graph;
    },

    /**
     * Возвращает Инстанс BuildProfiler.
     * @returns {BuildProfiler}
     */
    getBuildProfiler: function () {
        return this._profiler;
    },

    /**
     * Загружает кэш из временной папки.
     * В случае, если обновился пакет enb, либо изменился режим сборки, либо изменились make-файлы, сбрасывается кэш.
     */
    loadCache: function () {
        this._cacheStorage.load();
        var version = require('../package.json').version,
            mtimes = this._cacheStorage.get(':make', 'makefiles') || {},
            dropCache = false;
        // Invalidate cache if mode was changed.
        if (this._cacheStorage.get(':make', 'mode') !== this._mode) {
            dropCache = true;
        }
        // Invalidate cache if ENB package was updated.
        if (this._cacheStorage.get(':make', 'version') !== version) {
            dropCache = true;
        }
        // Invalidate cache if any of makefiles were updated.
        var currentMTimes = this._getMakefileMTimes();
        Object.keys(currentMTimes).forEach(function (makefilePath) {
            if (currentMTimes[makefilePath] !== mtimes[makefilePath]) {
                dropCache = true;
            }
        });
        if (dropCache) {
            this._cacheStorage.drop();
        }
    },

    /**
     * Возвращает время изменения каждого загруженного make-файла в виде unix-time (.bem/enb-make.js).
     * @returns {Object}
     * @private
     */
    _getMakefileMTimes: function () {
        var res = {};
        this._makefiles.forEach(function (makefilePath) {
            if (fs.existsSync(makefilePath)) {
                res[makefilePath] = fs.statSync(makefilePath).mtime.getTime();
            }
        });
        return res;
    },

    /**
     * Сохраняет кэш во временную папку.
     */
    saveCache: function () {
        this._setCacheAttrs();
        return this._cacheStorage.save();
    },

    /**
     * Сохраняет кэш во временную папку асинхронно.
     */
    saveCacheAsync: function () {
        this._setCacheAttrs();
        return this._cacheStorage.saveAsync();
    },

    _setCacheAttrs: function () {
        this._cacheStorage.set(':make', 'mode', this._mode);
        this._cacheStorage.set(':make', 'version', require('../package.json').version);
        this._cacheStorage.set(':make', 'makefiles', this._getMakefileMTimes());
    },

    /**
     * Возвращает переменные окружения.
     * @returns {Object}
     */
    getEnv: function () {
        return this._env;
    },

    /**
     * Устанавливает переменные окружения.
     * @param {Object} env
     */
    setEnv: function (env) {
        this._env = env;
    },

    /**
     * Возвращает хранилище кэша.
     * @returns {CacheStorage}
     */
    getCacheStorage: function () {
        return this._cacheStorage;
    },

    /**
     * Устанавливает хранилище кэша.
     * @param {CacheStorage} cacheStorage
     */
    setCacheStorage: function (cacheStorage) {
        this._cacheStorage = cacheStorage;
    },

    /**
     * Возвращает языки для проекта.
     * Вроде, уже больше не нужно. Надо избавиться в будущих версиях.
     * @returns {String[]}
     * @deprecated
     */
    getLanguages: function () {
        return this._languages;
    },

    /**
     * Устанавливает языки для проекта.
     * Вроде, уже больше не нужно. Надо избавиться в будущих версиях.
     * @param {String[]} languages
     * @deprecated
     */
    setLanguages: function (languages) {
        this._languages = languages;
    },

    /**
     * Возвращает логгер для сборки.
     * @returns {Logger}
     */
    getLogger: function () {
        return this._logger;
    },

    /**
     * Устанавливает логгер для сборки.
     * Позволяет перенаправить вывод процесса сборки.
     *
     * @param {Logger} logger
     */
    setLogger: function (logger) {
        this._logger = logger;
    },

    /**
     * Инициализирует ноду по нужному пути.
     * @param {String} nodePath
     * @returns {Promise}
     */
    initNode: function (nodePath) {
        if (!this._nodeInitPromises[nodePath]) {
            var _this = this,
                cdir = this.getDir(),
                nodeConfig = this._projectConfig.getNodeConfig(nodePath),
                node = nodeFactory.mkNode(nodePath, this, this._cache, this._graph);

            node.setProfiler(this.getBuildProfiler(nodePath));
            node.setLogger(this._logger.subLogger(nodePath));
            this._nodes[nodePath] = node;
            this._nodeInitPromises[nodePath] = vowFs.makeDir(path.join(cdir, nodePath))
                .then(function () {
                    return vow.when(nodeConfig.exec());
                })
                .then(function () {
                    return vow.all(_this._projectConfig.getNodeMaskConfigs(nodePath).map(function (nodeMaskConfig) {
                        return nodeMaskConfig.exec([], nodeConfig);
                    }));
                })
                .then(function () {
                    var mode = nodeConfig.getModeConfig(_this._mode);
                    return mode && mode.exec(null, nodeConfig);
                })
                .then(function () {
                    node.setLanguages(nodeConfig.getLanguages() || _this._languages);
                    node.setTargetsToBuild(nodeConfig.getTargets());
                    node.setTargetsToClean(nodeConfig.getCleanTargets());
                    node.setTechs(nodeConfig.getTechs());
                    node.setBuildState(_this._buildState);
                    node.loadTechs();
                });
        }
        return this._nodeInitPromises[nodePath];
    },

    /**
     * Требует сборки таргетов для указанной ноды.
     * @param {String} nodePath Например, "pages/index".
     * @param {String[]} sources Таргеты, которые необходимо собрать.
     * @returns {Promise}
     */
    requireNodeSources: function (nodePath, sources) {
        var _this = this;
        return this.initNode(nodePath).then(function () {
            return _this._nodes[nodePath].requireSources(sources);
        });
    },

    /**
     * Сбрасывает кэш.
     */
    dropCache: function () {
        this._cacheStorage.drop();
    },

    /**
     * Возвращает массив строк путей к нодам, упорядоченные по убыванию длины.
     * Сортировка по убыванию нужна для случаев, когда на файловой системе одна нода находится
     * внутри другой (например, `bundles/page` и `bundles/page/bundles/header`).
     *
     * @returns {String[]}
     * @private
     */
    _getNodePathsLenDesc: function () {
        return Object.keys(this._projectConfig.getNodeConfigs()).sort(function (a, b) {
            return b.length - a.length;
        });
    },

    /**
     * Вычисляет (на основе переданного пути к таргету и списка путей к нодам)
     *  к какой ноде принадлежит переданный таргет.
     * @param {String} target
     * @param {String[]} nodePaths
     * @returns {{node: *, targets: String[]}}
     * @private
     */
    _resolveTarget: function (target, nodePaths) {
        target = target.replace(/^(\.\/)+|\/$/g, '');
        for (var i = 0, l = nodePaths.length; i < l; i++) {
            var nodePath = nodePaths[i];
            if (target.indexOf(nodePath) === 0) {
                var npl = nodePath.length,
                    charAtNpl = target.charAt(npl);
                if (target.length === npl) {
                    return {
                        node: nodePath,
                        targets: ['*']
                    };
                } else if (charAtNpl === '/' || charAtNpl === '\\') {
                    return {
                        node: nodePath,
                        targets: [target.substr(npl + 1)]
                    };
                }
            }
        }
        throw TargetNotFoundError('Target not found: ' + target);
    },

    /**
     * Вычисляет для списка таргетов, к каким нодам они принадлежат.
     * @param {String[]} targets
     * @returns {Object[]}
     * @private
     */
    _resolveTargets: function (targets) {
        var _this = this,
            buildTargets = [],
            nodeConfigs = this._projectConfig.getNodeConfigs(),
            nodePathsDesc = this._getNodePathsLenDesc();
        if (targets.length) {
            var targetIndex = {};
            targets.forEach(function (targetName) {
                var target = _this._resolveTarget(targetName, nodePathsDesc);
                if (targetIndex[target.node]) {
                    var currentTargetList = targetIndex[target.node].targets;
                    target.targets.forEach(function (resTargetName) {
                        if (currentTargetList.indexOf(resTargetName) === -1) {
                            currentTargetList.push(resTargetName);
                        }
                    });
                } else {
                    targetIndex[target.node] = target;
                    buildTargets.push(target);
                }
            });
        } else {
            Object.keys(nodeConfigs).forEach(function (nodePath) {
                buildTargets.push({
                    node: nodePath,
                    targets: ['*']
                });
            });
        }
        return buildTargets;
    },

    /**
     * Запускает сборку переданного списка таргетов.
     * @param {String[]} targets
     * @returns {Promise}
     */
    buildTargets: function (targets) {
        var _this = this;
        this._cache = new Cache(this._cacheStorage, this._projectName);
        try {
            var targetList = this._resolveTargets(targets);
            return vow.all(targetList.map(function (target) {
                return _this.initNode(target.node);
            })).then(function () {
                return vow.all(targetList.map(function (target) {
                    return _this._nodes[target.node].build(target.targets);
                })).then(function (builtInfoList) {
                    var builtTargets = [];

                    builtInfoList.forEach(function (builtInfo) {
                        builtTargets = builtTargets.concat(builtInfo.builtTargets);
                    });

                    return {
                        builtTargets: builtTargets
                    };
                });
            });
        } catch (err) {
            return vow.reject(err);
        }
    },

    /**
     * @returns {ProjectConfig}
     */
    getProjectConfig: function () {
        return this._projectConfig;
    },

    /**
     * Запускает удаление переданного списка таргетов.
     * @param {String[]} targets
     * @returns {Promise}
     */
    cleanTargets: function (targets) {
        var _this = this;
        this._cache = new Cache(this._cacheStorage, this._projectName);
        try {
            var targetList = this._resolveTargets(targets);
            return vow.all(targetList.map(function (target) {
                return _this.initNode(target.node);
            })).then(function () {
                return vow.all(targetList.map(function (target) {
                    return _this._nodes[target.node].clean(target.targets);
                }));
            });
        } catch (err) {
            return vow.reject(err);
        }
    },

    /**
     * Запускает выполнение таска.
     * @param {String} taskName
     * @param {String[]} args
     * @returns {Promise}
     */
    buildTask: function (taskName, args) {
        var task = this._projectConfig.getTaskConfig(taskName);
        task.setMakePlatform(this);
        return vow.when(task.exec(args));
    },

    /**
     * Деструктор.
     */
    destruct: function () {
        this._sharedResources.destruct();
        this._buildState = null;
        delete this._projectConfig;
        var nodes = this._nodes;
        Object.keys(nodes).forEach(function (nodeName) {
            nodes[nodeName].destruct();
        });
        delete this._nodes;
        if (this._cacheStorage) {
            this._cacheStorage.drop();
            delete this._cacheStorage;
        }
        if (this._cache) {
            this._cache.destruct();
            delete this._cache;
        }
        delete this._levelNamingSchemes;
    },

    /**
     * Заменяет слэши в путях к таргетам на обратные, если используется ОС Windows
     * @param {Array} targets
     * @returns {Array}
     */
    _fixPath: function (targets) {
        return path.sep === '/' ? targets : targets.map(function (target) {
            return target.replace(/\//g, '\\');
        });
    },

    /**
     * Запускает сборку.
     * Может запустить либо сборку таргетов, либо запуск тасков.
     * @param {String[]} targets
     * @returns {Promise}
     */
    build: function (targets) {
        targets = this._fixPath(targets);
        var deferred = vow.defer(),
            _this = this,
            targetTask;
        try {
            if (targets.length && this._projectConfig.getTaskConfig(targets[0])) {
                targetTask = this.buildTask(targets[0], targets.slice(1));
            } else {
                targetTask = this.buildTargets(targets);
            }
            targetTask.then(function () {
                Object.keys(_this._nodes).forEach(function (nodeName) {
                    _this._nodes[nodeName].getLogger().setEnabled(false);
                });
                return deferred.resolve();
            }, function (err) {
                return deferred.reject(err);
            });
        } catch (err) {
            deferred.reject(err);
        }
        return deferred.promise();
    },

    /**
     * Возвращает схему именования для уровня переопределения.
     * Схема именования содержит два метода:
     * ```javascript
     * // Выполняет построение структуры файлов уровня переопределения, используя методы инстанции класса LevelBuilder.
     * {Promise} buildLevel( {String} levelPath, {LevelBuilder} levelBuilder )
     * // Возвращает путь к файлу на основе пути к уровню переопределения и BEM-описания.
     * {String} buildFilePath(
     *     {String} levelPath, {String} blockName, {String} elemName, {String} modName, {String} modVal
     * )
     * ```
     * @returns {Object|undefined}
     */
    getLevelNamingScheme: function (levelPath) {
        return this._levelNamingSchemes[levelPath];
    }
});
module.exports = inherit({
    __constructor: function (fileSystemStructure, root) {
        this._structure = fileSystemStructure;
        this._root = root || process.cwd();
        this._originalFsFunctions = null;
        this._originalAsyncFsFunctions = null;
    },
    setup: function () {
        var mocks = createMocks(this._structure, this._root);

        this._originalAsyncFsFunctions = {};
        for (var asyncFsMethodName in asyncFs) {
            this._originalAsyncFsFunctions[asyncFsMethodName] = asyncFs[asyncFsMethodName];
            // Заменяем пустой функцией для безопасности.
            asyncFs[asyncFsMethodName] = createEmptyFunction(asyncFsMethodName);
        }
        for (var asyncFsMockName in mocks.vowFs) {
            asyncFs[asyncFsMockName] = mocks.vowFs[asyncFsMockName];
        }

        this._originalFsFunctions = {};
        for (var fsMethodName in fs) {
            this._originalFsFunctions[fsMethodName] = fs[fsMethodName];
            // Заменяем пустой функцией для безопасности.
            fs[fsMethodName] = createEmptyFunction(fsMethodName);
        }
        for (var fsMockName in mocks.fs) {
            fs[fsMockName] = mocks.fs[fsMockName];
        }
    },
    teardown: function () {
        for (var asyncFsMethodName in this._originalAsyncFsFunctions) {
            asyncFs[asyncFsMethodName] = this._originalAsyncFsFunctions[asyncFsMethodName];
        }
        for (var fsMethodName in this._originalFsFunctions) {
            fs[fsMethodName] = this._originalFsFunctions[fsMethodName];
        }
    }
});
Example #5
0
var Page = inherit({
    /**
     * Page
     *
     * @param {String} id Relative path to page (pages/index, for example)
     * @param {String} pageName Page name.
     * @param {Request} req Node request Object
     * @param {Response} res Node response Object
     */
    __constructor: function (id, pageName, req, res) {
        this._id = id;
        this._pageName = pageName;
        this._req = req;
        this._res = res;
        this._lang = req.query.lang || 'ru';
        this._query = req.query;
    },

    /**
     * Build page
     *
     * @returns {Promise} promise
     */
    handle: function () {
        return vow.all([
                this._getPages(),
                this._getTemplate(),
                this._getI18n()
            ])
            .spread(function (pages, bt, buildI18n) {
                var i18n = buildI18n();
                pages.setI18n(i18n);
                bt.lib.i18n = i18n;

                return pages.exec(this._pageName, {
                    query: this._query,
                    options: this._getPageOptions(),
                    lang: this._lang
                }).then(function (btJson) {
                    return this._applyTemplate(btJson, bt);
                }.bind(this));
            }.bind(this));
    },

    /**
     * Returns page handlers
     *
     * @returns {Promise} promise
     */
    _getPages: function () {
        return assets.requirePageAsset(this._buildAssetPath('page'));
    },

    /**
     * Returns bt templates
     *
     * @returns {Promise} promise
     */
    _getTemplate: function () {
        return assets.requirePageAsset(this._buildAssetPath('bt'));
    },

    /**
     * Returns i18n
     *
     * @returns {Promise} promise
     */
    _getI18n: function () {
        return assets.requirePageAsset(this._buildAssetPath('lang.' + this._lang));
    },

    /**
     * Returns path to a technology
     *
     * @param {String} tech
     * @returns {String} path
     */
    _buildAssetPath: function (tech) {
        return ['/', this._id, '/', path.basename(this._id), '.', tech, '.js'].join('');
    },

    /**
     * Returns path for css and js files
     *
     * @returns {Object}
     */
    _getPageOptions: function () {
        return {
            assetsPath: [
                'host' in assets ? assets.host : '',
                '/', this._id, '/_', path.basename(this._id)
            ].join('')
        };
    },

    /**
     * Returns path to a technology
     *
     * @param {Object} btJson
     * @param {BT} template
     * @returns {Promise} promise
     */
    _applyTemplate: function (btJson, template) {
        var startTime = Date.now();
        logger.verbose('bt running');
        var res = template.apply(btJson);
        logger.verbose('bt completed at %d ms', Date.now() - startTime);
        return res;
    }
}, {
    /**
     * @param {String} pageName
     */
    createHandler: function (pageName) {
        return function (req, res, next) {
            new Page('build/' + pageName, pageName + '-page', req, res)
                .handle()
                .then(
                    function (html) {
                        res.end(html);
                    },
                    next
                );
        };
    }
});
Example #6
0
var Import = inherit({
    __constructor : function (opts) {
        if (!opts)
            throw new Error('Input file required');

        this._opts = opts || {};
    },
    _js : [],
    _css : [],
    _temp : [
        INCLUDES_DEFAULT_NAME + 'css',
        INCLUDES_DEFAULT_NAME + 'js'
    ],
    _opts : null,

    push : function(tech) {
        this['_' + tech.getExtension()].push(tech.withInclude(this._opts));
        if (tech.type !== 'file')
            this._temp.push(tech.getName());
        else
            this._temp.push(tech.getName());
    },

    getContent : function(ext) {
        return this['_' + ext].join('\n');
    },

    getFileName : function(ext, isResolved) {
        if (isResolved)
            return FINAL_DEFAULT_NAME + ext;

        return INCLUDES_DEFAULT_NAME + ext;
    }
});
Example #7
0
File: apw.js Project: JIoJIaJIu/apw
module.exports = INHERIT(/** @lends APW.prototype */ {

    /**
     * Creates an instance of APW.
     *
     * @class APW
     * @constructs
     * @param {Arch} arch The Arch to work with.
     * @param {Number} [maxWorkers] Maximum number of workers to run simultaneously.
     * @param {Object} [ctx] The hash to mix with default context in node 'run' function.
     */
    __constructor: function(arch, maxWorkers, ctx) {
        this.arch = arch;

        if (arguments.length == 2) {
            if (!isFinite(maxWorkers)) {
                maxWorkers = undefined;
                ctx = arguments[1];
            }
        }

        this.workers = new this.__self.Workers(maxWorkers, ctx);
    },

    /**
     * Run targets processing.
     *
     * @param {String[]|String} targets IDs (or ID) of jobs to process.
     * @returns {Promise * Undefined} Promise of this process to complete.
     */
    process: function(targets) {
        return this.workers.start(this.arch.createPlan(targets));
    }

}, /** @lends APW */ {

    /** @type COA.api */
    api: require('./coa').api,

    /** @type Arch */
    Arch: require('./arch'),

    /** @type Plan */
    Plan: require('./plan'),

    /** @type Workers */
    Workers: require('./workers')

});
Example #8
0
File: http.js Project: narqo/jaggi
module.exports = inherit(Block, {
    run : function(params, promise) {
        var parsedUrl = url.parse(params.url, true),
            hasBody = params.method === 'POST' || params.method === 'PUT',
            queryParams = querystring.stringify(
                hasBody?
                    parsedUrl.query :
                    utils.merge(parsedUrl.query, params.data)),
            body = hasBody? querystring.stringify(params.data) : '';

        this._redirCounter = params.maxRedirects || 5;
        this._encoding = params.encoding || 'utf8';
        this._dataType = params.dataType;

        this._doHttp(
            {
                method   : params.method,
                headers  : utils.merge(
                    params.headers,
                    hasBody?
                        {
                            'Content-Type'   : 'application/x-www-form-urlencoded',
                            'Content-length' : Buffer.byteLength(body)
                        } :
                        null),
                protocol : parsedUrl.protocol,
                hostname : parsedUrl.hostname,
                port     : parsedUrl.port,
                path     : parsedUrl.pathname + (queryParams? '?' + queryParams : ''),
                auth     : params.auth
            },
            promise,
            params.dataType,
            body);
    },

    abort : function() {
        this._curReq && this._curReq.abort();
    },

    _doHttp : function(params, promise, dataType, body) {
        var _this = this;
        _this._curReq = (params.protocol === 'https:'? https : http).request(
                params,
                function(res) {
                    if(res.statusCode === 301 || res.statusCode === 302) {
                        return --_this._redirCounter?
                            _this._doHttp(url.parse(res.headers['location'], true), promise, dataType) :
                            promise.reject(Error('too many redirects'));
                    }
                    else if(res.statusCode >= 400) {
                        return promise.reject(new HttpError(res.statusCode));
                    }

                    var resp = '';
                    res.setEncoding(_this._encoding);
                    res
                        .on('data', function(chunk) {
                            resp += chunk;
                        })
                        .once('end', function() {
                            try {
                                promise.fulfill(processResponse(
                                    resp,
                                    _this._dataType || extractDataTypeFromHeaders(res.headers)));
                            }
                            catch(e) {
                                promise.reject(e);
                            }
                        })
                        .once('close', function() {
                            promise.reject(Error('connection closed'));
                        });
                });

        body && _this._curReq.write(body);

        _this._curReq
            .once('error', function(e) {
                promise.reject(e);
            })
            .end();
    }
});
Example #9
0
  if (!name) name = 'popup-' + (Math.random() * 0x10000000 | 0).toString(36);

  Emitter.call(this);
  this.name = name;
  this.opts = opts;
  this.optsStr = optsStr;

  // finally, open and return the popup window
  this.window = window.open(src, name, optsStr);
  this.focus();

  this.interval = setInterval(checkClose(this), interval);
}

// inherit from Emitter
inherit(Popup, Emitter);

/**
 * Closes the popup window.
 */

Popup.prototype.close = function () {
  this.window.close();
}

/**
 * Focuses the popup window (brings to front).
 */

Popup.prototype.focus = function () {
  this.window.focus();
Example #10
0
module.exports = inherit({
    /**
     *
     */
    __constructor: function(stats, customOpts) {
        customOpts = customOpts || {};

        this._options = _.merge({
            legend: {position: 'bottom'},
            title: {display: true, text: stats.login}
        }, this._options, customOpts.options);

        this._datasetsOptions = _.merge({}, this._datasetsOptions, customOpts.datasetsOptions);
        this._config = this._configure(stats);
    },

    /**
     *
     */
    _configure: function(stats) {
        return {
            type: this._type,
            data: this._formatData(stats),
            options: this._options
        };
    },

    /**
     *
     */
    _formatData: function(stats) {
        return {
            labels: stats.labels,
            datasets: _.map(stats.data, function(stat, index) {
                return _.extend(_.clone(this._datasetsOptions), {
                    label: this._datasetsOptions.labels && this._datasetsOptions.labels[index] || formatLabel_(index),
                    data: stat
                });
            }.bind(this))
        };

        ///
        function formatLabel_(index) {
            return (index === 0 && '1st'
                || index === 1 && '2nd'
                || index === 2 && '3rd'
                || format('%sth', index + 1)) + ' learning';
        }
    },

    /**
     *
     */
    getConfig: function() {
        return this._config;
    }
});
Example #11
0
var Process = inherit({
    __constructor: function(attrs, model3d) {
        /*
         * Process a pour vocation d'être étendue, c'est pourquoi tous ses champs sont précédés d'un underscore : on évite ainsi que des champs se fassent écrasés, ce qui pourrait produire des bugs bizarres
         */
        this._attrs = attrs;
        this._model3d = model3d;
        this._running = false;
        /*
         * Quand ce champ passe à vrai, on ignore toutes les erreurs qui peuvent arriver.
         * Utilité : on vient d'avoir une erreur (par ex. : impossible de trouver le fichier x) : la première est souvent l'erreur source, et elle est suivie par d'autres (puisqu'on fait ensuite un kill, on pourrait avoir des erreurs dues à des fermetures prématurées de processus).
         * Ces dernières sont moins intéressantes et écraseraient l'erreur d'origine. C'est pourquoi on met une sécurité.
         */
        this._ignoreError = false;
        this._stepCurrent = null;
    },
    step: function(options, cb) {
        if(_.isFunction(options)) {
            cb = options;
            options = {};
        }
        _.extend(options, {process_id: this._attrs.id});
        Step.get(options, this, cb);
    },
    update: function(fields, cb) {
        var self = this;
        // on met à jour les attributs de l'objet
        _.extend(self._attrs, fields);
        sqlCon.query('UPDATE process SET ? WHERE id=?', [fields, self._attrs.id], function(err) {
            if(err) {
                var message = '[Process] Erreur lors de la mise à jour de l\'enregistrement ' + self._attrs.id + ' en BDD : ' + err + '.';
                console.log(message);
                cb(new Error(message), null);
                return;
            }
            cb(null);
        });
    },
    /*
     * Démarre la chaine de Step associée au Process courant
     *
     * @param {Function} cb appelé quand le démarrage de la chaine de Step est effectif
     */
    start: function(cb) {
        var self = this;
        if(!self._running) {
            self._running = true;
            self._ignoreError = false;
            console.info('[Process] Processus "' + self._attrs.name + '" (ID = ' + self._attrs.id + ') lancé');
            self.update({
                state: Constants.STATE_RUNNING
            }, function(err) {
                if(!err)
                    self.startNextStep(cb);
            });
        }
    },
    /**
     * Trouve la prochaine Step à démarrer et la démarre
     *
     * @param {Function} cb appelé quand le démarrage de la Step est effectif
     */
    startNextStep: function(cb) {
        var self = this;
        if(self._attrs.state !== Constants.STATE_RUNNING) {
            return;
        }
        self.step(function(err, steps) {
            if(err) {
                cb(err);
                return;
            }
            steps.sort(function(a, b) {
                return a._attrs.ordering - b._attrs.ordering;
            });
            self._stepCurrent = undefined;
            for(var i = 0; i < steps.length; i++) {
                if(steps[i]._attrs.state == Constants.STATE_STOPPED)
                    continue;
                self._stepCurrent = steps[i];
                self._stepCurrent.start(cb);
                break;
            }
            if(!self._stepCurrent) {
                self.done(function(err) {
                    if(err)
                        console.log("[Process] N'a pas pu mettre fin au Process : " + err);
                    cb(err);
                });
            }
        });
    },
    /**
     * Met en pause le Process courant
     *
     * @param {boolean} hurry si le traitement actuel doit être interrompu dès que possible au risque de devoir par la suite recommencer la Step interrompue
     * @param {Function} cb appelé quand la mise en pause est effective, c'est-à-dire quand plus aucune Step lié à ce Model3d n'est en cours d'exécution
     */
    pause: function(hurry, cb) {
        var self = this;
        console.info('[Process] Processus "' + self._attrs.name + '" (ID = ' + self._attrs.id + ') mis en pause');
        if(hurry)
            self._ignoreError = true;
        if(self._stepCurrent) {
            self._stepCurrent.pause(hurry, function() {
                self._running = false;
                self._stepCurrent = null;
                self.update({
                    state: Constants.STATE_PAUSED
                }, cb);
            });
            return;
        }
        else {
            if(self._running)
                self._running = false;
            self.update({
                state: Constants.STATE_PAUSED
            }, cb);
        }
    },
    /*
     *
     *
     * @param {Function} cb appelé quand la chaine de traitement est vraiment terminée
     */
    stop: function(cb) {
        var self = this;
        console.info('[Process] Processus "' + self._attrs.name + '" (ID = ' + self._attrs.id + ') arrêté');
        self._ignoreError = true;
        if(self._stepCurrent) {
            self._stepCurrent.stop(function() {
                self._running = false;
                self._stepCurrent = null;
                self.update({
                    state: Constants.STATE_STOPPED
                }, cb);
            });
            return;
        }
        else {
            if(self._running)
                self._running = false;
            self.update({
                state: Constants.STATE_STOPPED
            }, cb);
        }
        self.removeCache();
    },
    error: function(err) {
        if(this._ignoreError)
            return;
        if(err.fatal)
            this._ignoreError = true;
        this._model3d.error(err);
    },
    done: function(cb) {
        var self = this;
        self._ignoreError = true;
        console.info('[Process] Processus "' + self._attrs.name + '" (ID = ' + self._attrs.id + ') terminé');
        self.update({
            state: Constants.STATE_STOPPED
        }, function(err) {
            if(err) {
                cb(err);
                return;
            }
            if(self._running)
                self._running = false;
            self._stepCurrent = null;
            self._model3d.startNextProcess(cb);
        });
    },
    sendNotification: function(message) {
        message.process_id = this._attrs.id;
        this._model3d.sendNotification(message);
    },
    removeCache: function() {
        Step.removeCache(this);
    }
}, {
    tabCachedModels: {},
    get: function(cond, model3d, cb) {
        var self = this;
        var queryArgs = Utils.getQueryArgs(cond);
        sqlCon.query('SELECT p.*, sp.name, sp.library_directory, sp.library_name, sp.ordering FROM process p INNER JOIN spec_process sp ON p.spec_process_id=sp.id WHERE ' + queryArgs.where, queryArgs.args, function(err, rows) {
            if(err) {
                var message = '[Process] Erreur lors de la récupération des enregistrements en BDD : ' + err + '.';
                console.error(message);
                cb(new Error(message), null);
            }
            else {
                var tabModels = _.map(rows, function(row) {
                    if(self.tabCachedModels.hasOwnProperty(row.id))
                        _.extend(self.tabCachedModels[row.id]._attrs, row);
                    else {
                        // require met en cache les fichiers déjà chargés
                        var ProcessObject = require('./process/' + row.library_directory + '/' + row.library_name + '.process');
                        self.tabCachedModels[row.id] = new ProcessObject(row, model3d);
                    }
                    return self.tabCachedModels[row.id];
                });
                cb(null, tabModels);
            }
        });
    },
    /**
     * Pour pouvoir ré-utiliser les mêmes objects entre chaque pause, ils sont mis en cache dans des tableaux associatifs (en JavaScript, ce sont tout simplement des objets) : tabCachedModels
     * On peut rencontrer les mêmes problèmes qu'en Java : tant qu'on garde une référence vers un objet, il ne sera pas nettoyé par le Garbage Collector : c'est donc le problème que résout cette fonction
     */
    removeCache: function(model3d) {
        _.forEach(this.tabCachedModels, function(cachedModel, index) {
            if(cachedModel._model3d == model3d)
                delete this.tabCachedModels[index];
        }, this);
    }
});
 */
module.exports = inherit({
    /**
     * Осуществляет обработку файла Борщиком.
     * @param {String} sourceFilename Исходный файл.
     * @param {String} destFilename Результирующий файл.
     * @param {Boolean} freeze Осуществлять ли фризинг.
     * @param {Boolean} minimize Осуществлять ли минимизацию.
     * @param {Tech} [tech]
     * @param {Object} [techOptions] Параметры для технологии.
     * @param {Boolean} comments Добавлять ли комментарии.
     * @returns {*}
     */
    preprocessFile: function (sourceFilename, destFilename, freeze, minimize, tech, techOptions, comments) {
        var opts = {
            input: sourceFilename,
            output: destFilename,
            freeze: freeze,
            minimize: minimize,
            comments: comments
        };
        if (tech) {
            opts.tech = tech;
            if (techOptions) {
                opts.techOptions = techOptions;
            }
        }
        return vow.when(borschik.api(opts));
    }
});
Example #13
0
var Config = module.exports = inherit({
    __constructor: function(configPath, configText, overrides) {
        overrides = overrides || {};
        var config;
        try {
            config = yaml.load(configText);
        } catch (e) {
            throw new GeminiError('Error while parsing a config file: ' + configPath + '\n' +
                    e.reason + ' ' + e.mark,
                    'Gemini config should be valid YAML file.'
            );
        }
        this.root = path.dirname(configPath);
        this.rootUrl = overrides.rootUrl || config.rootUrl;

        if (!this.rootUrl) {
            throw new GeminiError(
                'Required field "rootUrl" is not specified in config file: ' + configPath,
                '"rootUrl" should point to the root of website under test.\nSuite URLs are resolved relative to it.'
            );
        }
        this.gridUrl = overrides.gridUrl || config.gridUrl;
        this.browsers = this._parseBrowsers(config.browsers || {phantomjs: 'phantomjs'});
        this.capabilities = config.capabilities || {};
        this._validateCapabilities();

        this.http = this._parseHttp(config.http || {});

        if ('debug' in config && typeof config.debug !== 'boolean') {
            throw new GeminiError('Field "debug" must contain a boolean value');
        }
        this.debug = !!config.debug;

        if ('parallelLimit' in config) {
            if (typeof config.parallelLimit !== 'number') {
                throw new GeminiError('Field "parallelLimit" must be an integer number');
            }

            if (config.parallelLimit < 0) {
                throw new GeminiError('Field "parallelLimit" must be non-negative');
            }

            if (Math.floor(config.parallelLimit) !== config.parallelLimit) {
                throw new GeminiError('Field "parallelLimit" must be an integer number');
            }
            this.parallelLimit = config.parallelLimit;
        }

        if (this._requiresGrid() && !this.gridUrl) {
            throw new GeminiError(
                'Field "gridUrl" is required for using non-phantomjs browsers',
                [
                    'Specify selenium grid URL in your config file or use only',
                    'phantomjs browser.',
                    'Selenium server installation instructions:',
                    '',
                    'https://code.google.com/p/selenium/wiki/Grid2'
                ].join('\n')
            );
        }

        this.screenshotsDir = path.resolve(this.root,
            config.screenshotsDir || DEFAULT_SCREENSHOTS_DIR);
    },

    _requiresGrid: function() {
        return Object.keys(this.browsers).some(function(name) {
            return this.browsers[name].browserName !== 'phantomjs';
        }, this);
    },

    _validateCapabilities: function() {
        if ('takesScreenshot' in this.capabilities) {
            throw new GeminiError(
                'Setting `takesScreenshot` capability for all browsers is not allowed.\n' +
                'It is required and will be set automatically.'
            );
        }
    },

    _parseBrowsers: function(browsers) {
        var parsedBrowsers = {};
        // legacy browsers config
        if (Array.isArray(browsers)) {
            // Convert legacy browsers config value to the current one
            parsedBrowsers = this._parseLegacyBrowsers(browsers);

            // legacy browsers config option warning
            console.error([
                chalk.yellow('Warning! You are using deprecated format of "browsers" option'),
                chalk.yellow('in gemini config. Replace it\'s value with the following code:'),
                '', yaml.safeDump({browsers: parsedBrowsers}),
                chalk.yellow('For more info on project configuration see the instructions:'),
                chalk.yellow('https://github.com/bem/gemini#configuration')
            ].join('\n'));

            return parsedBrowsers;
        } else if (browsers !== null && typeof browsers === 'object') {
            // Convert `browser-id: browser-name` to `browser-id: {browserName: browser-name}`
            Object.keys(browsers).forEach(function(id) {
                if (typeof browsers[id] === 'string') {
                    parsedBrowsers[id] = {browserName: browsers[id]};
                } else {
                    parsedBrowsers[id] = browsers[id];
                }
            }, this);
            return parsedBrowsers;
        }
        throw new GeminiError('Field "browsers" must be an object or an array (deprecated).',
            'Configure your project by following the instructions:\n\n',
            'https://github.com/bem/gemini#configuration');
    },

    _parseLegacyBrowsers: function(browsers) {
        var parsedBrowsers = {};

        browsers
            .map(function(browser) {
                if (typeof browser === 'string') {
                    return {browserName: browser};
                }
                if ('name' in browser) {
                    browser = extend(true, {}, browser);
                    browser.browserName = browser.name;
                    delete browser.name;
                }
                return browser;
            })
            .forEach(function(browser) {
                var id = browser.browserName;
                if (browser.version) {
                    id += '-v' + browser.version;
                }
                parsedBrowsers[id] = browser;
            });

        return parsedBrowsers;
    },

    _parseHttp: function(http) {
        var conf = {};
        ['timeout', 'retries', 'retryDelay']
            .forEach(function(option) {
                if (option in http) {
                    if (typeof http[option] !== 'number') {
                        throw new GeminiError('Field "http.' + option + '" must be a number');
                    }
                    conf[option] = http[option];
                }
            });
        return conf;
    },

    getAbsoluteUrl: function getAbsoluteUrl(relUrl) {
        return url.resolve(this.rootUrl, relUrl);
    },

    getScreenshotsDir: function(suite, state) {
        return path.resolve(this.screenshotsDir, this._getPathForSuite(suite), state);
    },

    getScreenshotPath: function getScrenshotPath(suite, state, browser) {
        return path.join(this.getScreenshotsDir(suite, state), browser + '.png');
    },

    _getPathForSuite: function(suite) {
        var result = '';
        while (suite) {
            result = path.join(suite.name, result);
            suite = suite.parent;
        }
        return result;
    }

}, {
    read: function read(configPath, overrides) {
        return fs.read(configPath)
            .then(function(content) {
                return new Config(configPath, content, overrides);
            })
            .fail(function(e) {
                if (e.code === 'ENOENT') {
                    throw new GeminiError(
                        'Config file does not exists: ' + configPath,
                        'Specify config file or configure your project by following\nthe instructions:\n\n' +
                        'https://github.com/bem/gemini#configuration'
                    );
                }
                throw e;
            });
    }
});
Example #14
0
module.exports = inherit(require('../lib/tech/base-tech'), {
    getName: function() {
        return 'html-from-bemjson-i18n';
    },

    configure: function() {
        this._bemhtmlSource = this.node.unmaskTargetName(
            this.getOption('bemhtmlTarget', this.node.getTargetName('bemhtml.js'))
        );

        this._bemjsonSource = this.node.unmaskTargetName(
            this.getOption('bemjsonTarget', this.node.getTargetName('bemjson.js'))
        );

        this._allLangSource = this.node.unmaskTargetName(
            this.getOption('langAllTarget', this.node.getTargetName('lang.all.js'))
        );

        this._langSource = this.node.unmaskTargetName(
            this.getOption(
                'langTarget',
                this.node.getTargetName('lang.' + this.getOption('lang', this.node.getLanguages()[0]) + '.js')
            )
        );

        this._target = this.node.unmaskTargetName(
            this.getOption(
                'destTarget',
                this.node.getTargetName(this.getOption('lang', this.node.getLanguages()[0]) + '.html')
            )
        );
    },

    getTargets: function() {
        return [this.node.unmaskTargetName(this._target)];
    },

    getBuildResult: function(target, bemhtmlFile, bemjson, allLangFile, langFile) {
        var _this = this;
        delete require.cache[bemhtmlFile];
        delete require.cache[allLangFile];
        return Vow.all([
            asyncRequire(bemhtmlFile),
            asyncRequire(allLangFile)
        ]).spread(function(bemhtml, i18n) {
            delete require.cache[langFile];
            return asyncRequire(langFile).then(function(keysets) {
                if ((typeof i18n === 'function' || typeof keysets === 'function') && bemhtml.lib) {
                    if (typeof keysets === 'function') {
                        i18n = keysets(i18n);
                    }
                    bemhtml.lib.i18n = i18n;
                }
                var global = bemhtml.lib && bemhtml.lib.global;
                if (global) {
                    global.lang = _this.getOption('lang');
                    global.setTld(_this.getOption('lang'));
                }
                if (!bemhtml.BEMHTML && bemhtml.lib) {
                    return bemhtml.apply(bemjson);
                } else {
                    return bemhtml.BEMHTML.apply(bemjson);
                }
            });
        });
    },

    isRebuildRequired: function(target) {
        var cache = this.node.getNodeCache(target);
        return cache.needRebuildFile('bemhtml-file', this.node.resolvePath(this._bemhtmlSource)) ||
            cache.needRebuildFile('bemjson-file', this.node.resolvePath(this._bemjsonSource)) ||
            cache.needRebuildFile('allLang-file', this.node.resolvePath(this._allLangSource)) ||
            cache.needRebuildFile('lang-file', this.node.resolvePath(this._langSource)) ||
            cache.needRebuildFile('html-file', this.node.resolvePath(target));
    },

    storeCache: function(target) {
        var cache = this.node.getNodeCache(target);
        cache.cacheFileInfo('bemhtml-file', this.node.resolvePath(this._bemhtmlSource));
        cache.cacheFileInfo('bemjson-file', this.node.resolvePath(this._bemjsonSource));
        cache.cacheFileInfo('allLang-file', this.node.resolvePath(this._allLangSource));
        cache.cacheFileInfo('lang-file', this.node.resolvePath(this._langSource));
        cache.cacheFileInfo('html-file', this.node.resolvePath(target));
    },

    build: function() {
        var _this = this;
        return this.node.requireSources(
            [this._bemhtmlSource, this._bemjsonSource, this._allLangSource, this._langSource]
        ).then(function() {
            return Vow.when(_this.getTargets()).then(function(targets) {
                var targetsToBuild = [];
                return Vow.when(targets.map(function(target) {
                    return Vow.when(_this.isRebuildRequired(target)).then(function(rebuildRequired) {
                        if (!rebuildRequired) {
                            _this.node.isValidTarget(target);
                            _this.node.resolveTarget(target);
                        } else {
                            targetsToBuild.push(target);
                        }
                    });
                })).then(function() {
                    if (targetsToBuild.length) {
                        return requireOrEval(_this.node.resolvePath(_this._bemjsonSource)).then(function (bemjson) {
                            return Vow.all(targetsToBuild.map(function(target) {
                                return Vow.when(_this.getBuildResult(
                                        target,
                                        _this.node.resolvePath(_this._bemhtmlSource),
                                        bemjson,
                                        _this.node.resolvePath(_this._allLangSource),
                                        _this.node.resolvePath(_this._langSource)
                                    )).then(function(res) {
                                        return vowFs.write(_this.node.resolvePath(target), res, 'utf8');
                                    }).then(function() {
                                        _this.node.resolveTarget(target);
                                        _this.storeCache(target);
                                    });
                            }));
                        });
                    }
                    return null;
                });
            });
        });
    }
});
Example #15
0
module.exports = inherit(require('enb/lib/tech/base-tech'), {

    getName: function () {
        return 'deps';
    },

    configure: function () {
        var logger = this.node.getLogger();

        this._target = this.getOption('depsTarget');
        if (this._target) {
            logger.logOptionIsDeprecated(this.node.unmaskTargetName(this._target), 'enb-bem-techs', this.getName(),
                'depsTarget', 'target');
        } else {
            this._target = this.getOption('target', this.node.getTargetName('deps.js'));
        }
        this._target = this.node.unmaskTargetName(this._target);

        this._declFile = this.getOption('bemdeclTarget');
        if (this._declFile) {
            logger.logOptionIsDeprecated(this._target, 'enb-bem-techs', this.getName(), 'bemdeclTarget', 'bemdeclFile');
        } else {
            this._declFile = this.getOption('bemdeclFile', this.node.getTargetName('bemdecl.js'));
        }
        this._declFile = this.node.unmaskTargetName(this._declFile);

        this._levelsTarget = this.node.unmaskTargetName(
            this.getOption('levelsTarget', this.node.getTargetName('levels')));
    },

    getTargets: function () {
        return [this._target];
    },

    build: function () {
        var node = this.node,
            target = this._target,
            targetFilename = node.resolvePath(target),
            cache = node.getNodeCache(target),
            declFilename = this.node.resolvePath(this._declFile);

        return this.node.requireSources([this._levelsTarget, this._declFile])
            .spread(function (levels, sourceDeps) {
                var depFiles = levels.getFilesBySuffix('deps.js').concat(levels.getFilesBySuffix('deps.yaml'));

                if (cache.needRebuildFile('deps-file', targetFilename) ||
                    cache.needRebuildFile('source-deps-file', declFilename) ||
                    cache.needRebuildFileList('deps-file-list', depFiles)
                ) {
                    return requireSourceDeps(sourceDeps, declFilename)
                        .then(function (sourceDeps) {
                            var resolver = new DepsResolver(levels),
                                decls = resolver.normalizeDeps(sourceDeps);

                            return resolver.addDecls(decls)
                                .then(function () {
                                    var resolvedDeps = resolver.resolve(),
                                        str = 'exports.deps = ' + JSON.stringify(resolvedDeps, null, 4) + ';\n';

                                    return vfs.write(targetFilename, str, 'utf8')
                                        .then(function () {
                                            cache.cacheFileInfo('deps-file', targetFilename);
                                            cache.cacheFileInfo('source-deps-file', declFilename);
                                            cache.cacheFileList('deps-file-list', depFiles);
                                            node.resolveTarget(target, { deps: resolvedDeps });
                                        });
                                });
                        });
                } else {
                    node.isValidTarget(target);
                    dropRequireCache(require, targetFilename);

                    return asyncRequire(targetFilename)
                        .then(function (result) {
                            node.resolveTarget(target, result);
                            return null;
                        });
                }
            });
    }
});
Example #16
0
var StaticPage = inherit(Page, {
    /**
     * Build static page
     *
     * @returns {Promise} promise
     */
    handle: function () {
        return vow.all([
                this._getPages(),
                this._getTemplate(),
                this._getI18n()
            ])
            .spread(function (pages, bt, buildI18n) {
                var i18n = buildI18n();
                pages.setI18n(i18n);
                bt.lib.i18n = i18n;

                return pages
                    .exec(this._pageName, {
                        query: this._query,
                        options: this._getPageOptions(),
                        lang: this._lang
                    })

                    .then(function (btJson) {
                        var html = this._applyTemplate(btJson, bt);

                        return this._makeStaticPage(this._id, html);
                    }.bind(this));

            }.bind(this));
    },

    /**
     * Returns path for css and js files
     *
     * @returns {Object}
     */
    _getPageOptions: function () {
        return {
            assetsPath: '_' + path.basename(this._id)
        };
    },

    /**
     * Создаёт статическую страницу по переданному пути.
     *
     * @param {String} pageName
     * @param {String} html
     * @returns {Promise}
     */
    _makeStaticPage: function(pageName, html) {
        var fileName = path.basename(pageName);
        var filePath = pageName + '/' + fileName + '.html';

        return vowFs
            .write(filePath, html)
            .then(function () {
                return filePath;
            });
    }

}, {
    /**
     * @param {String} pageName
     * @param {String} lang
     */
    make: function (pageName, lang) {
        var req = {
            query: {
                lang: lang
            }
        };

        return new StaticPage('build/' + pageName, pageName + '-page', req, {})
                .handle()
                .then(function (filePath) {
                    console.log('Vow! Generated ' + filePath);
                });
    }
});
Example #17
0
'use strict';

var INHERIT = require('inherit'),
    Tech = require('../tech').Tech;

exports.Tech = INHERIT(Tech, {

    getBuildResultChunk: function(relPath, path, suffix) {
        return '/*borschik:include:' + relPath + '*/;\n';
    },

    getSuffixes: function() {
        return ['js'];
    }

});
Example #18
0
module.exports = inherit(EventEmitter, {

    __constructor: function(config, browserLauncher) {
        this.config = config;
        this._cancelled = false;
        this.browserLauncher = browserLauncher || new BrowserLauncher(config);
        this.coverage = new Coverage(config);
    },

    setGrepPattern: function(pattern) {
        this._grepPattern = pattern;
    },

    run: function(rootSuite) {
        var _this = this;
        this._stats = new Stats();

        return q.fcall(function() {
            _this.emit('begin', {
                config: _this.config,
                totalStates: rootSuite.deepStatesCount,
                browserIds: Object.keys(_this.config.browsers)
            });
        }).then(function() {
            return _this._prepare();
        })
        .then(function() {
            return _this._runBrowsers(rootSuite.children);
        })
        .then(function() {
            if (_this.config.coverage) {
                return _this.coverage.processStats();
            }
        })
        .then(function() {
            _this.emit('end');
            return _this._stats.data;
        });
    },

    _prepare: function() {
    },

    _runBrowsers: function(suites) {
        var _this = this;
        return q.all(Object.keys(this.config.browsers).map(function(browserId) {
            return _this.browserLauncher.launch(browserId)
                .then(function(browser) {
                    _this.emit('startBrowser', {browserId: browser.id});
                    return _this._runSuitesInBrowser(suites, browser)
                        .fin(function() {
                            _this.emit('stopBrowser', {browserId: browser.id});
                            return _this.browserLauncher.stop(browser);
                        });
                })
                .fail(function(e) {
                    _this._cancelled = true;
                    return q.reject(e);
                });
        }));
    },

    _runSuitesInBrowser: function(suites, browser) {
        var _this = this;
        return promiseUtils.seqMap(suites, function(suite) {
            return _this._runSuiteInBrowser(suite, browser);
        });
    },

    _runSuiteInBrowser: function(suite, browser) {
        if (this._cancelled) {
            return q.resolve();
        }

        var _this = this,
            eventData = {
                browserId: browser.id,
                suiteName: suite.name,
                suiteId: suite.id
            };

        this.emit('beginSuite', eventData);

        return this._runSuiteStateIfMatches(suite, browser)
            .then(function() {
                return _this._runSuitesInBrowser(suite.children, browser);
            })
            .then(function() {
                _this.emit('endSuite', eventData);
            });
    },

    _runSuiteStateIfMatches: function(suite, browser) {
        if (this._grepPattern && !this._grepPattern.test(suite.fullName)) {
            return q.resolve();
        }

        return this._runSuiteStates(suite, browser);
    },

    _runSuiteStates: function(suite, browser) {
        if (!suite.hasStates) {
            return q.resolve();
        }
        var _this = this,
            session = new CaptureSession(browser);

        return browser.open(this.config.getAbsoluteUrl(suite.url))
            .then(function() {
                return session.runHook(suite.beforeHook);
            })
            .then(function() {
                return promiseUtils.seqMap(suite.states, function(state) {
                    return _this._runStateInSession(state, session);
                });
            })
            .then(function() {
                return session.runHook(suite.afterHook);
            });
    },

    _runStateInSession: function(state, session) {
        if (this._cancelled) {
            return q.resolve();
        }
        var _this = this,
            suite = state.suite,
            eventData = {
                browserId: session.browser.id,
                suiteName: state.suite.name,
                suiteId: state.suite.id,
                stateName: state.name
            };

        _this._stats.add('total');
        if (state.shouldSkip(session.browser)) {
            _this.emit('skipState', eventData);
            this._stats.add('skipped');
            return q();
        }

        _this.emit('beginState', eventData);

        return session.capture(state, {coverage: this.config.coverage})
            .then(function(data) {
                if (_this.config.coverage) {
                    _this.coverage.addStats(data.coverage);
                }
                return q(_this._processCapture({
                    suite: suite,
                    state: state,
                    browser: session.browser,
                    image: data.image,
                    canHaveCaret: data.canHaveCaret
                }));
            })
            .fail(function(e) {
                if (e instanceof StateError) {
                    e.suiteId = state.suite.id;
                    e.suiteName = state.suite.name;
                    e.stateName = state.name;
                    e.browserId = session.browserId;

                    _this._stats.add('errored');
                    _this.emit('error', e);
                } else {
                    return q.reject(e);
                }
            })
            .fin(function() {
                _this.emit('endState', eventData);
            });
    },

    _processCapture: function() {
    }

});
Example #19
0
 *
 * @api private
 */

Scrollbar.Horizontal = function (pane) {
  pane.el.insertAdjacentHTML('beforeend',
    '<div class="antiscroll-scrollbar antiscroll-scrollbar-horizontal"/>');
  this.el = q('.antiscroll-scrollbar-horizontal', pane.el);
  Scrollbar.call(this, pane);
};

/**
 * Inherits from Scrollbar.
 */

inherit(Scrollbar.Horizontal, Scrollbar);

/**
 * Updates size/position of scrollbar.
 *
 * @api private
 */

Scrollbar.Horizontal.prototype.update = function () {
  var paneWidth = this.pane.el.offsetWidth,
    trackWidth = paneWidth - this.pane.padding * 2,
    scrollWidth = this.pane.inner.scrollWidth;

  css(this.el, {
    width: Math.floor(trackWidth * paneWidth / scrollWidth),
    transform: 'translateX(' + Math.floor(trackWidth * this.pane.inner.scrollLeft / scrollWidth) + 'px)'
Example #20
0
File: node.js Project: bratva/enb
module.exports = inherit( /** @lends Node.prototype */ {
    /**
     * Конструктор.
     * @param {String} nodePath
     * @param {MakePlatform} makePlatform
     * @param {Cache} cache
     */
    __constructor: function(nodePath, makePlatform, cache) {
        var root = makePlatform.getDir();
        /**
         * Ссылка на платформу.
         * @type {MakePlatform}
         * @name Node.prototype._makePlatform
         * @private
         */
        this._makePlatform = makePlatform;
        /**
         * Путь к директории с нодой относительно корня проекта.
         * @type {String}
         * @name Node.prototype._path
         * @private
         */
        this._path = nodePath;
        /**
         * Абсолютный путь к корню проекта.
         * @type {String}
         * @name Node.prototype._root
         * @private
         */
        this._root = root;
        /**
         * Абсолютный путь к директории с нодой.
         * @type {String}
         * @name Node.prototype._dirname
         * @private
         */
        this._dirname = root + '/' + nodePath;
        /**
         * Имя директории с нодой. Например, "index" для ноды "pages/index".
         * @type {String}
         * @name Node.prototype._targetName
         * @private
         */
        this._targetName = path.basename(nodePath);
        /**
         * Зарегистрированные технологии.
         * @type {Tech[]}
         * @name Node.prototype._techs
         * @private
         */
        this._techs = [];
        /**
         * Ссылка на кэш платформы.
         * @type {Cache}
         * @name Node.prototype._cache
         * @private
         */
        this._cache = cache;
        /**
         * Кэш для ноды.
         * @type {Cache}
         * @name Node.prototype._nodeCache
         * @private
         */
        this._nodeCache = cache.subCache(nodePath);
        /**
         * Логгер для ноды.
         * @type {Logger}
         * @name Node.prototype._logger
         * @private
         */
        this._logger = null;
        /**
         * Зарегистрированные таргеты со ссылками на технологии и с промисами на выполнение таргетов.
         * Формат:
         *  { 'index.js': { tech: <ссылка на технологию>, started: true|false, promise: <промис на выполнение> } }
         * @type {Object}
         * @name Node.prototype._targetNames
         * @private
         */
        this._targetNames = {};
        /**
         * Список таргетов на сборку.
         * @type {String[]}
         * @name Node.prototype._targetNamesToBuild
         * @private
         */
        this._targetNamesToBuild = [];
        /**
         * Список таргетов на удаление (для команды enb make clean).
         * @type {String[]}
         * @name Node.prototype._targetNamesToClean
         * @private
         */
        this._targetNamesToClean = [];
        // TODO: Удалить this._languages.
        /**
         * Список языков для ноды. Уже почти не используется в связи с переходом на новый формат настроек.
         * Будет удалено в будущих версиях.
         * @type {String[]}
         * @name Node.prototype._languages
         * @deprecated
         * @private
         */
        this._languages = null;
        /**
         * Промис на регистрацию всех таргетов для добавленных технологий.
         * @type {Promise}
         * @name Node.prototype._registerTargetsPromise
         * @private
         */
        this._registerTargetsPromise = null;
        /**
         * Построитель графа сборки.
         * @type {BuildGraph}
         * @name Node.prototype._graph
         * @private
         */
        this._graph = null;
    },

    /**
     * Внутреннее состояние текущей сборки. Используется для обмена данными между нодами.
     * @param {Object} buildState
     */
    setBuildState: function(buildState) {
        this.buildState = buildState;
    },

    /**
     * Устанавливает логгер для ноды (для того, чтобы логгировать ход сборки в консоль).
     * @param {Logger} logger
     * @returns {Node}
     */
    setLogger: function(logger) {
        this._logger = logger;
        return this;
    },

    /**
     * Возвращает логгер для ноды. Технологии могут пользоваться этим методов для дополнительного логгирования.
     * @returns {Logger}
     */
    getLogger: function() {
        return this._logger;
    },

    /**
     * Устанавливает языки для ноды.
     * @param {String[]} languages
     * @returns {Node}
     */
    setLanguages: function(languages) {
        this._languages = languages;
        return this;
    },

    /**
     * Возвращает языки для текущей ноды.
     * @returns {String[]}
     */
    getLanguages: function() {
        return this._languages;
    },

    /**
     * Возвращает абсолютный путь к директории с нодой.
     * @returns {String}
     */
    getDir: function() {
        return this._dirname;
    },

    /**
     * Возвращает абсолютный путь к директории с проектом.
     * @returns {String}
     */
    getRootDir: function() {
        return this._root;
    },

    /**
     * Возвращает относительный путь к директории с нодой (от корня проекта).
     * @returns {*}
     */
    getPath: function() {
        return this._path;
    },

    /**
     * Возвращает технологии, зарегистрированные для данной ноды.
     * @returns {Tech[]}
     */
    getTechs: function() {
        return this._techs;
    },

    /**
     * Устанавливает технологии для ноды.
     * @param {Tech[]} techs
     */
    setTechs: function(techs) {
        this._techs = techs;
    },

    /**
     * Устанавливает таргеты для сборки.
     * @param {String[]} targetsToBuild
     */
    setTargetsToBuild: function(targetsToBuild) {
        this._targetNamesToBuild = targetsToBuild;
    },

    /**
     * Устанавливает таргеты для удаления.
     * @param {String[]} targetsToClean
     */
    setTargetsToClean: function(targetsToClean) {
        this._targetNamesToClean = targetsToClean;
    },

    /**
     * Устанавливает построитель графа сборки.
     * @param {BuildGraph} graph
     * @returns {Node}
     */
    setBuildGraph: function(graph) {
        this._graph = graph;
        return this;
    },

    /**
     * Возвращает абсолютный путь к файлу, лежащему в директории с нодой.
     * @param {String} filename
     * @returns {String}
     */
    resolvePath: function(filename) {
        return this._dirname + '/' + filename;
    },

    /**
     * Возвращает абсолютный путь к файлу, лежащему в директории с указанной нодой.
     * @param {String} nodePath Имя ноды (например, "pages/index").
     * @param {String} filename
     * @returns {String}
     */
    resolveNodePath: function(nodePath, filename) {
        return this._root + '/' + nodePath + '/' + filename;
    },

    /**
     * Демаскирует имя таргета для указанной ноды. Например, для ноды "pages/index" заменяет "?.js" на "index.js".
     * @param {String} nodePath Например, "pages/login".
     * @param {String} targetName
     * @returns {String}
     */
    unmaskNodeTargetName: function(nodePath, targetName) {
        return targetName.replace(/\?/g, path.basename(nodePath));
    },

    /**
     * Возвращает относительный ноды путь к файлу (заданному абсолютным путем).
     * @param {String} filename
     * @returns {String}
     */
    relativePath: function(filename) {
        var res = path.relative(this._path, filename);
        if (res.charAt(0) !== '.') {
            res = './' + res;
        }
        return res;
    },

    /**
     * Возвращает www-путь к файлу (заданному абсолютным путем).
     * @param {String} filename
     * @param {String} wwwRoot Адрес соответствующий корню проекта.
     * @returns {String}
     */
    wwwRootPath: function(filename, wwwRoot) {
        wwwRoot = wwwRoot || '/';
        return wwwRoot + path.relative(this._root, filename);
    },

    /**
     * Удаляет файл, лежащий в директории ноды. Вспомогательный метод для технологий.
     * @param {String} target
     */
    cleanTargetFile: function(target) {
        var targetPath = this.resolvePath(target);
        if (fs.existsSync(targetPath)) {
            fs.unlinkSync(targetPath);
            this.getLogger().logClean(target);
        }
    },

    /**
     * Создает временный файл для указанного таргета.
     * @param {String} targetName
     * @returns {String}
     */
    createTmpFileForTarget: function(targetName) {
        var dir = this._dirname;
        function createTmpFilename() {
            var prefix = '_tmp_' + (+new Date()) + (Math.random() * 0x1000000000).toString(36) + '_',
                filename = dir + '/' + prefix + targetName;
            return vowFs.exists(filename).then(function(exists) {
                if (exists) {
                    return createTmpFilename();
                } else {
                    return vowFs.write(filename, '').then(function() {
                        return filename;
                    });
                }
            });
        }
        return createTmpFilename();
    },

    /**
     * Инициализирует технологии, зарегистрированные в рамках ноды.
     * @returns {Promise}
     */
    loadTechs: function() {
        var _this = this;
        return Vow.all(this._techs.map(function(t) {
            var nodeMirrorClass = function() {};
            nodeMirrorClass.prototype = _this;
            var mirror = new nodeMirrorClass();
            return Vow.when(t.init(mirror)).then(function() {
                return Vow.when(t.getTargets()).then(function(targets) {
                    if (_this._graph) {
                        targets.forEach(function(target) {
                            var targetPath = _this._path + '/' + target;
                            _this._graph.addTarget(targetPath, t.getName());
                        });
                    }
                    var origRequireSources = _this.requireSources,
                        origRequireNodeSources = _this.requireNodeSources;
                    mirror.requireSources = function(sources) {
                        if (_this._graph) {
                            targets.forEach(function(target) {
                                var targetPath = _this._path + '/' + target;
                                sources.forEach(function(source) {
                                    _this._graph.addDep(targetPath, _this._path + '/' + _this.unmaskTargetName(source));
                                });
                            });
                        }
                        return origRequireSources.apply(_this, arguments);
                    };
                    mirror.requireNodeSources = function(sources) {
                        if (_this._graph) {
                            Object.keys(sources).forEach(function(nodeName) {
                                targets.forEach(function(target) {
                                    var targetPath = _this._path + '/' + target;
                                    sources[nodeName].forEach(function(source) {
                                        _this._graph.addDep(targetPath, nodeName + '/' + _this.unmaskNodeTargetName(nodeName, source));
                                    });
                                });
                            });
                        }
                        return origRequireNodeSources.apply(_this, arguments);
                    };
                });
            });
        }));
    },

    /**
     * Возвращает техническую информацию об указанном таргете.
     * Формат результата: { tech: <ссылка на технологию>, started: true|false, promise: <промис на выполнение> }
     * @param {String} name Имя таргета.
     * @returns {Object}
     * @private
     */
    _getTarget: function(name) {
        var targets = this._targetNames, target;
        if (!(target = targets[name])) {
            target = targets[name] = {started: false};
        }
        if (!target.promise) {
            target.promise = Vow.promise();
        }
        return target;
    },

    /**
     * Возвращает true, если таргет под указанным именем может быть собран. В противном случае возвращает false.
     * @param {String} name
     * @returns {Boolean}
     */
    hasRegisteredTarget: function(name) {
        return !!this._targetNames[name];
    },

    /**
     * Возвращает базовое имя таргета по умолчанию для ноды. Например, "index" для "pages/index".
     * Добавляет суффикс если не обходимо. Например, для "pages/index": node.getTargetName("js") -> index.js
     * @param {String} suffix
     * @returns {String}
     */
    getTargetName: function(suffix) {
        return this._targetName + (suffix ? '.' + suffix : '');
    },

    /**
     * Демаскирует имя таргета. Например, для ноды "pages/index" заменяет "?.js" на "index.js".
     * @param {String} targetName
     * @returns {String}
     */
    unmaskTargetName: function(targetName) {
        return targetName.replace(/\?/g, this._targetName);
    },

    /**
     * Регистрирует таргет для указанной технологии.
     * @param {String} target
     * @param {Tech} tech
     * @private
     */
    _registerTarget: function(target, tech) {
        var targetObj = this._getTarget(target);
        if (targetObj.tech) {
            throw Error(
                'Concurrent techs for target: ' + target + ', techs: "' + targetObj.tech.getName() + '" vs "' + tech.getName() + '"'
            );
        }
        targetObj.tech = tech;
    },

    /**
     * Оповещает ноду о том, что таргет собран. Технологии, которые зависят от этого таргета могут продолжить работу.
     * @param {String} target
     * @param {Object} [value]
     * @returns {Promise}
     */
    resolveTarget: function(target, value) {
        var targetObj = this._getTarget(target);
        if (!targetObj.isValid) {
            this._logger.logAction('rebuild', target, targetObj.tech.getName());
        }
        if (this._graph) {
            this._graph.resolveTarget(this._path + '/' + target);
        }
        return targetObj.promise.fulfill(value);
    },

    /**
     * Вывод сообщение в лог о том, что таргет не был пересобран, т.к. в этом нет нужды.
     * @param {String} target
     */
    isValidTarget: function(target) {
        var targetObj = this._getTarget(target);
        this._logger.isValid(target, targetObj.tech.getName());
        targetObj.isValid = true;
    },

    /**
     * Оповещает ноду о том, что таргет не удалось собрать. В этот метод следует передать ошибку.
     * @param {String} target
     * @param {Error} err
     * @returns {Promise}
     */
    rejectTarget: function(target, err) {
        var targetObj = this._getTarget(target);
        this._logger.logErrorAction('failed', target, targetObj.tech.getName());
        return targetObj.promise.reject(err);
    },

    /**
     * Требует выполнения таргетов для переданных нод.
     * Требование в формате: { "node/path": [ "target1", "target2", ... ], "another-node/path": ... }.
     * @param {Object} sourcesByNodes
     * @returns {Promise}
     */
    requireNodeSources: function(sourcesByNodes) {
        var _this = this,
            resultByNodes = {};
        return Vow.all(Object.keys(sourcesByNodes).map(function(nodePath) {
            return _this._makePlatform.requireNodeSources(nodePath, sourcesByNodes[nodePath]).then(function(results) {
                resultByNodes[nodePath] = results;
            });
        })).then(function() {
            return resultByNodes;
        });
    },

    /**
     * Требует выполнения таргетов.
     * Требование в формате: ["target1", "target2", ...].
     * Например, node.requireSources(["index.js"]).then(...);
     * @param {String[]} sources
     * @returns {Promise}
     */
    requireSources: function(sources) {
        var _this = this;
        return this._registerTargets().then(function() {
            return Vow.all(sources.map(function(source) {
                source = _this.unmaskTargetName(source);
                var targetObj = _this._getTarget(source);
                if (!targetObj.tech) {
                    throw TargetNotFoundEror('There is no tech for target ' + _this._path + '/' + source + '.');
                }
                if (!targetObj.started) {
                    targetObj.started = true;
                    if (!targetObj.tech.__started) {
                        targetObj.tech.__started = true;
                        try {
                            Vow.when(targetObj.tech.build()).fail(function(err) {
                                _this.rejectTarget(source, err);
                            });
                        } catch (err) {
                            _this.rejectTarget(source, err);
                        }
                    }
                }
                return targetObj.promise;
            }));
        });
    },

    /**
     * Удаляет таргеты с помощью технологий.
     * @param {String[]} targets
     * @returns {Promise}
     */
    cleanTargets: function(targets) {
        var _this = this;
        return Vow.all(targets.map(function(target) {
            var targetObj = _this._getTarget(target);
            if (!targetObj.tech) {
                throw Error('There is no tech for target ' + target + '.');
            }
            return Vow.when(targetObj.tech.clean());
        }));
    },

    /**
     * Регистрирует таргеты по имеющимся технологиям.
     * Часть инициализации ноды.
     * @returns {Promise}
     * @private
     */
    _registerTargets: function() {
        var _this = this;
        if (!this._registerTargetsPromise) {
            this._registerTargetsPromise = Vow.all(this._techs.map(function (t) {
                    return t.getTargets();
                })).then(function (targetLists) {
                    function registerTarget(targetName) {
                        _this._registerTarget(targetName, _this._techs[i]);
                    }
                    for (var i = 0, l = _this._techs.length; i < l; i++) {
                        targetLists[i].forEach(registerTarget);
                    }
                });
        }
        return this._registerTargetsPromise;
    },

    /**
     * Вычисляет список имен таргетов по переданным данным.
     * @param {String[]} targets Список целей (указанный в настройках сборки, например).
     * @param {String[]} defaultTargetList Полный список целей (для случая, когда указана маска "*").
     * @returns {String[]}
     * @private
     */
    _resolveTargets: function(targets, defaultTargetList) {
        var targetsToBuild = this._targetNamesToBuild, _this = this;
        if (targets) {
            targetsToBuild = targets;
            targetsToBuild = [].concat.apply([], targetsToBuild.map(function(targetName) {
                if (targetName == '*') {
                    return (defaultTargetList.length ? defaultTargetList : Object.keys(_this._targetNames));
                } else {
                    return [targetName];
                }
            }));
        }
        if (!targetsToBuild) {
            targetsToBuild = Object.keys(this._targetNames);
        }
        targetsToBuild = targetsToBuild.filter(function(elem, pos) {
            return targetsToBuild.indexOf(elem) == pos;
        });
        return targetsToBuild;
    },

    /**
     * Запускает сборку указанных целей для ноды.
     * @param {String[]} targets
     * @returns {Promise}
     */
    build: function(targets) {
        var _this = this;
        return this.requireSources(_this._resolveTargets(targets, _this._targetNamesToBuild));
    },

    // TODO: Удалить параметр buildCache.
    /**
     * Запускает удаление указанных целей для ноды.
     * @param {String[]} targets
     * @param {Object} buildCache Вроде, лишний параметр, надо удалить.
     * @returns {Promise}
     */
    clean: function(targets, buildCache) {
        var _this = this;
        this.buildState = buildCache || {};
        return this._registerTargets().then(function(){
            return _this.cleanTargets(_this._resolveTargets(targets, _this._targetNamesToClean));
        });
    },

    /**
     * Возвращает кэш для таргета ноды. Этим методом могут пользоваться технологии для кэширования.
     * @param {String} subCacheName
     * @returns {Cache}
     */
    getNodeCache: function(subCacheName) {
        return subCacheName ? this._nodeCache.subCache(subCacheName) : this._nodeCache;
    },

    /**
     * Возвращает схему именования для уровня переопределения.
     * Схема именования содержит два метода:
     * ```javascript
     * // Выполняет построение структуры файлов уровня переопределения, используя методы инстанции класса LevelBuilder.
     * {Promise} buildLevel( {String} levelPath, {LevelBuilder} levelBuilder )
     * // Возвращает путь к файлу на основе пути к уровню переопределения и BEM-описания.
     * {String} buildFilePath( {String} levelPath, {String} blockName, {String} elemName, {String} modName, {String} modVal )
     * ```
     * @returns {Object|undefined}
     */
    getLevelNamingScheme: function(levelPath) {
        return this._makePlatform.getLevelNamingScheme(levelPath);
    }
});
Example #21
0
module.exports = inherit(Runner, {

    __constructor: function(config, options) {
        this.__base(config);
        options = options || {};
        this._tempDir = options.tempDir || temp.path('gemini');
    },

    _prepare: function() {
        return fs.makeTree(this._tempDir);
    },

    _processCapture: function(capture) {
        var refPath = this.config.getScreenshotPath(
                capture.suite,
                capture.state.name,
                capture.browser.id),
            tmpPath = this._tempPath(),
            _this = this;

        return fs.exists(refPath)
            .then(function(refExists) {
                if (!refExists) {
                    return q.reject(new StateError(
                        'Can not find reference image at ' + refPath + '\n' +
                        'Run `gemini gather` command to capture all reference images.'
                    ));
                }
            })
            .then(function() {
                return capture.image.save(tmpPath);
            })
            .then(function() {
                return [tmpPath, Image.compare(tmpPath, refPath, {
                    strictComparison: _this.config.strictComparison,
                    canHaveCaret: capture.canHaveCaret
                })];
            })
            .spread(function(currentPath, isEqual) {
                _this._stats.add(isEqual? 'passed' : 'failed');
                _this.emit('endTest', {
                    suiteName: capture.suite.name,
                    suiteId: capture.suite.id,
                    stateName: capture.state.name,
                    equal: isEqual,
                    referencePath: refPath,
                    currentPath: currentPath,
                    browserId: capture.browser.id
                });
            });
    },

    _tempPath: function() {
        return temp.path({dir: this._tempDir, suffix: '.png'});
    }

});
Example #22
0
 */

exports.Overlay = Overlay;

function overlay(options) {
  return new Overlay(options);
}

function Overlay(options) {
  Emitter.call(this);
  options = options || {};
  this.$el = o(require("./template"));
  this.$el.appendTo("body");
}

inherit(Overlay, Emitter);

Overlay.prototype.show = function() {
  this.emit("show");
  this.$el.removeClass("hide");
  return this;
};

Overlay.prototype.hide = function() {
  this.emit("hide");
  return this.remove();
};

Overlay.prototype.remove = function() {
  var self = this;
  this.emit('close');
Example #23
0
module.exports.OldDeps = (function() {
    /**
     * Класс, раскрывающий зависимости. Взят из bem-tools.
     *
     * @name OldDeps
     */
    var OldDeps = inherit({

        /**
         * Конструктор.
         * Принимает блоки из bemdecl.
         *
         * @param {Array} deps
         */
        __constructor: function(deps) {
            this.items = {};
            this.itemsByOrder = [];
            this.uniqExpand = {};

            // Force adding of root item to this.items
            var rootItem = this.rootItem = new OldDepsItem({});
            this.items[rootItem.buildKey()] = rootItem;

            deps && this.parse(deps);
        },

        /**
         * Добавляет зависимость в коллекцию.
         *
         * @param {OldDepsItem} target
         * @param {String} depsType shouldDeps/mustDeps
         * @param {OldDepsItem} item
         */
        add: function(target, depsType, item) {
            var items = this.items,
                targetKey = target.buildKey(),
                itemKey = item.buildKey();

            if (!items[itemKey]) {
                items[itemKey] = item;
                this.itemsByOrder.push(itemKey);
            }

            (items[targetKey] || (items[targetKey] = target))[depsType].push(itemKey);
        },

        /**
         * Удаляет зависимость из коллекции.
         *
         * @param {OldDepsItem} target
         * @param {OldDepsItem} item
         */
        remove: function(target, item) {
            target = this.items[target.buildKey()];
            var itemKey = item.buildKey();
            removeFromArray(target.shouldDeps, itemKey);
            removeFromArray(target.mustDeps, itemKey);
        },

        /**
         * Клонирует резолвер зависимостей.
         *
         * @param {OldDeps} [target]
         * @returns {OldDeps}
         */
        clone: function(target) {
            target || (target = new this.__self());

            var items = this.items;
            for (var i in items) {
                if (!items.hasOwnProperty(i)) continue;
                target.items[i] = items[i].clone();
            }

            target.itemsByOrder = this.itemsByOrder.concat();
            target.tech = this.tech;
            target.uniqExpand = this.uniqExpand;

            return target;
        },

        /**
         * Разбирает bemdecl.
         *
         * @param {Array} deps
         * @param {Object} [ctx]
         * @param {Function} [fn]
         * @returns {OldDeps}
         */
        parse: function(deps, ctx, fn) {
            fn || (fn = function(i) { this.add(this.rootItem, 'shouldDeps', i); });

            var _this = this,

                forEachItem = function(type, items, ctx) {
                    items && !isEmptyObject(items) && (Array.isArray(items) ? items : [items]).forEach(function(item) {

                        if (isSimple(item)) {
                            var i = item;
                            (item = {})[type] = i;
                        }
                        item.name && (item[type] = item.name);

                        var depsItem = new OldDepsItem(item, ctx);

                        fn.call(_this, depsItem); // _this.add(rootItem, 'shouldDeps', depsItem);

                        _this.parse(
                            item.mustDeps,
                            depsItem,
                            function(i) { this.add(depsItem, 'mustDeps', i) });

                        _this.parse(
                            item.shouldDeps,
                            depsItem,
                            function(i) { this.add(depsItem, 'shouldDeps', i) });

                        _this.parse(
                            item.noDeps,
                            depsItem,
                            function(i) { this.remove(depsItem, i) });

                        forEachItem('elem', item.elems, depsItem);

                        var mods = item.mods;
                        if (mods && !Array.isArray(mods)) { // Object
                            var modsArr = [];
                            for (var m in mods) {
                                if (!mods.hasOwnProperty(m)) continue;
                                modsArr.push({ mod: m });
                                var mod = { mod: m }, v = mods[m];
                                Array.isArray(v) ? (mod.vals = v) : (mod.val = v);
                                modsArr.push(mod);
                            }
                            mods = modsArr;
                        }
                        forEachItem('mod', mods, depsItem);

                        forEachItem('val', item.vals, depsItem);

                    });
                };

            forEachItem('block', deps, ctx);

            return this;
        },

        /**
         * Раскрывает зависимости, используя deps.js-файлы.
         *
         * @param {Object} tech
         * @returns {Promise}
         */
        expandByFS: function(tech) {

            this.tech = tech;

            var _this = this,
                depsCount1 = this.getCount(),
                depsCount2;

            return Vow.when(this.expandOnceByFS())
                .then(function again(newDeps) {

                    depsCount2 = newDeps.getCount();
                    if (depsCount1 !== depsCount2) {
                        depsCount1 = depsCount2;
                        return Vow.when(newDeps.expandOnceByFS(), again);
                    }

                    return newDeps.clone(_this);

                });

        },

        /**
         * Раскрывает зависимости, используя deps.js-файлы без повторений.
         *
         * @returns {Promise}
         */
        expandOnceByFS: function() {

            var newDeps = this.clone();
            var items = this.filter(function(item) {
                return !newDeps.uniqExpand.hasOwnProperty(item.buildKey());
            });

            function keepWorking(item) {
                newDeps.uniqExpand[item.buildKey()] = true;
                return newDeps.expandItemByFS(item).then(function() {
                    if (items.length > 0) {
                        return keepWorking(items.shift());
                    } else {
                        return null;
                    }
                });
            }

            if (items.length > 0) {
                return keepWorking(items.shift()).then(function() {
                    return newDeps;
                });
            } else {
                return Vow.fulfill(newDeps);
            }
        },

        /**
         * Раскрывает одну зависимость, используя deps.js-файлы.
         *
         * @param {OldDepsItem} item
         * @returns {Promise}
         */
        expandItemByFS: function(item) {

            var _this = this,
                tech = this.tech;

            var files = tech.levels.getFilesByDecl(item.item.block, item.item.elem, item.item.mod, item.item.val)
                .filter(function(file) { return file.suffix === 'deps.js'; });

            var promise = Vow.fulfill();

            files.forEach(function(file) {
                promise = promise.then(function() {
                    return vowFs.read(file.fullname, 'utf8').then(function(content) {
                        try {
                            _this.parse(vm.runInThisContext(content, file.fullname), item);
                        } catch (e) {
                            throw new Error('Syntax error in file "' + file.fullname + '": ' + e.message);
                        }
                    });
                });
            });

            return promise;
        },

        /**
         * Вычитает зависимости из переданного OldDeps.
         *
         * @param {OldDeps} deps
         * @returns {OldDeps}
         */
        subtract: function(deps) {
            var items1 = this.items,
                items2 = deps.items;

            for (var k in items2)
                if (k && items2.hasOwnProperty(k)) delete items1[k];
            return this;
        },

        /**
         * Сохраняет пересечение с другим OldDeps.
         *
         * @param {OldDeps} deps
         * @returns {OldDeps}
         */
        intersect: function(deps) {
            var items1 = this.items,
                items2 = deps.items,
                newItems = {};

            for (var k in items2) {
                if ((items2.hasOwnProperty(k) && items1.hasOwnProperty(k)) || !k)
                    newItems[k] = items1[k];
            }

            this.items = newItems;

            return this;
        },

        /**
         * Возвращает количество зависимостей.
         *
         * @returns {Number}
         */
        getCount: function() {
            var res = 0,
                items = this.items;

            for (var k in items) items.hasOwnProperty(k) && res++;

            return res;
        },

        /**
         * Итерирует по набору зависимостей.
         *
         * @param {Function} fn
         * @param {Object} [uniq]
         * @param {Array} [itemsByOrder]
         * @param {Object} [ctx]
         */
        forEach: function(fn, uniq, itemsByOrder, ctx) {
            uniq || (uniq = {});
            var _this = this;

            (itemsByOrder || this.items[''].shouldDeps).forEach(function(i) {
                if (i = _this.items[i]) {
                    var key = i.buildKey();
                    if (!uniq.hasOwnProperty(key)) {
                        uniq[key] = true;
                        var newCtx = ctx || i;
                        _this.forEach(fn, uniq, i.mustDeps, newCtx);
                        fn.call(_this, i, newCtx);
                        _this.forEach(fn, uniq, i.shouldDeps, newCtx);
                    }
                }
            })
        },

        /**
         * Вызывает map для набора зависимостей.
         *
         * @param {Function} fn
         * @returns {Array}
         */
        map: function(fn) {
            var res = [];
            this.forEach(function(item) { res.push(fn.call(this, item)); });
            return res;
        },

        /**
         * Фильтрует зависимости, возвращает результат.
         * @param {Function} fn
         * @returns {Array}
         */
        filter: function(fn) {
            var res = [];
            this.forEach(function(item) { if (fn.call(this, item)) res.push(item); });
            return res;
        },

        /**
         * Возвращает результат резолвинга.
         *
         * @returns {Object}
         */
        serialize: function() {
            var byTech = {};
            this.forEach(function(item, ctx) {
                var t1 = ctx.item.tech || '',
                    t2 = item.item.tech || '',
                    techsByTech = byTech[t1] || (byTech[t1] = {}),
                    i = item.serialize();
                i && (techsByTech[t2] || (techsByTech[t2] = [])).push(i);
            });
            return byTech;
        },

        /**
         * Сериализует в строку.
         *
         * @returns {String}
         */
        stringify: function() {
            var res = [],
                deps = this.serialize();

            if (deps['']) {
                res.push('exports.deps = ' + JSON.stringify(deps[''][''], null, 4) + ';\n');
                delete deps[''][''];
            } else {
                res.push('exports.deps = [];\n');
            }

            isEmptyObject(deps) || res.push('exports.depsByTechs = ' + JSON.stringify(deps, null, 4) + ';\n');

            return res.join('');
        },

        /**
         * Возвращает результат раскрытия зависимостей.
         *
         * @returns {Object|*|*|Array}
         */
        getDeps: function() {
            var serializedData = this.serialize();
            return (serializedData && serializedData[''] && serializedData['']['']) || [];
        }

    });

    /**
     * Элемент зависимостей.
     *
     * @name OldDepsItem
     */
    var OldDepsItem = inherit({

        __constructor: function(item, ctx) {
            this.shouldDeps = [];
            this.mustDeps = [];
            this.item = {};
            this.extendByCtx({ item: item });
            this.extendByCtx(ctx);
        },

        /**
         * Раскрывает зависимости.
         *
         * @param {Object} ctx
         * @returns {OldDepsItem}
         */
        extendByCtx: function(ctx) {
            if (ctx && (ctx = ctx.item)) {
                var ks = ['tech', 'block', 'elem', 'mod', 'val'],
                    k;

                while (k = ks.shift()) {
                    if (this.item[k]) {
                        break;
                    } else {
                        ctx[k] && (this.item[k] = ctx[k]);
                    }
                }
            }
            return this;
        },

        /**
         * Возвращает копию.
         *
         * @returns {OldDepsItem}
         */
        clone: function() {
            var res = new this.__self({}, this);
            res.shouldDeps = this.shouldDeps.concat();
            res.mustDeps = this.mustDeps.concat();
            this.hasOwnProperty('key') && (res.key = this.key);
            return res;
        },

        /**
         * Расширяет зависимость.
         *
         * @param {OldDepsItem} item
         * @returns {OldDepsItem}
         */
        extend: function(item) {
            if (!item) return this;
            var ds = ['mustDeps', 'shouldDeps'], d,
                thisDeps, itemDeps;
            while (d = ds.shift()) {
                itemDeps = item[d] || (item[d] = {});
                if (thisDeps = this.item[d]) {
                    for (var k in thisDeps)
                        if (thisDeps.hasOwnProperty(k)) {
                            if (!thisDeps[k].extend) throw 'bla';
                            (itemDeps[k] = thisDeps[k].extend(itemDeps[k]));
                        }
                }
            }
            return item;
        },

        /**
         * Записывает зависимость в кэш по ключу.
         *
         * @param {Object} cache
         * @returns {OldDepsItem}
         */
        cache: function(cache) {
            var key = this.buildKey();
            return cache[key] = this.extend(cache[key]);
        },

        /**
         * Строит ключ для зависимости.
         *
         * @returns {String}
         */
        buildKey: function() {
            if ('key' in this) return this.key;

            var i = this.item,
                k = '';

            if (i.block) {
                k += i.block;
                i.elem && (k += '__' + i.elem);
                if (i.mod) {
                    k += '_' + i.mod;
                    i.val && (k += '_' + i.val);
                }
            }
            i.tech && (k += '.' + i.tech);
            return this.key = k;
        },

        /**
         * Сериализует зависимость в объект.
         *
         * @returns {Object}
         */
        serialize: function() {
            var res = {},
                ks = ['tech', 'block', 'elem', 'mod', 'val'], k;

            while (k = ks.shift()) this.item[k] && (res[k] = this.item[k]);
            if (res.block) return res;
        }

    });

    exports.DepsItem = OldDepsItem;

    /**
     * Возвращает true при String/Number.
     * @param {*} value
     * @returns {Boolean}
     */
    function isSimple(value) {
        var t = typeof value;
        return t === 'string' || t === 'number';
    }

    /**
     * Хэлпер для удаления значений из массива.
     * Возвращает true в случае успеха.
     *
     * @param {Array} arr
     * @param {*} value
     * @returns {Boolean}
     */
    function removeFromArray(arr, value) {
        var i = arr.indexOf(value);
        if (i >= 0) {
            arr.splice(i, 1);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Возвращает true, если переданный объект пуст.
     * @param {Object} obj
     * @returns {Boolean}
     */
    function isEmptyObject(obj) {
        for (var i in obj) return false;
        return true;
    }

    return OldDeps;
})();
Example #24
0
var NodesSerializer = inherit({
    /**
     * @param {BaseNode[]} nodes
     * @param {String|Boolean} [options.inputSourceMap=false] One of the 'file', 'inline', false.
     * @param {String|Boolean} [options.sourceMap=false] One of the 'file', 'inline', false.
     * @param {String} [options.sourceMapRoot] Relative root for sources (i.e. all source paths will be relative to this path).
     * @param {String} [options.sourceMapFilename] `file` property of the resulting source map.
     * @param {String} [options.sourceMapSourceRoot] `sourceRoot` property of the resulting source map.
     */
    __constructor: function(nodes, options) {
        this.nodes = nodes;

        options = (options || {});
        options.sourceMapFilename = options.sourceMapFilename || '';
        options.sourceMapRoot = options.sourceMapRoot || path.dirname(options.sourceMapFilename);
        this.options = options;

        this.builder = new Builder({
            generateSourceMap: !!options.sourceMap,
            sourceMapFilename: options.sourceMapFilename,
            sourceMapSourceRoot: options.sourceMapSourceRoot
        });

        if (options.sourceMap) {
            this.sourceMapRegistry = new SourceMapRegistry({
                sourceMapLocation: options.inputSourceMap
            });
        }

        /**
         * @type {String[]}
         */
        this.passedDirectives = [];
    },

    /**
     * @returns {Builder}
     */
    serialize: function() {
        var self = this;
        var options = this.options;
        var builder = this.builder;
        var inputSourceMap = options.sourceMap && options.inputSourceMap;

        this.nodes.forEach(function append(node, i) {
            if (node.hasChildren()) {
                node.eachChild(append);
            } else {
                var resetFile = i === 0;
                var mappings = inputSourceMap ? self.getMappingsForNode(node) : null;

                builder.append(path.relative(options.sourceMapRoot, node.path), node, mappings, resetFile);
            }

            if (node.directive) {
                // Mark the directive as passed in order to correct offsets
                // of the source mappings for the following node.
                self.passedDirectives.push(node.directive);
            }
        });

        return builder;
    },

    /**
     * @param {BaseNode} node
     * @returns {Mapping[]}
     */
    getMappingsForNode: function(node) {
        // Always extract passed directive, since the presence of the source map
        // is not guaranteed for all source files.
        var passedDirective = this.passedDirectives.pop();

        var mappingsIterator = this.sourceMapRegistry.getMappingsIterator(node.path);
        if (!mappingsIterator) {
            return null;
        }

        var lines = node.getLines();
        var linesCount = lines.length;
        // Lines are 1-based.
        var firstLine = mappingsIterator.lastLine;
        var lastLine = firstLine + linesCount - 1;
        // First column starts after borschik's directive.
        var firstColumn = mappingsIterator.lastColumn + (passedDirective ? passedDirective.length : 0);
        // One-liners should add the start offset to the end offset. -1 since columns are 0-based;
        var lastColumn = (linesCount === 1 ? firstColumn : 0) + lines[linesCount - 1].length - 1;

        mappingsIterator.skipWhile(function(m) {
            return m.generatedLine === firstLine && m.generatedColumn < firstColumn;
        });
        var mappings = mappingsIterator.readWhile(function(m) {
            return m.generatedLine < lastLine || m.generatedLine === lastLine && m.generatedColumn <= lastColumn;
        });

        // Correct offsets.
        mappings.forEach(function(m) {
            m.generatedColumn = m.generatedColumn - (m.generatedLine === firstLine ? firstColumn : 0);
            m.generatedLine = m.generatedLine - (firstLine - 1);
        });

        mappingsIterator.lastLine = lastLine;
        mappingsIterator.lastColumn = node.ignoreMappings() ? firstColumn : (lastColumn + 1);

        return mappings;
    },
}, {
    inherit: _inherit
});
Example #25
0
module.exports = inherit(Base, {

  __constructor: function(id, iframeContainer) {
    this.__base(id);
    this.iframeContainer = iframeContainer;
  },

  initialize: function() {
    var self = this;
    self.getIframe().addEventListener('load', function iframeLoadHandler(event) {
      var lazyLoadInit = self.__self.getLazyLoad();
      lazyLoadInit(this);
      self.getIframe().removeEventListener('load', iframeLoadHandler);
    });
  }

}, {

  instances: {},

  createInstance: function(id, iframeContainer) {
    var instance = new this(id, iframeContainer);
    instance.initialize();
    this.instances[id] = instance;
    return instance;
  },

  sourceLazyLoad: null,

  getLazyLoad: function() {
    if (!this.sourceLazyLoad) {
      //Initialize the lazy load
      this.sourceLazyLoad = lazyLoad({
        container: doc.body,
        offset: 1000,
        src: 'data-src'
      });
    }
    return this.sourceLazyLoad;
  }

});
Example #26
0
function _inherit(d, s) {
    return inherit(this, d, s);
}
Example #27
0
module.exports = inherit(require('../lib/tech/base-tech'), {
    getName: function() {
        return 'borschik';
    },

    configure: function() {
        this._source = this.node.unmaskTargetName(this.getRequiredOption('sourceTarget'));
        this._target = this.node.unmaskTargetName(this.getRequiredOption('destTarget'));
        this._freeze = this.getOption('freeze', false);
        this._minify = this.getOption('minify', true);
    },

    getTargets: function() {
        return [this._target];
    },

    build: function() {
        var target = this._target,
            targetPath = this.node.resolvePath(target),
            source = this._source,
            sourcePath = this.node.resolvePath(source),
            _this = this,
            cache = this.node.getNodeCache(target);
        return this.node.requireSources([source]).then(function() {
            if (cache.needRebuildFile('source-file', sourcePath)
                    || cache.needRebuildFile('target-file', targetPath)) {
                var borschikProcessor = BorschikProcessorSibling.fork();
                return Vow.when(borschikProcessor.process(sourcePath, targetPath, _this._freeze, _this._minify)).then(function() {
                    cache.cacheFileInfo('source-file', sourcePath);
                    cache.cacheFileInfo('target-file', targetPath);
                    _this.node.resolveTarget(target);
                    borschikProcessor.dispose();
                });

            } else {
                _this.node.isValidTarget(target);
                _this.node.resolveTarget(target);
                return null;
            }
        });
    }
});
Example #28
0
File: track.js Project: seiies/fist
var Track = inherit(/** @lends Track.prototype */{

    /**
     * @private
     * @memberOf {Track}
     * @method
     *
     * @constructs
     *
     * @returns void
     * */
    __constructor: function (agent) {

        /**
         * @public
         * @memberOf {Track}
         * @property
         * @type {Tracker}
         * */
        this.agent = agent;

        /**
         * @public
         * @memberOf {Track}
         * @property
         * @type {String}
         * */
        this.id = uniqueId();

        /**
         * @private
         * @memberOf {Track}
         * @property
         * @type {Object}
         * */
        this.__tasks = {};
    },

    /**
     * @public
     * @memberOf {Track}
     * @method
     *
     * @param {String} path
     * @param {Object} [locals]
     *
     * @returns {vow.Promise}
     *  */
    invoke: function (path, locals) {
        var result;

        if ( !_.has(this.__tasks, path) ) {
            this.__tasks[path] = new TaskCache();
        }

        result = this.__tasks[path].get(locals);

        if ( result ) {

            return result;
        }

        result = this.__executeUnit(path, locals);

        this.__tasks[path].set(locals, result);

        return result;
    },

    /**
     * @protected
     * @memberOf {Track}
     * @method
     *
     * @param {String} path
     * @param {Object} [params]
     *
     * @returns {Deps}
     * */
    _createContext: function (path, params) {

        return new Deps(this, path, params);
    },

    /**
     * @private
     * @memberOf {Track}
     * @method
     *
     * @param {String} path
     * @param {Object} [params]
     *
     * @returns {vow.Promise}
     * */
    __executeUnit: function (path, params) {

        return this._createContext(path, params).execute();
    }

});
Example #29
0
  // unique ID
  this.id = window.ZeroClipboard.nextId++;
  this.movieId = 'ZeroClipboardMovie_' + this.id;

  // register client with ZeroClipboard global to receive flash events
  window.ZeroClipboard.clients[this.id] = this;

  // create movie
  if (node) this.render(node, parent);
}

/**
 * Inherits from `Emitter.prototype`.
 */

inherit(Client, Emitter);

/**
 * Render the SWF movie on top of the "elem" DOM element.
 *
 * @param elem DOMNode The DOM node that will be "converted"
 * @param appendElem DOMNode (optional) The DOM node that the SWF will be inserted into
 * @api public
 */

Client.prototype.glue =
Client.prototype.render = function(elem, appendElem) {
  this.domElement = elem;

  // float just above object, or default zIndex if dom element isn't set
  if (this.domElement.style.zIndex) {
Example #30
0
module.exports = inherit({

    /**
     * Конструктор.
     * @param {Level[]} levels
     */
    __constructor: function(levels) {
        this.levels = levels;
        this.declarations = [];
        this.resolved = {};
        this.declarationIndex = {};
    },

    /**
     * Раскрывает шорткаты deps'а.
     * @param {String|Object} dep
     * @param {String} blockName
     * @param {String} elemName
     * @returns {Array}
     */
    normalizeDep: function(dep, blockName, elemName) {
        var levels = this.levels;
        if (typeof dep === 'string') {
            return [{ name: dep }];
        } else {
            var res = [];
            if (dep.view) {
                (dep.mods || (dep.mods = {})).view = dep.view;
            }
            if (dep.skin) {
                (dep.mods || (dep.mods = {})).skin = dep.skin;
            }
            if (dep.elem) {
                if (dep.mods) {
                    Object.keys(dep.mods).forEach(function(modName) {
                        var modVals = dep.mods[modName];
                        if (!Array.isArray(modVals)) {
                            modVals = [modVals];
                        }
                        res = res.concat(modVals.map(function(modVal) {
                            return { name: dep.block || blockName, elem: dep.elem, modName: modName, modVal: modVal };
                        }));
                    });
                } else if (dep.mod) {
                    res.push({ name: dep.block || blockName, elem: dep.elem, modName: dep.mod, modVal: dep.val });
                } else {
                    res.push({ name: dep.block || blockName, elem: dep.elem });
                }
            } else if (dep.mod || dep.mods || dep.elems) {
                if (dep.mod) {
                    res.push({ name: dep.block || blockName, modName: dep.mod, modVal: dep.val });
                }
                Object.keys(dep.mods || {}).forEach(function(modName) {
                    var modVals = dep.mods[modName];
                    if (modVals === '*') {
                        modVals = levels.getModValues(dep.block || blockName, modName);
                    }
                    if (!Array.isArray(modVals)) {
                        modVals = [modVals];
                    }
                    res = res.concat(modVals.map(function(modVal) {
                        if (elemName && !dep.block && !dep.elem) {
                            return { name: dep.block || blockName, elem: elemName, modName: modName, modVal: modVal };
                        } else {
                            return { name: dep.block || blockName, modName: modName, modVal: modVal };
                        }
                    }));
                });
                if (dep.elems) {
                    res.push({ name: dep.block || blockName });
                    var elems = dep.elems || [];
                    if (!Array.isArray(elems)) {
                        elems = [elems];
                    }
                    elems.forEach(function(elem) {
                        if (typeof elem === 'object') {
                            res.push({ name: dep.block || blockName, elem: elem.elem });
                            Object.keys(elem.mods || {}).forEach(function(modName) {
                                var modVals = elem.mods[modName];
                                if (!Array.isArray(modVals)) {
                                    modVals = [modVals];
                                }
                                res = res.concat(modVals.map(function(modVal) {
                                    return {
                                        name: dep.block || blockName,
                                        elem: elem.elem,
                                        modName: modName,
                                        modVal: modVal
                                    };
                                }));
                            });
                        } else {
                            res.push({ name: dep.block || blockName, elem: elem });
                        }
                    });
                }
            } else {
                res = [{ name: dep.block || blockName }];
            }
            if (dep.required) {
                res.forEach(function (subDep) {
                    subDep.required = true;
                });
            }
            return res;
        }
    },

    /**
     * Раскрывает шорткаты для списка deps'ов.
     * @param {String|Object|Array} deps
     * @param {String} [blockName]
     * @param {String} [elemName]
     * @returns {Array}
     */
    normalizeDeps: function(deps, blockName, elemName) {
        if (Array.isArray(deps)) {
            var result = [];
            for (var i = 0, l = deps.length; i < l; i++) {
                result = result.concat(this.normalizeDep(deps[i], blockName, elemName));
            }
            return result;
        } else {
            return this.normalizeDep(deps, blockName, elemName);
        }
    },

    /**
     * Возвращает deps'ы для декларации (с помощью levels).
     * @param {Object} decl
     * @returns {{mustDeps: Array, shouldDeps: Array}}
     */
    getDeps: function(decl) {
        var _this = this, files, key, mustDecls, mustDepIndex, mustDeps, shouldDepIndex, shouldDeps;
        if (decl.elem) {
            files = this.levels.getElemFiles(decl.name, decl.elem, decl.modName, decl.modVal);
        } else {
            files = this.levels.getBlockFiles(decl.name, decl.modName, decl.modVal);
        }
        files = files.filter(function(file) {
            return file.suffix === 'deps.js' || file.suffix === 'deps.yaml';
        });
        mustDepIndex = {};
        shouldDepIndex = {};
        mustDepIndex[declKey(decl)] = true;
        mustDeps = [];
        if (decl.modName) {
            if (decl.elem) {
                mustDecls = [
                    { name: decl.name, elem: decl.elem }
                ];
                if (decl.modVal) {
                    mustDecls.push({ name: decl.name, elem: decl.elem, modName: decl.modName });
                }
            } else {
                mustDecls = [
                    { name: decl.name }
                ];
                if (decl.modVal) {
                    mustDecls.push({ name: decl.name, modName: decl.modName });
                }
            }
            mustDecls.forEach(function(mustDecl) {
                mustDecl.key = declKey(mustDecl);
                mustDepIndex[mustDecl.key] = true;
                mustDeps.push(mustDecl);
            });
        }
        shouldDeps = [];

        function keepWorking(file) {
            return vowFs.read(file.fullname, 'utf8').then(function(depContent) {
                if (file.suffix === 'deps.js') {
                    var depData;
                    try {
                        depData = vm.runInThisContext(depContent);
                    } catch (e) {
                        throw new Error('Syntax error in file "' + file.fullname + '": ' + e.message);
                    }
                    depData = Array.isArray(depData) ? depData : [depData];
                    depData.forEach(function(dep) {
                        if (!dep.tech) {
                            if (dep.mustDeps) {
                                _this.normalizeDeps(dep.mustDeps, decl.name, decl.elem).forEach(function(nd) {
                                    key = declKey(nd);
                                    if (!mustDepIndex[key]) {
                                        mustDepIndex[key] = true;
                                        nd.key = key;
                                        mustDeps.push(nd);
                                    }
                                });
                            }
                            if (dep.shouldDeps) {
                                _this.normalizeDeps(dep.shouldDeps, decl.name, decl.elem).forEach(function(nd) {
                                    key = declKey(nd);
                                    if (!shouldDepIndex[key]) {
                                        shouldDepIndex[key] = true;
                                        nd.key = key;
                                        shouldDeps.push(nd);
                                    }
                                });
                            }
                            if (dep.noDeps) {
                                _this.normalizeDeps(dep.noDeps, decl.name, decl.elem).forEach(function(nd) {
                                    key = declKey(nd);
                                    nd.key = key;
                                    removeFromDeps(nd, mustDepIndex, mustDeps);
                                    removeFromDeps(nd, shouldDepIndex, shouldDeps);
                                });
                            }
                        }
                    });
                } else if (file.suffix === 'deps.yaml') {
                    var depYamlStructure = yaml.safeLoad(depContent, {
                        filename: file.fullname,
                        strict: true
                    });
                    if (!Array.isArray(depYamlStructure)) {
                        throw new Error('Invalid yaml deps structure at: ' + file.fullname);
                    }
                    _this.normalizeDeps(depYamlStructure, decl.name, decl.elem).forEach(function(nd) {
                        key = declKey(nd);
                        var index;
                        var depList;
                        if (nd.required) {
                            index = mustDepIndex;
                            depList = mustDeps;
                        } else {
                            index = shouldDepIndex;
                            depList = shouldDeps;
                        }
                        if (!index[key]) {
                            index[key] = true;
                            nd.key = key;
                            depList.push(nd);
                        }
                    });
                }
                if (files.length > 0) {
                    return keepWorking(files.shift());
                } else {
                    return null;
                }
            });
        }

        function removeFromDeps(decl, index, list) {
            if (index[decl.key]) {
                for (var i = 0, l = list.length; i < l; i++) {
                    if (list[i].key === decl.key) {
                        return list.splice(i, 1);
                    }
                }
            } else {
                index[decl.key] = true;
            }
            return null;
        }

        var result = { mustDeps: mustDeps, shouldDeps: shouldDeps };

        if (files.length > 0) {
            return keepWorking(files.shift()).then(function() {
                return result;
            });
        } else {
            return Vow.fulfill(result);
        }
    },

    /**
     * Добавляет декларацию блока в резолвер.
     * @param {String} blockName
     * @param {String} modName
     * @param {String} modVal
     * @returns {Promise}
     */
    addBlock: function(blockName, modName, modVal) {
        if (modName) {
            this.addDecl({
                name: blockName,
                modName: modName,
                modVal: modVal
            });
        } else {
            this.addDecl({
                name: blockName
            });
        }
    },

    /**
     * Добавляет декларацию элемента в резолвер.
     * @param {String} blockName
     * @param {String} elemName
     * @param {String} modName
     * @param {String} modVal
     * @returns {Promise}
     */
    addElem: function(blockName, elemName, modName, modVal) {
        if (modName) {
            return this.addDecl({
                name: blockName,
                elem: elemName,
                modName: modName,
                modVal: modVal
            });
        } else {
            return this.addDecl({
                name: blockName,
                elem: elemName
            });
        }
    },

    /**
     * Добавляет декларацию в резолвер.
     * @param {Object} decl
     * @returns {Promise}
     */
    addDecl: function(decl) {
        var _this = this, key = declKey(decl);
        if (this.declarationIndex[key]) {
            return null;
        }
        this.declarations.push(decl);
        this.declarationIndex[key] = decl;
        return this.getDeps(decl).then(function(deps) {
            decl.key = key;
            decl.deps = {};
            decl.depCount = 0;
            return _this.addDecls(deps.mustDeps, function(dep) {
                decl.deps[dep.key] = true;
                decl.depCount++;
            }).then(function() {
                return _this.addDecls(deps.shouldDeps);
            });
        });
    },

    /**
     * Добавляет набор деклараций.
     * @param {Array} decls
     * @returns {Promise}
     * @param {Function} [preCallback]
     */
    addDecls: function(decls, preCallback) {
        var promise = Vow.fulfill();
        var _this = this;
        decls.forEach(function(decl) {
            promise = promise.then(function() {
                if (preCallback) {
                    preCallback(decl);
                }
                return _this.addDecl(decl);
            });
        });
        return promise;
    },

    /**
     * Упорядочивает deps'ы, возвращает в порядке зависимостей.
     * @returns {Array}
     */
    resolve: function() {
        var decl, hasChanges, item, items, newItems, result, subDecl, i, j, l;
        items = this.declarations.slice(0);
        result = [];
        hasChanges = true;
        while (hasChanges) {
            newItems = [];
            hasChanges = false;
            for (i = 0, l = items.length; i < l; i++) {
                decl = items[i];
                if (decl.depCount === 0) {
                    hasChanges = true;
                    for (j = 0; j < l; j++) {
                        subDecl = items[j];
                        if (subDecl.deps[decl.key]) {
                            delete subDecl.deps[decl.key];
                            subDecl.depCount--;
                        }
                    }
                    item = {
                        block: decl.name
                    };
                    if (decl.elem) {
                        item.elem = decl.elem;
                    }
                    if (decl.modName) {
                        item.mod = decl.modName;
                        if (decl.hasOwnProperty('modVal')) {
                            item.val = decl.modVal;
                        }
                    }
                    result.push(item);
                } else {
                    newItems.push(decl);
                }
            }
            items = newItems;
        }
        if (items.length) {
            var errorMessage = items.map(function(item) {
                return item.key + ' <- ' + Object.keys(item.deps).join(', ');
            });
            throw Error('Unresolved deps: \n' + errorMessage.join('\n'));
        }
        return result;
    }
});