UNPKG

angular-material-npfixed

Version:

The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M

278 lines (240 loc) 8.81 kB
var config = require('./config'); var gulp = require('gulp'); var gutil = require('gulp-util'); var frep = require('gulp-frep'); var fs = require('fs'); var args = require('minimist')(process.argv.slice(2)); var path = require('path'); var rename = require('gulp-rename'); var filter = require('gulp-filter'); var concat = require('gulp-concat'); var series = require('stream-series'); var lazypipe = require('lazypipe'); var glob = require('glob').sync; var uglify = require('gulp-uglify'); var sass = require('gulp-sass'); var plumber = require('gulp-plumber'); var ngAnnotate = require('gulp-ng-annotate'); var insert = require('gulp-insert'); var gulpif = require('gulp-if'); var nano = require('gulp-cssnano'); var postcss = require('postcss'); var _ = require('lodash'); var constants = require('./const'); var VERSION = constants.VERSION; var BUILD_MODE = constants.BUILD_MODE; var IS_DEV = constants.IS_DEV; var ROOT = constants.ROOT; var utils = require('../scripts/gulp-utils.js'); exports.buildJs = buildJs; exports.autoprefix = utils.autoprefix; exports.buildModule = buildModule; exports.filterNonCodeFiles = filterNonCodeFiles; exports.readModuleArg = readModuleArg; exports.themeBuildStream = themeBuildStream; exports.minifyCss = minifyCss; exports.dedupeCss = dedupeCss; exports.args = args; /** * Builds the entire component library javascript. * @param {boolean} isRelease Whether to build in release mode. */ function buildJs () { var jsFiles = config.jsBaseFiles.concat([path.join(config.paths, '*.js')]); gutil.log("building js files..."); var jsBuildStream = gulp.src( jsFiles ) .pipe(filterNonCodeFiles()) .pipe(utils.buildNgMaterialDefinition()) .pipe(plumber()) .pipe(ngAnnotate()) .pipe(utils.addJsWrapper(true)); var jsProcess = series(jsBuildStream, themeBuildStream() ) .pipe(concat('angular-material.js')) .pipe(BUILD_MODE.transform()) .pipe(insert.prepend(config.banner)) .pipe(insert.append(';window.ngMaterial={version:{full: "' + VERSION +'"}};')) .pipe(gulp.dest(config.outputDir)) .pipe(gulpif(!IS_DEV, uglify({ preserveComments: 'some' }))) .pipe(rename({ extname: '.min.js' })) .pipe(gulp.dest(config.outputDir)); return series(jsProcess, deployMaterialMocks()); // Deploy the `angular-material-mocks.js` file to the `dist` directory function deployMaterialMocks() { return gulp.src(config.mockFiles) .pipe(gulp.dest(config.outputDir)); } } function minifyCss(extraOptions) { var options = { autoprefixer: false, reduceTransforms: false, svgo: false, safe: true }; return nano(_.assign(options, extraOptions)); } function buildModule(module, opts) { opts = opts || {}; if ( module.indexOf(".") < 0) { module = "material.components." + module; } gutil.log('Building ' + module + (opts.isRelease && ' minified' || '') + ' ...'); var name = module.split('.').pop(); utils.copyDemoAssets(name, 'src/components/', 'dist/demos/'); var stream = utils.filesForModule(module) .pipe(filterNonCodeFiles()) .pipe(filterLayoutAttrFiles()) .pipe(gulpif('*.scss', buildModuleStyles(name))) .pipe(gulpif('*.js', buildModuleJs(name))); if (module === 'material.core') { stream = splitStream(stream); } return stream .pipe(BUILD_MODE.transform()) .pipe(insert.prepend(config.banner)) .pipe(gulpif(opts.minify, buildMin())) .pipe(gulpif(opts.useBower, buildBower())) .pipe(gulp.dest(BUILD_MODE.outputDir + name)); function splitStream (stream) { var js = series(stream, themeBuildStream()) .pipe(filter('**/*.js')) .pipe(concat('core.js')); var css = stream .pipe(filter(['**/*.css', '!**/ie_fixes.css'])) return series(js, css); } function buildMin() { return lazypipe() .pipe(gulpif, /.css$/, minifyCss(), uglify({ preserveComments: 'some' }) .on('error', function(e) { console.log('\x07',e.message); return this.end(); } ) ) .pipe(rename, function(path) { path.extname = path.extname .replace(/.js$/, '.min.js') .replace(/.css$/, '.min.css'); }) (); } function buildBower() { return lazypipe() .pipe(utils.buildModuleBower, name, VERSION)(); } function buildModuleJs(name) { var patterns = [ { pattern: /\@ngInject/g, replacement: 'ngInject' }, { // Turns `thing.$inject` into `thing['$inject']` in order to prevent // Closure from stripping it from objects with an @constructor // annotation. pattern: /\.\$inject\b/g, replacement: "['$inject']" } ]; return lazypipe() .pipe(plumber) .pipe(ngAnnotate) .pipe(frep, patterns) .pipe(concat, name + '.js') (); } function buildModuleStyles(name) { var files = []; config.themeBaseFiles.forEach(function(fileGlob) { files = files.concat(glob(fileGlob, { cwd: ROOT })); }); var baseStyles = files.map(function(fileName) { return fs.readFileSync(fileName, 'utf8').toString(); }).join('\n'); return lazypipe() .pipe(insert.prepend, baseStyles) .pipe(gulpif, /theme.scss/, rename(name + '-default-theme.scss'), concat(name + '.scss')) // Theme files are suffixed with the `default-theme.scss` string. // In some cases there are multiple theme SCSS files, which should be concatenated together. .pipe(gulpif, /default-theme.scss/, concat(name + '-default-theme.scss')) .pipe(sass) .pipe(dedupeCss) .pipe(utils.autoprefix) (); // Invoke the returning lazypipe function to create our new pipe. } } function readModuleArg() { var module = args.c ? 'material.components.' + args.c : (args.module || args.m); if (!module) { gutil.log('\nProvide a component argument via `-c`:', '\nExample: -c toast'); gutil.log('\nOr provide a module argument via `--module` or `-m`.', '\nExample: --module=material.components.toast or -m material.components.dialog'); process.exit(1); } return module; } /** * We are not injecting the layout-attributes selectors into the core module css, * otherwise we would have the layout-classes and layout-attributes in there. */ function filterLayoutAttrFiles() { return filter(function(file) { return !/.*layout-attributes\.scss/g.test(file.path); }); } function filterNonCodeFiles() { return filter(function(file) { return !/demo|module\.json|script\.js|\.spec.js|README/.test(file.path); }); } // builds the theming related css and provides it as a JS const for angular function themeBuildStream() { return gulp.src( config.themeBaseFiles.concat(path.join(config.paths, '*-theme.scss')) ) .pipe(concat('default-theme.scss')) .pipe(utils.hoistScssVariables()) .pipe(sass()) .pipe(dedupeCss()) // The PostCSS orderedValues plugin modifies the theme color expressions. .pipe(minifyCss({ orderedValues: false })) .pipe(utils.cssToNgConstant('material.core', '$MD_THEME_CSS')); } // Removes duplicated CSS properties. function dedupeCss() { var prefixRegex = /-(webkit|moz|ms|o)-.+/; return insert.transform(function(contents) { // Parse the CSS into an AST. var parsed = postcss.parse(contents); // Walk through all the rules, skipping comments, media queries etc. parsed.walk(function(rule) { // Skip over any comments, media queries and rules that have less than 2 properties. if (rule.type !== 'rule' || !rule.nodes || rule.nodes.length < 2) return; // Walk all of the properties within a rule. rule.walk(function(prop) { // Check if there's a similar property that comes after the current one. var hasDuplicate = validateProp(prop) && _.find(rule.nodes, function(otherProp) { return prop !== otherProp && prop.prop === otherProp.prop && validateProp(otherProp); }); // Remove the declaration if it's duplicated. if (hasDuplicate) { prop.remove(); gutil.log(gutil.colors.yellow( 'Removed duplicate property: "' + prop.prop + ': ' + prop.value + '" from "' + rule.selector + '"...' )); } }); }); // Turn the AST back into CSS. return parsed.toResult().css; }); // Checks if a property is a style declaration and that it // doesn't contain any vendor prefixes. function validateProp(prop) { return prop && prop.type === 'decl' && ![prop.prop, prop.value].some(function(value) { return value.indexOf('-') > -1 && prefixRegex.test(value); }); } }