├── .editorconfig ├── .fecsrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── htmlcs ├── browser.js ├── index.js ├── lib ├── cli │ ├── format.js │ ├── helper.js │ ├── hint.js │ └── index.js ├── config.js ├── default │ ├── htmlcsrc │ └── rule-map.json ├── element.js ├── fs-util.js ├── htmlcs.js ├── node.js ├── other-formatter.js ├── parse.js ├── reporter.js ├── rules.js ├── rules │ ├── asset-type.js │ ├── attr-lowercase.js │ ├── attr-no-duplication.js │ ├── attr-value-double-quotes.js │ ├── bool-attribute-value.js │ ├── button-name.js │ ├── button-type.js │ ├── charset.js │ ├── css-in-head.js │ ├── doctype.js │ ├── html-lang.js │ ├── id-class-ad-disabled.js │ ├── ie-edge.js │ ├── img-alt.js │ ├── img-src.js │ ├── img-title.js │ ├── img-width-height.js │ ├── indent-char.js │ ├── label-for-input.js │ ├── lowercase-class-with-hyphen.js │ ├── lowercase-id-with-hyphen.js │ ├── max-len.js │ ├── multiple-stylesheets.js │ ├── nest.js │ ├── new-line-for-blocks.js │ ├── no-bom.js │ ├── no-duplication-id-and-name.js │ ├── no-hook-class.js │ ├── no-meta-css.js │ ├── no-space-before-tag-end.js │ ├── protocol-omitted-in-href.js │ ├── rel-stylesheet.js │ ├── script-content.js │ ├── script-in-tail.js │ ├── self-close.js │ ├── spec-char-escape.js │ ├── style-content.js │ ├── style-disabled.js │ ├── tag-pair.js │ ├── tagname-lowercase.js │ ├── title-required.js │ ├── unique-id.js │ ├── unnecessary-whitespace-in-text.js │ └── viewport.js └── util.js ├── package.json └── test ├── config-in-comment ├── .htmlcsrc ├── case1.html ├── case10.html ├── case11.html ├── case2.html ├── case3.html ├── case4.html ├── case5.html ├── case6.html ├── case7.html ├── case8.html ├── case9.html └── test.spec.js ├── fixture └── all.html ├── lib ├── config.spec.js ├── element.spec.js ├── fs-util.spec.js ├── htmlcs.spec.js ├── node.spec.js ├── other-formatter.spec.js ├── parse.spec.js ├── reporter.spec.js ├── rules.spec.js ├── rules │ ├── asset-type │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── attr-lowercase │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── attr-no-duplication │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── attr-value-double-quotes │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── bool-attribute-value │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── button-name │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── button-type │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── charset │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ ├── case4.html │ │ ├── case5.html │ │ ├── case6.html │ │ └── test.spec.js │ ├── css-in-head │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── doctype │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ ├── case4.html │ │ └── test.spec.js │ ├── html-lang │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ └── test.spec.js │ ├── id-class-ad-disabled │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ └── test.spec.js │ ├── ie-edge │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ ├── case4.html │ │ ├── case5.html │ │ └── test.spec.js │ ├── img-alt │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── img-src │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── img-title │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── img-width-height │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── indent-char │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ ├── case4.html │ │ ├── case5.html │ │ └── test.spec.js │ ├── label-for-input │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── lowercase-class-with-hyphen │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── lowercase-id-with-hyphen │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── max-len │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── multiple-stylesheets │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── nest │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── new-line-for-blocks │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── no-bom │ │ ├── .htmlcsrc │ │ ├── case-no-bom.html │ │ ├── case-with-bom.html │ │ └── test.spec.js │ ├── no-duplication-id-and-name │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── no-hook-class │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── no-meta-css │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── no-space-before-tag-end │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── protocol-omitted-in-href │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── rel-stylesheet │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── script-content │ │ ├── case.html │ │ └── test.spec.js │ ├── script-in-tail │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── self-close │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ └── test.spec.js │ ├── spec-char-escape │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── style-content │ │ ├── case.html │ │ └── test.spec.js │ ├── style-disabled │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── tag-pair │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── tagname-lowercase │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── title-required │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ ├── case4.html │ │ ├── case5.html │ │ ├── case6.html │ │ ├── case7.html │ │ ├── case8.html │ │ └── test.spec.js │ ├── unique-id │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ ├── unnecessary-trailing-whitespace-in-text │ │ ├── .htmlcsrc │ │ ├── case.html │ │ └── test.spec.js │ └── viewport │ │ ├── .htmlcsrc │ │ ├── case1.html │ │ ├── case2.html │ │ ├── case3.html │ │ ├── case4.html │ │ └── test.spec.js └── util.spec.js └── max-error ├── .htmlcsrc ├── case.html └── test.spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.fecsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "lib", 4 | "cli", 5 | "test/**/*.spec.js" 6 | ], 7 | 8 | "eslint": { 9 | "env": { 10 | "node": true, 11 | "browser": false 12 | }, 13 | 14 | "rules": { 15 | "no-console": 0 16 | } 17 | }, 18 | 19 | "csshint": { 20 | 21 | }, 22 | 23 | "htmlcs": { 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | .editorconfig 3 | .fecsrc 4 | .gitignore 5 | .travis.yml 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4" 4 | - "5" 5 | - "6" 6 | after_script: 7 | - npm run coveralls 8 | sudo: false 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Baidu EFE team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/htmlcs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var yargs = require('yargs'); 4 | var cli = require('../lib/cli'); 5 | 6 | // usage, version & help info 7 | yargs = yargs 8 | .usage('Usage: $0 [options] [target...]') 9 | .version(require('../package.json').version).alias('v', 'version') 10 | .help('h').alias('h', 'help'); 11 | 12 | // commands 13 | cli.commands.forEach(function (command) { 14 | yargs = yargs.command(command.name, command.describe); 15 | command.examples.forEach(function (example) { 16 | yargs = yargs.example(example[0], example[1]); 17 | }); 18 | }); 19 | 20 | // options 21 | cli.options.forEach(function (option) { 22 | yargs = yargs.option(option.name, option); 23 | }); 24 | 25 | var argv = yargs.argv._ || []; 26 | 27 | // command name 28 | var commandName = argv[0]; 29 | if (!commandName) { 30 | cli.helper.dealError('Command is required.'); 31 | } 32 | 33 | // command 34 | var command = cli.commands.filter(function (item) { 35 | return item.name == commandName; 36 | })[0]; 37 | if (!command) { 38 | cli.helper.dealError('Unknown command: "' + commandName + '".'); 39 | } 40 | 41 | // targets 42 | var targets = argv.slice(1); 43 | if (!targets.length) { 44 | console.log('Warn: Target is not specified, use "./" as default.\n'); 45 | targets.push('./'); 46 | } 47 | 48 | // target files 49 | var targetFiles = cli.helper.getTargetFiles(targets); 50 | if (!targetFiles.length) { 51 | cli.helper.dealError('No matched file found.'); 52 | } 53 | 54 | // execute command 55 | command.handler(yargs.argv, targetFiles); 56 | -------------------------------------------------------------------------------- /browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main file for browser 3 | * @author nighca 4 | */ 5 | 6 | var htmlcs = require('./lib/htmlcs'); 7 | 8 | var notSupported = function () { 9 | throw new Error('Sorry, this method is not supported in browser.') 10 | }; 11 | 12 | module.exports = { 13 | addRule: htmlcs.addRule, 14 | 15 | hint: htmlcs.hint, 16 | format: htmlcs.format, 17 | 18 | hintFile: notSupported, 19 | formatFile: notSupported 20 | }; 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main file 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | 8 | var config = require('./lib/config'); 9 | var htmlcs = require('./lib/htmlcs'); 10 | 11 | /** 12 | * Do hint with given filePath & option for readFile. 13 | * 14 | * @param {string} filePath - path of the target file 15 | * @param {Object=} options - option for readFile 16 | * @return {Report[]} the hint result, list of reports 17 | */ 18 | var hintFile = function (filePath, options) { 19 | options = options || { 20 | encoding: 'utf-8' 21 | }; 22 | 23 | var cnt = fs.readFileSync(filePath, options); 24 | var cfg = config.load(filePath); 25 | 26 | return htmlcs.hint(cnt, cfg); 27 | }; 28 | 29 | /** 30 | * Do format with given filePath & option for readFile 31 | * 32 | * @param {string} filePath - path of the target file 33 | * @param {Object=} options - option for readFile 34 | * @return {string} the formatted code 35 | */ 36 | var formatFile = function (filePath, options) { 37 | options = options || { 38 | encoding: 'utf-8' 39 | }; 40 | 41 | var cnt = fs.readFileSync(filePath, options); 42 | var cfg = config.load(filePath); 43 | 44 | return htmlcs.format(cnt, cfg); 45 | }; 46 | 47 | module.exports = { 48 | addRule: htmlcs.addRule, 49 | 50 | hint: htmlcs.hint, 51 | hintAsync: htmlcs.hintAsync, 52 | format: htmlcs.format, 53 | formatAsync: htmlcs.formatAsync, 54 | 55 | hintFile: hintFile, 56 | formatFile: formatFile 57 | }; 58 | -------------------------------------------------------------------------------- /lib/cli/format.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file command: format 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var differ = require('differ-cli/lib/differ'); 8 | var helper = require('./helper'); 9 | var htmlcs = require('../../'); 10 | 11 | module.exports = { 12 | name: 'format', 13 | describe: 'Do format given file(s)', 14 | examples: [ 15 | ['$0 format foo.html', 'do format foo.html'], 16 | ['$0 format --diff foo.html', 'do format foo.html & show diff result'], 17 | ['$0 format --in-place foo.html', 'do format foo.html & write file in place'] 18 | ], 19 | 20 | handler: function (options, targetFiles) { 21 | // format directly 22 | var format = htmlcs.formatFile; 23 | 24 | // specified config 25 | if (options.config) { 26 | var config = helper.loadSpecifiedConfig(options.config); 27 | // format with specified config 28 | format = function (filePath) { 29 | return htmlcs.format(helper.readFile(filePath), config); 30 | }; 31 | } 32 | 33 | targetFiles.forEach(function (filePath) { 34 | var result = format(filePath); 35 | 36 | if (options.diff) { 37 | console.log( 38 | filePath 39 | + ':' 40 | + differ(helper.readFile(filePath), result) 41 | ); 42 | return; 43 | } 44 | 45 | if (options['in-place']) { 46 | fs.writeFileSync(filePath, result); 47 | console.log('√', filePath); 48 | return; 49 | } 50 | 51 | console.log(result); 52 | }); 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /lib/cli/helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file helpers for cli operation 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | var walk = require('walk'); 9 | var yargs = require('yargs'); 10 | var config = require('../config'); 11 | 12 | /** 13 | * Deal with error & exit. 14 | * 15 | * @param {string} msg - error message 16 | */ 17 | var dealError = function (msg) { 18 | console.log('Error: ' + msg + '\n'); 19 | yargs.showHelp(); 20 | process.exit(1); 21 | }; 22 | 23 | /** 24 | * Read file. 25 | * 26 | * @param {string} filePath - path of given file 27 | * @return {string} file content 28 | */ 29 | var readFile = function (filePath) { 30 | return fs.readFileSync(filePath, {encoding: 'utf-8'}); 31 | }; 32 | 33 | /** 34 | * Load content of specified config file. 35 | * 36 | * @param {string} configFilePath - path of specified config file 37 | * @return {?Object} the config content 38 | */ 39 | var loadSpecifiedConfig = function (configFilePath) { 40 | try { 41 | return config.parse(readFile(configFilePath)); 42 | } 43 | catch (e) { 44 | dealError('Load config (' + configFilePath + ') failed: ' + e.message); 45 | } 46 | }; 47 | 48 | var HTML_EXT_PATTERN = /\.html?$/; 49 | 50 | /** 51 | * Get target files with given targets (file / directory path). 52 | * 53 | * @param {Array} targets - list of given targets 54 | * @return {Array} list of target files' path 55 | */ 56 | var getTargetFiles = function (targets) { 57 | return targets.reduce(function (files, target) { 58 | var stat = fs.statSync(target); 59 | 60 | if (stat.isFile()) { 61 | files.push(target); 62 | return files; 63 | } 64 | 65 | if (stat.isDirectory()) { 66 | walk.walkSync(target, { 67 | followLinks: false, 68 | filters: ['node_modules', 'bower_components', 'Temp', '_Temp'], 69 | listeners: { 70 | file: function (root, fileStat, next) { 71 | var filePath = path.join(root, fileStat.name); 72 | 73 | // filter with suffix (.html) 74 | if (HTML_EXT_PATTERN.test(filePath)) { 75 | files.push(filePath); 76 | } 77 | next(); 78 | } 79 | } 80 | }); 81 | return files; 82 | } 83 | }, []); 84 | }; 85 | 86 | module.exports = { 87 | dealError: dealError, 88 | readFile: readFile, 89 | loadSpecifiedConfig: loadSpecifiedConfig, 90 | getTargetFiles: getTargetFiles 91 | }; 92 | -------------------------------------------------------------------------------- /lib/cli/hint.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file command: hint 3 | * @author nighca 4 | */ 5 | 6 | var helper = require('./helper'); 7 | var htmlcs = require('../../'); 8 | 9 | module.exports = { 10 | name: 'hint', 11 | describe: 'Do hint given file(s)', 12 | examples: [ 13 | ['$0 hint foo.html', 'do hint foo.html'], 14 | ['$0 hint foo.html bar.html', 'do hint foo.html & bar.html'], 15 | ['$0 hint ./', 'do hint html files under ./'] 16 | ], 17 | 18 | handler: function (options, targetFiles) { 19 | // hint directly 20 | var hint = htmlcs.hintFile; 21 | 22 | // specified config 23 | if (options.config) { 24 | var config = helper.loadSpecifiedConfig(options.config); 25 | // hint with specified config 26 | hint = function (filePath) { 27 | return htmlcs.hint(helper.readFile(filePath), config); 28 | }; 29 | } 30 | 31 | var hasError = false; 32 | 33 | targetFiles.forEach(function (filePath) { 34 | var result = hint(filePath); 35 | 36 | console.log(filePath + ':'); 37 | 38 | if (result.length) { 39 | hasError = true; 40 | 41 | result.forEach(function (item) { 42 | console.log( 43 | '[%s] line %d, column %d: %s (%s, %s)', 44 | item.type, 45 | item.line, 46 | item.column, 47 | item.message, 48 | item.rule, 49 | item.code 50 | ); 51 | }); 52 | } 53 | else { 54 | console.log('No hint result.'); 55 | } 56 | 57 | console.log(''); 58 | }); 59 | 60 | if (hasError) { 61 | process.exit(1); 62 | } 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /lib/cli/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cli methods 3 | * @author nighca 4 | */ 5 | 6 | module.exports = { 7 | 8 | commands: [ 9 | require('./hint'), 10 | require('./format') 11 | ], 12 | 13 | options: [ 14 | { 15 | name: 'c', 16 | alias: 'config', 17 | describe: 'Path to custom configuration file.', 18 | type: 'string' 19 | }, 20 | { 21 | name: 'diff', 22 | describe: 'Check code style and output char diff.', 23 | type: 'boolean' 24 | }, 25 | { 26 | name: 'i', 27 | alias: 'in-place', 28 | describe: 'Edit input files in place; use with care!', 29 | type: 'boolean' 30 | } 31 | ], 32 | 33 | helper: require('./helper') 34 | }; 35 | -------------------------------------------------------------------------------- /lib/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file get config 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var Manis = require('manis'); 8 | 9 | var util = require('./util'); 10 | var fsUtil = require('./fs-util'); 11 | 12 | /** 13 | * Name of the config file. 14 | * 15 | * @type {string} 16 | * @const 17 | */ 18 | var CONFIG_FILENAME = '.htmlcsrc'; 19 | 20 | /** 21 | * Parse given config text content. 22 | * 23 | * @param {string} text - given config text content 24 | * @return {?Object} the config content 25 | */ 26 | var parseConfig = function (text) { 27 | return Manis.loader(text, ''); 28 | }; 29 | 30 | /** 31 | * Load config for given file. 32 | * 33 | * @param {string} filePath - path of given file 34 | * @param {boolean=} refresh - if skips cache 35 | * @return {?Object} the config content 36 | */ 37 | var loadConfig = util.cachable(function (filePath, refresh) { 38 | var options = { 39 | orphan: true 40 | }; 41 | 42 | var manis = new Manis(CONFIG_FILENAME, options); 43 | manis.setDefault(path.join(fsUtil.app.root, 'lib/default/htmlcsrc'), options); 44 | manis.setUserConfig(); 45 | 46 | return manis.from(filePath); 47 | }); 48 | 49 | module.exports = { 50 | fileName: CONFIG_FILENAME, 51 | parse: parseConfig, 52 | load: loadConfig 53 | }; 54 | -------------------------------------------------------------------------------- /lib/default/rule-map.json: -------------------------------------------------------------------------------- 1 | { 2 | "asset-type": "001,002", 3 | 4 | "attr-lowercase": "029", 5 | 6 | "attr-no-duplication": "030", 7 | 8 | "attr-value-double-quotes": "028", 9 | 10 | "bool-attribute-value": "003", 11 | 12 | "button-name": "004", 13 | 14 | "button-type": "005", 15 | 16 | "charset": "006,007", 17 | 18 | "css-in-head": "008", 19 | 20 | "doctype": "009,041", 21 | 22 | "html-lang": "010", 23 | 24 | "id-class-ad-disabled": "031", 25 | 26 | "ie-edge": "011", 27 | 28 | "img-alt": "012", 29 | 30 | "img-src": "013", 31 | 32 | "img-title": "014", 33 | 34 | "img-width-height": "015,016,017", 35 | 36 | "lowercase-class-with-hyphen": "018,019", 37 | 38 | "lowercase-id-with-hyphen": "020,021", 39 | 40 | "nest": "041,042", 41 | 42 | "rel-stylesheet": "022", 43 | 44 | "script-content": "037", 45 | 46 | "script-in-tail": "023", 47 | 48 | "indent-char": "032", 49 | 50 | "self-close": "039,040", 51 | 52 | "spec-char-escape": "033", 53 | 54 | "style-content": "038", 55 | 56 | "style-disabled": "034", 57 | 58 | "tag-pair": "035", 59 | 60 | "tagname-lowercase": "036", 61 | 62 | "title-required": "024,025", 63 | 64 | "unique-id": "026", 65 | 66 | "no-duplication-id-and-name": "043", 67 | 68 | "viewport": "027", 69 | 70 | "label-for-input": "044", 71 | 72 | "no-meta-css": "045", 73 | 74 | "no-hook-class": "047", 75 | 76 | "max-len": "048", 77 | 78 | "no-bom": "046" 79 | } 80 | -------------------------------------------------------------------------------- /lib/fs-util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fs-relative util methods 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | 9 | /** 10 | * Application (htmlcs) info. 11 | * 12 | * @type {Object} 13 | * @property {string} root - root path of application (htmlcs) code 14 | */ 15 | var app = { 16 | root: path.resolve(__dirname, '../') 17 | }; 18 | 19 | 20 | /** 21 | * Get path of home(~). 22 | * 23 | * @return {string} path of home 24 | */ 25 | var getHomePath = function () { 26 | var homePath = ''; 27 | var environment = process.env; 28 | var paths = [ 29 | environment.USERPROFILE, 30 | environment.HOME, 31 | environment.HOMEPATH, 32 | environment.HOMEDRIVE + environment.HOMEPATH 33 | ]; 34 | 35 | while (paths.length) { 36 | homePath = paths.shift(); 37 | if (fs.existsSync(homePath)) { 38 | return homePath; 39 | } 40 | } 41 | }; 42 | 43 | module.exports = { 44 | app: app, 45 | getHomePath: getHomePath 46 | }; 47 | -------------------------------------------------------------------------------- /lib/other-formatter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file formatters for non-html content (js, css) 3 | * @author nighca 4 | */ 5 | 6 | var jformatter = require('jformatter'); 7 | var cssbeautify = require('cssbeautify'); 8 | 9 | /** 10 | * 自定义formatter方法格式 11 | * 12 | * formatter 13 | * @param {string} content 标签内部的内容 14 | * @param {Node} node 标签节点 15 | * @param {Object} opt 当前format配置 16 | * @param {Object} helper 辅助方法(具体格式见下) 17 | * @return {string} format后的结果 18 | * 19 | * helper 20 | * @property {function} indent 为内容添加缩进,具体长度取决于当前节点层级及format配置(具体格式见下) 21 | * @property {function} trim 移除内容首尾的空行(无内容或仅含\s\t)(具体格式见下) 22 | * 23 | * indent 24 | * @param {string} content 原始内容 25 | * @return {string} 添加缩进后的结果 26 | * 27 | * trim 28 | * @param {string} content 原始内容 29 | * @return {string} 移除内容首尾空行后的结果 30 | */ 31 | 32 | module.exports = { 33 | 34 | script: function (content, node, opt, helper) { 35 | var type = node.getAttribute('type'); 36 | 37 | // javascript content 38 | if (!type || type === 'text/javascript') { 39 | var formatted = jformatter.format(content); 40 | 41 | // add indent 42 | content = helper.indent(formatted); 43 | } 44 | 45 | return helper.trim(content); 46 | }, 47 | 48 | style: function (content, node, opt, helper) { 49 | var formatted = cssbeautify(content); 50 | 51 | // add indent 52 | content = helper.indent(formatted); 53 | 54 | return helper.trim(content); 55 | } 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /lib/parse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file parse code 3 | * @author nighca 4 | */ 5 | 6 | var htmlparser2 = require('htmlparser2'); 7 | var Parser = htmlparser2.Parser; 8 | var DomHandler = htmlparser2.DomHandler; 9 | 10 | var util = require('./util'); 11 | var Node = require('./node'); 12 | 13 | /** 14 | * Transform node to Node instance & recursively transform its children. 15 | * 16 | * @param {Object} node - given node 17 | * @return {Node} result node 18 | */ 19 | var transformRecursively = function (node) { 20 | Node.init(node); 21 | 22 | node.childNodes.forEach(function (childNode) { 23 | transformRecursively(childNode); 24 | }); 25 | 26 | return node; 27 | }; 28 | 29 | /** 30 | * Wrap node list with . 31 | * 32 | * @param {Array} arr - node list 33 | * @return {Node} document node 34 | */ 35 | var wrapDocument = function (arr) { 36 | var document = htmlparser2.parseDOM('')[0]; 37 | 38 | document.children = arr; 39 | 40 | for (var i = 0; i < arr.length; i++) { 41 | var node = arr[i]; 42 | 43 | node.prev = arr[i - 1] || null; 44 | node.next = arr[i + 1] || null; 45 | 46 | node.root = document; 47 | node.parent = null; 48 | } 49 | 50 | transformRecursively(document); 51 | 52 | // fix startIndex missing, cause is parsed seperately 53 | document.startIndex = document.documentElement && document.documentElement.startIndex | 0; 54 | 55 | return document; 56 | }; 57 | 58 | /** 59 | * Get a HTML parser. 60 | * 61 | * @param {Object} options - options for create parser 62 | * @return {Parser} HTML parser 63 | */ 64 | var getParser = function (options) { 65 | // merge with default options 66 | options = util.extend({ 67 | lowerCaseAttributeNames: false, 68 | recognizeCDATA: true 69 | }, options); 70 | 71 | // init handler 72 | var handler = new DomHandler({ 73 | withStartIndices: true 74 | }); 75 | 76 | // init parser 77 | var parser = new Parser(handler, options); 78 | 79 | // make handler accessible 80 | parser.handler = handler; 81 | 82 | // make tokenizer emittable & accessible 83 | parser.tokenizer = util.emittable(parser._tokenizer, [ 84 | 'attribdata', 85 | 'opentagname', 86 | 'opentagend', 87 | 'selfclosingtag', 88 | 'attribname', 89 | 'attribend', 90 | 'closetag', 91 | 'declaration', 92 | 'processinginstruction', 93 | 'comment', 94 | 'cdata', 95 | 'text', 96 | 'error', 97 | 'end' 98 | ]); 99 | 100 | // make parser emittable 101 | parser = util.emittable(parser, [ 102 | 'processinginstruction', 103 | 'comment', 104 | 'commentend', 105 | 'cdatastart', 106 | 'text', 107 | 'cdataend', 108 | 'error', 109 | 'closetag', 110 | 'end', 111 | 'reset', 112 | 'parserinit', 113 | 'opentagname', 114 | 'opentag', 115 | 'attribute' 116 | ]); 117 | 118 | return parser; 119 | }; 120 | 121 | /** 122 | * Parse given html content to document node. 123 | * 124 | * @param {string} htmlCode - HTML code content 125 | * @param {Parser=} parser - given parser 126 | * @return {Node} document node 127 | */ 128 | var parse = function (htmlCode, parser) { 129 | // get parser 130 | parser = parser || getParser(); 131 | 132 | // replace "\r\n" with "\n" 133 | htmlCode = htmlCode.replace(/\r\n/g, '\n'); 134 | 135 | // do parse 136 | parser.end(htmlCode); 137 | 138 | // get dom & wrap it with 139 | var document = wrapDocument(parser.handler.dom); 140 | 141 | return document; 142 | }; 143 | 144 | parse.getParser = getParser; 145 | 146 | module.exports = parse; 147 | -------------------------------------------------------------------------------- /lib/rules/asset-type.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file rule: asset-type 3 | * @author nighca 4 | */ 5 | 6 | module.exports = { 7 | 8 | name: 'asset-type', 9 | 10 | desc: 'Default value of attribute "type" (/ 15 | 16 | 19 | 22 | 23 | 24 | 25 |

26 | i'm a p. 27 |

28 | i'm a div. 29 |
30 |

31 | 32 | 33 | there's a div in me. 34 |
i'm a div in span.
35 |
36 | 37 | aaa 38 | 39 |
40 | i'm another div. 41 |
42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /test/lib/fs-util.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for fs-relative util methods 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var util = require('../../lib/fs-util'); 8 | var packageInfo = require('../../package.json'); 9 | 10 | describe('app', function () { 11 | var app = util.app; 12 | 13 | describe('root', function () { 14 | it('should be a string', function () { 15 | expect(typeof app.root).toBe('string'); 16 | }); 17 | 18 | it('should be the dir path where package.json locates', function () { 19 | expect(require(path.join(app.root, 'package.json'))).toBe(packageInfo); 20 | }); 21 | }); 22 | }); 23 | 24 | describe('getHomePath', function () { 25 | var getHomePath = util.getHomePath; 26 | 27 | it('should return a path', function () { 28 | expect(typeof getHomePath()).toBe('string'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/lib/parse.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for parse 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | var parse = require('../../lib/parse'); 9 | 10 | var testCasePath = path.resolve(__dirname, '../fixture/all.html'); 11 | var testCase = fs.readFileSync(testCasePath, { 12 | encoding: 'utf-8' 13 | }); 14 | 15 | describe('parse', function () { 16 | var document = parse(testCase); 17 | 18 | it('should return a dom tree', function () { 19 | expect(document.nodeName).toBe('#document'); 20 | 21 | var html = document.firstElementChild; 22 | expect(html.tagName).toBe('HTML'); 23 | expect(html.firstElementChild.tagName).toBe('HEAD'); 24 | expect(html.lastElementChild.tagName).toBe('BODY'); 25 | 26 | var imgs = document.querySelectorAll('img'); 27 | expect(imgs.length).toBe(3); 28 | expect(imgs[0].id).toBe('img1'); 29 | expect(imgs[1].id).toBe('img2'); 30 | expect(imgs[2].id).toBe('img3'); 31 | }); 32 | 33 | it('should record positions', function () { 34 | var titlePos = document.querySelector('title').startIndex; 35 | expect(titlePos).toBe(61); 36 | 37 | var divPos = document.querySelector('#div').startIndex; 38 | expect(divPos).toBe(751); 39 | 40 | var img1Pos = document.querySelector('#img1').startIndex; 41 | expect(img1Pos).toBe(999); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/lib/rules.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rules 3 | * @author nighca 4 | */ 5 | 6 | var rules = require('../../lib/rules'); 7 | 8 | describe('rules', function () { 9 | describe('init', function () { 10 | 11 | it('should init correctly', function () { 12 | rules.init(); 13 | }); 14 | 15 | it('should list rules', function () { 16 | var ruleList = rules.list(); 17 | expect(Array.isArray(ruleList)).toBe(true); 18 | 19 | var parserRuleList = rules.list('parser'); 20 | expect(Array.isArray(parserRuleList)).toBe(true); 21 | 22 | for (var i = parserRuleList.length - 1; i >= 0; i--) { 23 | expect(parserRuleList[i].target).toBe('parser'); 24 | } 25 | 26 | var documentRuleList = rules.list('document'); 27 | expect(Array.isArray(documentRuleList)).toBe(true); 28 | 29 | for (var j = documentRuleList.length - 1; j >= 0; j--) { 30 | expect(documentRuleList[j].target).toBe('document'); 31 | } 32 | 33 | expect(parserRuleList.length + documentRuleList.length).toBe(ruleList.length); 34 | }); 35 | 36 | it('should add rule correctly', function () { 37 | var ruleNum = rules.list().length; 38 | var parserRuleNum = rules.list('parser').length; 39 | var documentRuleNum = rules.list('document').length; 40 | 41 | rules.add({ 42 | name: 'test', 43 | desc: 'rule for test', 44 | target: 'parser', 45 | lint: function () {} 46 | }); 47 | expect(rules.list().length).toBe(ruleNum + 1); 48 | expect(rules.list('parser').length).toBe(parserRuleNum + 1); 49 | expect(rules.list('document').length).toBe(documentRuleNum); 50 | 51 | rules.add({ 52 | name: 'test2', 53 | desc: 'another rule for test', 54 | target: 'document', 55 | lint: function () {} 56 | }); 57 | expect(rules.list().length).toBe(ruleNum + 2); 58 | expect(rules.list('parser').length).toBe(parserRuleNum + 1); 59 | expect(rules.list('document').length).toBe(documentRuleNum + 1); 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /test/lib/rules/asset-type/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "asset-type": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/asset-type/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/lib/rules/asset-type/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule asset-type 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('hint rule ' + rule, function () { 13 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 14 | 15 | it('should return right result', function () { 16 | expect(result.length).toBe(3); 17 | 18 | expect(result[0].type).toBe('WARN'); 19 | expect(result[0].code).toBe('001'); 20 | expect(result[0].line).toBe(11); 21 | expect(result[0].column).toBe(5); 22 | 23 | expect(result[1].type).toBe('WARN'); 24 | expect(result[1].code).toBe('001'); 25 | expect(result[1].line).toBe(13); 26 | expect(result[1].column).toBe(5); 27 | 28 | expect(result[2].type).toBe('WARN'); 29 | expect(result[2].code).toBe('002'); 30 | expect(result[2].line).toBe(16); 31 | expect(result[2].column).toBe(5); 32 | }); 33 | }); 34 | 35 | describe('format rule ' + rule, function () { 36 | var result = htmlcs.formatFile(path.join(__dirname, 'case.html')); 37 | 38 | var document = parse(result); 39 | 40 | var links = document.querySelectorAll('link'); 41 | var styles = document.querySelectorAll('style'); 42 | var scripts = document.querySelectorAll('script'); 43 | 44 | it('should format well', function () { 45 | expect(links[0].hasAttribute('type')).toBe(false); 46 | expect(links[1].hasAttribute('type')).toBe(false); 47 | expect(styles[0].hasAttribute('type')).toBe(false); 48 | expect(styles[1].hasAttribute('type')).toBe(false); 49 | expect(scripts[0].hasAttribute('type')).toBe(false); 50 | expect(scripts[1].getAttribute('type')).toBe('text/plain'); 51 | expect(scripts[2].hasAttribute('type')).toBe(false); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/lib/rules/attr-lowercase/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "attr-lowercase": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/attr-lowercase/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/attr-lowercase/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for attr-lowercase 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('029'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(10); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('029'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(10); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/attr-no-duplication/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "attr-no-duplication": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/attr-no-duplication/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/attr-no-duplication/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for attr-no-duplication 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('030'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(21); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('030'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(34); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/attr-value-double-quotes/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "attr-value-double-quotes": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/attr-value-double-quotes/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/lib/rules/attr-value-double-quotes/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for attr-value-double-quotes 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(6); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('028'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(14); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('028'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(14); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('028'); 29 | expect(result[2].line).toBe(13); 30 | expect(result[2].column).toBe(30); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('028'); 34 | expect(result[3].line).toBe(13); 35 | expect(result[3].column).toBe(45); 36 | 37 | expect(result[4].type).toBe('WARN'); 38 | expect(result[4].code).toBe('028'); 39 | expect(result[4].line).toBe(16); 40 | expect(result[4].column).toBe(33); 41 | 42 | expect(result[5].type).toBe('WARN'); 43 | expect(result[5].code).toBe('028'); 44 | expect(result[5].line).toBe(18); 45 | expect(result[5].column).toBe(32); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/lib/rules/bool-attribute-value/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "bool-attribute-value": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/bool-attribute-value/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/lib/rules/bool-attribute-value/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule bool-attribute-value 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(6); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('003'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('003'); 24 | expect(result[1].line).toBe(13); 25 | expect(result[1].column).toBe(5); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('003'); 29 | expect(result[2].line).toBe(15); 30 | expect(result[2].column).toBe(5); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('003'); 34 | expect(result[3].line).toBe(17); 35 | expect(result[3].column).toBe(5); 36 | 37 | expect(result[4].type).toBe('WARN'); 38 | expect(result[4].code).toBe('003'); 39 | expect(result[4].line).toBe(19); 40 | expect(result[4].column).toBe(5); 41 | 42 | expect(result[5].type).toBe('WARN'); 43 | expect(result[5].code).toBe('003'); 44 | expect(result[5].line).toBe(21); 45 | expect(result[5].column).toBe(5); 46 | }); 47 | }); 48 | 49 | describe('format rule ' + rule, function () { 50 | var result = htmlcs.formatFile(path.join(__dirname, 'case.html')); 51 | 52 | it('should format well', function () { 53 | expect(/\sasync\=/.test(result)).toBe(false); 54 | expect(/\schecked\=/.test(result)).toBe(false); 55 | expect(/\sdefer\=/.test(result)).toBe(false); 56 | expect(/\sdisabled\=/.test(result)).toBe(false); 57 | expect(/\sreadonly\=/.test(result)).toBe(false); 58 | expect(/\srequired\=/.test(result)).toBe(false); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/lib/rules/button-name/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "button-name": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/button-name/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/button-name/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule button-name 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('004'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('004'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/button-type/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "button-type": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/button-type/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/button-type/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule button-type 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('005'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('005'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/charset/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "charset": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/charset/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | standard file 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/charset/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | standard file 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/charset/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | standard file 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/charset/case4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/lib/rules/charset/case5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/charset/case6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/lib/rules/charset/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule charset 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 14 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 15 | var result3 = htmlcs.hintFile(path.join(__dirname, 'case3.html')); 16 | var result4 = htmlcs.hintFile(path.join(__dirname, 'case4.html')); 17 | var result5 = htmlcs.hintFile(path.join(__dirname, 'case5.html')); 18 | 19 | it('should return right result', function () { 20 | expect(result1.length).toBe(1); 21 | expect(result1[0].type).toBe('WARN'); 22 | expect(result1[0].code).toBe('006'); 23 | expect(result1[0].line).toBe(3); 24 | expect(result1[0].column).toBe(1); 25 | 26 | expect(result2.length).toBe(1); 27 | expect(result2[0].type).toBe('WARN'); 28 | expect(result2[0].code).toBe('007'); 29 | expect(result2[0].line).toBe(5); 30 | expect(result2[0].column).toBe(5); 31 | 32 | expect(result3.length).toBe(1); 33 | expect(result3[0].type).toBe('WARN'); 34 | expect(result3[0].code).toBe('006'); 35 | expect(result3[0].line).toBe(3); 36 | expect(result3[0].column).toBe(1); 37 | 38 | expect(result4.length).toBe(0); 39 | expect(result5.length).toBe(0); 40 | }); 41 | }); 42 | 43 | describe('format rule ' + rule, function () { 44 | var result1 = htmlcs.formatFile(path.join(__dirname, 'case1.html')); 45 | var head1 = parse(result1).querySelector('head'); 46 | var charset1 = head1.querySelector('meta[charset]'); 47 | 48 | var result2 = htmlcs.formatFile(path.join(__dirname, 'case2.html')); 49 | var head2 = parse(result2).querySelector('head'); 50 | var charset2 = head2.querySelector('meta[charset]'); 51 | 52 | var result3 = htmlcs.formatFile(path.join(__dirname, 'case3.html')); 53 | var head3 = parse(result3).querySelector('head'); 54 | var charset3 = head3.querySelector('meta[charset]'); 55 | 56 | var result5 = htmlcs.formatFile(path.join(__dirname, 'case5.html')); 57 | var head5 = parse(result5).querySelector('head'); 58 | var charset5 = head5.querySelector('meta[charset]'); 59 | 60 | var result6 = htmlcs.formatFile(path.join(__dirname, 'case6.html')); 61 | var head6 = parse(result6).querySelector('head'); 62 | var charset6 = head6.querySelector('meta[charset]'); 63 | 64 | it('should format well', function () { 65 | expect(!!charset1).toBe(true); 66 | expect(charset1 === head1.firstElementChild).toBe(true); 67 | 68 | expect(!!charset2).toBe(true); 69 | expect(charset2 === head2.firstElementChild).toBe(true); 70 | 71 | expect(!!charset3).toBe(true); 72 | expect(charset3 === head3.firstElementChild).toBe(true); 73 | 74 | expect(!!charset5).toBe(true); 75 | expect(charset5 === head5.firstElementChild).toBe(true); 76 | 77 | expect(!!charset6).toBe(true); 78 | expect(charset6 === head6.firstElementChild).toBe(true); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /test/lib/rules/css-in-head/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "css-in-head": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/css-in-head/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 14 | 15 | 16 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/lib/rules/css-in-head/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule css-in-head 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 14 | 15 | it('should return right result', function () { 16 | expect(result.length).toBe(2); 17 | 18 | expect(result[0].type).toBe('WARN'); 19 | expect(result[0].code).toBe('008'); 20 | expect(result[0].line).toBe(16); 21 | expect(result[0].column).toBe(5); 22 | 23 | expect(result[1].type).toBe('WARN'); 24 | expect(result[1].code).toBe('008'); 25 | expect(result[1].line).toBe(21); 26 | expect(result[1].column).toBe(5); 27 | }); 28 | }); 29 | 30 | describe('format rule ' + rule, function () { 31 | var result = htmlcs.formatFile(path.join(__dirname, 'case.html')); 32 | 33 | var document = parse(result); 34 | 35 | var head = document.querySelector('head'); 36 | var styles = document.querySelectorAll('link[rel="stylesheet"], style'); 37 | 38 | it('should format well', function () { 39 | for (var i = 0, l = styles.length; i < l; i++) { 40 | expect(head.contains(styles[i])).toBe(true); 41 | } 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/lib/rules/doctype/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "doctype": "upper" 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/doctype/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | standard file 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/doctype/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/doctype/case3.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | standard file 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/doctype/case4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/doctype/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule doctype 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 14 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 15 | var result3 = htmlcs.hintFile(path.join(__dirname, 'case3.html')); 16 | var result4 = htmlcs.hintFile(path.join(__dirname, 'case4.html')); 17 | 18 | it('should return right result', function () { 19 | expect(result1.length).toBe(1); 20 | 21 | expect(result1[0].type).toBe('WARN'); 22 | expect(result1[0].code).toBe('009'); 23 | expect(result1[0].line).toBe(1); 24 | expect(result1[0].column).toBe(1); 25 | 26 | expect(result2.length).toBe(0); 27 | 28 | expect(result3[0].type).toBe('WARN'); 29 | expect(result3[0].code).toBe('041'); 30 | expect(result3[0].line).toBe(1); 31 | expect(result3[0].column).toBe(1); 32 | 33 | expect(result4[0].type).toBe('WARN'); 34 | expect(result4[0].code).toBe('041'); 35 | expect(result4[0].line).toBe(1); 36 | expect(result4[0].column).toBe(1); 37 | }); 38 | }); 39 | 40 | describe('format rule ' + rule, function () { 41 | var doctype1 = parse(htmlcs.formatFile(path.join(__dirname, 'case1.html'))).doctype; 42 | var doctype3 = parse(htmlcs.formatFile(path.join(__dirname, 'case3.html'))).doctype; 43 | 44 | it('should format well', function () { 45 | expect(!!doctype1).toBe(true); 46 | expect(doctype1.name).toBe('html'); 47 | 48 | expect(!!doctype3).toBe(true); 49 | expect(doctype3.name).toBe('html'); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/lib/rules/html-lang/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "html-lang": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/html-lang/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/html-lang/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | standard file 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/lib/rules/html-lang/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/html-lang/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule html-lang 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 14 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 15 | var result3 = htmlcs.hintFile(path.join(__dirname, 'case3.html')); 16 | 17 | it('should return right result', function () { 18 | expect(result1.length).toBe(1); 19 | 20 | expect(result1[0].type).toBe('WARN'); 21 | expect(result1[0].code).toBe('010'); 22 | expect(result1[0].line).toBe(2); 23 | expect(result1[0].column).toBe(1); 24 | 25 | expect(result2.length).toBe(0); 26 | expect(result3.length).toBe(0); 27 | }); 28 | }); 29 | 30 | describe('format rule ' + rule, function () { 31 | var html1 = parse(htmlcs.formatFile(path.join(__dirname, 'case1.html'))).querySelector('html'); 32 | var html2 = parse(htmlcs.formatFile(path.join(__dirname, 'case2.html'))).querySelector('html'); 33 | 34 | it('should format well', function () { 35 | expect(html1.getAttribute('lang')).toBe('zh-CN'); 36 | expect(!html2).toBe(true); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/lib/rules/id-class-ad-disabled/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "id-class-ad-disabled": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/id-class-ad-disabled/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 | 16 | -------------------------------------------------------------------------------- /test/lib/rules/id-class-ad-disabled/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | standard file 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/id-class-ad-disabled/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for id-class-ad-disabled 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 13 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 14 | 15 | it('should return right result (use ["ad"] as default)', function () { 16 | expect(result1.length).toBe(4); 17 | 18 | expect(result1[0].type).toBe('WARN'); 19 | expect(result1[0].code).toBe('031'); 20 | expect(result1[0].line).toBe(11); 21 | expect(result1[0].column).toBe(14); 22 | 23 | expect(result1[1].type).toBe('WARN'); 24 | expect(result1[1].code).toBe('031'); 25 | expect(result1[1].line).toBe(12); 26 | expect(result1[1].column).toBe(14); 27 | 28 | expect(result1[2].type).toBe('WARN'); 29 | expect(result1[2].code).toBe('031'); 30 | expect(result1[2].line).toBe(13); 31 | expect(result1[2].column).toBe(17); 32 | 33 | expect(result1[3].type).toBe('WARN'); 34 | expect(result1[3].code).toBe('031'); 35 | expect(result1[3].line).toBe(14); 36 | expect(result1[3].column).toBe(17); 37 | }); 38 | 39 | it('should be configable', function () { 40 | expect(result2.length).toBe(4); 41 | 42 | expect(result2[0].type).toBe('WARN'); 43 | expect(result2[0].code).toBe('031'); 44 | expect(result2[0].line).toBe(12); 45 | expect(result2[0].column).toBe(14); 46 | 47 | expect(result2[1].type).toBe('WARN'); 48 | expect(result2[1].code).toBe('031'); 49 | expect(result2[1].line).toBe(13); 50 | expect(result2[1].column).toBe(14); 51 | 52 | expect(result2[2].type).toBe('WARN'); 53 | expect(result2[2].code).toBe('031'); 54 | expect(result2[2].line).toBe(14); 55 | expect(result2[2].column).toBe(17); 56 | 57 | expect(result2[3].type).toBe('WARN'); 58 | expect(result2[3].code).toBe('031'); 59 | expect(result2[3].line).toBe(15); 60 | expect(result2[3].column).toBe(17); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "ie-edge": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/case4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/case5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/ie-edge/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule ie-edge 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 14 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 15 | var result3 = htmlcs.hintFile(path.join(__dirname, 'case3.html')); 16 | var result4 = htmlcs.hintFile(path.join(__dirname, 'case4.html')); 17 | var result5 = htmlcs.hintFile(path.join(__dirname, 'case5.html')); 18 | 19 | it('should return right result', function () { 20 | expect(result1.length).toBe(1); 21 | 22 | expect(result1[0].type).toBe('WARN'); 23 | expect(result1[0].code).toBe('011'); 24 | expect(result1[0].line).toBe(3); 25 | expect(result1[0].column).toBe(1); 26 | 27 | expect(result2.length).toBe(0); 28 | expect(result3.length).toBe(0); 29 | 30 | expect(result4[0].type).toBe('WARN'); 31 | expect(result4[0].code).toBe('011'); 32 | expect(result4[0].line).toBe(3); 33 | expect(result4[0].column).toBe(1); 34 | 35 | expect(result5[0].type).toBe('WARN'); 36 | expect(result5[0].code).toBe('011'); 37 | expect(result5[0].line).toBe(3); 38 | expect(result5[0].column).toBe(1); 39 | }); 40 | }); 41 | 42 | describe('format rule ' + rule, function () { 43 | var head1 = parse(htmlcs.formatFile(path.join(__dirname, 'case1.html'))).querySelector('head'); 44 | var head2 = parse(htmlcs.formatFile(path.join(__dirname, 'case2.html'))).querySelector('head'); 45 | var head4 = parse(htmlcs.formatFile(path.join(__dirname, 'case4.html'))).querySelector('head'); 46 | var head5 = parse(htmlcs.formatFile(path.join(__dirname, 'case5.html'))).querySelector('head'); 47 | 48 | it('should format well', function () { 49 | expect(head1.querySelector('meta[http-equiv="X-UA-Compatible"]').getAttribute('content')).toBe('IE=Edge'); 50 | expect(!head2).toBe(true); 51 | expect(head4.querySelector('meta[http-equiv="X-UA-Compatible"]').getAttribute('content')).toBe('IE=Edge'); 52 | expect(head5.querySelector('meta[http-equiv="X-UA-Compatible"]').getAttribute('content')).toBe('IE=Edge'); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/lib/rules/img-alt/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "img-alt": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/img-alt/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | submit 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/img-alt/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule img-alt 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('012'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('012'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/img-src/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "img-src": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/img-src/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | submit 14 | 15 | -------------------------------------------------------------------------------- /test/lib/rules/img-src/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule img-src 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(1); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('013'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(5); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/lib/rules/img-title/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "img-title": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/img-title/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/img-title/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule img-title 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('014'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('014'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/img-width-height/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "img-width-height": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/img-width-height/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/lib/rules/img-width-height/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule img-width-height 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(7); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('015'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('015'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(5); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('015'); 29 | expect(result[2].line).toBe(12); 30 | expect(result[2].column).toBe(5); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('017'); 34 | expect(result[3].line).toBe(13); 35 | expect(result[3].column).toBe(5); 36 | 37 | expect(result[4].type).toBe('WARN'); 38 | expect(result[4].code).toBe('016'); 39 | expect(result[4].line).toBe(14); 40 | expect(result[4].column).toBe(5); 41 | 42 | expect(result[5].type).toBe('WARN'); 43 | expect(result[5].code).toBe('017'); 44 | expect(result[5].line).toBe(15); 45 | expect(result[5].column).toBe(5); 46 | 47 | expect(result[6].type).toBe('WARN'); 48 | expect(result[6].code).toBe('016'); 49 | expect(result[6].line).toBe(16); 50 | expect(result[6].column).toBe(5); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/lib/rules/indent-char/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "indent-char": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/indent-char/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |
8 |
9 | 14 |
15 | 中文 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/indent-char/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |
8 |
9 | 14 |
15 | 中文 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/indent-char/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |
8 |
9 | 14 |
15 | 中文 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/indent-char/case4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |
8 |
9 | 14 |
15 | 中文 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/indent-char/case5.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/label-for-input/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "label-for-input": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/label-for-input/case.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | -------------------------------------------------------------------------------- /test/lib/rules/label-for-input/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for label-for-input 3 | * @author chris 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | 13 | it('should return the right result', function () { 14 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('044'); 19 | expect(result[0].line).toBe(8); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('044'); 24 | expect(result[1].line).toBe(10); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/lowercase-class-with-hyphen/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "lowercase-class-with-hyphen": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/lowercase-class-with-hyphen/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/lowercase-class-with-hyphen/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule lowercase-class-with-hyphen 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('018'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('019'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/lowercase-id-with-hyphen/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "lowercase-id-with-hyphen": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/lowercase-id-with-hyphen/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/lowercase-id-with-hyphen/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule lowercase-id-with-hyphen 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('020'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('021'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/max-len/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "max-len": 50 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/max-len/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello HTMLCS 6 | 7 | 8 | 14 | 15 | 16 | Hello HTMLCS 17 | 18 | 21 | 22 | 24 |

bbbbbbbbbbbbbbbbbbbbbbbbbb

cccccccccccccccccccccc 25 | 26 |
27 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /test/lib/rules/max-len/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for max-len 3 | * @author chris 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(6); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('048'); 19 | expect(result[0].line).toBe(6); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('048'); 24 | expect(result[1].line).toBe(7); 25 | expect(result[1].column).toBe(5); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('048'); 29 | expect(result[2].line).toBe(22); 30 | expect(result[2].column).toBe(5); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('048'); 34 | expect(result[3].line).toBe(24); 35 | expect(result[3].column).toBe(61); 36 | 37 | expect(result[4].type).toBe('WARN'); 38 | expect(result[4].code).toBe('048'); 39 | expect(result[4].line).toBe(27); 40 | expect(result[4].column).toBe(86); 41 | 42 | expect(result[5].type).toBe('WARN'); 43 | expect(result[5].code).toBe('048'); 44 | expect(result[5].line).toBe(27); 45 | expect(result[5].column).toBe(95); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/lib/rules/multiple-stylesheets/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "multiple-stylesheets": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/multiple-stylesheets/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/multiple-stylesheets/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule no-space-before-tag-end 3 | * @author Oleg Krivtsov 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(1); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('028'); 19 | expect(result[0].line).toBe(9); 20 | expect(result[0].column).toBe(5); 21 | 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/lib/rules/nest/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "nest": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/nest/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | test for rule nest 6 | 7 | 8 | 9 | another head 10 | 11 |

12 | 13 | 14 | 15 |

16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/nest/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule nest 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(5); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('042'); 19 | expect(result[0].line).toBe(9); 20 | expect(result[0].column).toBe(9); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('041'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(8); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('041'); 29 | expect(result[2].line).toBe(12); 30 | expect(result[2].column).toBe(5); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('042'); 34 | expect(result[3].line).toBe(12); 35 | expect(result[3].column).toBe(5); 36 | 37 | expect(result[4].type).toBe('WARN'); 38 | expect(result[4].code).toBe('041'); 39 | expect(result[4].line).toBe(13); 40 | expect(result[4].column).toBe(13); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/lib/rules/new-line-for-blocks/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "new-line-for-blocks": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/new-line-for-blocks/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |
    12 |
  • Item 1
  • 13 |
  • Item 2
  • 14 |
  • Item 3
  • 15 |
16 |
    17 |
  • Item 1
  • Item 2
  • 18 |
  • Item 3
  • 19 |
      20 |
    21 |
22 | 23 | -------------------------------------------------------------------------------- /test/lib/rules/new-line-for-blocks/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule new-line-for-blocks 3 | * @author Oleg Krivtsov 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(3); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('049'); 19 | expect(result[0].line).toBe(17); 20 | expect(result[0].column).toBe(24); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('049'); 24 | expect(result[1].line).toBe(17); 25 | expect(result[1].column).toBe(24); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('049'); 29 | expect(result[2].line).toBe(19); 30 | expect(result[2].column).toBe(5); 31 | 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/lib/rules/no-bom/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "no-bom": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/no-bom/case-no-bom.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/no-bom/case-with-bom.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/no-bom/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for no-duplication-id-and-name 3 | * @author chris 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | 13 | it('no bom should be all right', function () { 14 | var result = hinter.hintFile(path.join(__dirname, 'case-no-bom.html')); 15 | expect(result.length).toBe(0); 16 | }); 17 | 18 | it('with bom should be warning', function () { 19 | var result = hinter.hintFile(path.join(__dirname, 'case-with-bom.html')); 20 | expect(result.length).toBe(1); 21 | 22 | expect(result[0].type).toBe('WARN'); 23 | expect(result[0].code).toBe('046'); 24 | expect(result[0].line).toBe(1); 25 | expect(result[0].column).toBe(1); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/no-duplication-id-and-name/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "no-duplication-id-and-name": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/no-duplication-id-and-name/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/lib/rules/no-duplication-id-and-name/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for no-duplication-id-and-name 3 | * @author chris 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(4); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('043'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(14); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('043'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(15); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('043'); 29 | expect(result[2].line).toBe(13); 30 | expect(result[2].column).toBe(17); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('043'); 34 | expect(result[3].line).toBe(14); 35 | expect(result[3].column).toBe(31); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/lib/rules/no-hook-class/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "no-hook-class": { 3 | "keys": "/[-_#](?:js|hook)[-_#]/" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/lib/rules/no-hook-class/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |
12 | Lorem ipsum 13 |
14 | 15 | 16 |
17 | 18 |

Lorem ipsum

19 |
20 | 21 |

22 | fecs [WARN] line 24, column 81: Class name(red) should be semantic. (no-meta-css, 045) 23 |

24 | 25 |

26 | 27 | 28 |
29 | 30 | 31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /test/lib/rules/no-hook-class/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for no-hook-class 3 | * @author chris 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(4); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('047'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(13); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('047'); 24 | expect(result[1].line).toBe(18); 25 | expect(result[1].column).toBe(15); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('047'); 29 | expect(result[2].line).toBe(21); 30 | expect(result[2].column).toBe(11); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('047'); 34 | expect(result[3].line).toBe(28); 35 | expect(result[3].column).toBe(14); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/lib/rules/no-meta-css/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "no-meta-css": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/no-meta-css/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |
12 | Lorem ipsum 13 |
14 | 15 |
16 |

Lorem ipsum

17 |
18 | 19 |

20 | fecs [WARN] line 24, column 81: Class name(red) should be semantic. (no-meta-css, 045) 21 |

22 | 23 |

24 | 25 |
26 | 27 | 28 |
29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /test/lib/rules/no-meta-css/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for no-meta-css 3 | * @author chris 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(9); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('045'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(13); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('045'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(13); 26 | 27 | expect(result[4].type).toBe('WARN'); 28 | expect(result[4].code).toBe('045'); 29 | expect(result[4].line).toBe(15); 30 | expect(result[4].column).toBe(13); 31 | 32 | expect(result[5].type).toBe('WARN'); 33 | expect(result[5].code).toBe('045'); 34 | expect(result[5].line).toBe(16); 35 | expect(result[5].column).toBe(15); 36 | 37 | expect(result[8].type).toBe('WARN'); 38 | expect(result[8].code).toBe('045'); 39 | expect(result[8].line).toBe(26); 40 | expect(result[8].column).toBe(30); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/lib/rules/no-space-before-tag-end/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "no-space-before-tag-end": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/no-space-before-tag-end/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/lib/rules/no-space-before-tag-end/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule no-space-before-tag-end 3 | * @author Oleg Krivtsov 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(1); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('050'); 19 | expect(result[0].line).toBe(4); 20 | expect(result[0].column).toBe(26); 21 | 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/lib/rules/protocol-omitted-in-href/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "protocol-omitted-in-href": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/protocol-omitted-in-href/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/lib/rules/protocol-omitted-in-href/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule protocol-omitted-in-href 3 | * @author Oleg Krivtsov 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('051'); 19 | expect(result[0].line).toBe(8); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('051'); 24 | expect(result[1].line).toBe(9); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/rel-stylesheet/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "rel-stylesheet": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/rel-stylesheet/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/lib/rules/rel-stylesheet/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule rel-stylesheet 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 14 | 15 | it('should return right result', function () { 16 | expect(result.length).toBe(2); 17 | 18 | expect(result[0].type).toBe('WARN'); 19 | expect(result[0].code).toBe('022'); 20 | expect(result[0].line).toBe(8); 21 | expect(result[0].column).toBe(5); 22 | 23 | expect(result[1].type).toBe('WARN'); 24 | expect(result[1].code).toBe('022'); 25 | expect(result[1].line).toBe(9); 26 | expect(result[1].column).toBe(5); 27 | 28 | }); 29 | }); 30 | 31 | describe('format rule ' + rule, function () { 32 | var document = parse(htmlcs.formatFile(path.join(__dirname, 'case.html'))); 33 | 34 | it('should format well', function () { 35 | document.querySelectorAll('link').forEach(function (element) { 36 | expect(!element.getAttribute('rel')).toBe(false); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/lib/rules/script-content/case.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/script-content/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for script-content 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | var htmlcs = require('../../../../'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('hint rule ' + rule, function () { 13 | var code = fs.readFileSync(path.join(__dirname, 'case.html'), { 14 | encoding: 'utf-8' 15 | }); 16 | 17 | var result = []; 18 | 19 | var scriptLinter = function (content, pos, element, indent) { 20 | result.push({ 21 | content: content, 22 | pos: pos, 23 | element: element, 24 | indent: indent 25 | }); 26 | }; 27 | 28 | htmlcs.hint(code, { 29 | 'script-content': true, 30 | 'linters': { 31 | script: scriptLinter 32 | } 33 | }); 34 | 35 | htmlcs.hint(code, { 36 | linters: { 37 | script: scriptLinter 38 | } 39 | }); 40 | 41 | htmlcs.hint(code, {'script-content': true}); 42 | 43 | it('should call linter on script', function () { 44 | expect(result.length).toBe(3); 45 | 46 | expect(result[0].content).toBe('var a = 1;'); 47 | expect(result[0].pos.line).toBe(1); 48 | expect(result[0].pos.column).toBe(9); 49 | expect(result[0].element.tagName).toBe('SCRIPT'); 50 | expect(result[0].indent).toBe(''); 51 | 52 | expect(result[1].content).toBe('\n\t var a = 1;\n\t'); 53 | expect(result[1].pos.line).toBe(2); 54 | expect(result[1].pos.column).toBe(10); 55 | expect(result[1].element.tagName).toBe('SCRIPT'); 56 | expect(result[1].indent).toBe('\t'); 57 | 58 | expect(result[2].content).toBe('\n var a = {\n index: 1\n };\n '); 59 | expect(result[2].pos.line).toBe(5); 60 | expect(result[2].pos.column).toBe(36); 61 | expect(result[2].element.tagName).toBe('SCRIPT'); 62 | expect(result[2].indent).toBe(' '); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/lib/rules/script-in-tail/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "script-in-tail": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/script-in-tail/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 18 | 19 |
20 | 21 | 24 |
25 | 26 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /test/lib/rules/script-in-tail/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule script-in-tail 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(6); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('023'); 19 | expect(result[0].line).toBe(8); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('023'); 24 | expect(result[1].line).toBe(9); 25 | expect(result[1].column).toBe(5); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('023'); 29 | expect(result[2].line).toBe(14); 30 | expect(result[2].column).toBe(5); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('023'); 34 | expect(result[3].line).toBe(15); 35 | expect(result[3].column).toBe(5); 36 | 37 | expect(result[4].type).toBe('WARN'); 38 | expect(result[4].code).toBe('023'); 39 | expect(result[4].line).toBe(20); 40 | expect(result[4].column).toBe(9); 41 | 42 | expect(result[5].type).toBe('WARN'); 43 | expect(result[5].code).toBe('023'); 44 | expect(result[5].line).toBe(21); 45 | expect(result[5].column).toBe(9); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/lib/rules/self-close/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "self-close": false 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/self-close/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/self-close/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/lib/rules/self-close/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /test/lib/rules/spec-char-escape/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "spec-char-escape": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/spec-char-escape/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 |
test<
11 |
test>
12 |
test>test<
13 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /test/lib/rules/spec-char-escape/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for spec-char-escape 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(4); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('033'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(14); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('033'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(14); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('033'); 29 | expect(result[2].line).toBe(12); 30 | expect(result[2].column).toBe(14); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('033'); 34 | expect(result[3].line).toBe(12); 35 | expect(result[3].column).toBe(19); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/lib/rules/style-content/case.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/style-content/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for style-content 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | var htmlcs = require('../../../../'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('hint rule ' + rule, function () { 13 | var code = fs.readFileSync(path.join(__dirname, 'case.html'), { 14 | encoding: 'utf-8' 15 | }); 16 | 17 | var result = []; 18 | 19 | var styleLinter = function (content, pos, element, indent) { 20 | result.push({ 21 | content: content, 22 | pos: pos, 23 | element: element, 24 | indent: indent 25 | }); 26 | }; 27 | 28 | htmlcs.hint(code, { 29 | 'style-content': true, 30 | 'linters': { 31 | style: styleLinter 32 | } 33 | }); 34 | 35 | htmlcs.hint(code, { 36 | linters: { 37 | style: styleLinter 38 | } 39 | }); 40 | 41 | htmlcs.hint(code, {'style-content': true}); 42 | 43 | it('should call linter on style', function () { 44 | expect(result.length).toBe(3); 45 | 46 | expect(result[0].content).toBe('body {}'); 47 | expect(result[0].pos.line).toBe(1); 48 | expect(result[0].pos.column).toBe(8); 49 | expect(result[0].element.tagName).toBe('STYLE'); 50 | expect(result[0].indent).toBe(''); 51 | 52 | expect(result[1].content).toBe('\n\t body {}\n\t'); 53 | expect(result[1].pos.line).toBe(2); 54 | expect(result[1].pos.column).toBe(9); 55 | expect(result[1].element.tagName).toBe('STYLE'); 56 | expect(result[1].indent).toBe('\t'); 57 | 58 | expect(result[2].content).toBe('\n body {\n\n }\n '); 59 | expect(result[2].pos.line).toBe(5); 60 | expect(result[2].pos.column).toBe(28); 61 | expect(result[2].element.tagName).toBe('STYLE'); 62 | expect(result[2].indent).toBe(' '); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/lib/rules/style-disabled/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "style-disabled": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/style-disabled/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 13 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /test/lib/rules/style-disabled/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for style-disabled 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('034'); 19 | expect(result[0].line).toBe(8); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('034'); 24 | expect(result[1].line).toBe(15); 25 | expect(result[1].column).toBe(5); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/tag-pair/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "tag-pair": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/tag-pair/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 |
11 |

12 | 13 | 14 |

15 | 16 | 17 | 19 | 20 |
18 | td in th
21 | -------------------------------------------------------------------------------- /test/lib/rules/tag-pair/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for tag-pair 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('035'); 19 | expect(result[0].line).toBe(2); 20 | expect(result[0].column).toBe(1); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('035'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(9); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lib/rules/tagname-lowercase/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "tagname-lowercase": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/tagname-lowercase/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /test/lib/rules/tagname-lowercase/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for tagname-lowercase 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(3); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('036'); 19 | expect(result[0].line).toBe(10); 20 | expect(result[0].column).toBe(6); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('036'); 24 | expect(result[1].line).toBe(11); 25 | expect(result[1].column).toBe(6); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('036'); 29 | expect(result[2].line).toBe(12); 30 | expect(result[2].column).toBe(17); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "title-required": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | standard file 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | standard file 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | standard file 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/case8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/lib/rules/title-required/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule title-required 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 14 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 15 | var result3 = htmlcs.hintFile(path.join(__dirname, 'case3.html')); 16 | var result4 = htmlcs.hintFile(path.join(__dirname, 'case4.html')); 17 | var result5 = htmlcs.hintFile(path.join(__dirname, 'case5.html')); 18 | var result6 = htmlcs.hintFile(path.join(__dirname, 'case6.html')); 19 | 20 | it('should return right result', function () { 21 | expect(result1.length).toBe(1); 22 | expect(result1[0].type).toBe('WARN'); 23 | expect(result1[0].code).toBe('024'); 24 | expect(result1[0].line).toBe(3); 25 | expect(result1[0].column).toBe(1); 26 | 27 | expect(result2.length).toBe(1); 28 | expect(result2[0].type).toBe('WARN'); 29 | expect(result2[0].code).toBe('024'); 30 | expect(result2[0].line).toBe(3); 31 | expect(result2[0].column).toBe(1); 32 | 33 | expect(result3.length).toBe(1); 34 | expect(result3[0].type).toBe('WARN'); 35 | expect(result3[0].code).toBe('025'); 36 | expect(result3[0].line).toBe(6); 37 | expect(result3[0].column).toBe(5); 38 | 39 | expect(result4.length).toBe(1); 40 | expect(result4[0].type).toBe('WARN'); 41 | expect(result4[0].code).toBe('025'); 42 | expect(result4[0].line).toBe(4); 43 | expect(result4[0].column).toBe(5); 44 | 45 | expect(result5.length).toBe(0); 46 | expect(result6.length).toBe(0); 47 | }); 48 | }); 49 | 50 | describe('format rule ' + rule, function () { 51 | var head1 = parse(htmlcs.formatFile(path.join(__dirname, 'case1.html'))).querySelector('head'); 52 | var head2 = parse(htmlcs.formatFile(path.join(__dirname, 'case2.html'))).querySelector('head'); 53 | var head3 = parse(htmlcs.formatFile(path.join(__dirname, 'case3.html'))).querySelector('head'); 54 | var head4 = parse(htmlcs.formatFile(path.join(__dirname, 'case4.html'))).querySelector('head'); 55 | var head5 = parse(htmlcs.formatFile(path.join(__dirname, 'case5.html'))).querySelector('head'); 56 | var head7 = parse(htmlcs.formatFile(path.join(__dirname, 'case7.html'))).querySelector('head'); 57 | var head8 = parse(htmlcs.formatFile(path.join(__dirname, 'case8.html'))).querySelector('head'); 58 | 59 | it('should format well', function () { 60 | var title; 61 | var charsetMeta; 62 | 63 | title = head1.querySelector('title'); 64 | charsetMeta = head1.querySelector('meta[charset]'); 65 | expect(title.previousElementSibling).toBe(charsetMeta); 66 | 67 | title = head2.querySelector('title'); 68 | charsetMeta = head2.querySelector('meta[charset]'); 69 | expect(title.previousElementSibling).toBe(charsetMeta); 70 | 71 | title = head3.querySelector('title'); 72 | charsetMeta = head3.querySelector('meta[charset]'); 73 | expect(title.previousElementSibling).toBe(charsetMeta); 74 | 75 | title = head4.querySelector('title'); 76 | charsetMeta = head4.querySelector('meta[charset]'); 77 | expect(title.previousElementSibling).toBe(charsetMeta); 78 | 79 | expect(!head5).toBe(true); 80 | 81 | title = head7.querySelector('title'); 82 | expect(title).toBe(head7.children[0]); 83 | 84 | title = head8.querySelector('title'); 85 | expect(title).toBe(head8.children[0]); 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /test/lib/rules/unique-id/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "unique-id": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/unique-id/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/lib/rules/unique-id/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule unique-id 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var hinter = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('rule ' + rule, function () { 12 | var result = hinter.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(4); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('026'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(5); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('026'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(5); 26 | 27 | expect(result[2].type).toBe('WARN'); 28 | expect(result[2].code).toBe('026'); 29 | expect(result[2].line).toBe(13); 30 | expect(result[2].column).toBe(5); 31 | 32 | expect(result[3].type).toBe('WARN'); 33 | expect(result[3].code).toBe('026'); 34 | expect(result[3].line).toBe(14); 35 | expect(result[3].column).toBe(5); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/lib/rules/unnecessary-trailing-whitespace-in-text/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "unnecessary-whitespace-in-text": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/unnecessary-trailing-whitespace-in-text/case.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 |

abc

12 |

ab c

13 | 14 | -------------------------------------------------------------------------------- /test/lib/rules/unnecessary-trailing-whitespace-in-text/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule no-space-before-tag-end 3 | * @author Oleg Krivtsov 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | 9 | var rule = path.basename(__dirname); 10 | 11 | describe('hint rule ' + rule, function () { 12 | var result = htmlcs.hintFile(path.join(__dirname, 'case.html')); 13 | 14 | it('should return right result', function () { 15 | expect(result.length).toBe(2); 16 | 17 | expect(result[0].type).toBe('WARN'); 18 | expect(result[0].code).toBe('052'); 19 | expect(result[0].line).toBe(11); 20 | expect(result[0].column).toBe(11); 21 | 22 | expect(result[1].type).toBe('WARN'); 23 | expect(result[1].code).toBe('052'); 24 | expect(result[1].line).toBe(12); 25 | expect(result[1].column).toBe(11); 26 | 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/lib/rules/viewport/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "viewport": true 3 | } 4 | -------------------------------------------------------------------------------- /test/lib/rules/viewport/case1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/viewport/case2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/lib/rules/viewport/case3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/lib/rules/viewport/case4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | standard file 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/lib/rules/viewport/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for rule viewport 3 | * @author nighca 4 | */ 5 | 6 | var path = require('path'); 7 | var htmlcs = require('../../../../'); 8 | var parse = require('../../../../lib/parse'); 9 | 10 | var rule = path.basename(__dirname); 11 | 12 | describe('rule ' + rule, function () { 13 | var result1 = htmlcs.hintFile(path.join(__dirname, 'case1.html')); 14 | var result2 = htmlcs.hintFile(path.join(__dirname, 'case2.html')); 15 | var result3 = htmlcs.hintFile(path.join(__dirname, 'case3.html')); 16 | var result4 = htmlcs.hintFile(path.join(__dirname, 'case4.html')); 17 | 18 | it('should return right result', function () { 19 | expect(result1.length).toBe(1); 20 | expect(result1[0].type).toBe('WARN'); 21 | expect(result1[0].code).toBe('027'); 22 | expect(result1[0].line).toBe(3); 23 | expect(result1[0].column).toBe(1); 24 | 25 | expect(result2.length).toBe(1); 26 | expect(result2[0].type).toBe('WARN'); 27 | expect(result2[0].code).toBe('027'); 28 | expect(result2[0].line).toBe(3); 29 | expect(result2[0].column).toBe(1); 30 | 31 | expect(result3.length).toBe(0); 32 | expect(result4.length).toBe(0); 33 | }); 34 | }); 35 | 36 | describe('format rule ' + rule, function () { 37 | var head1 = parse(htmlcs.formatFile(path.join(__dirname, 'case1.html'))).querySelector('head'); 38 | var head2 = parse(htmlcs.formatFile(path.join(__dirname, 'case2.html'))).querySelector('head'); 39 | var head3 = parse(htmlcs.formatFile(path.join(__dirname, 'case3.html'))).querySelector('head'); 40 | var head4 = parse(htmlcs.formatFile(path.join(__dirname, 'case4.html'))).querySelector('head'); 41 | 42 | it('should format well', function () { 43 | expect(!!head1.querySelector('meta[name="viewport"]')).toBe(true); 44 | expect(!!head2.querySelector('meta[name="viewport"]')).toBe(true); 45 | expect(!head3).toBe(true); 46 | expect( 47 | head4.querySelector('meta[name="viewport"]').getAttribute('content') 48 | ).toBe('width=device-width, initial-scale=2, maximum-scale=1'); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /test/max-error/.htmlcsrc: -------------------------------------------------------------------------------- 1 | { 2 | "asset-type": true, // true: Default value of attribute "type" (/ 10 | 15 | 16 | 19 | 22 | 23 | 24 | 25 |

26 | i'm a p. 27 |

28 | i'm a div. 29 |
30 |

31 | 32 | 33 | there's a div in me. 34 |
i'm a div in span.
35 |
36 | 37 | aaa 38 | 39 |
40 | i'm another div. 41 |
42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /test/max-error/test.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test for config max-error 3 | * @author nighca 4 | */ 5 | 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | var config = require('../../lib/config'); 9 | var hinter = require('../../'); 10 | 11 | describe('config max-error', function () { 12 | var filePath = path.join(__dirname, 'case.html'); 13 | var code = fs.readFileSync(filePath, 'utf-8'); 14 | var cfg = config.load(filePath); 15 | 16 | var result = hinter.hint(code, cfg); 17 | 18 | cfg['max-error'] = 0; 19 | var result0 = hinter.hint(code, cfg); 20 | 21 | cfg['max-error'] = 5; 22 | var result5 = hinter.hint(code, cfg); 23 | 24 | cfg['max-error'] = 10; 25 | var result10 = hinter.hint(code, cfg); 26 | 27 | it('should return right result with given num', function () { 28 | expect(result5.length).toBe(5); 29 | expect(result10.length).toBe(10); 30 | }); 31 | 32 | it('should take 0 as no limit', function () { 33 | expect(result0.length).toBe(result.length); 34 | }); 35 | }); 36 | --------------------------------------------------------------------------------