Code Monkey home page Code Monkey logo

htmlhint-loader's Introduction


HTMLHint Loader

A Webpack loader for HTMLHint

Travis Build Status Codecov NPM count MIT Licence Chat Chat

  How To UseContributingRoadmapWebsite

Table of Contents

Install

npm install htmlhint-loader

Usage

module.exports = {
  module: {
    rules: [{
      enforce: 'pre',
      test: /\.html/,
      loader: 'htmlhint-loader',
      exclude: /node_modules/
    }]
  }
}

Options

You can directly pass some htmlhint rules by

  • Adding a query string to the loader for this loader usage only
module.exports = {
  module: {
    rules: [{
      enforce: 'pre',
      test: /\.html/,
      loader: 'htmlhint-loader?{tagname-lowercase: true}',
      exclude: /node_modules/
    }]
  }
}
  • Adding a htmlhint entry in your webpack loader options:
module.exports = {
  module: {
    rules: [{
      enforce: 'pre',
      test: /\.html/,
      loader: 'htmlhint-loader',
      exclude: /node_modules/,
      options: {
        configFile: 'path/.htmlhintrc'
      }
    }]
  }
}

configFile

A path to a json file containing the set of htmlhint rules you would like applied to this project. By default all rules are turned off and it is up to you to enable them.

Example file:

{
  "tagname-lowercase": true,
  "attr-lowercase": true,
  "attr-value-double-quotes": true
}

formatter (default: a function that pretty prints any warnings and errors)

The function is called with an array of messages direct for htmlhint and must return a string.

emitAs (default: null)

What to emit errors and warnings as. Set to warning to always emit errors as warnings and error to always emit warnings as errors. By default the plugin will auto detect whether to emit as a warning or an error.

failOnError (default false)

Whether to force webpack to fail the build on a htmlhint error

failOnWarning (default false)

Whether to force webpack to fail the build on a htmlhint warning

customRules

Any custom rules you would like added to htmlhint. Specify as an array like so:

module.exports = {
  module: {
    rules: [{
      enforce: 'pre',
      test: /\.html/,
      loader: 'htmlhint-loader',
      exclude: /node_modules/,
      options: {
        customRules: [{
          id: 'my-rule-name',
          description: 'Example description',
          init: function(parser, reporter) {
            //see htmlhint docs / source for what to put here
          }
        }]
      }
    }]
  }
}

rulesDir

You can add a path to a folder containing your custom rules. See below for the format of the rule, it is not the same as HTMLHINT - you can pass a value to a rule.

// webpack config
module.exports = {
  module: {
    rules: [{
      enforce: 'pre',
      test: /\.html/,
      loader: 'htmlhint-loader',
      exclude: /node_modules/,
      options: {
        rulesDir: path.join(__dirname, 'rules/'),
        'my-new-rule': 'this is pass to the rule (option)'
      }
    }]
  }
}
// rules/myNewRule.js
const id = 'my-new-rule';

module.exports = {
  id,
  rule: function(HTMLHint, option /* = 'this is pass to the rule (option)' */) {
    HTMLHint.addRule({
      id,
      description: 'my-new-rule',
      init: () => {
        //see htmlhint docs / source for what to put here
      }
    });
  }
};
outputReport (default: false)

Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI

The filePath is relative to the webpack config: output.path The use of [name] is supported when linting multiple files. You can pass in a different formatter for the output file, if none is passed in the default/configured formatter will be used

module.exports = {
  module: {
    rules: [{
      enforce: 'pre',
      test: /\.html/,
      loader: 'htmlhint-loader',
      exclude: /node_modules/,
      options: {
        outputReport: {
          filePath: 'checkstyle-[name].xml',
          formatter(messages) {
            // convert messages to a string that will be written to the file
            return messagesFormattedToString;
          }
        }
      }
    }]
  }
}

Licence

Project initially created by @mattlewis and transferred to the HTMLHint organization.

