Giter Club home page Giter Club logo

grunt-usemin's Introduction

grunt-usemin Linux Build Status Windows Build status

Gitter

Replaces references from non-optimized scripts, stylesheets and other assets to their optimized version within a set of HTML files (or any templates/views).

Important

3.1.0 has a breaking change with uglify step renamed to uglify to be consistent with grunt-contrib-uglify task which name is uglify (and not uglifyjs).

Stick to 3.0.0 while we find a good solution to not have a breaking change while having name consistency.

Notice

grunt-usemin is going under some major developments to tackle the long list of issues. As they might break with master they are merged into dev branch.

Currently what has been merged:

  • Support for a resolveSource function option
  • Warning for any missing files instead of silent errors
  • Migrate from regex to HTML parser
  • Support for multiple target (current)

Getting Started

If you haven't used grunt before, be sure to check out the Getting Started guide, as it explains how to create a gruntfile as well as install and use grunt plugins. Once you're familiar with that process, install this plugin with this command:

$ npm install grunt-usemin --save-dev

Tasks

usemin replaces the references of scripts, stylesheets and other assets within HTML files dynamically with optimized versions of them. To do this usemin exports 2 built-in tasks called useminPrepare and usemin and utilizes a couple of other Grunt plugins for the optimization process. usemin does this by generating the subtasks for these Grunt plugins dynamically.

The built-in tasks of usemin:

  • useminPrepare prepares the configuration to transform specific blocks in the scrutinized file into a single line, targeting an optimized version of the files. This is done by generating subtasks called generated for each of the optimization steps handled by the Grunt plugins listed below.
  • usemin replaces the blocks by the file they reference, and replaces all references to assets by their revisioned version if it is found on the disk. This target modifies the files it is working on.

Grunt plugins which usemin can use to optimize files:

  • concat concatenates files (usually JS or CSS).
  • uglify minifies JS files.
  • cssmin minifies CSS files.
  • filerev revisions static assets through a file content hash.

To install these plugins, run:

$ npm install grunt-contrib-concat grunt-contrib-uglify grunt-contrib-cssmin grunt-filerev --save-dev

Important: You still need to manually install and load these dependencies.

In a typical usemin setup you launch useminPrepare first, then call every optimization step you want through their generated subtask and call usemin in the end. It could look like this:

// simple build task
grunt.registerTask('build', [
  'useminPrepare',
  'concat:generated',
  'cssmin:generated',
  'uglify:generated',
  'filerev',
  'usemin'
]);

The useminPrepare task

useminPrepare task updates the grunt configuration to apply a configured transformation flow to tagged files (i.e. blocks). By default the transformation flow is composed of concat and uglify for JS files, but it can be configured.

Blocks

Blocks are expressed as:

<!-- build:<type>(alternate search path) <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
  • type: can be js, css or a custom type with a block replacement function defined
  • If another type, the block will be ignored. Useful for "development only" blocks that won't appear in your build
  • alternate search path: (optional) By default the input files are relative to the treated file. Alternate search path allows one to change that
  • path: the file path of the optimized file, the target output

An example of this in completed form can be seen below:

<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

Transformation flow

The transformation flow is made of sequential steps: each of the steps transform the file, and useminPrepare will modify the configuration in order for the described steps to be correctly performed.

By default the flow is: concat -> uglify. Additionally to the flow, at the end, some postprocessors can be launched to further alter the configuration.

Let's have an example, using the default flow (we're just going to look at the steps), app for input dir, dist for output dir, and the following block:

<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

The produced configuration will look like:

{
  concat: {
    generated: {
      files: [
        {
          dest: '.tmp/concat/js/app.js',
          src: [
            'app/js/app.js',
            'app/js/controllers/thing-controller.js',
            'app/js/models/thing-model.js',
            'app/js/views/thing-view.js'
          ]
        }
      ]
    }
  },
  uglify: {
    generated: {
      files: [
        {
          dest: 'dist/js/app.js',
          src: [ '.tmp/concat/js/app.js' ]
        }
      ]
    }
  }
}

Directories

Internally, the task parses your HTML markup to find each of these blocks, and initializes the corresponding Grunt config for the concat / uglify tasks when type=js, the concat / cssmin tasks when type=css.

One doesn't need to specify a concat/uglify/cssmin configuration anymore.

It uses only one target: html, with a list of the concerned files. For example, in your Gruntfile.js:

By default, it will consider the directory where the looked-at file is located as the 'root' filesystem. Each relative path (for example to a JavaScript file) will be resolved from this path. Same goes for the absolute ones. If you need to change the 'root' dir, use the root option (see below).

useminPrepare: {
  html: 'index.html'
}

Targets can also be configured using the grunt src-dest files syntax http://gruntjs.com/configuring-tasks#files, e.g.

useminPrepare: {
  foo: {
    src: ['index.html', 'another.html']
  },
  bar: {
    src: 'index.html'
  }
}

Options

dest

Type: string
Default: nil

Base directory where the transformed files should be output.

staging

Type: string
Default: .tmp

Base directory where the temporary files should be output (e.g. concatenated files).

root

Type: string, array
Default: null

The root directory from which your files will be resolved.

flow

Type: object
Default: { steps: { js: ['concat', 'uglify'], css: ['concat', 'cssmin'] }, post: {} }

This allow you to configure the workflow, either on a per-target basis, or for all the targets. You can change the steps or the post-processors (post) separately.

For example:

  • to change the js steps and post for the target html:
useminPrepare: {
  html: 'index.html',
  options: {
    flow: {
      html: {
        steps: {
          js: ['uglify']
        },
        post: {}
      }
    }
  }
}
  • to change the js steps and post for all targets:
useminPrepare: {
  html: 'index.html',
  options: {
    flow: {
      steps: {
        js: ['uglify']
      },
      post: {}
    }
  }
}
  • to customize the generated configuration via post-processors:
