ericclemmons / grunt-angular-templates

Grunt build task to concatenate & pre-load your AngularJS templates
MIT License
710 stars 107 forks source link

javascript < is evaluated as invalid html and throws parse error #102

Closed constellates closed 10 years ago

constellates commented 10 years ago

I'm trying to use grunt-angular-templates in conjunction with angular ui-bootstrap's templates. This default ratings template causes it to throw a parse error https://github.com/angular-ui/bootstrap/blob/master/template/rating/rating.html . The less than sign on line 3 is the culprit. Considering angular allows people to evaluate javascript in their templates is there a way to allow things like this? I tried toggling various settings that seemed potentially related and wasn't able to get it to work.

ericclemmons commented 10 years ago

Can you post up the templatized version of rating.html?

Have you tried using what's compiled for Bower?

https://github.com/angular-ui/bootstrap-bower/blob/master/ui-bootstrap-tpls.js

angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/rating/rating.html",
    "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\">\n" +
    "    <i ng-repeat=\"r in range track by $index\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\">\n" +
    "        <span class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
    "    </i>\n" +
    "</span>");
}]);
constellates commented 10 years ago

When I try to run ngtemplates with that file it throws this error to the console.

Warning: Parse Error: < value ? '*' : ' ' }})</span>
    </i>
</span>

<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">
    <i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')">
        <span class="sr-only">({{ $index < value ? '*' : ' ' }})</span>
    </i>
</span>

 Use --force to continue.

After running it again with the --force flag. I get the same error but it does seem to compile fine at a quick glance. Here is the output.

$templateCache.put('template/rating/rating.html',
  "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\">\n" +
  "    <i ng-repeat=\"r in range track by $index\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\">\n" +
  "        <span class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
  "    </i>\n" +
  "</span>"
);

Their compiled templates work great. However my current project requires me to edit their default templates so I'm setting up a workflow to do so. At this time I'm not actually using the rating directive so I can remove it and keep working. But it does seem somewhat likely that I or someone else would be using greater than or less than symbols in templates.

I also just checked and I am using version 0.5.7. Let me know if I can do anything to help.

ericclemmons commented 10 years ago

@constellates Thanks for this! I'd be surprised if I can't track it down now...

ericclemmons commented 10 years ago

I just created a test case for this, and I didn't see the issue. Dollars to donutes says it's html min as usual :)

Can you post the relevant part of your ngtemplates section for me? Thanks!

  // Gruntfile.js
  ngtemplates: {
      rating: {
        src: 'test/fixtures/rating.html',
        dest: 'tmp/rating.js',
      },
  }
// tmp/rating.js
angular.module('rating').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('test/fixtures/rating.html',
    "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\">\n" +
    "    <i ng-repeat=\"r in range track by $index\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\">\n" +
    "        <span class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
    "    </i>\n" +
    "</span>\n"
  );

}]);
constellates commented 10 years ago

Here you go.

ngtemplates: {
    bootstrap: {
        options: {
            module: 'ui-templates',
            standalone: true,
            htmlmin: {
              collapseBooleanAttributes: true,
              collapseWhitespace: true,
              removeAttributeQuotes: true,
              removeComments: true,
              removeEmptyAttributes: true,
              removeScriptTypeAttributes: true,
              removeStyleLinkTypeAttributes: true
            }
        },
        cwd: 'src/libs/ui-bootstrap',
        src: '**/**/*.html',
        dest: 'dist/ui-templates.js'
    }
}

Yea I tried tracing where the error originated and it looks like it came from the html-minifier library.

ericclemmons commented 10 years ago

TBH, that library has been the cause of many, many issues =/ #99 #98 #97 #91 #82

My recommendation would be to just try collapseWhitespace, as minified HTML can save significant amount of savings (since the quoted HTML is left uncompressed when minifying the JS):

https://github.com/ericclemmons/grunt-angular-templates/issues/32#issuecomment-20628575

Unless there's something I can do (switch libs, update html-minifier, etc.) I'm not sure what to do... :(