├── test ├── html │ ├── invalid │ │ ├── improperly_closed_tag.tmpl.html │ │ ├── missing_closing_tag.tmpl.html │ │ ├── improperly_nested_tags.tmpl.html │ │ └── template_missing_extension.html │ └── valid │ │ ├── template │ │ ├── valid_angular_table_row.tmpl.html │ │ ├── valid_angular.tmpl.html │ │ └── valid_regular.tmpl.html │ │ └── full │ │ ├── valid_regular.html │ │ ├── valid_angular.html │ │ └── valid_angular_directives.html └── htmlangular_test.js ├── .gitignore ├── .travis.yml ├── .jshintrc ├── package.json ├── LICENSE-MIT ├── tasks └── htmlangular.js ├── Gruntfile.js └── README.md /test/html/invalid/improperly_closed_tag.tmpl.html: -------------------------------------------------------------------------------- 1 |

Some content

2 | -------------------------------------------------------------------------------- /test/html/invalid/missing_closing_tag.tmpl.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Some content. 4 |
-------------------------------------------------------------------------------- /test/html/invalid/improperly_nested_tags.tmpl.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Very noticeable 4 |

5 |
-------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | tmp 4 | html-angular-validate-report.json 5 | html-angular-validate-report-checkstyle.xml 6 | -------------------------------------------------------------------------------- /test/html/valid/template/valid_angular_table_row.tmpl.html: -------------------------------------------------------------------------------- 1 | 2 | {name} 3 | {birthdate} 4 | {address} 5 | -------------------------------------------------------------------------------- /test/html/valid/full/valid_regular.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test HTML - Valid 5 | 6 | 7 |

Hi Nik!

8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "9" 5 | - "8" 6 | - "7" 7 | - "6" 8 | - "5" 9 | 10 | branches: 11 | only: 12 | - master 13 | 14 | before_script: 15 | - npm install -g grunt-cli 16 | - grunt jshint 17 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "immed": true, 5 | "indent": 4, 6 | "latedef": true, 7 | "newcap": true, 8 | "noarg": true, 9 | "plusplus": true, 10 | "sub": true, 11 | "undef": true, 12 | "boss": true, 13 | "eqnull": true, 14 | "node": true 15 | } 16 | -------------------------------------------------------------------------------- /test/html/valid/template/valid_angular.tmpl.html: -------------------------------------------------------------------------------- 1 |
2 | {{fragLabel}} 3 |
4 |
    5 |
  • {{item}}
  • 6 |
7 |
8 |
-------------------------------------------------------------------------------- /test/html/invalid/template_missing_extension.html: -------------------------------------------------------------------------------- 1 |
2 | Nothing Special Div Fragment 3 |
4 |
    5 |
  • Item One
  • 6 |
  • Item Two
  • 7 |
  • Item Three
  • 8 |
9 |
10 |
-------------------------------------------------------------------------------- /test/html/valid/template/valid_regular.tmpl.html: -------------------------------------------------------------------------------- 1 |
2 | Nothing Special Div Fragment 3 |
4 |
    5 |
  • Item One
  • 6 |
  • Item Two
  • 7 |
  • Item Three
  • 8 |
9 |
10 |
-------------------------------------------------------------------------------- /test/html/valid/full/valid_angular.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test HTML - Valid 5 | 6 | 7 |

{{paraBody}}