useminPrepare: {
  html: 'index.html',
  options: {
    flow: {
      steps: {
        js: ['uglify']
      },
      post: {
        js: [{
          name: 'uglify',
          createConfig: function (context, block) {
            var generated = context.options.generated;
            generated.options = {
              foo: 'bar'
            };
          }
        }]
      }
    }
  }
}

The given steps or post-processors may be specified as strings (for the default steps and post-processors), or as an object (for the user-defined ones).

User-defined steps and post-processors

User-defined steps and post-processors must have 2 attributes:

  • name: name of the Gruntfile attribute that holds the corresponding config
  • createConfig which is a 2 arguments function ( a context and the treated block)

For an example of steps/post-processors, you can have a look at concat and uglify in the lib/config directory of this repository.

createConfig

The createConfig function is responsible for creating (or updating) the configuration associated to the current step/post-processor. It takes 2 arguments ( a context and the treated block), and returns a configuration object.

context

The context object represent the current context the step/post-processor is running in. As the step/post-processor is a step of a flow, it must be listed in the input files and directory it must write a configuration for, potentially the already existing configuration. It must also indicate to the other steps/post-processor which files it will output in which directory. All this information is held by the context object. Attributes:

  • inDir: the directory where the input file for the step/post-processors will be
  • inFiles: the list of input file to take care of
  • outDir: where the files created by the step/post-processors will be
  • outFiles: the files that are going to be created
  • last: whether or not we're the last step of the flow
  • options: options of the Gruntfile.js for this step (e.g. if the step is named foo, holds configuration of the Gruntfile.js associated to the attribute foo)
block

The actual looked-at block, parsed and put in a structure.

Example: The following block

<!-- build:js scripts/site.js -->',
<script src="foo.js"></script>',
<script src="bar.js"></script>',
<script src="baz.js"></script>',
<!-- endbuild -->'

is parsed as, and given to createConfig as:

var block = {
  type: 'js',
  dest: 'scripts/site.js',
  src: [
    'foo.js',
    'bar.js',
    'baz.js'
  ],
  raw: [
    '    <!-- build:js scripts/site.js -->',
    '    <script src="foo.js"></script>',
    '    <script src="bar.js"></script>',
    '    <script src="baz.js"></script>',
    '    <!-- endbuild -->'
  ]
};

The usemin task

The usemin task has 2 actions:

  • First it replaces all the blocks with a single "summary" line, pointing to a file creating by the transformation flow.
  • Then it looks for references to assets (i.e. images, scripts, ...), and tries to replace them with their revved version if it can find one on disk

Finding assets

By default usemin will look for a map object created by grunt-filerev, located in grunt.filerev.summary. If it does not find it it will revert to disk lookup which is longer.

Note that by using the options.revmap (see below), you can furnish a map object.

On directories

When usemin tries to replace referenced assets with their revved version it has to look at a collection of directories (asset search paths): for each of the directories of this collection it will look at the below tree, and try to find the revved version. This asset search directories collection is by default set to the location of the file that is scrutinized but can be modified (see Options below).

Example 1: file dist/html/index.html has the following content:

<link rel="stylesheet" href="styles/main.css">
<img src="../images/test.png">

