0

In my yo angular-fullstack project I added the angular-timezone-selector which works very well. The issue is that the chosen-sprite.png image does not get moved to the public/app/directory. (NOTE: grunt serve, works properly. It is only grunt serve:dist where the failure occurs - so this is related to the renaming, etc.. somehow).

To resolve this I manually moved the two sprite files from bower_componenets/angular-timezone-selector/dist/chosen-sprite*.png to dist/public/app/. How can I modify the Gruntfile.js to cause this to happen automatically? I am okay with having added a cp to my build process, but I would like to learn how to modify this Gruntfile to make this happen. Can you help?

The Gruntfile.js is show below. If you need other info to make this easier to solve, please ask! Thanks!!!

// Generated on 2015-02-27 using generator-angular-fullstack 2.0.13
  'use strict';

  module.exports = function (grunt) {
    var localConfig;
    try {
      localConfig = require('./server/config/local.env');
    } catch(e) {
      localConfig = {};
    }

    // Load grunt tasks automatically, when needed
    require('jit-grunt')(grunt, {
      express: 'grunt-express-server',
      useminPrepare: 'grunt-usemin',
      ngtemplates: 'grunt-angular-templates',
      cdnify: 'grunt-google-cdn',
      protractor: 'grunt-protractor-runner',
      injector: 'grunt-asset-injector',
      buildcontrol: 'grunt-build-control'
    });

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    // Define the configuration for all the tasks
    grunt.initConfig({

      // Project settings
      pkg: grunt.file.readJSON('package.json'),
      yeoman: {
        // configurable paths
        client: require('./bower.json').appPath || 'client',
        dist: 'dist'
      },
      express: {
        options: {
          port: process.env.PORT || 9000
        },
        dev: {
          options: {
            script: 'server/app.js',
            debug: true
          }
        },
        prod: {
          options: {
            script: 'dist/server/app.js'
          }
        }
      },
      open: {
        server: {
          url: 'http://localhost:<%= express.options.port %>'
        }
      },
      watch: {
        injectJS: {
          files: [
            '<%= yeoman.client %>/{app,components}/**/*.js',
            '!<%= yeoman.client %>/{app,components}/**/*.spec.js',
            '!<%= yeoman.client %>/{app,components}/**/*.mock.js',
            '!<%= yeoman.client %>/app/app.js'],
          tasks: ['injector:scripts']
        },
        injectCss: {
          files: [
            '<%= yeoman.client %>/{app,components}/**/*.css'
          ],
          tasks: ['injector:css']
        },
        mochaTest: {
          files: ['server/**/*.spec.js'],
          tasks: ['env:test', 'mochaTest']
        },
        jsTest: {
          files: [
            '<%= yeoman.client %>/{app,components}/**/*.spec.js',
            '<%= yeoman.client %>/{app,components}/**/*.mock.js'
          ],
          tasks: ['newer:jshint:all', 'karma']
        },
        injectSass: {
          files: [
            '<%= yeoman.client %>/{app,components}/**/*.{scss,sass}'],
          tasks: ['injector:sass']
        },
        sass: {
          files: [
            '<%= yeoman.client %>/{app,components}/**/*.{scss,sass}'],
          tasks: ['sass', 'autoprefixer']
        },
        gruntfile: {
          files: ['Gruntfile.js']
        },
        livereload: {
          files: [
            '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.css',
            '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.html',
            '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',
            '!{.tmp,<%= yeoman.client %>}{app,components}/**/*.spec.js',
            '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js',
            '<%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}'
          ],
          options: {
            livereload: true
          }
        },
        express: {
          files: [
            'server/**/*.{js,json}'
          ],
          tasks: ['express:dev', 'wait'],
          options: {
            livereload: true,
            nospawn: true //Without this option specified express won't be reloaded
          }
        }
      },

      // Make sure code styles are up to par and there are no obvious mistakes
      jshint: {
        options: {
          jshintrc: '<%= yeoman.client %>/.jshintrc',
          reporter: require('jshint-stylish'),
          "jasmine": true
        },
        server: {
          options: {
            jshintrc: 'server/.jshintrc',
            "jasmine": true
          },
          src: [
            'server/**/*.js',
            '!server/**/*.spec.js'
          ]
        },
        serverTest: {
          options: {
            jshintrc: 'server/.jshintrc-spec',
            "jasmine": true
          },
          src: ['server/**/*.spec.js']
        },
        all: [
          '<%= yeoman.client %>/{app,components}/**/*.js',
          '!<%= yeoman.client %>/{app,components}/**/*.spec.js',
          '!<%= yeoman.client %>/{app,components}/**/*.mock.js'
        ],
        test: {
          src: [
            '<%= yeoman.client %>/{app,components}/**/*.spec.js',
            '<%= yeoman.client %>/{app,components}/**/*.mock.js'
          ]
        }
      },

      // Empties folders to start fresh
      clean: {
        dist: {
          files: [{
            dot: true,
            src: [
              '.tmp',
              '<%= yeoman.dist %>/*',
              '!<%= yeoman.dist %>/.git*',
              '!<%= yeoman.dist %>/.openshift',
              '!<%= yeoman.dist %>/Procfile'
            ]
          }]
        },
        server: '.tmp'
      },

      // Add vendor prefixed styles
      autoprefixer: {
        options: {
          browsers: ['last 1 version']
        },
        dist: {
          files: [{
            expand: true,
            cwd: '.tmp/',
            src: '{,*/}*.css',
            dest: '.tmp/'
          }]
        }
      },

      // Debugging with node inspector
      'node-inspector': {
        custom: {
          options: {
            'web-host': 'localhost'
          }
        }
      },

      // Use nodemon to run server in debug mode with an initial breakpoint
      nodemon: {
        debug: {
          script: 'server/app.js',
          options: {
            nodeArgs: ['--debug-brk'],
            env: {
              PORT: process.env.PORT || 9000
            },
            callback: function (nodemon) {
              nodemon.on('log', function (event) {
                console.log(event.colour);
              });

              // opens browser on initial server start
              nodemon.on('config:update', function () {
                setTimeout(function () {
                  require('open')('http://localhost:8080/debug?port=5858');
                }, 500);
              });
            }
          }
        }
      },

      // Automatically inject Bower components into the app
      wiredep: {
        target: {
          src: '<%= yeoman.client %>/index.html',
          ignorePath: '<%= yeoman.client %>/',
          exclude: [/bootstrap-sass-official/, /bootstrap.js/, '/json3/', '/es5-shim/', /bootstrap.css/, /font-awesome.css/ ]
        }
      },

      // Renames files for browser caching purposes
      rev: {
        dist: {
          files: {
            src: [
              '<%= yeoman.dist %>/public/{,*/}*.js',
              '<%= yeoman.dist %>/public/{,*/}*.css',
              '<%= yeoman.dist %>/public/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
              '<%= yeoman.dist %>/public/assets/fonts/*',
              '!<%= yeoman.dist %>/public/bower_components/uri.js'
            ]
          }
        }
      },

      // Reads HTML for usemin blocks to enable smart builds that automatically
      // concat, minify and revision files. Creates configurations in memory so
      // additional tasks can operate on them
      useminPrepare: {
        html: ['<%= yeoman.client %>/index.html'],
        options: {
          dest: '<%= yeoman.dist %>/public'
        }
      },

      // Performs rewrites based on rev and the useminPrepare configuration
      usemin: {
        html: ['<%= yeoman.dist %>/public/{,*/}*.html'],
        css: ['<%= yeoman.dist %>/public/{,*/}*.css'],
        js: ['<%= yeoman.dist %>/public/{,*/}*.js'],
        options: {
          assetsDirs: [
            '<%= yeoman.dist %>/public',
            '<%= yeoman.dist %>/public/assets/images'
          ],
          // This is so we update image references in our ng-templates
          patterns: {
            js: [
              [/(assets\/images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']
            ],
            css: [
              [/(assets\/images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']
            ]
          }
        }
      },

      // The following *-min tasks produce minified files in the dist folder
      imagemin: {
        dist: {
          files: [{
            expand: true,
            cwd: '<%= yeoman.client %>/assets/images',
            src: '{,*/}*.{png,jpg,jpeg,gif}',
            dest: '<%= yeoman.dist %>/public/assets/images'
          }]
        }
      },

      svgmin: {
        dist: {
          files: [{
            expand: true,
            cwd: '<%= yeoman.client %>/assets/images',
            src: '{,*/}*.svg',
            dest: '<%= yeoman.dist %>/public/assets/images'
          }]
        }
      },

      // Allow the use of non-minsafe AngularJS files. Automatically makes it
      // minsafe compatible so Uglify does not destroy the ng references
      ngAnnotate: {
        dist: {
          files: [{
            expand: true,
            cwd: '.tmp/concat',
            src: '*/**.js',
            dest: '.tmp/concat'
          }]
        }
      },

      uglify: {
        options: {
          mangle: false
        },
      },

      cssmin: {

      },

      // Package all the html partials into a single javascript payload
      ngtemplates: {
        options: {
          // This should be the name of your apps angular module
          module: 'tracker2App',
          htmlmin: {
            collapseBooleanAttributes: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true,
            removeEmptyAttributes: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true
          },
          usemin: 'app/app.js'
        },
        main: {
          cwd: '<%= yeoman.client %>',
          src: ['{app,components}/**/*.html'],
          dest: '.tmp/templates.js'
        },
        tmp: {
          cwd: '.tmp',
          src: ['{app,components}/**/*.html'],
          dest: '.tmp/tmp-templates.js'
        }
      },

      // Replace Google CDN references
      cdnify: {
        dist: {
          html: ['<%= yeoman.dist %>/public/*.html']
        }
      },

      // Copies remaining files to places other tasks can use
      copy: {
        dist: {
          files: [{
            expand: true,
            dot: true,
            cwd: '<%= yeoman.client %>',
            dest: '<%= yeoman.dist %>/public',
            src: [
              '*.{ico,png,txt}',
              '.htaccess',
              'bower_components/**/*',
              'assets/images/{,*/}*.{webp}',
              'assets/fonts/**/*',
              'public/images/**/*',
              'index.html'
            ]
          }, {
            expand: true,
            cwd: '.tmp/images',
            dest: '<%= yeoman.dist %>/public/assets/images',
            src: ['generated/*']
          }, {
            expand: true,
            dest: '<%= yeoman.dist %>',
            src: [
              'package.json',
              'server/**/*'
            ]
          }]
        },
        styles: {
          expand: true,
          cwd: '<%= yeoman.client %>',
          dest: '.tmp/',
          src: ['{app,components}/**/*.css']
        }
      },

      buildcontrol: {
        options: {
          dir: 'dist',
          commit: true,
          push: true,
          connectCommits: false,
          message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
        },
        heroku: {
          options: {
            remote: 'heroku',
            branch: 'master'
          }
        },
        openshift: {
          options: {
            remote: 'openshift',
            branch: 'master'
          }
        }
      },

      // Run some tasks in parallel to speed up the build process
      concurrent: {
        server: [
          'sass',
        ],
        test: [
          'sass',
        ],
        debug: {
          tasks: [
            'nodemon',
            'node-inspector'
          ],
          options: {
            logConcurrentOutput: true
          }
        },
        dist: [
          'sass',
          'imagemin',
          'svgmin'
        ]
      },

      // Test settings
      karma: {
        unit: {
          configFile: 'karma.conf.js',
          singleRun: true
        }
      },

      mochaTest: {
        options: {
          reporter: 'spec'
        },
        src: ['server/**/*.spec.js']
      },

      protractor: {
        options: {
          configFile: 'protractor.conf.js'
        },
        chrome: {
          options: {
            args: {
              browser: 'chrome'
            }
          }
        }
      },

      env: {
        test: {
          NODE_ENV: 'test'
        },
        prod: {
          NODE_ENV: 'production'
        },
        all: localConfig
      },

      // Compiles Sass to CSS
      sass: {
        server: {
          options: {
            loadPath: [
              '<%= yeoman.client %>/bower_components',
              '<%= yeoman.client %>/app',
              '<%= yeoman.client %>/components'
            ],
            compass: false
          },
          files: {
            '.tmp/app/app.css' : '<%= yeoman.client %>/app/app.scss'
          }
        }
      },

      injector: {
        options: {

        },
        // Inject application script files into index.html (doesn't include bower)
        scripts: {
          options: {
            transform: function(filePath) {
              filePath = filePath.replace('/client/', '');
              filePath = filePath.replace('/.tmp/', '');
              return '<script src="' + filePath + '"></script>';
            },
            starttag: '<!-- injector:js -->',
            endtag: '<!-- endinjector -->'
          },
          files: {
            '<%= yeoman.client %>/index.html': [
                ['{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',
                 '!{.tmp,<%= yeoman.client %>}/app/app.js',
                 '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.spec.js',
                 '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js']
              ]
          }
        },

        // Inject component scss into app.scss
        sass: {
          options: {
            transform: function(filePath) {
              filePath = filePath.replace('/client/app/', '');
              filePath = filePath.replace('/client/components/', '');
              return '@import \'' + filePath + '\';';
            },
            starttag: '// injector',
            endtag: '// endinjector'
          },
          files: {
            '<%= yeoman.client %>/app/app.scss': [
              '<%= yeoman.client %>/{app,components}/**/*.{scss,sass}',
              '!<%= yeoman.client %>/app/app.{scss,sass}'
            ]
          }
        },

        // Inject component css into index.html
        css: {
          options: {
            transform: function(filePath) {
              filePath = filePath.replace('/client/', '');
              filePath = filePath.replace('/.tmp/', '');
              return '<link rel="stylesheet" href="' + filePath + '">';
            },
            starttag: '<!-- injector:css -->',
            endtag: '<!-- endinjector -->'
          },
          files: {
            '<%= yeoman.client %>/index.html': [
              '<%= yeoman.client %>/{app,components}/**/*.css'
            ]
          }
        }
      },
    });

    // Used for delaying livereload until after server has restarted
    grunt.registerTask('wait', function () {
      grunt.log.ok('Waiting for server reload...');

      var done = this.async();

      setTimeout(function () {
        grunt.log.writeln('Done waiting!');
        done();
      }, 1500);
    });

    grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
      this.async();
    });

    grunt.registerTask('serve', function (target) {
      if (target === 'dist') {
        return grunt.task.run(['build', 'env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']);
        //return grunt.task.run(['env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']);
      }

      if (target === 'debug') {
        return grunt.task.run([
          'clean:server',
          'env:all',
          'injector:sass',
          'concurrent:server',
          'injector',
          'wiredep',
          'autoprefixer',
          'concurrent:debug'
        ]);
      }

      grunt.task.run([
        'clean:server',
        'env:all',
        'injector:sass',
        'concurrent:server',
        'injector',
        'wiredep',
        'autoprefixer',
        'express:dev',
        'wait',
        'open',
        'watch'
      ]);
    });

    grunt.registerTask('server', function () {
      grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
      grunt.task.run(['serve']);
    });

    grunt.registerTask('test', function(target) {
      if (target === 'server') {
        return grunt.task.run([
          'env:all',
          'env:test',
          'mochaTest'
        ]);
      }

      else if (target === 'client') {
        return grunt.task.run([
          'clean:server',
          'env:all',
          'injector:sass',
          'concurrent:test',
          'injector',
          'autoprefixer',
          'karma'
        ]);
      }

      else if (target === 'e2e') {
        return grunt.task.run([
          'clean:server',
          'env:all',
          'env:test',
          'injector:sass',
          'concurrent:test',
          'injector',
          'wiredep',
          'autoprefixer',
          'express:dev',
          'protractor'
        ]);
      }

      else grunt.task.run([
        'test:server',
        'test:client'
      ]);
    });

    grunt.registerTask('build', [
      'clean:dist',
      'injector:sass',
      'concurrent:dist',
      'injector',
      'wiredep',
      'useminPrepare',
      'autoprefixer',
      'ngtemplates',
      'concat',
      'ngAnnotate',
      'copy:dist',
      'cdnify',
      'cssmin',
      'uglify',
      'rev',
      'usemin'
    ]);

    grunt.registerTask('default', [
      'newer:jshint',
      'test',
      'build'
    ]);
  };
JoelParke
  • 2,676
  • 2
  • 24
  • 38

1 Answers1

0

Images and fonts are not copied by default like the rest of the assets. You should add it like this:

  copy: {
    dist: {
      files: [{
        expand: true,
        dot: true,
        cwd: '<%= yeoman.client %>',
        dest: '<%= yeoman.dist %>/public',
        src: [
          ...
        ]
      }, {
          src: 'bower_components/angular-timezone-selector/dist/*.png',
          dest: 'public/app/directory'
      }]
    },
Ahmad Alfy
  • 13,107
  • 6
  • 65
  • 99