UNPKG

closure-builder

Version:

Simple Closure, Soy and JavaScript Build system

313 lines (278 loc) 8.7 kB
/** * @fileoverview Closure Builder - Build tools * * @license Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @author mbordihn@google.com (Markus Bordihn) */ var fs = require('fs-extra'); var os = require('os'); var BuildType = require('./build_types.js'); /** * Build Tools. * @constructor * @struct * @final */ var BuildTools = function() {}; /** * Detects the needed compiler types. * @param {BuildConfig} config */ BuildTools.detectType = function(config) { if (config.hasSoyFiles() > 0) { if (config.hasClosureFiles() === 0) { return BuildType.SOY; } else { return BuildType.SOY_CLOSURE; } } else if (config.hasClosureFiles()) { return BuildType.CLOSURE; } else if (config.hasNodeFiles()) { return BuildType.NODEJS; } else if (config.hasJsFiles()) { return BuildType.JAVASCRIPT; } else if (config.hasCssFiles()) { return BuildType.CSS; } else if (config.hasMarkdownFiles()) { return BuildType.MARKDOWN; } else if (config.hasResourceFiles()) { return BuildType.RESOURCES; } else { return BuildType.UNKNOWN; } }; /** * @param {array} files * @param {boolean=} opt_all Show all files and folders. * @param {boolean=} opt_exclude_test Exclude test files. * @return {array} */ BuildTools.sortFiles = function(files, opt_all, opt_exclude_test) { var fileList = []; var knownFile = {}; for (var i = files.length - 1; i >= 0; i--) { var file = files[i]; if (file.constructor === Array) { for (var i2 = file.length - 1; i2 >= 0; i2--) { var subFile = file[i2]; if (!knownFile[subFile] && (opt_all || subFile.indexOf('.') !== -1)) { fileList.push(subFile); knownFile[subFile] = true; } } } else { if (!knownFile[file] && (opt_all || file.indexOf('.') !== -1)) { fileList.push(file); knownFile[file] = true; } } } if (opt_exclude_test) { return BuildTools.filterTestFiles(fileList); } return fileList; }; /** * Returns the needed build requirements for the given config. * @param {BuildConfig} config * @return {Object} Build requirements */ BuildTools.getBuildRequirements = function(config) { var depsConfig = this.scanFiles(config.deps); var srcsConfig = this.scanFiles(config.srcs, config.name); var soyConfig = this.scanFiles(config.soy); var mdConfig = this.scanFiles(config.markdown); return { closureFiles: [].concat(depsConfig.closureFiles, srcsConfig.closureFiles), cssFiles: [].concat(srcsConfig.cssFiles), jsFiles: [].concat(depsConfig.jsFiles, srcsConfig.jsFiles), markdownFiles: [].concat(mdConfig.markdownFiles), nodeFiles: [].concat(srcsConfig.nodeFiles), soyFiles: [].concat(depsConfig.soyFiles, soyConfig.soyFiles, srcsConfig.soyFiles), entryPoint: (depsConfig.entryPoint || srcsConfig.entryPoint), requireClosureExport: (srcsConfig.requireClosureExport), requireClosureLibrary: (depsConfig.requireClosureLibrary || srcsConfig.requireClosureLibrary), requireECMAScript6: (depsConfig.requireECMAScript6 || srcsConfig.requireECMAScript6), requireSoyLibrary: (depsConfig.requireSoyLibrary || srcsConfig.requireSoyLibrary || soyConfig.requireSoyLibrary), requireSoyi18n: (soyConfig.requireSoyi18n || srcsConfig.requireSoyi18n) }; }; /** * Scan files for certain file types and return list of files and requirements. * @param {array} files * @param {string=} opt_entry_point * @return {Object} */ BuildTools.scanFiles = function(files, opt_entry_point) { var closureFiles = []; var cssFiles = []; var jsFiles = []; var markdownFiles = []; var nodeFiles = []; var soyFiles = []; var entryPoint = ''; var requireClosureExport = false; var requireClosureLibrary = false; var requireECMAScript6 = false; var requireSoyLibrary = false; var requireSoyi18n = false; for (var i = files.length - 1; i >= 0; i--) { var file = files[i]; // Handling soy files. if (file.endsWith('.soy')) { var soyContent = fs.readFileSync(file, 'utf8'); if (soyContent.includes('{i18n}') && soyContent.includes('{/i18n}')) { requireSoyi18n = true; } requireSoyLibrary = true; soyFiles.push(file); // Handling JavaScript files. } else if (file.endsWith('.js')) { var fileContent = fs.readFileSync(file, 'utf8'); if (fileContent.includes('goog.provide(') || fileContent.includes('goog.require(') || fileContent.includes('goog.module(')) { if (fileContent.includes(' * @export')) { requireClosureExport = true; } closureFiles.push(file); } else if (fileContent.includes('require(') && fileContent.includes('module.exports')) { nodeFiles.push(file); } else { jsFiles.push(file); } // Validating possible entry points. if (opt_entry_point) { if (fileContent.includes('goog.provide(\'' + opt_entry_point + '\'') || fileContent.includes('goog.module(\'' + opt_entry_point + '\'')) { entryPoint = opt_entry_point; } } // Require closure library ? if (fileContent.includes('goog.require(\'goog.') || fileContent.includes('goog.require("goog.')) { requireClosureLibrary = true; } // Require soy library ? if (fileContent.includes('goog.require(\'soy') || fileContent.includes('goog.require(\'soydata')) { requireSoyLibrary = true; } // ECMAScript6 if (/(let|const)\s+\w+\s?=/.test(fileContent)) { requireECMAScript6 = true; } // Handling CSS files. } else if (file.endsWith('.css')) { cssFiles.push(file); // Handling Markdown files. } else if (file.endsWith('.md')) { markdownFiles.push(file); } } return { closureFiles: closureFiles, cssFiles: cssFiles, entryPoint: entryPoint, jsFiles: jsFiles, nodeFiles: nodeFiles, soyFiles: soyFiles, markdownFiles: markdownFiles, requireClosureExport: requireClosureExport, requireClosureLibrary: requireClosureLibrary, requireSoyLibrary: requireSoyLibrary, requireSoyi18n: requireSoyi18n, requireECMAScript6: requireECMAScript6 }; }; /** * @param {array} files * @return {array} */ BuildTools.filterTestFiles = function(files) { for (var i = files.length - 1; i >= 0; i--) { var file = files[i]; if (file.indexOf('_test.js') !== -1 || file.indexOf('_testhelper.js') !== -1 || file.indexOf('/demos/') !== -1 || file.indexOf('/deps.js') !== -1) { files.splice(i, 1); } } return files; }; /** * @param {array} files * @return {array} */ BuildTools.getSafeFileList = function(files) { var result = []; var cache = {}; for (var file in files) { var fileEntry = files[file]; var safeFileEntry = '"' + fileEntry + '"'; if (fileEntry && !(fileEntry in cache || safeFileEntry in cache)) { if ((fileEntry.charAt(0) === '"' && fileEntry.charAt(0) === '"') || (fileEntry.charAt(0) === '\'' && fileEntry.charAt(0) === '\'')){ result.push(fileEntry); } else { result.push(safeFileEntry); } cache[fileEntry] = true; } } return result; }; /** * @param {!number} size in megabyte. * @return {!boolean} */ BuildTools.checkAvailableMemory = function(size) { return size <= BuildTools.getMemory(); }; /** * @param {boolean=} opt_raw * @return {!number} Available memory in megabyte. */ BuildTools.getMemory = function(opt_raw) { var memory = os.freemem() / 1000000; if (memory > 512 && process.env.C9_PROJECT) { memory = 384; } if (opt_raw) { return memory; } return Math.floor(memory); }; /** * @return {number} 90% of the available memory in megabyte and max of 1024. */ BuildTools.getSafeMemory = function() { var safeMemory = Math.floor(BuildTools.getMemory(true) * 0.9); if (safeMemory > 1024) { return 1024; } return safeMemory; }; module.exports = BuildTools;