By default usemin will look under dist/html for revved versions of:

  • styles/main.css: a revved version of main.css will be looked at under the dist/html/styles directory. For example a file dist/html/styles/main.1234.css will match (although dist/html/main.1234.css won't: the path of the referenced file is important)
  • ../images/test.png: it basically means that a revved version of test.png will be looked for under the dist/images directory

Example 2: file dist/html/index.html has the following content:

<link rel="stylesheet" href="/styles/main.css">
<img src="/images/test.png">

By default usemin will look under dist/html for revved versions of styles/main.css and images/test.png. Now let's suppose our assets are scattered in dist/assets. By changing the asset search path list to ['dist/assets'], the revved versions of the files will be searched for under dist/assets (and thus, for example, dist/assets/images/test.875487.png and dist/assets/styles/main.98090.css) will be found.

Options

assetsDirs

Type: array
Default: Single item array set to the value of the directory where the currently looked at file is.

List of directories where we should start to look for revved version of the assets referenced in the currently looked at file.

Example:

usemin: {
  html: 'build/index.html',
  options: {
    assetsDirs: ['foo/bar', 'bar']
  }
}

Suppose in index.html you have a reference to /images/foo.png, usemin will search for the revved version of /images/foo.png, say /images/foo.12345678.png in any directories in assetsDirs options.

In others words, given the configuration above, usemin will search for the existence of one of these files:

  • foo/bar/images/foo.12345678.png
  • bar/images/foo.12345678.png

patterns

Type: object
Default: {}

Allows for user defined pattern to replace reference to files. For example, let's suppose that you want to replace all references to 'image.png' in your Javascript files by the revved version of image.png found below the directory images.

By specifying something along the lines of:

usemin: {
  js: '*.js',
  options: {
    assetsDirs: 'images',
    patterns: {
      js: [
        [/(image\.png)/, 'Replacing reference to image.png']
      ]
    }
  }
}

So in short:

  • key in pattern should match the target (e.g js key for the target js)
  • Each pattern is an array of arrays. These arrays are composed of 4 items (last 2 are optional):
    • First one if the regexp to use. The first group is the one that is supposed to represent the file reference to replace
    • Second one is a logging string
    • A function which behaves like a filter-in. Receives the matched group and must return the file path of the asset. Great functionality when you have a compiled file by a template engine.
    • A function which behaves like a filter-out. It receives the revved path of the asset and must return it as an url from it will be reached from web server.

blockReplacements

Type: 'Object'
Default: { css: function (block) { ... }, js: function (block) { ... } }

This lets you define how blocks get their content replaced. Useful to have block types other that css and js.

  • Object key matches a block type
  • Value is the replacement function for that block type.
    • The replacement function gets called with a single argument: a block object.
    • Must return a String, the "summary" line that will replace the block content.

For example, to create a less block you could define its replacement function like this:

usemin: {
  html: 'index.html',
  options: {
    blockReplacements: {
      less: function (block) {
          return '<link rel="stylesheet" href="' + block.dest + '">';
      }
    }
  }
}

revmap

Type: string
Default: ''

Indicate the location of a map file, as produced by grunt-filerev for example. This map file is a simple JSON file, holding an object which attributes are the original file and associated value is the transformed file. For example:

{
  "foo.png": "foo.1234.png"
}

This map will be used instead of looking for file on the disk.

On directories

The main difference to be kept in mind, regarding directories and tasks, is that for useminPrepare, the directories needs to indicate the input, transient and output path needed to output the right configuration for the processors pipeline, whereas in the case of usemin it only reflects the output paths, as all the needed assets should have been output to the destination dir (either transformed or just copied)

useminPrepare

useminPrepare is trying to prepare the right configuration for the pipeline of actions that are going to be applied on the blocks (for example concatenation and uglify-cation). As such it needs to have the input directory, temporary directories (staging) and destination directory. The files referenced in the block are either absolute or relative (/images/foo.png or ../../images/foo.png). Absolute files references are looked in a given set of search path (input), which by default is set to the directory where the html/css file examined is located (can be overridden per block, or more generally through root option). Relative files references are also looked at from location of the examined file, unless stated otherwise.

usemin

usemin target replaces references to images, scripts, css, ... in the furnished files (html, css, ...). These references may be either absolute (i.e. /images/foo.png) or relative (i.e. image/foo.png or ../images/foo.png). When the reference is absolute a set of asset search paths should be looked at under the destination directory (for example, using the previous example, and searchpath equal to ['assets'], usemin would try to find either a revved version of the image of the image below the assets directory: for example dest/assets/images/foo.1223443.png). When the reference is relative, by default the referenced item is looked in the path relative to the current file location in the destination directory (e.g. with the preceding example, if the file is build/bar/index.html, then transformed index.html will be in dist/bar, and usemin will look for dist/bar/../images/foo.32323.png).

Use cases

Simple one

|
+- app
|   +- index.html
|   +- assets
|       +- js
|          +- foo.js
|          +- bar.js
+- dist

We want to optimize foo.js and bar.js into optimized.js, referenced using relative path. index.html should contain the following block:

<!-- build:js assets/js/optimized.js -->
<script src="assets/js/foo.js"></script>
<script src="assets/js/bar.js"></script>
<!-- endbuild -->

We want our files to be generated in the dist directory.

By using the following useminPrepare config:

{
  useminPrepare: {
    html: 'app/index.html',
    options: {
      dest: 'dist'
    }
  }
}

This will, on the fly, generate the following configuration:

{
  concat: {
    '.tmp/concat/assets/js/optimized.js': [
      'app/assets/js/foo.js',
      'app/assets/js/bar.js'
    ]
  },

  uglify: {
    'dist/assets/js/optimized.js': ['.tmp/concat/assets/js/optimized.js']
  }
}

HTML file and asset files in sibling directories

app
|
+- html
|   +- index.html
+- assets
|   +- js
|      +- foo.js
|      +- bar.js
+- dist

We want to optimize foo.js and bar.js into optimized.js, referenced using absolute path. index.html should contain the following block:

<!-- build:js /assets/js/optimized.js -->
<script src="/assets/js/foo.js"></script>
<script src="/assets/js/bar.js"></script>
<!-- endbuild -->

We want our files to be generated in the dist directory.

By using the following useminPrepare config:

{
  useminPrepare: {
    html: 'html/index.html',
    options: {
      root: 'app',
      dest: 'dist'
    }
  }
}

This will, on the fly, generate the following configuration:

{
  concat:
  {
    '.tmp/concat/assets/js/optimized.js': [
      'app/assets/js/foo.js',
      'app/assets/js/bar.js'
    ]
  },

  uglify:
  {
    'dist/assets/js/optimized.js': ['.tmp/concat/assets/js/optimized.js']
  }
}

License

BSD license and copyright Google

grunt-usemin's People

Contributors

0xjjpa avatar addyosmani avatar akinofftz avatar arthurvr avatar chulkilee avatar donaldpipowitch avatar eskimoblood avatar halkeye avatar iamolivinius avatar kavanagh avatar kevva avatar lukebussey avatar mcampo avatar necolas avatar passy avatar rgalkas avatar sebdeckers avatar sergiolopes avatar silvenon avatar sindresorhus avatar sleeper avatar sorich87 avatar sparanoid avatar stephanebachelier avatar tedjp avatar timhettler avatar tinganho avatar trevors avatar wbinnssmith avatar xhmikosr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grunt-usemin's Issues

Make sure it filters files in expand

ref this: yeoman/yeoman#811

Noticed there where still a couple of expand() methods without file filter, can you make sure that's correct and if not add a isFile filter?

tasks/usemin.js:81
tasks/usemin.js:94
tasks/usemin.js:132

Regex breaking on anchors with PHP code in them

Bit of an edge case I guess, but I'm running usemin over Laravel blade templates, and the following nav breaks the regex..

<ul class='nav'>
                <li class='divider-vertical'></li>
                <li>
                    <a href="<?php echo URL::to('admin') ?>"><i class='icon-list icon-white'></i>&nbsp;&nbsp;List</a>
                </li>
                <li class='divider-vertical'></li>
                <li>
                    <a href="<?php echo URL::to('admin/create') ?>"><i class='icon-plus icon-white'></i>&nbsp;&nbsp;New</a>
                </li>
                <li class='divider-vertical'></li>
                <li>
                    <a href="<?php echo URL::to('logout') ?>"><i class='icon-off icon-white'></i>&nbsp;&nbsp;Logout</a>
                </li>
                <li class='divider-vertical'></li>
            </ul>

gives the error...

Update the HTML with anchors images
Warning: Invalid regular expression: /[0-9a-fA-F]+\.<?php echo URL::to($/: Unterminated group Use --force to continue.

...however if I just change the first anchor to use single instead of double quotes it fixes the error for the whole block even though there are still other anchors using double quotes?

Error appears to be in the regex on line 231 of htmlprocessor.js...

[/<a[^\>]+href=['"]([^"']+)["']/gm,
'Update the HTML with anchors images'

Globbing

Regarding yeoman/yeoman#661 (comment)

Not a priority, but might be useful to have at some point.

<!-- build:js js/app.js -->
<script src="scripts/vendor/*"></script>
<script src="scripts/models/*"></script>
<script src="scripts/views/*"></script>
<!-- endbuild -->

Configure the destination directory

So far useminPrepare output concat/uglify/cssmin configuration that do not take into account a destination directory: i.e. something like

<!-- build:js scripts/plugins.js -->

will create the destination file in app/scripts/plugins.js.
However we do potentially want to supersede this but outputting in another dir (for example: dist/scripts/plugins.js).

useminPrepare complains "Object #<Object> has no method 'options'"

Given the instructions:

'useminPrepare': {
    html: 'app/index.html'
},

I get a complaint from grunt (grunt v0.3.17) that this.options() does't exist

Running "useminPrepare:html" (useminPrepare) task

TypeError: Object #<Object> has no method 'options'
    at Object.module.exports (/home/halkeye/git/infinicatr/node_modules/grunt-usemin/tasks/usemin.js:110:24)
    at Object.task.registerMultiTask.thisTask (/home/halkeye/npm/lib/node_modules/grunt/lib/grunt/task.js:109:15)
    at Object.task.registerTask.thisTask.fn (/home/halkeye/npm/lib/node_modules/grunt/lib/grunt/task.js:58:16)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:343:36)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:319:9)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:346:11)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:319:9)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:346:11)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:319:9)
    at Task.<anonymous> (/home/halkeye/npm/lib/node_modules/grunt/lib/util/task.js:346:11)

