Commits (17)
# html-validate changelog
# [2.23.0](https://gitlab.com/html-validate/html-validate/compare/v2.22.0...v2.23.0) (2020-05-18)
### Bug Fixes
- **cli:** `expandFiles` path normalization for windows ([b902853](https://gitlab.com/html-validate/html-validate/commit/b902853e696a04202959ae6c4cf086bd48911e4d))
### Features
- **config:** add two new config presets `html-validate:standard` and `html-validate:a17y` ([36bf9ec](https://gitlab.com/html-validate/html-validate/commit/36bf9ec3be7356d534d352d00610d8253885de22)), closes [#90](https://gitlab.com/html-validate/html-validate/issues/90)
- **rules:** add `include` and `exclude` options to `prefer-button` ([b046dc5](https://gitlab.com/html-validate/html-validate/commit/b046dc5943a4bd05dff9766ea6b9c9f522c09d1a)), closes [#90](https://gitlab.com/html-validate/html-validate/issues/90)
- **rules:** add `isKeywordExtended` method for rule authors ([ca7e835](https://gitlab.com/html-validate/html-validate/commit/ca7e835d384c7ed43967bec14f56836353a0b1f6))
# [2.22.0](https://gitlab.com/html-validate/html-validate/compare/v2.21.0...v2.22.0) (2020-05-15)
### Bug Fixes
......
......@@ -82,7 +82,7 @@ module.exports = new Package("html-validate-docs", [
.config(function (computePathsProcessor, computeIdsProcessor) {
computeIdsProcessor.idTemplates.push({
docTypes: ["content", "frontpage", "rule", "rules", "changelog", "error"],
docTypes: ["content", "frontpage", "rule", "rules", "presets", "error"],
getId: function (doc) {
const dir = path.dirname(doc.fileInfo.relativePath);
if (dir === ".") {
......@@ -109,7 +109,7 @@ module.exports = new Package("html-validate-docs", [
});
computePathsProcessor.pathTemplates.push({
docTypes: ["content", "frontpage", "rule", "rules"],
docTypes: ["content", "frontpage", "rule", "rules", "presets"],
getPath: function (doc) {
const dirname = path.dirname(doc.fileInfo.relativePath);
const p = path.join(dirname, doc.fileInfo.baseName);
......@@ -118,11 +118,25 @@ module.exports = new Package("html-validate-docs", [
outputPathTemplate: "${path}",
});
computeIdsProcessor.idTemplates.push({
docTypes: ["changelog"],
getId: function (doc) {
return doc.fileInfo.baseName.toLowerCase();
},
getAliases: function (doc) {
return [doc.id];
},
});
computePathsProcessor.pathTemplates.push({
docTypes: ["changelog"],
getPath: function (doc) {
const dirname = path.dirname(doc.fileInfo.relativePath);
return path.join(dirname, doc.fileInfo.baseName, "index.html");
return path.join(
dirname,
doc.fileInfo.baseName.toLowerCase(),
"index.html"
);
},
outputPathTemplate: "${path.toLowerCase()}",
});
......
/** @todo this will break when typescript is actually used */
const recommended = require("../../../src/config/recommended.ts");
const document = require("../../../src/config/document.ts");
const a17y = require("../../../build/config/presets/a17y");
const document = require("../../../build/config/presets/document");
const recommended = require("../../../build/config/presets/recommended");
const standard = require("../../../build/config/presets/standard");
/* sort order */
const availablePresets = ["recommended", "standard", "a17y", "document"];
/* preset configuration */
const presets = {
a17y,
document,
recommended,
standard,
};
function compareName(a, b) {
if (a.name < b.name) {
......@@ -48,13 +60,18 @@ module.exports = function rulesProcessor(renderDocsProcessor) {
url: doc.outputPath,
category: doc.category,
summary: doc.summary,
recommended: !!recommended.rules[doc.name],
document: !!document.rules[doc.name],
presets: availablePresets.reduce((result, presetName) => {
const config = presets[presetName];
if (config && config.rules) {
result[presetName] = Boolean(config.rules[doc.name]);
}
return result;
}, {}),
}))
.sort(compareName);
/* group rules into categories */
const categories = {};
const categories = { all: rules };
rules.forEach((rule) => {
const category = rule.category || "other";
if (!(category in categories)) {
......@@ -64,5 +81,6 @@ module.exports = function rulesProcessor(renderDocsProcessor) {
});
renderDocsProcessor.extraData.rules = categories;
renderDocsProcessor.extraData.presets = availablePresets;
}
};
......@@ -39,19 +39,20 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">User guide <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/usage">Getting started</a></li>
<li><a href="/usage/cli.html">Using CLI</a></li>
<li><a href="/usage/elements.html">Elements</a></li>
<li><a href="/usage/transformers.html">Transfomers</a></li>
<li>{@link usage Getting started}</li>
<li>{@link usage/cli Using CLI}</li>
<li>{@link usage/elements Elements}</li>
<li>{@link rules/presets Presets}</li>
<li>{@link usage/transformers Transfomers}</li>
<li role="separator" class="divider"></li>
<li><a href="/usage/vscode.html">VS Code</a></li>
<li>{@link usage/vscode VS Code}</li>
<li role="separator" class="divider"></li>
<li><a href="/frameworks/angularjs.html">AngularJS</a></li>
<li><a href="/usage/cypress.html">Cypress</a></li>
<li><a href="/usage/grunt.html">Grunt</a></li>
<li><a href="/frameworks/jest.html">Jest</a></li>
<li><a href="/usage/protractor.html">Protractor</a></li>
<li><a href="/frameworks/vue.html">Vue.js</a></li>
<li>{@link frameworks/angularjs AngularJS}</li>
<li>{@link usage/cypress Cypress}</li>
<li>{@link usage/grunt Grunt}</li>
<li>{@link frameworks/jest Jest}</li>
<li>{@link usage/protractor Protractor}</li>
<li>{@link frameworks/vue Vue.js}</li>
</ul>
</li>
<li class="dropdown">
......@@ -65,22 +66,22 @@
<li>{@link guide/metadata/writing-tests Writing tests}</li>
</ul>
</li>
<li><a href="/rules">Rules</a></li>
<li>{@link rules Rules}</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Developers guide <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{{ pkg.repository.url }}">Getting the source code</a></li>
<li><a href="{{ pkg.bugs.url }}">File issue</a></li>
<li role="separator" class="divider"></li>
<li><a href="/dev/using-api.html">Using API</a></li>
<li><a href="/dev/writing-rules.html">Writing rules</a></li>
<li><a href="/dev/writing-plugins.html">Writing plugins</a></li>
<li><a href="/dev/transformers.html">Writing transformers</a></li>
<li><a href="/dev/events.html">List of events</a></li>
<li>{@link dev/using-api Using API}</li>
<li>{@link dev/writing-rules Writing rules}</li>
<li>{@link dev/writing-plugins Writing plugins}</li>
<li>{@link dev/transformers Writing transformers}</li>
<li>{@link dev/events List of events}</li>
</ul>
</li>
<li><a href="/changelog">Changelog</a></li>
<li><a href="/about">About</a></li>
<li>{@link changelog Changelog}</li>
<li>{@link about About}</li>
</ul>
<p class="navbar-text navbar-right hidden-xs hidden-sm">{{ pkg.name }}-{{ pkg.version }}</p>
</div>
......
{% extends "base.template.html" %}
{%- macro ruleTable(rules) %}
<table class="table table-striped preset-table">
<colgroup>
<col class="name">
{% for preset in presets %}
<col class="preset-name">
{% endfor %}
</colgroup>
<thead>
<tr>
<td>Rule</td>
{% for preset in presets %}
<td><code>{{ preset }}</code></td>
{% endfor %}
</tr>
</thead>
<tbody>
{% for rule in rules %}
<tr>
<td>{@link {{ rule.name }} {{ rule.name }}}</td>
{% for preset in presets %}
<td>
{% if rule.presets[preset] %}
<span class="fa fa-check"></span>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endmacro -%}
{% block content %}
{{ doc.description | marked }}
{{ ruleTable(rules['all']) }}
{% endblock %}
......@@ -7,22 +7,22 @@
<col class="name">
<col class="summary">
</colgroup>
{% for rule in rules %}
<tbody>
{% for rule in rules %}
<tr>
<td>
{% if rule.recommended %}
{% if rule.presets.recommended %}
<span class="fa fa-check"></span>
{% endif %}
{% if rule.document %}
{% if rule.presets.document %}
<span class="fa fa-file-text-o"></span>
{% endif %}
</td>
<td><a href="/{{ rule.url }}">{{ rule.name }}</a></td>
<td>{{ rule.summary | escape }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
{% endmacro -%}
......
......@@ -10,7 +10,9 @@ Array [
"messages": Array [
Object {
"column": 14,
"context": undefined,
"context": Object {
"type": "button",
},
"line": 1,
"message": "Prefer to use <button> instead of <input type=\\"button\\"> when adding buttons",
"offset": 13,
......
......@@ -7,3 +7,5 @@ Rules with <span class="fa fa-check"></span> are enabled by
`html-validate:recommended`.<br>
Rules with <span class="fa fa-file-text-o"></span> are enabled by
`html-validate:document`.
Additional presets can be compared in {@link rules/presets preset comparision}.
......@@ -4,20 +4,52 @@ name: prefer-button
summary: Prefer to use <button> instead of <input> for buttons
---
# prefer to use `<button>` (`prefer-button`)
# Prefer to use `<button>` (`prefer-button`)
HTML5 introduces the generic `<button>` element which replaces `<input type="button">` and similar constructs.
The `<button>` elements has some advantages:
- It can contain markup as content compared to the `value` attribute of `<input>` which can only hold text. Especially useful to add `<svg>` icons.
- The button text is a regular text node, no need to quote characters in the `value` attribute.
- Styling is easier, compare the selector `button` to `input[type="submit"], input[type="button"], ...`.
This rule will target the following input types:
- `<input type="button">`
- `<input type="submit">`
- `<input type="reset">`
- `<input type="image">`
## Rule details
Examples of **incorrect** code for this rule:
<validate name="incorrect" rules="prefer-button">
<input type="button">
<input type="button">
</validate>
Examples of **correct** code for this rule:
<validate name="correct" rules="prefer-button">
<button type="button"></button>
<button type="button"></button>
</validate>
## Options
This rule takes an optional object:
```javascript
{
"include": [],
"exclude": [],
}
```
### `include`
If set only types listed in this array generates errors.
### `exclude`
If set types listed in this array is ignored.
---
docType: presets
name: Configuration presets
---
# Configuration presets
HTML-validate comes with a few predefined presets.
Presets can be configured in `.htmlvalidate.json` using:
```json
{
"extends": ["html-validate:PRESET"]
}
```
Multiple presets can be set and will be enabled in the order they appear in `"extends"`.
See {@link usage configuration usage guide} for more details.
## Available presets
### `html-validate:recommended`
This is the default preset and enables most rules including standards validation, WCAG and best practices.
It is a superset of the other presets.
### `html-validate:standard`
Enables rules related to validating according to the WHATWG HTML standard (Living Standard).
Use this preset if you want validation similar to the Nu Html Checker and similar tools.
### `html-validate:a17y`
Enables rules related to accessibility.
Most rules but not all enabled rules relates to WCAG compliance.
On its own it will not validate if the document/template itself is valid but only if accessibility issues can be found.
This preset should be used togeher with `html-validate:standard` to ensure the document structure is valid (a requirement of WCAG) and if possible `html-validate:document` (to ensure references are valid, etc).
### `html-validate:document`
Enables rules requiring a full document to validate, i.e. not a partial template.
Examples include missing doctype and invalid references.
Use this preset together with other presets for full coverage.
This preset is enabled by plugins such as {@link usage/cypress cypress-html-validate} and {@link usage/protractor protractor-html-validate}.
## Comparision
......@@ -31,19 +31,31 @@ Run with:
### `extends`
Configuration can be extended from sharable configuration.
Configuration can be extended from bundled preset or sharable configurations.
```js
```json
{
"extends": [
/* bundled preset */
"html-validate:recommended",
/* npm package */
"my-npm-package",
"./file"
],
/* plugin with custom preset */
"my-plugin:custom",
/* local file */
"./file"
]
}
```
Each package and file must export a valid configuration object. Plugins may also
create [configuration presets](/dev/writing-plugins.html).
A list of bundled presets is available at the {@link rules/presets preset list}.
By default `html-validate:recommended` is used.
When using NPM packages and files each must export a valid configuration object.
Plugins may create [custom configuration presets](/dev/writing-plugins.html) by exposing one or more preset in the plugin declaration.
### `rules`
......
{
"name": "html-validate",
"version": "2.22.0",
"version": "2.23.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -2469,9 +2469,9 @@
}
},
"@html-validate/eslint-config": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@html-validate/eslint-config/-/eslint-config-1.5.0.tgz",
"integrity": "sha512-XbMa6P6VG5fLHywd1Iy/hy9R7Jxp3R6djPSpLzvRbOccDDyjaDJejlyXOhRnxGHhvuGQSH2ZrE3eweraToDXFg==",
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@html-validate/eslint-config/-/eslint-config-1.5.1.tgz",
"integrity": "sha512-4Kqgc/7EXw3DxE07dmeRh6un6yLX8hh2guA7UToxeOxLU9ni9ZGwN75ITBfA1OQ+ZLtJG09SEZp53MsgmaPnAQ==",
"dev": true,
"requires": {
"@typescript-eslint/eslint-plugin": "^2.12.0",
......@@ -2542,9 +2542,9 @@
}
},
"@html-validate/jest-config": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@html-validate/jest-config/-/jest-config-1.0.7.tgz",
"integrity": "sha512-0VeLc4MJLEK3UIE+YHpGo3PmumZoMGBCilHhufOscZz9eubc9+uVPiyjYmFoI+pUh8ty+GagPxFBU3wTnzAacA==",
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@html-validate/jest-config/-/jest-config-1.0.8.tgz",
"integrity": "sha512-Vc5doBGFRWeiZMs2VBS9Px0hQqZxE0ueDJUlBjiDoAc6MleUm2H7Qh1R/0FUVWO52DaN8kBDSR4qR3+HD/HgOw==",
"dev": true,
"requires": {
"jest-junit": "10.0.0"
......@@ -2557,9 +2557,9 @@
"dev": true
},
"@html-validate/semantic-release-config": {
"version": "1.0.20",
"resolved": "https://registry.npmjs.org/@html-validate/semantic-release-config/-/semantic-release-config-1.0.20.tgz",
"integrity": "sha512-S4gtnOm3fOQsF7I82YYnyrj1ZdtqlL/ucgfT8uIgtjpGOFwp4+79s7wncdodhl3IfI9bOpzMHkE7Fc9G0JrOEA==",
"version": "1.0.21",
"resolved": "https://registry.npmjs.org/@html-validate/semantic-release-config/-/semantic-release-config-1.0.21.tgz",
"integrity": "sha512-RwkB1JkmQ/wTxlDXteBJfGOpD7sfwn3VTwMqi2JwGE5AqyZQBPZAmIguDtfq6tXDlGXfLpCqprnUQLy6qHQXeQ==",
"dev": true,
"requires": {
"@semantic-release/changelog": "5.0.1",
......@@ -4425,9 +4425,9 @@
}
},
"@types/json-merge-patch": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/@types/json-merge-patch/-/json-merge-patch-0.0.4.tgz",
"integrity": "sha1-pSgtqWkKgSpiEoo0cIr0dqMI2UE=",
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@types/json-merge-patch/-/json-merge-patch-0.0.5.tgz",
"integrity": "sha512-7C4g+W/pPyhHUpwXCf2u5zuyPBaqKr7yjqcX+gxaqhxDIJHPEXCTqQwMeSkMOCKQH45++UQO1sRYNkjY9zN8nQ==",
"dev": true
},
"@types/json-schema": {
......@@ -4544,9 +4544,9 @@
}
},
"@types/yargs": {
"version": "13.0.8",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz",
"integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==",
"version": "13.0.9",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz",
"integrity": "sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==",
"dev": true,
"requires": {
"@types/yargs-parser": "*"
......@@ -4559,12 +4559,12 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "2.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.32.0.tgz",
"integrity": "sha512-nb1kSUa8cd22hGgxpGdVT6/iyP7IKyrnyZEGYo+tN8iyDdXvXa+nfsX03tJVeFfhbkwR/0CDk910zPbqSflAsg==",
"version": "2.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.33.0.tgz",
"integrity": "sha512-QV6P32Btu1sCI/kTqjTNI/8OpCYyvlGjW5vD8MpTIg+HGE5S88HtT1G+880M4bXlvXj/NjsJJG0aGcVh0DdbeQ==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "2.32.0",
"@typescript-eslint/experimental-utils": "2.33.0",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
"tsutils": "^3.17.1"
......@@ -4579,13 +4579,13 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "2.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.32.0.tgz",
"integrity": "sha512-oDWuB2q5AXsQ/mLq2N4qtWiBASWXPf7KhqXgeGH4QsyVKx+km8F6Vfqd3bspJQyhyCqxcbLO/jKJuIV3DzHZ6A==",
"version": "2.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.33.0.tgz",
"integrity": "sha512-qzPM2AuxtMrRq78LwyZa8Qn6gcY8obkIrBs1ehqmQADwkYzTE1Pb4y2W+U3rE/iFkSWcWHG2LS6MJfj6SmHApg==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/typescript-estree": "2.32.0",
"@typescript-eslint/typescript-estree": "2.33.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
},
......@@ -4618,14 +4618,14 @@
}
},
"@typescript-eslint/parser": {
"version": "2.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.32.0.tgz",
"integrity": "sha512-swRtH835fUfm2khchiOVNchU3gVNaZNj2pY92QSx4kXan+RzaGNrwIRaCyX8uqzmK0xNPzseaUYHP8CsmrsjFw==",
"version": "2.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.33.0.tgz",
"integrity": "sha512-AUtmwUUhJoH6yrtxZMHbRUEMsC2G6z5NSxg9KsROOGqNXasM71I8P2NihtumlWTUCRld70vqIZ6Pm4E5PAziEA==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "2.32.0",
"@typescript-eslint/typescript-estree": "2.32.0",
"@typescript-eslint/experimental-utils": "2.33.0",
"@typescript-eslint/typescript-estree": "2.33.0",
"eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
......@@ -4638,9 +4638,9 @@
}
},
"@typescript-eslint/typescript-estree": {
"version": "2.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.32.0.tgz",
"integrity": "sha512-hQpbWM/Y2iq6jB9FHYJBqa3h1R9IEGodOtajhb261cVHt9cz30AKjXM6WP7LxJdEPPlyJ9rPTZVgBUgZgiyPgw==",
"version": "2.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.33.0.tgz",
"integrity": "sha512-d8rY6/yUxb0+mEwTShCQF2zYQdLlqihukNfG9IUlLYz5y1CH6G/9XYbrxQLq3Z14RNvkCC6oe+OcFlyUpwUbkg==",
"dev": true,
"requires": {
"debug": "^4.1.1",
......@@ -5531,18 +5531,18 @@
"dev": true
},
"autoprefixer": {
"version": "9.7.6",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.6.tgz",
"integrity": "sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ==",
"version": "9.8.0",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.0.tgz",
"integrity": "sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A==",
"dev": true,
"requires": {
"browserslist": "^4.11.1",
"caniuse-lite": "^1.0.30001039",
"browserslist": "^4.12.0",
"caniuse-lite": "^1.0.30001061",
"chalk": "^2.4.2",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
"postcss": "^7.0.27",
"postcss-value-parser": "^4.0.3"
"postcss": "^7.0.30",
"postcss-value-parser": "^4.1.0"
},
"dependencies": {
"ansi-styles": {
......@@ -5555,21 +5555,21 @@
}
},
"browserslist": {
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz",
"integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==",
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
"integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001038",
"electron-to-chromium": "^1.3.390",
"caniuse-lite": "^1.0.30001043",
"electron-to-chromium": "^1.3.413",
"node-releases": "^1.1.53",
"pkg-up": "^2.0.0"
}
},
"caniuse-lite": {
"version": "1.0.30001039",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001039.tgz",
"integrity": "sha512-SezbWCTT34eyFoWHgx8UWso7YtvtM7oosmFoXbCkdC6qJzRfBTeTgE9REtKtiuKXuMwWTZEvdnFNGAyVMorv8Q==",
"version": "1.0.30001061",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001061.tgz",
"integrity": "sha512-SMICCeiNvMZnyXpuoO+ot7FHpMVPlrsR+HmfByj6nY4xYDHXLqMTbgH7ecEkDNXWkH1vaip+ZS0D7VTXwM1KYQ==",
"dev": true
},
"chalk": {
......@@ -5584,9 +5584,9 @@
}
},
"electron-to-chromium": {
"version": "1.3.398",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.398.tgz",
"integrity": "sha512-BJjxuWLKFbM5axH3vES7HKMQgAknq9PZHBkMK/rEXUQG9i1Iw5R+6hGkm6GtsQSANjSUrh/a6m32nzCNDNo/+w==",
"version": "1.3.441",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.441.tgz",
"integrity": "sha512-leBfJwLuyGs1jEei2QioI+PjVMavmUIvPYidE8dCCYWLAq0uefhN3NYgDNb8WxD3uiUNnJ3ScMXg0upSlwySzQ==",
"dev": true
},
"find-up": {
......@@ -5609,9 +5609,9 @@
}
},
"node-releases": {
"version": "1.1.53",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz",
"integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==",
"version": "1.1.55",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.55.tgz",
"integrity": "sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w==",
"dev": true
},
"p-limit": {
......@@ -5654,9 +5654,9 @@
}
},
"postcss": {
"version": "7.0.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz",
"integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==",
"version": "7.0.30",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.30.tgz",
"integrity": "sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
......@@ -5676,9 +5676,9 @@
}
},
"postcss-value-parser": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz",
"integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"dev": true
},
"supports-color": {
......@@ -9715,9 +9715,9 @@
}
},
"eslint-plugin-jest": {
"version": "23.10.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.10.0.tgz",
"integrity": "sha512-cHC//nesojSO1MLxVmFJR/bUaQQG7xvMHQD8YLbsQzevR41WKm8paKDUv2wMHlUy5XLZUmNcWuflOi4apS8D+Q==",
"version": "23.13.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.13.1.tgz",
"integrity": "sha512-TRLJH6M6EDvGocD98a7yVThrAOCK9WJfo9phuUb0MJptcrOYZeCKzC9aOzZCD93sxXCsiJVZywaTHdI/mAi0FQ==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "^2.5.0"
......@@ -16604,9 +16604,9 @@
}
},
"marked": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz",
"integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-1.1.0.tgz",
"integrity": "sha512-EkE7RW6KcXfMHy2PA7Jg0YJE1l8UPEZE8k45tylzmZM30/r1M1MUXWQfJlrSbsTeh7m/XTwHbWUENvAJZpp1YA==",
"dev": true
},
"marked-terminal": {
......@@ -26761,9 +26761,9 @@
"dev": true
},
"ts-jest": {
"version": "25.5.1",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-25.5.1.tgz",
"integrity": "sha512-kHEUlZMK8fn8vkxDjwbHlxXRB9dHYpyzqKIGDNxbzs+Rz+ssNDSDNusEK8Fk/sDd4xE6iKoQLfFkFVaskmTJyw==",
"version": "26.0.0",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.0.0.tgz",
"integrity": "sha512-eBpWH65mGgzobuw7UZy+uPP9lwu+tPp60o324ASRX4Ijg8UC5dl2zcge4kkmqr2Zeuk9FwIjvCTOPuNMEyGWWw==",
"dev": true,
"requires": {
"bs-logger": "0.x",
......@@ -26773,15 +26773,21 @@
"lodash.memoize": "4.x",
"make-error": "1.x",
"micromatch": "4.x",
"mkdirp": "0.x",
"semver": "6.x",
"mkdirp": "1.x",
"semver": "7.x",
"yargs-parser": "18.x"
},
"dependencies": {
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
"dev": true
}
}
......
import path from "path";
import minimatch from "minimatch";
const glob: any = jest.requireActual("glob");
......@@ -9,7 +10,7 @@ interface Options {
let mockFiles: string[] = null;
function setMockFiles(files: string[]): void {
mockFiles = files;
mockFiles = files.map((cur) => path.normalize(cur));
}
function resetMock(): void {
......@@ -25,7 +26,10 @@ function syncMock(pattern: string, options: Options = {}): string[] {
/* slice the cwd away since it is prepended automatically and makes it harder
* to test with */
const cwd = options.cwd || "";
const dir = cwd.replace(process.cwd(), "").replace(/^\/(.*)/, "$1/");
const dir = cwd
.replace(process.cwd(), "")
.replace("\\", "/")
.replace(/^\/(.*)/, `$1${path.sep}`);
let src = mockFiles;
if (dir) {
......
......@@ -2,6 +2,7 @@ jest.mock("fs");
jest.mock("glob");
import fs from "fs";
import path from "path";
import glob from "glob";
import { CLI } from "./cli";
......@@ -41,9 +42,9 @@ describe("expandFiles()", () => {
expect.assertions(3);
const spy = jest.spyOn(glob, "sync");
expect(cli.expandFiles(["foo.html", "bar/**/*.html"])).toEqual([
"foo.html",
"bar/fred.html",
"bar/barney.html",
path.normalize("foo.html"),
path.normalize("bar/fred.html"),
path.normalize("bar/barney.html"),
]);
expect(spy).toHaveBeenCalledWith("foo.html", expect.anything());
expect(spy).toHaveBeenCalledWith("bar/**/*.html", expect.anything());
......@@ -52,26 +53,26 @@ describe("expandFiles()", () => {
it("should expand directories (default extensions)", () => {
expect.assertions(1);
expect(cli.expandFiles(["bar"])).toEqual([
"bar/fred.html",
"bar/barney.html",
path.normalize("bar/fred.html"),
path.normalize("bar/barney.html"),
]);
});
it("should expand directories (explicit extensions)", () => {
expect.assertions(1);
expect(cli.expandFiles(["bar"], { extensions: ["js", "json"] })).toEqual([
"bar/fred.json",
"bar/barney.js",
path.normalize("bar/fred.json"),
path.normalize("bar/barney.js"),
]);
});
it("should expand directories (no extensions => all files)", () => {
expect.assertions(1);
expect(cli.expandFiles(["bar"], { extensions: [] })).toEqual([
"bar/fred.html",
"bar/fred.json",
"bar/barney.html",
"bar/barney.js",
path.normalize("bar/fred.html"),
path.normalize("bar/fred.json"),
path.normalize("bar/barney.html"),
path.normalize("bar/barney.js"),
]);
});
......
......@@ -27,9 +27,9 @@ function directoryPattern(extensions: string[]): string {
case 0:
return "**";
case 1:
return `**/*.${extensions[0]}`;
return path.join("**", `*.${extensions[0]}`);
default:
return `**/*.{${extensions.join(",")}}`;
return path.join("**", `*.{${extensions.join(",")}}`);
}
}
......
......@@ -13,6 +13,7 @@ import { ConfigData, TransformMap } from "./config-data";
import defaultConfig from "./default";
import { ConfigError } from "./error";
import { parseSeverity, Severity } from "./severity";
import Presets from "./presets";
interface TransformerEntry {
pattern: RegExp;
......@@ -28,9 +29,6 @@ interface LoadedPlugin extends Plugin {
originalName: string;
}
const recommended = require("./recommended");
const document = require("./document");
let rootDirCache: string = null;
const ajv = new Ajv({ jsonPointers: true });
......@@ -378,12 +376,9 @@ export class Config {
const configs: Map<string, ConfigData> = new Map();
/* builtin presets */
configs.set("html-validate:recommended", recommended);
configs.set("html-validate:document", document);
/* aliases for convenience */
configs.set("htmlvalidate:recommended", recommended);
configs.set("htmlvalidate:document", document);
for (const [name, config] of Object.entries(Presets)) {
configs.set(name, config);
}
/* presets from plugins */
for (const plugin of plugins) {
......
import { ConfigData } from "../config-data";
const config: ConfigData = {
rules: {
"deprecated-rule": "warn",
"empty-heading": "error",
"empty-title": "error",
"meta-refresh": "error",
"no-autoplay": ["error", { include: ["audio", "video"] }],
"no-dup-id": "error",
"no-redundant-role": "error",
"prefer-native-element": "error",
"svg-focusable": "error",
"wcag/h30": "error",
"wcag/h32": "error",
"wcag/h36": "error",
"wcag/h37": "error",
"wcag/h67": "error",
"wcag/h71": "error",
},
};
export = config;
module.exports = {
import { ConfigData } from "../config-data";
const config: ConfigData = {
rules: {
"input-missing-label": "error",
"heading-level": "error",
......@@ -7,3 +9,5 @@ module.exports = {
"require-sri": "error",
},
};
export = config;
import { ConfigData } from "../config-data";
import a17y from "./a17y";
import document from "./document";
import recommended from "./recommended";
import standard from "./standard";
const presets: Record<string, ConfigData> = {
"html-validate:a17y": a17y,
"html-validate:document": document,
"html-validate:recommended": recommended,
"html-validate:standard": standard,
/* @deprecated aliases */
"htmlvalidate:recommended": recommended,
"htmlvalidate:document": document,
};
export = presets;