8 | 9 | Some sort of directive content would go here, I presume. 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/html/valid/full/valid_angular_directives.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test HTML - Valid 5 | 6 | 7 |
8 |
9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-html-angular-validate", 3 | "description": "An HTML validator aimed at AngularJS projects.", 4 | "version": "0.6.1", 5 | "homepage": "https://github.com/nikestep/grunt-html-angular-validate", 6 | "author": { 7 | "name": "Nik Estep", 8 | "email": "nik.estep@gmail.com", 9 | "url": "http://nikestep.me" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/nikestep/grunt-html-angular-validate.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/nikestep/grunt-html-angular-validate/issues" 17 | }, 18 | "license": "MIT", 19 | "engines": { 20 | "node": ">= 5.0.0" 21 | }, 22 | "scripts": { 23 | "test": "grunt test" 24 | }, 25 | "devDependencies": { 26 | "ansi-styles": "^3.2.0", 27 | "grunt": "~1.0.1", 28 | "grunt-contrib-clean": "~1.1.0", 29 | "grunt-contrib-jshint": "~1.1.0", 30 | "grunt-contrib-nodeunit": "~1.0.0" 31 | }, 32 | "dependencies": { 33 | "colors": "~1.1.2", 34 | "html-angular-validate": "~0.2.3" 35 | }, 36 | "keywords": [ 37 | "gruntplugin" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Nik Estep 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /tasks/htmlangular.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-html-angular-validate 3 | * https://github.com/nikestep/grunt-html-angular-validate 4 | * 5 | * Copyright (c) 2014 Nik Estep 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var colors = require('colors'); 12 | var validate = require('html-angular-validate'); 13 | 14 | var writeFileErrors = function(grunt, file) { 15 | // Start writing this file 16 | grunt.log.writeln('Validating ' + 17 | file.filepath + 18 | ' ...' + 19 | 'ERROR'.red); 20 | 21 | if (file.errors[0].msg === 'Unable to validate file') { 22 | grunt.log.writeln('Validating ' + 23 | file.filepath + 24 | ' ...' + 25 | 'ERROR'.red); 26 | grunt.log.writeln('Unable to validate file'.yellow); 27 | return; 28 | } 29 | 30 | // Write each error 31 | for (var i = 0; i < file.errors.length; i += 1) { 32 | var err = file.errors[i]; 33 | if (err.line !== undefined) { 34 | grunt.log.writeln('['.red + 35 | 'L'.yellow + 36 | ('' + err.line).yellow + 37 | ':'.red + 38 | 'C'.yellow + 39 | ('' + err.col).yellow + 40 | ']'.red + 41 | ' ' + 42 | err.msg.yellow); 43 | } else { 44 | grunt.log.writeln('['.red + 45 | 'file'.yellow + 46 | ']'.red + 47 | ' ' + 48 | err.msg.yellow); 49 | } 50 | } 51 | }; 52 | 53 | module.exports = function(grunt) { 54 | grunt.registerMultiTask('htmlangular', 'An HTML5 validator aimed at AngularJS projects.', function() { 55 | // Merge task-specific and/or target-specific options with these defaults. 56 | var options = this.options({ 57 | angular: true, 58 | customtags: [], 59 | customattrs: [], 60 | wrapping: {}, 61 | relaxerror: [], 62 | tmplext: 'tmpl.html', 63 | doctype: 'HTML5', 64 | charset: 'utf-8', 65 | reportpath: 'html-angular-validate-report.json', 66 | reportCheckstylePath: 'html-angular-validate-report-checkstyle.xml', 67 | w3clocal: null, 68 | w3cproxy: null, 69 | concurrentJobs: 1, 70 | maxvalidateattempts: 3 71 | }); 72 | options.concurrentjobs = options.concurrentJobs; 73 | 74 | // Delete existing reports if present 75 | if (options.reportpath !== null && grunt.file.exists(options.reportpath)) { 76 | grunt.file.delete(options.reportpath); 77 | } 78 | if (options.reportCheckstylePath !== null && grunt.file.exists(options.reportCheckstylePath)) { 79 | grunt.file.delete(options.reportCheckstylePath); 80 | } 81 | 82 | // Force task into async mode and grab a handle to the "done" function. 83 | var done = this.async(); 84 | 85 | // Run the validation plug in 86 | validate.validate(this.filesSrc, options).then(function(result) { 87 | // Finished, let user and grunt know how it went 88 | if (result.allpassed) { 89 | // No errors to output - task success 90 | grunt.log.oklns(result.filessucceeded + ' files passed validation'); 91 | done(); 92 | } else { 93 | // Output failures - task failure 94 | for (var i = 0; i < result.failed.length; i += 1) { 95 | writeFileErrors(grunt, result.failed[i]); 96 | } 97 | 98 | // Finalize output and send control back to grunt 99 | grunt.fail.warn('HTML validation failed'); 100 | done(false); 101 | } 102 | }, function(err) { 103 | // Validator failure - task failure 104 | grunt.log.errorlns('Unable to perform validation'); 105 | grunt.log.errorlns('html-angular-validate error: ' + err); 106 | done(false); 107 | }); 108 | }); 109 | }; 110 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-html-angular-validate 3 | * https://github.com/nikestep/grunt-html-angular-validate 4 | * 5 | * Copyright (c) 2014 Nik Estep 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | module.exports = function(grunt) { 12 | 13 | // Project configuration. 14 | grunt.initConfig({ 15 | jshint: { 16 | all: [ 17 | 'Gruntfile.js', 18 | 'tasks/*.js', 19 | '<%= nodeunit.all %>', 20 | ], 21 | options: { 22 | jshintrc: '.jshintrc', 23 | }, 24 | }, 25 | 26 | // Before generating any new files, remove any previously-created files. 27 | clean: { 28 | tests: ['tmp'], 29 | }, 30 | 31 | // Configurations to be run (and then tested). 32 | htmlangular: { 33 | default_options: { 34 | options: { 35 | customtags: ['custom-tag', 'custom-*'], 36 | customattrs: ['fixed-div-label', 'custom-*'], 37 | wrapping: { 38 | 'tr': '{0}
' 39 | } 40 | }, 41 | files: { 42 | src: ['test/html/valid/**/*.html'] 43 | } 44 | }, 45 | default_options_concurrent: { 46 | options: { 47 | customtags: ['custom-tag', 'custom-*'], 48 | customattrs: ['fixed-div-label', 'custom-*'], 49 | wrapping: { 50 | 'tr': '{0}
' 51 | }, 52 | concurrentJobs: 4 53 | }, 54 | files: { 55 | src: ['test/html/valid/**/*.html'] 56 | } 57 | }, 58 | missing_wrapping: { 59 | options: { 60 | }, 61 | files: { 62 | src: ['test/html/valid/template/valid_angular_table_row.tmpl.html'] 63 | } 64 | }, 65 | missing_custom_tags: { 66 | options: { 67 | }, 68 | files: { 69 | src: ['test/html/valid/full/valid_angular.html'] 70 | } 71 | }, 72 | missing_custom_attrs: { 73 | options: { 74 | }, 75 | files: { 76 | src: ['test/html/valid/template/valid_angular.tmpl.html'] 77 | } 78 | }, 79 | template_missing_extension: { 80 | options: { 81 | }, 82 | files: { 83 | src: ['test/html/invalid/template_missing_extension.html'] 84 | } 85 | }, 86 | missing_closing_tag: { 87 | options: { 88 | }, 89 | files: { 90 | src: ['test/html/invalid/missing_closing_tag.tmpl.html'] 91 | } 92 | }, 93 | improperly_closed_tag: { 94 | options: { 95 | }, 96 | files: { 97 | src: ['test/html/invalid/improperly_closed_tag.tmpl.html'] 98 | } 99 | }, 100 | improperly_nested_tags: { 101 | options: { 102 | }, 103 | files: { 104 | src: ['test/html/invalid/improperly_nested_tags.tmpl.html'] 105 | } 106 | }, 107 | improper_angular_operator_relaxed: { 108 | options: { 109 | relaxerror: [ 110 | '“&” did not start a character reference. (“&” probably should have been escaped as “&”.)' 111 | ], 112 | }, 113 | files: { 114 | src: ['test/html/invalid/improper_angular_operator.tmpl.html'] 115 | } 116 | } 117 | }, 118 | 119 | // Unit tests. 120 | nodeunit: { 121 | all: ['test/*_test.js'], 122 | }, 123 | 124 | }); 125 | 126 | // Actually load this plugin's task(s). 127 | grunt.loadTasks('tasks'); 128 | 129 | // These plugins provide necessary tasks. 130 | grunt.loadNpmTasks('grunt-contrib-jshint'); 131 | grunt.loadNpmTasks('grunt-contrib-clean'); 132 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 133 | 134 | // Whenever the "test" task is run, first clean the "tmp" dir, then run this 135 | // plugin's task(s), then test the result. 136 | grunt.registerTask('test', ['clean', 'nodeunit:all']); 137 | 138 | // By default, lint and run all tests. 139 | grunt.registerTask('default', ['clean', 'jshint', 'test']); 140 | 141 | }; 142 | -------------------------------------------------------------------------------- /test/htmlangular_test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* 4 | ======== A Handy Little Nodeunit Reference ======== 5 | https://github.com/caolan/nodeunit 6 | 7 | Test methods: 8 | test.expect(numAssertions) 9 | test.done() 10 | Test assertions: 11 | test.ok(value, [message]) 12 | test.equal(actual, expected, [message]) 13 | test.notEqual(actual, expected, [message]) 14 | test.deepEqual(actual, expected, [message]) 15 | test.notDeepEqual(actual, expected, [message]) 16 | test.strictEqual(actual, expected, [message]) 17 | test.notStrictEqual(actual, expected, [message]) 18 | test.throws(block, [error], [message]) 19 | test.doesNotThrow(block, [error], [message]) 20 | test.ifError(value) 21 | */ 22 | 23 | var 24 | path = require('path'), 25 | exec = require('child_process').exec, 26 | execOptions = { 27 | cwd: path.join(__dirname, '..') 28 | } 29 | ; 30 | 31 | exports.tests = { 32 | default_options: function(test) { 33 | test.expect(1); 34 | exec('grunt htmlangular:default_options', execOptions, function(error, stdout) { 35 | test.equal( 36 | stdout.indexOf('6 files passed validation') > -1, 37 | true, 38 | 'valid files pass' 39 | ); 40 | test.done(); 41 | }); 42 | }, 43 | default_options_concurrent: function(test) { 44 | test.expect(1); 45 | exec('grunt htmlangular:default_options_concurrent', execOptions, function(error, stdout) { 46 | test.equal( 47 | stdout.indexOf('6 files passed validation') > -1, 48 | true, 49 | 'valid files pass' 50 | ); 51 | test.done(); 52 | }); 53 | }, 54 | missing_wrapping: function(test) { 55 | test.expect(4); 56 | exec('grunt htmlangular:missing_wrapping', execOptions, function(error, stdout) { 57 | test.equal( 58 | stdout.indexOf('Stray start tag “tr”') > -1, 59 | true, 60 | 'found unwrapped starting ' 61 | ); 62 | test.equal( 63 | stdout.indexOf('Stray start tag “td”') > -1, 64 | true, 65 | 'found unwrapped starting ' 66 | ); 67 | test.equal( 68 | stdout.indexOf('Stray end tag “td”') > -1, 69 | true, 70 | 'found unwrapped starting ' 71 | ); 72 | test.equal( 73 | stdout.indexOf('Stray end tag “tr”') > -1, 74 | true, 75 | 'found unwrapped starting ' 76 | ); 77 | test.done(); 78 | }); 79 | }, 80 | /*missing_custom_tags: function(test) { 81 | test.expect(1); 82 | exec('grunt htmlangular:missing_custom_tags', execOptions, function(error, stdout) { 83 | test.equal( 84 | stdout.indexOf('Element “custom-tag” not allowed as child') > -1, 85 | true, 86 | 'found custom tag' 87 | ); 88 | test.done(); 89 | }); 90 | },*/ 91 | missing_custom_attrs: function(test) { 92 | test.expect(1); 93 | exec('grunt htmlangular:missing_custom_attrs', execOptions, function(error, stdout) { 94 | test.equal( 95 | stdout.indexOf('Attribute “fixed-div-label” not allowed on element') > -1, 96 | true, 97 | 'found custom attribute' 98 | ); 99 | test.done(); 100 | }); 101 | }, 102 | template_missing_extension: function(test) { 103 | test.expect(1); 104 | exec('grunt htmlangular:template_missing_extension', execOptions, function(error, stdout) { 105 | test.equal( 106 | stdout.indexOf('Element “head” is missing a required instance of child element “title”') > -1, 107 | true, 108 | 'figured out it is just template' 109 | ); 110 | test.done(); 111 | }); 112 | }, 113 | missing_closing_tag: function(test) { 114 | test.expect(1); 115 | exec('grunt htmlangular:missing_closing_tag', execOptions, function(error, stdout) { 116 | test.equal( 117 | stdout.indexOf('Unclosed element “div”') > -1, 118 | true, 119 | 'found unclosed div' 120 | ); 121 | test.done(); 122 | }); 123 | }, 124 | improperly_closed_tag: function(test) { 125 | test.expect(2); 126 | exec('grunt htmlangular:improperly_closed_tag', execOptions, function(error, stdout) { 127 | test.equal( 128 | stdout.indexOf('Self-closing syntax (“/>”) used on a non-void HTML element') > -1, 129 | true, 130 | 'found self-closed span' 131 | ); 132 | test.equal( 133 | stdout.indexOf('Unclosed element “span”') > -1, 134 | true, 135 | 'found unclosed span' 136 | ); 137 | test.done(); 138 | }); 139 | }, 140 | improperly_nested_tags: function(test) { 141 | test.expect(2); 142 | exec('grunt htmlangular:improperly_nested_tags', execOptions, function(error, stdout) { 143 | test.equal( 144 | stdout.indexOf('End tag “b” violates nesting rules') > -1, 145 | true, 146 | 'found closed too early' 147 | ); 148 | test.equal( 149 | stdout.indexOf('No “i” element in scope but a “i” end tag seen') > -1, 150 | true, 151 | 'found closed too late' 152 | ); 153 | test.done(); 154 | }); 155 | }, 156 | improper_angular_operator_relaxed: function(test) { 157 | test.expect(1); 158 | exec('grunt htmlangular:improper_angular_operator_relaxed', execOptions, function(error, stdout) { 159 | test.equal( 160 | stdout.indexOf('“&” did not start a character reference. (“&” probably should have been escaped as “&”.)') === -1, 161 | true, 162 | 'relaxed ignored error' 163 | ); 164 | test.done(); 165 | }); 166 | } 167 | }; 168 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # grunt-html-angular-validate 2 | [![Build Status](https://travis-ci.org/nikestep/grunt-html-angular-validate.svg?branch=master)](https://travis-ci.org/nikestep/grunt-html-angular-validate) [![Dependency Status](https://david-dm.org/nikestep/grunt-html-angular-validate.svg)](https://david-dm.org/nikestep/grunt-html-angular-validate) [![devDependency Status](https://david-dm.org/nikestep/grunt-html-angular-validate/dev-status.svg)](https://david-dm.org/nikestep/grunt-html-angular-validate#info=devDependencies) 3 | [![npm Downloads Count](https://img.shields.io/npm/dm/grunt-html-angular-validate.svg)](https://github.com/nikestep/grunt-html-angular-validate) 4 | 5 | > An HTML validator aimed at AngularJS projects. 6 | 7 | While there are other Grunt plugins that will validate HTML files, there are lacking a couple important features: 8 | 9 | * Support for AngularJS attributes and tags (both from AngularJS and custom created) 10 | * Support for templated/fragmented HTML files 11 | * Ability to concurrently validate files for greatly increased speed 12 | 13 | This plugin looks to solve these problems and provide the value that comes with having HTML validation in the build chain. 14 | 15 | Please note that this plugin works with the [w3cjs](https://github.com/thomasdavis/w3cjs) node plugin and will send files to be validated 16 | against the W3C online validator tool. W3C asks that you be considerate of their free validator service and they will block your IP if 17 | your traffic is deemed "excessive" by their servers. Such a block will automatically clear once the traffic subsides, but if your 18 | project is large enough, you may need to run your own local W3C validator server. A guide for how to do this can be found 19 | [here](https://github.com/tlvince/w3c-validator-guide). See the options below for pointing this plugin to a local validator service. 20 | 21 | ## v0.5.0 Upgrade Notes 22 | Version 0.4.2 has been published as a stop-gap between versions 0.4.1 and 0.5.0. You may use this version to maintain v0.4.1-style 23 | comptability; however, there is no guarantee that W3C will continue to support the validation path used here. 24 | 25 | If you are upgrading to use v0.5.0, there are a couple of things you should keep in mind. The warning messages have changed slightly 26 | as a result of changes in other packages used by this plugin. You may find that existing excluded messages no longer work and you'll 27 | need to update your gruntfile. 28 | 29 | If you are using a local version of the w3c validator, upgrading may cause an incompatibility. You should investigate this and also 30 | upgrading your local validator before commiting the upgrade to your project. 31 | 32 | ## Getting Started 33 | This plugin requires Grunt `~1.0.1` 34 | 35 | If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) 36 | guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once 37 | you're familiar with that process, you may install this plugin with this command: 38 | 39 | ```shell 40 | npm install grunt-html-angular-validate --save-dev 41 | ``` 42 | 43 | Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: 44 | 45 | ```js 46 | grunt.loadNpmTasks('grunt-html-angular-validate'); 47 | ``` 48 | 49 | ## The "htmlangular" task 50 | 51 | ### Overview 52 | In your project's Gruntfile, add a section named `htmlangular` to the data object passed into `grunt.initConfig()`. 53 | 54 | ```js 55 | grunt.initConfig({ 56 | htmlangular: { 57 | options: { 58 | // Task-specific options go here. 59 | }, 60 | your_target: { 61 | // Target-specific file lists and/or options go here. 62 | }, 63 | }, 64 | }); 65 | ``` 66 | 67 | ### Options 68 | 69 | #### options.angular 70 | Type: `Boolean` 71 | Default value: `true` 72 | 73 | Turns on ignoring of validation errors that are caused by AngularJS. 74 | 75 | #### options.customtags 76 | Type: `Array` 77 | Default value: `[]` 78 | 79 | List all of the custom tags you have created through directives and other means here. The validator will ignore warnings about these tags. 80 | 81 | You can use the `'*'` wildcard, e.g.: `'custom-tags-*'` 82 | 83 | #### options.customattrs 84 | Type: `Array` 85 | Default value: `[]` 86 | 87 | List all of the custom attributes you have created through directives and other means here. The validator will ignore warnings about 88 | these attributes. 89 | 90 | You can use the `*` wildcard, e.g.: `'custom-attrs-*'` 91 | 92 | #### options.wrapping 93 | Type: `Object` 94 | Default value: `{}` 95 | 96 | Not all Angular templates start with tags that can be wrapped directly within the `` tag. For templates like this, they first need 97 | to be wrapped before the regular full-document wrapping that the plugin performs. As an example, a template for a row in a table might 98 | look like this: 99 | 100 | 101 | {name} 102 | {birthdate} 103 | {address} 104 | 105 | 106 | The entry into the `options.wrapping` plugin option would look like this: 107 | 108 | wrapping: { 109 | 'tr': '{0}
' 110 | } 111 | 112 | The content of the template will be placed within the `{0}` and then the whole block will be wrapped like other templates. Note that the 113 | name of the tag should not be wrapped with `<` and `>`. 114 | 115 | #### options.relaxerror 116 | Type: `Array` 117 | Default value: `[]` 118 | 119 | List the error strings you want explicitly ignored by the validator. 120 | 121 | #### options.tmplext 122 | Type: `String` 123 | Default value: `tmpl.html` 124 | 125 | The extension of HTML files that are templated or otherwise not complete and valid HTML files (i.e. do not start and end with ``). The validator will wrap these files as complete HTML pages for validation. 126 | 127 | #### options.doctype 128 | Type: `String` 129 | Default value: `HTML5` 130 | 131 | The doctype to use when validating HTML files. Set to `false` to have the validator auto-detect the doctype. 132 | 133 | #### options.charset 134 | Type: `String` 135 | Default value: `utf-8` 136 | 137 | The charset to use when validating HTML files. Set to `false` to have the validator auto-detect the charset. 138 | 139 | #### options.reportpath 140 | Type: `String` 141 | Default value: `html-angular-validate-report.json` 142 | 143 | The path to write a JSON report of validation and linting output to after completion. Set to `null` to not create this file. 144 | 145 | ### reportCheckstylePath 146 | Type: `String` 147 | Default value: `html-angular-validate-report-checkstyle.xml` 148 | 149 | The path to write a checkstyle compatible xml report of validation and linting output to after completion. Set to `null` to not create this file. 150 | 151 | #### options.w3clocal 152 | Type: `String` 153 | Default value: `null` 154 | 155 | Use this when running a local instance of the W3C validator service (e.g. `http://localhost:8080`). Do not use in conjunction with 156 | `options.w3cproxy`. 157 | 158 | #### options.w3cproxy 159 | Type: `String` 160 | Default value: `null` 161 | 162 | The proxy to the W3C validator service. Use this as an alternative when running a local instance of the W3C validator service 163 | (e.g. `http://localhost:8080`). Do not use in conjunction with `options.w3clocal`. 164 | 165 | #### options.concurrentJobs 166 | Type: `Integer` 167 | Default value: `1` 168 | 169 | The maximum number of validation jobs to run concurrently. Using a number greater than `1` can greatly increase validation speed 170 | with many files, especially when running a local validation server. 171 | 172 | This should only be used when you have your own validation server. W3C will shut you down much faster if you run concurrent 173 | requests against them. 174 | 175 | #### maxvalidateattempts 176 | Type: `Integer` 177 | Default value: `3` 178 | 179 | The maxinum number of attempts to validate a single file. Retries will be triggered if an error occurs during file validation and no 180 | result is retrieved. This is not the same as validation completing and the result having errors. Instead the aim is to guard against 181 | a flaky validator server. 182 | 183 | ### Usage Examples 184 | 185 | #### Default Options 186 | In this example, the default options are used to do something with whatever. So if the `testing` file has the content `Testing` and the `123` file had the content `1 2 3`, the generated result would be `Testing, 1 2 3.` 187 | 188 | ```js 189 | grunt.initConfig({ 190 | htmlangular: { 191 | options: { 192 | tmplext: 'html.tmpl', 193 | customtags: [ 194 | 'top-nav', 195 | 'left-bar', 196 | 'right-bar', 197 | 'client-footer' 198 | ], 199 | customattrs: [ 200 | 'fixed-width-box', 201 | 'video-box' 202 | ], 203 | relaxerror: [ 204 | 'The frameborder attribute on the iframe element is obsolete. Use CSS instead.' 205 | ], 206 | reportpath: 'target/html-angular-validate-report.json' 207 | }, 208 | files: { 209 | src: ['src/www/**/*.html', 'src/www/**/*.html.tmpl'] 210 | } 211 | } 212 | }); 213 | ``` 214 | 215 | ## Contributing 216 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/). 217 | 218 | Before submitting a pull request, please run the tests to make sure you did not break any existing functionality: 219 | 220 | ```shell 221 | grunt test 222 | ``` 223 | 224 | ## Release History 225 | * 2018-02-03 v0.6.1 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 226 | * 2018-01-09 v0.6.0 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) and updating Node versions 227 | * 2017-08-06 v0.5.9 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 228 | * 2016-05-14 v0.5.8 Fixed #35 229 | * 2015-11-09 v0.5.7 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 230 | * 2015-11-09 v0.5.6 Accidental unchanged version 231 | * 2015-11-09 v0.5.5 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 232 | * 2015-10-31 v0.5.4 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 233 | * 2015-09-24 v0.5.3 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 234 | * 2015-08-28 v0.5.2 Updating version of [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) 235 | * 2015-08-09 v0.5.1 Switched to using [html-angular-validate](https://www.npmjs.com/package/html-angular-validate) npm package 236 | * 2015-06-16 v0.4.2 Patched v0.4.1 to continue working in liu of upgrading v0.5.0 (code not in repository - see #23) 237 | * 2015-06-15 v0.5.0 Fixed #22 (using new w3c validator) 238 | * 2015-03-26 v0.4.1 Fixed #17 239 | * 2014-08-08 v0.4.0 Pulled in #9 (concurrency introduced) 240 | * 2014-08-04 v0.3.5 Pulled in #7 and #8, dropped support for NodeJS 0.8 241 | * 2014-04-26 v0.3.0 Fixed #4, Fixed #5, created unit tests 242 | * 2014-02-04 v0.2.3 Fixed #2, fixed silly push mistake, add ui-* to default angular tags/attrs 243 | * 2014-02-04 v0.2.2 Fixed #1 and added W3C proxy option 244 | * 2014-01-27 v0.2.1 Renamed project 245 | * 2014-01-12 v0.2.0 Increased recognition of AngularJS caused validation erros 246 | * 2014-01-11 v0.1.0 Initial release 247 | --------------------------------------------------------------------------------