revvedfinder does not work with files containing trailing hex characters.

Using a modified version of the rev.js task in yeoman to work with grunt 0.4, I created some revved files.

One revved file I created looked like this: 11916fba.app.min.js.

The current version of grunt-usemin does not recognize trailing hex characters as the regexp only looks for one or more digit characters for the rev.

Perhaps we should search for hex characters instead of just digits.

Add plugin like mechanism

Actually in several cases the usemin task does not replace files by their revved version (for example with js dile using requirejs).
We need to have a way to add plugin like mechanism to extend the capability of grunt-usemin when needed

Grunt 0.4 Release

I'm posting this issue to let you know that we will be publishing Grunt 0.4 on Monday, February 18th.

If your plugin is not already Grunt 0.4 compatible, would you please consider updating it? For an overview of what's changed, please see our migration guide.

If you'd like to develop against the final version of Grunt before Monday, please specify "grunt": "0.4.0rc8" as a devDependency in your project. After Monday's release, you'll be able to use "grunt": "~0.4.0" to actually publish your plugin. If you depend on any plugins from the grunt-contrib series, please see our list of release candidates for compatible versions. All of these will be updated to final status when Grunt 0.4 is published.

Also, in an effort to reduce duplication of effort and fragmentation in the developer community, could you review the grunt-contrib series of plugins to see if any of your functionality overlaps significantly with them? Grunt-contrib is community maintained with 40+ contributors—we'd love to discuss any additions you'd like to make.

Finally, we're working on a new task format that doesn't depend on Grunt: it's called node-task. Once this is complete, there will be one more conversion, and then we'll never ask you to upgrade your plugins to support our changes again. Until that happens, thanks for bearing with us!

If you have any questions about how to proceed, please respond here, or join us in #grunt on irc.freenode.net.

Thanks, we really appreciate your work!

How does it support media="screen" and other attributes?

My issue right now is how to make media="screen" out.

grunt before:

<!-- build:css "/static/css/app.min.css -->
<link rel="stylesheet" href="/static/css/a.css" media="screen" />
<link rel="stylesheet" href="/static/css/b.css"  media="screen" />
<link rel="stylesheet" href="/static/css/c.css"  media="screen" />
<!-- endbuild -->
<link rel="stylesheet" href="/static/css/print.css"  media="print" />

grunt after:

<link rel="stylesheet" href="/static/css/app.min.css" />
<link rel="stylesheet" href="/static/css/print.css"  media="print" />

Thanks.

Absolute paths not honored for CSS & JS files (PHP includes)

I am using grunt-usemin with PHP includes and so I need absolute paths to my files.

<!-- build:css /assets/css/style.min.css -->
<link rel="stylesheet" href="/assets/css/style.css">
<!-- endbuild -->

Compiles to:

<link rel="stylesheet" href="assets/css/style.min.css"/>

The absolute / path is removed. Also, note the closing bracket?

Same thing happens with JS files.

SVG embeds with <object>

Hey,

I'm embedding SVG's into my index.html using:

<object data="images/report.svg" type="image/svg+xml"></object>

Doing it this way to be able to access the SVG DOM from the main frame easily. However, usemin renames the SVG files under images/, but doesn't update the reference in index.html. This is a problem.

I'm using yeoman v0.9.6.