Logo HTMLHint

MIT License

htmlhint-loader's People

Contributors

benoit-vasseur avatar colinwkirk avatar greenkeeper[bot] avatar jaythomas avatar mattlewis92 avatar snyk-bot avatar thedaviddias avatar

Stargazers

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

Watchers

 avatar

htmlhint-loader's Issues

Angular inline templates

Hi there,

I am using Angular inline templates in my project and I would like to lint them with HTMLHint via htmlhint-loader.

It works with this configuration:

            {
                enforce: "pre",
                test: /\.ts$/,
                loader: "htmlhint-loader",
                include: [...],
                options: {
                    configFile: [...],
                    failOnError: false,
                    failOnWarning: false,
                }
            },

The actual HTML part within inline templates is situated inside a template variable in those *.ts files. I guess htmlhint-loader is currently linting the whole file including the TypeScript code. This probably causes the following loader plugin error when the linter finds something what it thinks is an error:

Error:
at lint ([...]\node_modules\htmlhint-loader\index.js:115:15)
at fs.readFile ([...]\node_modules\htmlhint-loader\index.js:163:11)
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:528:3)
@ ./assets/scripts/ts/modules/shared/shared.module.ts 81:39-113
@ ./assets/scripts/ts/modules/app/app.module.ts
@ ./assets/scripts/ts/modules/app/standalone-app.module.ts
@ ./assets/scripts/ts/main.jit.ts

I would like to know if it is somehow possible to tell htmlhint-loader that it should only lint the template part within those files. (Maybe something like the regExp option of file-loader to only target a part of the loaded file.)

Suggestion: improve handling of configFile paths

Before using htmllint-loader, I was able to execute my webpack build from various directories (cwd); now, I am forced to do so from one specific location, because otherwise the config file cannot be found. The reason is that every given configFile path is processed by this line:

const configFilePath = path.join(process.cwd(), options.configFile);

I would suggest two changes to further improve the code:

(1.) Allow absolute paths to be passed in. If a path is already absolute, do not join the cwd:

let configFilePath = options.configFile;
if (!path.isAbsolute(configFilePath)) {
  configFilePath = path.join(process.cwd(), configFilePath);
}

(2.) Throw an error if a configFile was specified and cannot be located. Currently, this would be silently ignored!

How to get it working?

I have this setup.

webpack.config.js

var path = require("path");

// console.log(path.join(__dirname, 'src'));
// console.log(path.resolve(__dirname, "src"));

module.exports = {
    entry: {
        app : "./entry.js", 
        src : "./src/a.js"
    } ,
    output: {
        path: path.join(__dirname, "out"),
        filename: "[name].js"
    },
    module: {
        preLoaders: [
            {
               test: /\.jsx?$/,
               exclude: /node_modules/,
               loader: 'jshint-loader',
            },
            {test: /\.html/, loader: 'htmlhint?{tagname-lowercase: true}', exclude: /node_modules/}
        ]
    },
    htmlhint: {
            configFile: './.htmlhintrc'
    }
};

test.html

<!DOCTYPE html>
<html>
<head>
    <title>Title is here</title>
</head>
<body>
<DIV ></DIV>

<img src="http://kevinpelgrims.com/blog/files/images/2015/05/gradle_icon.png" />
</body>
</html>

.htmlhintrc

{
  "tagname-lowercase": true,
  "attr-lowercase": true,
  "attr-value-double-quotes": true
}

It should have shown error for capitalized div elements, but it's not doing so.

Could you please tell me some points or hints?

Use `strip-json-comments` before parsing the config file.

Is your feature request related to a problem? Please describe.

htmlhint use strip-json-comments for config file so you can use comments inside the .htmlhintrc file.

Code here: https://github.com/htmlhint/HTMLHint/blob/85a1c78984a8ec09ab17595efba2e6ac479e6f31/bin/htmlhint#L319

