'use strict'; var gulp = require('gulp'); var concat = require('gulp-concat'); var eslint = require('gulp-eslint'); var Dgeni = require('dgeni'); var merge = require('event-stream').merge; var path = require('canonical-path'); var foreach = require('gulp-foreach'); var uglify = require('gulp-uglify'); var sourcemaps = require('gulp-sourcemaps'); var rename = require('gulp-rename'); // We indicate to gulp that tasks are async by returning the stream. // Gulp can then wait for the stream to close before starting dependent tasks. // See clean for an async task, and see assets and doc-gen for dependent tasks below. var outputFolder = '../build/docs'; var src = 'app/src/**/*.js'; var ignoredFiles = '!src/angular.bind.js'; var assets = 'app/assets/**/*'; var getMergedEslintConfig = function(filepath) { return { configFile: filepath, baseConfig: '../.eslintrc.json', rules: { // Examples don't run in strict mode; accept that for now. strict: 'off', // Generated examples may miss the final EOL; ignore that. 'eol-last': 'off', // Generated files use the system's default linebreak style (e.g. CRLF on Windows) 'linebreak-style': 'off', // While alerts would be bad to have in the library or test code, // they're perfectly fine in examples. 'no-alert': 'off', // The following rules have to be disabled or tweaked because dgeni template wrappers // don't follow them and we have no way to validate only the parts taken // from ngdoc. // some dgeni-packages templates generate whitespace-only lines 'no-trailing-spaces': ['error', { 'skipBlankLines': true }], // dgeni templates use double quotes as string delimiters quotes: 'off' }, ignore: false, useEslintrc: false }; }; var copyComponent = function(component, pattern, base, sourceFolder, packageFile) { pattern = pattern || '/**/*'; base = base || ''; sourceFolder = sourceFolder || '../node_modules'; packageFile = packageFile || 'package.json'; var version = require(path.resolve(sourceFolder, component, packageFile)).version; return gulp .src(sourceFolder + '/' + component + pattern, {base: sourceFolder + '/' + component + '/' + base}) .pipe(gulp.dest(outputFolder + '/components/' + component + '-' + version)); }; gulp.task('build-app', function() { var file = 'docs.js'; var minFile = 'docs.min.js'; var folder = outputFolder + '/js/'; return gulp.src([src, ignoredFiles]) .pipe(sourcemaps.init()) .pipe(concat(file)) .pipe(gulp.dest(folder)) .pipe(rename(minFile)) .pipe(uglify()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(folder)); }); gulp.task('assets', function() { var JS_EXT = /\.js$/; return merge( gulp.src(['img/**/*']).pipe(gulp.dest(outputFolder + '/img')), gulp.src([assets]).pipe(gulp.dest(outputFolder)), gulp.src([assets]) .pipe(foreach(function(stream, file) { if (JS_EXT.test(file.relative)) { var minFile = file.relative.replace(JS_EXT, '.min.js'); return stream .pipe(sourcemaps.init()) .pipe(concat(minFile)) .pipe(uglify()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(outputFolder)); } })), copyComponent('bootstrap', '/dist/css/bootstrap?(.min).css', 'dist'), copyComponent('bootstrap', '/dist/fonts/*', 'dist'), copyComponent('open-sans-fontface', '/fonts/{Regular,Semibold,Bold}/*'), copyComponent('lunr', '/lunr?(.min).js'), copyComponent('google-code-prettify', '/**/{lang-css,prettify}.js'), copyComponent('jquery', '/dist/jquery.js', 'dist'), copyComponent('marked', '/lib/marked.js'), copyComponent('marked', '/marked.min.js') ); }); gulp.task('doc-gen', function() { var dgeni = new Dgeni([require('./config')]); return dgeni.generate().catch(function() { process.exit(1); }); }); // Lint the example and protractor test files gulp.task('eslint', ['doc-gen'], function() { var examplesConfig = getMergedEslintConfig('../docs/app/test/.eslintrc.json'); // While in source we don't want to assume the browser environment so that we're // compatible with non-browser window implementations like jsdom, it's not necessary // in examples and may look weird to casual readers. examplesConfig.envs = ['browser']; var protractorConfig = getMergedEslintConfig('../docs/app/e2e/.eslintrc.json'); protractorConfig.rules['no-unused-vars'] = ['error', { vars: 'local', args: 'none', // This variable is declared in code generated by dgeni-packages // and not always used. varsIgnorePattern: '^rootEl$' }]; return merge( gulp.src([ outputFolder + '/examples/**/*.js', '!' + outputFolder + '/examples/**/protractor.js' ]) // eslint() attaches the lint output to the "eslint" property // of the file object so it can be used by other modules. .pipe(eslint(examplesConfig)) // eslint.format() outputs the lint results to the console. // Alternatively use eslint.formatEach() (see Docs). .pipe(eslint.format()) // To have the process exit with an error code (1) on // lint error, return the stream and pipe to failAfterError last. .pipe(eslint.failAfterError()), gulp.src([ outputFolder + '/ptore2e/**/*.js', outputFolder + '/examples/**/protractor.js' ]) .pipe(eslint(protractorConfig)) .pipe(eslint.format()) .pipe(eslint.failAfterError()) ); }); // The default task that will be run if no task is supplied gulp.task('default', ['assets', 'doc-gen', 'build-app', 'eslint']); gulp.task('watch', function() { gulp.watch([src, ignoredFiles, assets], ['assets', 'build-app']); });