I can throw a pull request your way with a proposed fix, but I'd first like to know if simply adding <object> handling (maybe for *.svg files, or type=image) in https://github.com/yeoman/grunt-usemin/blob/master/lib/htmlprocessor.js#L174 would be considered appropriate by you guys, or if there's some better way.

Thanks for your hard work!

Where is the rev task?

Hey sorry if this is a dumb question, but where is the 'rev' task for Grunt? I was using the one from mklabs' old h5bp node-build-script, and the one found in Yeoman 0.9.6, but they don't seem to be compatible with the latest Grunt 0.4.x.

Is 'rev' meant to be included in grunt-usemin, or is it available in a separate git repository / npm package?

Missing either a "name", "include" or "modules" option

The name or out is never set by usemin.

Could it be because all default js was replaced with javascript, and compiled to .tmp?

Gruntfile

// Generated on 2013-03-21 using generator-webapp 0.1.5
'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dist: 'dist'
    };

    grunt.initConfig({
        yeoman: yeomanConfig,
        watch: {
            coffee: {
                files: ['<%= yeoman.app %>/coffeescripts/{,*/}*.coffee'],
                tasks: ['coffee:dist']
            },
            coffeeTest: {
                files: ['test/spec/{,*/}*.coffee'],
                tasks: ['coffee:test']
            },
            jade: {
                files: ['<%= yeoman.app %>/templates/{,*/}*.{jade}'],
                tasks: ['jade']
            },
            compass: {
                files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
                tasks: ['compass']
            },
            livereload: {
                files: [
                    '<%= yeoman.app %>/*.html',
                    '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
                    '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                    '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,webp}'
                ],
                tasks: ['livereload']
            }
        },
        connect: {
            options: {
                port: 9000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'app')
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test')
                        ];
                    }
                }
            },
            dist: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, 'dist')
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: ['.tmp', '<%= yeoman.dist %>/*'],
            server: '.tmp'
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                'Gruntfile.js',
                '<%= yeoman.app %>/scripts/{,*/}*.js',
                '!<%= yeoman.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://localhost:<%= connect.options.port %>/index.html']
                }
            }
        },
        coffee: {
            dist: {
                files: [{
                    // rather than compiling multiple files here you should
                    // require them into your main .coffee file
                    expand: true,
                    cwd: '<%= yeoman.app %>/coffeescripts',
                    src: '*.coffee',
                    dest: '.tmp/scripts',
                    ext: '.js'
                }]
            },
            test: {
                files: [{
                    expand: true,
                    cwd: '.tmp/spec',
                    src: '*.coffee',
                    dest: 'test/spec'
                }]
            }
        },
        jade: {
            compile: {
                options: {
                    client: false,
                    basePath: 'app/jade',
                    pretty: true,
                    data: {
                        debug: false
                    }
                },
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/templates/',
                    src: '*.jade',
                    dest: '<%= yeoman.app %>/',
                    rename: function (destBase, destPath) {
                        return destBase + destPath.replace(/\.jade$/, '.html');
                    }
                }]
            }
        },
        compass: {
            options: {
                sassDir: '<%= yeoman.app %>/styles',
                cssDir: '.tmp/styles',
                imagesDir: '<%= yeoman.app %>/images',
                javascriptsDir: '<%= yeoman.app %>/scripts',
                fontsDir: '<%= yeoman.app %>/styles/fonts',
                importPath: 'app/components',
                relativeAssets: true
            },
            dist: {},
            server: {
                options: {
                    debugInfo: true
                }
            }
        },
        // not used since Uglify task does concat,
        // but still available if needed
        /*concat: {
            dist: {}
        },*/
        requirejs: {
            dist: {
                // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
                options: {
                    // `name` and `out` is set by grunt-usemin
                    baseUrl: 'app/scripts',
                    optimize: 'none',
                    // TODO: Figure out how to make sourcemaps work with grunt-usemin
                    // https://github.com/yeoman/grunt-usemin/issues/30
                    //generateSourceMaps: true,
                    // required to support SourceMaps
                    // http://requirejs.org/docs/errors.html#sourcemapcomments
                    preserveLicenseComments: false,
                    useStrict: true,
                    wrap: true,
                    //uglify2: {} // https://github.com/mishoo/UglifyJS2
                }
            }
        },
        useminPrepare: {
            html: '<%= yeoman.app %>/index.html',
            options: {
                dest: '<%= yeoman.dist %>'
            }
        },
        usemin: {
            html: ['<%= yeoman.dist %>/{,*/}*.html'],
            css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
            options: {
                dirs: ['<%= yeoman.dist %>']
            }
        },
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/images',
                    src: '{,*/}*.{png,jpg,jpeg}',
                    dest: '<%= yeoman.dist %>/images'
                }]
            }
        },
        cssmin: {
            dist: {
                files: {
                    '<%= yeoman.dist %>/styles/main.css': [
                        '.tmp/styles/{,*/}*.css',
                        '<%= yeoman.app %>/styles/{,*/}*.css'
                    ]
                }
            }
        },
        htmlmin: {
            dist: {
                options: {
                    /*removeCommentsFromCDATA: true,
                    // https://github.com/yeoman/grunt-usemin/issues/44
                    //collapseWhitespace: true,
                    collapseBooleanAttributes: true,
                    removeAttributeQuotes: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true*/
                },
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>',
                    src: '*.html',
                    dest: '<%= yeoman.dist %>'
                }]
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        '*.{ico,txt}',
                        '.htaccess'
                    ]
                }]
            }
        },
        bower: {
            all: {
                rjsConfig: '<%= yeoman.app %>/scripts/main.js'
            }
        }
    });

    grunt.renameTask('regarde', 'watch');

    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'coffee:dist',
            'jade:compile',
            'compass:server',
            'livereload-start',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });

    grunt.registerTask('test', [
        'clean:server',
        'coffee',
        'jade',
        'compass',
        'connect:test',
        'mocha'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
        'coffee',
        'jade',
        'compass:dist',
        'useminPrepare',
        'requirejs',
        'imagemin',
        'htmlmin',
        'concat',
        'cssmin',
        'uglify',
        'copy',
        'usemin'
    ]);

    grunt.registerTask('default', [
        'jshint',
        'test',
        'build'
    ]);
};