But htmlhint-loader doesn't support it.

Describe the solution you'd like

Use strip-json-comments

Describe alternatives you've considered

I advice to use http://json5.org/

Additional context

None

Better tests

Current tests mock too much out, it's much better to have integration tests instead

Error when report is generated

Hi, I got the next while webpack generates a report of a HTML which violated some htmlhint rules:

ERROR in Error: Child compilation failed:
Module build failed: TypeError: formatter.on is not a function

  • checkstyle.js:8 Object.checkstyleFormatter [as formatter]
    [angular-hello-world]/[htmlhint]/bin/formatters/checkstyle.js:8:15

  • index.js:98 lint
    [angular-hello-world]/[htmlhint-loader]/index.js:98:47

  • index.js:164 fs.readFile
    [angular-hello-world]/[htmlhint-loader]/index.js:164:13

  • TypeError: formatter.on is not a function

  • compiler.js:76
    [angular-hello-world]/[html-webpack-plugin]/lib/compiler.js:76:16

  • Compiler.js:291 Compiler.
    [angular-hello-world]/[webpack]/lib/Compiler.js:291:10

  • Compiler.js:494
    [angular-hello-world]/[webpack]/lib/Compiler.js:494:13

  • Tapable.js:138 next
    [angular-hello-world]/[tapable]/lib/Tapable.js:138:11

  • CachePlugin.js:62 Compiler.
    [angular-hello-world]/[webpack]/lib/CachePlugin.js:62:5

  • Tapable.js:142 Compiler.applyPluginsAsyncSeries
    [angular-hello-world]/[tapable]/lib/Tapable.js:142:13

  • Compiler.js:491
    [angular-hello-world]/[webpack]/lib/Compiler.js:491:10

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries
    [angular-hello-world]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:645 self.applyPluginsAsync.err
    [angular-hello-world]/[webpack]/lib/Compilation.js:645:19

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries
    [angular-hello-world]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:636 self.applyPluginsAsync.err
    [angular-hello-world]/[webpack]/lib/Compilation.js:636:11

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries
    [angular-hello-world]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:631 self.applyPluginsAsync.err
    [angular-hello-world]/[webpack]/lib/Compilation.js:631:10

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries
    [angular-hello-world]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:627 sealPart2
    [angular-hello-world]/[webpack]/lib/Compilation.js:627:9

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries
    [angular-hello-world]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:575 Compilation.seal
    [angular-hello-world]/[webpack]/lib/Compilation.js:575:8

  • Compiler.js:488
    [angular-hello-world]/[webpack]/lib/Compiler.js:488:16

  • Tapable.js:225
    [angular-hello-world]/[tapable]/lib/Tapable.js:225:11

  • Compilation.js:477 _addModuleChain
    [angular-hello-world]/[webpack]/lib/Compilation.js:477:11

  • Compilation.js:448 processModuleDependencies.err
    [angular-hello-world]/[webpack]/lib/Compilation.js:448:13

  • next_tick.js:73 _combinedTickCallback
    internal/process/next_tick.js:73:7

  • next_tick.js:104 process._tickCallback
    internal/process/next_tick.js:104:9

Child html-webpack-plugin for "index.html":
[./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 616 bytes {0} [built] [failed] [1 error]

ERROR in ./~/html-webpack-plugin/lib/loader.js!./src/index.html
Module build failed: TypeError: formatter.on is not a function
    at Object.checkstyleFormatter [as formatter] (/media/DATA/Programming/AngularJS/AngularJS 4/angular-hello-world/node_modules/htmlhint/bin/formatters/checkstyle.js:8:15)
    at lint (/media/DATA/Programming/AngularJS/AngularJS 4/angular-hello-world/node_modules/htmlhint-loader/index.js:98:47)
    at fs.readFile (/media/DATA/Programming/AngularJS/AngularJS 4/angular-hello-world/node_modules/htmlhint-loader/index.js:164:13)
    at tryToString (fs.js:449:3)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:436:12)