`min` and `css` task change

min and css task change has changed name to uglify and cssmin

Although it should probably be configurable or something.

Insufficient linefeed detection

The current approach to detect the linefeed via a regex leads to problems when you have files where the line endings are mixed up (of cause that shouldn't be the case, but can happen). This leads to problems when replacing the code blocks, where they are not getted replaced and finding that bug was really hard.

In the current version the linefeed is only used for rejoining the extracted code blocks. There should be no need for the rejoining when simply reusing the extracted codeblock for replacing.

Proper handling of "extended" <script> tags

The regexp for <script>s is too restrictive. I'm using RequireJS and type-Attributes like this:

  <script data-main="scripts/main.min" src="scripts/require-jquery.min.js" type="text/javascript"></script>

This isn't matched by usemin at all, since the regexp only allows one single src attribute and no more. By replacing it with /<script.+src=['"]([^"']+)["'].+[\/>]?><[\\]?\/script>/gm</code> the output is more accurate:

  <script data-main="scripts/main.min" src="scripts/bc4a736aa96480b4e9dfaffef2c49d50.require-jquery.min.js type="text/javascript"></script>

However scripts/main.min still isn't replaced by revved version. I think because of the lacking .js extension. Maybe we need a special handling of data-main attributes.

data-main tag with requirejs not replaced correctly

I am using usemin version 0.1.4 with grunt 0.4.0rc7.

My HTML file has this tag

    <!-- build:js /static/etms/js/app.min.js -->
    <script data-main="/static/etms/js/app.min" type="text/javascript" src="/static/common/js/external/require.min.js"></script>
    <!-- endbuild -->

And the grunt file has these entries for usemin

    'useminPrepare': {
      html: 'static/etms/html/index.html'
    },
    usemin: {
      html: ['static/etms/html/index.html']
    },

When I run grunt, I end up with this in my index.html

    <script src="/static/etms\js\app.min.js"></script>

The data-main is just replaced with a reference to the min file which does not work since I still need to load require.js and pass it the data-main reference.

I also tried using the latest version of htmlprocessor.js since it had a change to the regex for data-main but the replaced tag is still the same.

As an aside, the path still has the Windows style / even though the html processor has a line to replace them.

Does this support replacing the revved versions as the prior version did?

I'm wondering how to use this in conjunction with the hash revving it used to have. I'm not using it with Yeoman, but stand alone, I can use the old rev task to generate the hashed files, but this task doesn't seem to pick them up. I'm wondering if I'm doing something wrong or this just doesn't support it yet, and if so, is there a plan to? or an alternative in mind?

concat javascript files with leading "/"

Please refer to SO post details regarding this issue.
http://stackoverflow.com/questions/14076927/grunt-yeoman-concat-javascript-files-with-absolute-path


By default, JS files are included as

    <script src="scripts/app.js"></script>
    <script src="scripts/controllers/main.js"></script>
    <!-- endbuild -->

$ ls dist/scripts/
ab541b7e.app.js afa864c8.scripts.js controllers vendor
$ cat dist/scripts/afa864c8.scripts.js
"use strict";var ...
....
App Engine application configuration require to use "/" prepended.

    <script src="/scripts/app.js"></script>
    <script src="/scripts/controllers/main.js"></script>
    <!-- endbuild -->

Build results in the concatenated file,
$ ls dist/scripts/
9eecb7db.scripts.js ab541b7e.app.js controllers vendor
$ cat dist/scripts/9eecb7db.scripts.js
But, then the concatenated script file is empty.

I use the default Gruntfile generated by Yeoman.

Pass JShint

Superlow pri, but would be nice to eventually pass the strict JSHint.

requirejs not properly handled in 0.1.6

Following 0.1.6, requirejs is not properly treated. A input file with:

        <!-- build:js scripts/main.js -->
        <script data-main="scripts/main" src="components/requirejs/require.js"></script>
        <!-- endbuild -->

will be changed into

       <script data-main="scripts/main.js" src="components/requirejs/require.js"></script>

but the components/requirejs/require.js is not created/does not exist in dist directory.

Allow user to optionally turn off processors (RequireJS)

Hey -

So in my build process, I want to continue managing RequireJS on my own, as I use almond.js for deployment. The way this extension works now, this

<!-- build:js scripts/app.js -->
    <script data-main="scripts/config" src="scripts/lib/require.js"></script>
<!-- endbuild -->

gets turned into this

<script data-main="scripts/app" src="scripts/vendor/require.js"></script>

I don't want the extension to make that assumption, since almond.js doesn't use data-main. Instead, I want to turn off the bit that changes my requirejs settings. The resulting tag in my html should be

<script src="scripts/app.js"></script>

Does that sound reasonable?

Requiejs can only find the base module but not the dependencies

I have the following structure in my project:

js-
   | - app.js
   | -module1.js

My html block look like this:

    <!-- build:js ../dist/app.min.js -->
    <script data-main="js/app" src="../lib/js/requirejs/requirejs.js"></script>
    <!-- endbuild -->

In the app module I require module1 like this:

require(['module1'], function(module1) {
  module1();
});

The problem is that usemin sets the name of the requirejs config to js/app instead of setting the name to app and set the basePath to js. So the outcome of this is that the requirejs compiler couldn't find module1 as he search in the root of the project. But when I set the basePath to /js it can not find the app module as usemin sets the name to js/app.

I'm not sure whats the best way to fix this. I for my self patch it like this:

requirejs.name = requirejs.name || block.requirejs.name.replace(requirejs.baseUrl, '');

where I set the basePath in my config and delete it from the incoming name.

Maybe its better to split the name string on / and use the last item as name parameter and the rest as the basePath.

Usemin 2.0

Usemin needs a big overhaul to be simpler to understand and use, and be more configurable.
Namely we need:

  • configurable pipe for useminPrepare (e.g. users may want to disable uglifyjs, concat, ..)
  • simpler directories (input, output) configuration:
    • differentiate location dir (i.e. where the looked at file is), search path (where to look for assets), staging dirs and output dir
  • flexible parsers for usemin (e.g. add for example create a new parser for AngularJS)
  • comprehensive docs about how it works and how it should be used.

"usemin:html" generates incorrect css files

Originally from yeoman #826


I'm using an IE conditional, but when the usemin:html task is run during yeoman build, it only references 1 stylesheet.

index.html

<link rel="stylesheet" href="styles/styles.css">

<!--[if IE]>
  <link rel="stylesheet" href="styles/ie-styles.css">
<![endif]-->

Output of the console

>> styles/styles.css
was <link rel="stylesheet" href="styles/styles.css"
now <link rel="stylesheet" href="styles/43a5b6dc.ie-styles.css"
>> styles/ie-styles.css
was <link rel="stylesheet" href="styles/ie-styles.css"
now <link rel="stylesheet" href="styles/43a5b6dc.ie-styles.css"

It incorrectly replaces styles/styles.css with styles/43a5b6dc.ie-styles.css.

As noted by @sleeper, it's a regex issue.

I might try to dig into the source if I have some time, but in the meantime, I've used usemin directives to fix this:

<!-- build:css styles/styles.css -->
  <link rel="stylesheet" href="styles/styles.css">
<!-- endbuild -->

<!--[if IE]>
  <!-- build:css styles/ie-styles.css -->
    <link rel="stylesheet" href="styles/ie-styles.css">
  <!-- endbuild -->
<![endif]-->

Creating sourcemap for built file

When building out the uglify block; usemin sets the destination and source filenames to the same value: uglify[block.dest] = block.dest;.

This conflicts with building a source map via grunt-contrib-uglify, as the source and destination files are the same file. Since we populate the uglify config, do we want to specify a way to populate the config with a list of files (like what is pushed into concat)?

Usemin no longer concatenates require.js with rjs output?

I used yeoman 0.9.6 with this data-main block:
https://github.com/darwin/cmx.js/blob/master/app/edit/sample.html#L8
All worked as expected. Produced cmx.js which had require.js prepended to the output of rjs.

I upgraded to yeoman 1.0 beta and now I'm unable to configure usemin, to produce the same result. The thing I get is:

<script data-main="v/cmx" src="scripts/vendor/require.js"></script>

I tried to poke around in the code and I'm not even able to find related parts.

Am I missing something? Was this done by usemin or some other yeoman task? Thank you.

Task should not override mainConfigFile

The task should not override an existing mainConfigFile attribute in the requirejs settings. I like to have my build settings in an external file and not in the same as my bootstrap js file.

Problem with output path

I wanna build a distribution of my in the dist folder. So I add the following block comments to my index.html:

<!-- build:css dist/css/lib.css -->
    <link href="lib/css/bootstrap/bootstrap.css" rel="stylesheet">
    <link href="lib/css/bootstrap/bootstrap-responsive.css" rel="stylesheet">
    <!-- endbuild -->

My build process looks like this:

  • copy the original index.html into distfolder
  • run useminPrepare on the original index.html so it could find the sources
  • run useMin with the dist/index.hmtl to replace the path there
copy: {
      build: {
        files: {
          'dist/index.html': 'index.html'
        }
      }
    },
    'useminPrepare': {
      html: 'index.html',
      options: {
        cssmin: 'mincss'
      }
    },
    // use the copy in dist folder 
    usemin: {
      html: ['dist/index.html']
    }

The problem is, that the replaced filename in the the dist/index.html point to dist/css/lib.css instead of pointing to css/lib.css

proposal: wider support of tag attributes to detect assets

at the moment only href and src attributes are being searched for assets reference,
it will be a good idea to have possibility to add additional tags here.

rationale is that sometimes there are additional data- tags, or e.g. poster tag of the HTML5 video tag.

Usemin does not include require.js in the build file

Hi,

I am using requirejs with my project and generated it using Yeoman. All the js files are concatenated, uglified and so on correctly but I still end up having require.js in a seperate file.

Source:
HTML part:

    <!-- build:js main.js -->
    <script data-main="scripts/main" src="components/requirejs/require.js"></script>
    <!-- endbuild -->

Gruntfile part:

// configurable paths
var yeomanConfig = {
    app : 'app',
    dist : 'dist'
};
            useminPrepare : {
                html : '<%= yeoman.app %>/index.html',
                options : {
                    dest : '<%= yeoman.dist %>'
                }
            },
            usemin : {
                html : [ '<%= yeoman.dist %>/{,*/}*.html' ],
                css : [ '<%= yeoman.dist %>/*.css' ],
                options : {
                    dirs : [ '<%= yeoman.dist %>' ]
                }
            },
            requirejs : {
                compile : {
                    options : {
                        optimize : 'none',
                    }
                }
            }

Built HTML file:

<script data-main="main" src="components/requirejs/require.js"></script>

It was working before I upgraded Yeoman. But as the building process is now purely managed via GruntJS I hope I have come to the right place. :) I think I am just missing a configuration somewhere so that require.js is put into the build js file and the HTML file is altered accordingly. Thx in advance

incorrect generated cssmin config on v0.1.5

I just upgraded a project of mine to the latest version 0.1.5 and am getting a failure during the cssmin step.

useminPrepare is now generating the following cssmin config:

cssmin: {
  'tmp/css/landing.css': 
     [ 'tmp/css/landing/foundation.css',
       'tmp/css/landing/flexslider.css',
       'tmp/css/landing/index.css' ],
} 

Previously the cssmin step would generate as

cssmin: { 'tmp/css/landing.css': [ 'tmp/css/landing.css'] }

Here is my html:

<!-- build:css css/landing.css -->
<link rel="stylesheet" href="css/landing/foundation.css">
<link rel="stylesheet" href="css/landing/flexslider.css">
<link rel="stylesheet" href="css/landing/index.css">
<!-- endbuild -->

The cssmin config is now identical to the concat task for the css file.

Configure require path

I'm not using yeoman, just trying to use this task through grunt.
It seems yeoman will always copy require to scripts/vendor/require.js and for blocks that contain the data-main attribute, the task will always replace the src attribute with scripts/vendor/require.js.

What's the way to configure that path so it maches my actual configuration?

Ability to replace revved urls inside of js files

I would like to rev my templates that I use with angular, and they get referenced in my module declaration in angular, with a path of something like this:

$routeProvider.when('/dashboard', { templateUrl: 'templates/dashboard.html', controller: etv.DashboardCtrl });

I'm revving them up, but need to have them replaced in that one file. Is there any way to register an additional 'matcher' to have these replaced, or do I just need to fork the task to add that?

usemin doesn’t update revved files when the html file is in a subdirectory

I have the following directory structure:

– Gruntfile.js
– app
    |– index.php
    |– js
    |– css
    |– templates
        |– template.php
– dist

Usemin should update the references in the template.php
I managed to get usemin to work with the alternate search path option:

<!-- build:js(app) js/main.js -->
    <script src="js/script1.js"></script>
    <script src="js/script2.js"></script>
<!-- endbuild -->

In the Gruntfile.js:

usemin: {
    html: '<%= yeoman.dist %>/templates/template.php',
    css: ['<%= yeoman.dist %>/css/*.css'],
    options: {
        dirs: ['<%= yeoman.dist %>']
    }
}

Then I added grunt-rev:

rev: {
    files: {
        src: ['dist/js/main.js', 'dist/css/main.css']
    }
} 

The css and js files get revved but usemin won’t update them.

Multiple targets

I'm trying to use usemin as a multi task. Is this currently supported?

My use case is as follows:

  1. rev my images/fonts
  2. usemin:html my templates
  3. handlebars the templates into an AMD module
  4. requirejs the template module into my app code into a single app.js
  5. rev the app.js
  6. usemin:html my index.html to load the revved app.js

The problem is that usemin currently only takes one 'html' set of files, but I need to usemin the templates separately from the index.html file.

Ideally this would be my configuration:

{
  usemin: {
    templates: {
      options: {
        type: 'html'
      },
      files: [{
        src: ['templates/**/*.html']
      }]
    },
    app: {
      options: {
        type: 'html'
      },
      files: [{
        src: ['index.html']
      }]
    }
  }
}

I added the type option to tell usemin which processor to use (html or css). Otherwise it cannot support any other target names besides "html" and "css".

Thoughts?

Fails with grunt-contrib-requirejs

When I try to use the task with a requirejs block I got the following log from the task that updates the config:

requirejs: { out: 'dist/app.min.js', name: 'dev/js/modules/app' }

But the requirejs task stops with this error:

Running "requirejs:out" (requirejs) task
Error: Missing either a "name", "include" or "modules" option
    at Function.build.createConfig (/Users/akoeberle/grunt_example/node_modules/grunt-contrib-requirejs/node_modules/requirejs/bin/r.js:22690:19)

Writing the config by myself like this the requirejs task runs without errors:

requirejs: {
  compile: {
    options: {
      baseUrl: "dev/js/modules/",
      name: "app",
      out: "dist/app.min.js"
    }
  }
}

Does not support setting up the current working directory (cwd)

I'm using grunt-usemin without yeoman and having a problem where the resulted files are empty and end up in a folder next to gruntfile.

Structure

  • grunt.js
  • build /
  • build/index.html
  • build/scripts/(source files)

When executing following tasks: useminPrepare concat min usemin
what I get is correct files but in wrong place and the files are empty.

  • grunt.js
  • build /
  • build/index.html
  • build/scripts/
  • scripts/(usemin generated files)

I think the problem is with the working folder. Usemin does find the script references from index.html and correctly generates the concat and min tasks but the file locations in the generated tasks are wrong as they're missing the /build part of the path.

collapseWhitespace in htmlmin task makes usemin destroy the html

collapseWhitespace: true in the grunt-contrib-htmlmin makes usemin destroy most of the html.

The resulting index.html from generator-webapp becomes:

<script src="scripts/vendor/modernizr.js"></script>
            <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
        <![endif]--><!-- Google Analytics: change UA-XXXXX-X to be your site's ID. --><script>var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
            (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
            g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
            <script src="scripts/plugins.js"></script>

Usemin moves the closing anchor tag, breaking CSS

At this point during the Yeoman build process,

Processing as HTML - dist/views/main.html
Update the HTML to reference our concat/min/revved script files
Update the HTML with the new css filenames
Update the HTML with the new img filenames
Update the HTML with data-main tags
Update the HTML with the data tags
Update the HTML with background imgs, case there is some inline style
Update the HTML with anchors images
Update the HTML with reference in input

This code:

<a href="...">
  <img ng-src='{{image_url}'>
  <div class="hi"></div>
</a>

becomes

<a href="...">
  <img ng-src='{{image_url}}'>
  </a><div class="hi"></div>

So, the closing anchor tag moves between the two img and div elements it contains. Thanks for any tips. Right now, I'm thinking of running usemin on index.html only.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.