The following is a extract of my webpack.config.js

"rules": [
      {
        "enforce": 'pre',
        "test": /\.html$/,
        "loader": 'htmlhint-loader',
        "exclude": /node_modules/,
        "options": {
          "configFile": '.htmlhintrc.json',
          "failOnError": true,
          "failOnWarning": false,
          "outputReport": {
            "filePath": 'checkstyle-[name].xml',
            "formatter": require('htmlhint/bin/formatters/checkstyle')
          }
        }
     },
  // . . . 

I am using

  • htmlhint-loader 1.3.0
  • htmlhint 0.9.13
  • webpack 2.6.1

wepback 4.0.0 compatiblity

hello,
this loader throws an exception when used with webpack 4.0.0
it throws:

ERROR in ./app/test.html
Module build failed: TypeError: Cannot read property 'htmlhint' of undefined
    at Object.module.exports

got error in a vue project.

I'm using htmlhint-loader in a vue project.and I just follow the docs like:

      {
        test: /\.html/,
        enforce: 'pre',
        loader: 'htmlhint-loader',
        exclude: /node_modules/
      },

error as following:

ERROR in   Error: Child compilation failed:
  Module parse failed: /Users/zsd/repo/vue-webpack/test/node_modules/html-webpack-plugin/lib/loader.js!/Users/zsd/repo/vue-webpack/test/node_modul
  es/htmlhint-loader/index.js!/Users/zsd/repo/vue-webpack/test/index.html Unexpected token (1:0)
  You may need an appropriate loader to handle this file type.
  | <!DOCTYPE html>
  | <html>
  |   <head>:
  SyntaxError: Unexpected token (1:0)

am I missing something?

supporting info:
"node": "7.9.0",
"webpack": "^2.6.1",
"htmlhint-loader": "1.3.0",
"vue-loader": "^12.1.0",

configFile option ignored

Hi,

It doesn't seem that the configFile option described in the documentation actually does anything.

Skimming through the source code, it appears that this parameter gets handed directly to htmlhint, which doesn't actually do anything with it.

Incorrect config, or something else?

Should it run on built when the loader is configured? Or would it just work on calling npx htmlhint script.

The output of my npx webpack command (from build script) does not mention htmlhint,

I am not sure if this is an issue with how I configured, or if its not compatible with webpack 5 (or should just call in script)?

Node: v17.0.1
Npm: 8.1.0
webpack: 5.60.0
webpack-cli: 4.9.1
webpack-dev-server 4.4.0
mac-os: 12.0.1

Package.json:

  "scripts": {
    "lint:html": "npx htmlhint src/*.html",
    "build": "npx webpack --config webpack.config.dev.js"
    "dev": "npx webpack serve --live-reload --config webpack.config.dev.js",
  },
"devDependencies": {
    "@babel/cli": "^7.15.7",
    "@babel/core": "^7.15.8",
    "@babel/node": "^7.15.8",
    "@babel/preset-env": "^7.15.8",
    "@babel/register": "^7.15.3",
    "babel-loader": "^8.2.3",
    "css-loader": "^6.5.0",
    "htmlhint": "^0.15.2",
    "htmlhint-loader": "^1.3.1",
    "numeral": "^2.0.6",
    "style-loader": "^3.3.1",
    "stylelint": "^13.13.1",
    "stylelint-webpack-plugin": "^3.0.1",
    "webpack": "^5.60.0",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.4.0"
  }

.htmlhintrc:

{
  "tagname-lowercase": true,
  "attr-lowercase": true,
  "attr-no-duplication": true,
  "attr-value-double-quotes": true,
  "attr-unsafe-chars": true,
  "attr-no-unnecessary-whitespace": true,
  "attr-value-not-empty": false,
  "doctype-first": true,
  "tag-pair": true,
  "spec-char-escape": true,
  "src-not-empty": true,
  "title-require": true,
  "tag-self-close": false,
  "head-script-disabled": true,
  "alt-require": true,
  "doctype-html5": true,
  "inline-script-disabled": true,
  "inline-style-disabled":true,
  "id-unique": true,
  "id-class-ad-disabled": true,
  "id-class-value": "aaa-bbb",
  "style-disabled": true,
  "input-requires-label": true,
  "tags-check": true,
  "space-tab-mixed-disabled": true
}

webpack config:

const path = require('path');
var StyleLintPlugin = require('stylelint-webpack-plugin');

module.exports = {
    mode: "development",
    devtool: "eval-source-map",
    entry: './src/index.js',
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ["babel-loader"]
            },
            {
                test: /\.css$/,
                use: ["style-loader", "css-loader"]
            },
            {
                enforce: 'pre',
                test: /\.html/,
                loader: 'htmlhint-loader',
                exclude: /node_modules/,
                options: {
                    configFile: '.htmlhintrc'
                }
            }
        ]
    },
    output: {
        path: path.resolve(__dirname, 'src'),
        filename: "bundle.js",

        //enable clean on dist only. otherwise, it will delete all files and cannot recover.
        // clean: true, 
    },
    devServer: {
        static: {
            directory: path.join(__dirname, 'src'),
        },
        compress: true,
        port: 9000,
    },
    plugins: [
        new StyleLintPlugin({
            configFile: '.stylelintrc',
            failOnError: true,
            emitErrors: true,
            emitWarning: true
        }),
    ],
}

npm run build:

asset bundle.js 136 KiB [compared for emit] (name: main)
runtime modules 997 bytes 4 modules
modules by path ./node_modules/ 41.5 KiB
  modules by path ./node_modules/style-loader/dist/runtime/*.js 5.75 KiB 6 modules
  modules by path ./node_modules/css-loader/dist/runtime/*.js 2.94 KiB
    ./node_modules/css-loader/dist/runtime/sourceMaps.js 688 bytes [built] [code generated]
    ./node_modules/css-loader/dist/runtime/api.js 2.26 KiB [built] [code generated]
  ./node_modules/numeral/numeral.js 32.8 KiB [built] [code generated]
modules by path ./src/ 2.86 KiB
  ./src/index.js 125 bytes [built] [code generated]
  ./src/style.css 1.11 KiB [built] [code generated]
  ./node_modules/css-loader/dist/cjs.js!./src/style.css 1.63 KiB [built] [code generated]
webpack 5.60.0 compiled successfully in 1260 ms

npm run lint:html

Config loaded: /Users/jenn/GitHub/dev-starter-kit/.htmlhintrc

   /Users/jenn/GitHub/dev-starter-kit/src/index.html
      L11 |    <P></P>
               ^ The html element name of [ P ] must be in lowercase. (tagname-lowercase)
      L11 |    <P></P>
                  ^ The html element name of [ P ] must be in lowercase. (tagname-lowercase)

Scanned 1 files, found 2 errors in 1 files (17 ms)

simpler custom rules import

is it possible to make creating multiple custom rules simpler.
I want to make about 50-100 rules to my project, and creating those files and adding reference going to be hard task

Latest version stills installs htmlhint 0.9.13 which installs also minimatch 0.3.0 with vulnerabilities

Describe the bug
When I install the latest version of the module I got a warning of security vulnerability

npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue

To Reproduce
Steps to reproduce the behavior:

  1. Run `npm install htmlhint-loader --save-dev
  2. Error appears

Expected behavior
Install the latest version of htmlhint which already uses the correr minimatch package

Screenshots

image

Recommend Projects

  • React photo React

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

  • Vue.js photo Vue.js

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

  • Typescript photo Typescript

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

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

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

Recommend Topics

  • javascript

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

  • web

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

  • server

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

  • Machine learning

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

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

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

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.