Commits (65)
......@@ -42,9 +42,8 @@ pages:
artifacts:
paths:
- public
only:
- tags
- triggers
rules:
- if: '$CI_COMMIT_REF_NAME == "master" && $CI_COMMIT_MESSAGE =~ /^chore\(release\):/'
script:
- npm run --if-present build
- npm run build:docs
......@@ -161,6 +160,7 @@ Dry run:
extends: .release
rules:
- if: '$CI_COMMIT_REF_NAME == "master"'
- if: '$CI_COMMIT_REF_NAME =~ /^release\//'
script:
- npm exec semantic-release -- --dry-run
......@@ -169,6 +169,8 @@ Release:
rules:
- if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "web"'
when: manual
- if: '$CI_COMMIT_REF_NAME =~ /^release\// && $CI_PIPELINE_SOURCE == "web"'
when: manual
script:
- npm exec semantic-release
......
# html-validate changelog
## [6.0.0](https://gitlab.com/html-validate/html-validate/compare/v5.5.0...v6.0.0) (2021-09-26)
### ⚠ BREAKING CHANGES
- **htmlvalidate:** This change only affects API users, the CLI tool continues to
work as before.
The default configuration loader has changed from `FileSystemConfigLoader` to
`StaticConfigLoader`, i.e. the directory traversal looking for
`.htmlvalidate.json` configuration files must now be explicitly enabled.
See (MIGRATION.md)[https://html-validate.org/migration/index.html] for details.
- **event:** `ConfigReadyEvent` passes `ResolvedConfig` instance instead of `ConfigData`
- **meta:** `MetaElement.attribute` has changed from `string[]` to
`MetaAttribute[]` and both `requiredAttributes` and `deprecatedAttributes` has
been merged into object. This only affects API usage, primarily custom rules
accessing attribute metadata.See `MIGRATION.md` for details.
The old format is deprecated but is internally converted as to not break user
configuration. For compatibility it will probably be around for quite a while
but users should try to migrate as soon as possible.
### Features
- bump required node version to 12.22 ([80f3399](https://gitlab.com/html-validate/html-validate/commit/80f3399a3f863a81fcb505a4d0763bb8cffbbdeb))
- **elements:** migrate bundled html5 element metadata to new attribute syntax ([6132b82](https://gitlab.com/html-validate/html-validate/commit/6132b829e085689bd4d07aaf072e100609a950bd))
- **event:** `ConfigReadyEvent` passes `ResolvedConfig` instance instead of `ConfigData` ([5808a6b](https://gitlab.com/html-validate/html-validate/commit/5808a6b5ad3473f39b850778c1ae46d147abf1f6))
- **htmlvalidate:** use `StaticConfigLoader` by default ([bb94341](https://gitlab.com/html-validate/html-validate/commit/bb94341e411a40745d36362be37e0984420c6771))
- **meta:** add new list property to `MetaAttribute` ([4c1e3c9](https://gitlab.com/html-validate/html-validate/commit/4c1e3c97e741710e30765f9b3519b586462a2b87))
- **meta:** extend element attribute metadata ([6506aa6](https://gitlab.com/html-validate/html-validate/commit/6506aa6f109a5cb614d6e2817e4d26322758096b)), closes [#71](https://gitlab.com/html-validate/html-validate/issues/71)
### Dependency upgrades
- **deps:** update dependency espree to v9 ([3e0ea96](https://gitlab.com/html-validate/html-validate/commit/3e0ea96a4f8fd76db7a1113ff6ca8ea29edd62d9))
### [4.14.1](https://gitlab.com/html-validate/html-validate/compare/v4.14.0...v4.14.1) (2021-09-18)
### Bug Fixes
- **jest:** handle when `jest-diff` default import is object ([74f9b84](https://gitlab.com/html-validate/html-validate/commit/74f9b8424e0bf5071823e82bfc79d8904025808a))
## [5.5.0](https://gitlab.com/html-validate/html-validate/compare/v5.4.1...v5.5.0) (2021-09-05)
### Features
......
# Migration guide
## Upgrading to `%version%`
- CLI users: No required changes but if custom element metadata is present it can benefit from upgrading format.
- API users: Breaking changes!
### Configuration changes
The format for specifying attribute metadata has changed.
This will probably not affect most users but if you have custom element metadata (e.g. `elements.json`) and specify attribute restrictions you should migrate to the new format.
If you do not use custom element metadata you can safely upgrade to this version without any changes.
If you need to maintain backwards compatibility with older versions of `html-validate` you can safely hold of the migration (e.g. you publish a component framework with bundled element metadata and don't want to force an update for end users).
The old format is deprecated but will continue to be supported for now.
Previously the attributes was specified as an array of possible values (strings or regular expressions).
Boolean attributes was specified as `[]` and when value could be omitted it used the magic value `[""]`.
```jsonc
{
"my-custom-input": {
"attributes": {
/* enumeration: must have one of the specified values */
"type": ["text", "email", "tel"],
/* boolean: should not have a value */
"disabled": [],
/* allow omitting value, e.g. it can be set as a boolean or it should be "true" or "false" */
"multiline": ["", "true", "false"]
}
}
}
```
To migrate the array is changed to an object with the properties `enum`, `boolean` and `omit`:
```diff
{
"my-custom-input": {
"attributes": {
/* enumeration: must have one of the specified values */
- "type": ["text", "email", "tel"],
+ "type": {
+ "enum": ["text", "email", "tel"]
+ },
/* boolean: should not have a value */
- "disabled": [],
+ "disabled": {
+ "boolean": true
+ },
/* allow omitting value, e.g. it can be set as a boolean or it should be "true" or "false" */
- "multiline": ["", "true", "false"]
+ "multiline": {
+ "omit": true,
+ "enum": ["true", "false"] // the value "" is no longer specified in the enumeration
+ }
}
}
}
```
The properties `requiredAttributes` and `deprecatedAttributes` have been integrated into the same object:
```diff
{
"my-custom-input": {
- "requiredAttributes": ["type"],
- "deprecatedAttributes": ["autocorrect"]
+ "attributes": {
+ "type": {
+ "required": true
+ },
+ "autocorrect": {
+ "deprecated": true
+ }
+ }
}
}
```
It is perfectly valid to specify attributes as an empty object which is used to signal that an attribute is exists.
When [#68](https://gitlab.com/html-validate/html-validate/-/issues/68) (validate know attributes) is implemented it will be required to list all known attributes but for now no validation will happen without any properties set.
```jsonc
{
"my-custom-input": {
"attributes": {
/* signal that the "foobar" attribute exists but no validation will occur */
"foobar": {}
}
}
}
```
### API changes
If you use `MetaElement` to query attribute metadata you must use the new object.
Typically this should only be if you have a custom rule dealing with attributes.
While the old format is supported in userland internally it is converted to the new format.
For instance, given a rule such as:
```ts
function myCustomRule(node: DOMNode, attr: Attribute, rule: string[]): void {
/* ... */
}
const meta = node.meta.attributes;
for (const attr of node.attributes) {
if (meta[attr.key]) {
myCustomRule(node, attr, meta[attr.key]);
}
}
```
The signature of the function must be changed to:
```diff
-function myCustomRule(node: DOMNode, attr: Attribute, rule: string[]): void {
+function myCustomRule(node: DOMNode, attr: Attribute, rule: MetaAttribute): void {
/* ... */
}
```
If you want backwards compatibility you must handle both `string[]` and `MetaAttribute`, `Array.isArray` can be used to distinguish between the two:
```ts
function myCustomRule(node: DOMNode, attr: Attribute, rule: string[] | MetaAttribute): void {
if (Array.isArray(rule)) {
/* legacy code path */
} else {
/* modern code path */
}
}
```
If the rule used logic to determine if the attribute is boolean it must be changed to use the `boolean` property:
```diff
-const isBoolean = rule.length === 0;
+const isBoolean = rule.boolean;
```
If the rule used logic to determine if the attribute value can be omitted it must be changed to use the `omitted` property:
```diff
-const canOmit = rule.includes("");
+const canOmit = rule.omit;
```
The list of allowed values are must be read from the `enum` property but rules must take care to ensure they work even if `enum` is not set (`undefined`):
```diff
-const valid = rule.includes(attr.value);
+const valid = !rule.enum || rule.enum.includes(attr.value);
```
If you used `requiredAttributes` or `deprecatedAttributes` these have now been integrated into the same object:
```diff
-const isDeprecated = meta.deprecatedAttributes.includes(attr.key);
+const isDeprecated = meta.attribute[attr.key]?.deprecated;
```
### `ConfigReadyEvent`
**Only affects API users.**
If you have a rule or plugin listening to the `ConfigReadyEvent` event the datatype of the `config` property has changed from `ConfigData` to `ResolvedConfig`.
For most part it contains the same information but is normalized, for instance rules are now always passed as `Record<RuleID, [Severity, Options]>`.
Configured transformers, plugins etc are resolved instances and fields suchs as `root` and `extends` will never be present.
### `StaticConfigLoader`
**Only affects API users.**
The default configuration loader has changed from {@link dev/using-api#filesystemconfigloader `FileSystemConfigLoader`} to {@link dev/using-api#staticconfigloader- `StaticConfigLoader`}, i.e. the directory traversal looking for `.htmlvalidate.json` configuration files must now be explicitly enabled.
This will reduce the dependency on the NodeJS `fs` module and make it easier to use the library in browsers.
To restore the previous behaviour you must now enable `FileSystemConfigLoader`:
```diff
import { HtmlValidate, FileSystemConfigLoader } from "html-validate";
-const htmlvalidate = new HtmlValidate();
+const loader = new FileSystemConfigLoader();
+const htmlvalidate = new HtmlValidate(loader);
```
If you pass configuration to the constructor you now pass it to the loader instead:
```diff
import { HtmlValidate, FileSystemConfigLoader } from "html-validate";
-const htmlvalidate = new HtmlValidate({ ... });
+const loader = new FileSystemConfigLoader({ ... });
+const htmlvalidate = new HtmlValidate(loader);
```
If you use the `root` property as a workaround for the directory traversal you can now drop the workaround and rely on `StaticConfigLoader`:
```diff
import { HtmlValidate } from "html-validate";
-const htmlvalidate = new HtmlValidate({
- root: true,
-});
+const htmlvalidate = new HtmlValidate();
```
The CLI class is not affected as it will enable `FileSystemConfigLoader` automatically, so the following code will continue to work as expected:
```ts
const cli = new CLI();
const htmlvalidate = cli.getValidator();
```
......@@ -14,6 +14,10 @@ HTML-validate was created by David Sveningsson in early 2016 with a few goals in
- First-class support for views, components and templates, including when using
javascript frameworks.
## Talks
- [HTML5 validation with HTML-validate](https://video.fosdem.org/2021/D.javascript/html5_validation.webm) at FOSDEM 2021
## Contact
If you found a bug or want to suggest a new feature/enhancement please [file a
......
......@@ -167,13 +167,15 @@ console.log(stylish(report.results));
## Configuration loaders
By default `HtmlValidate` traverses the file system looking for configuration files such as `.htmlvalidate.json`.
If this behaviour is not desired a custom loader can be used instead:
Since v6 the `HtmlValidate` API uses `StaticConfigLoader` by default which only loads static configuration (configuration passed to constructor or calls to validation functions).
The CLI tool uses `FileSystemConfigLoader` instead which traversess the file system looking for configuration files such as `.htmlvalidate.json`.
To specify a loader pass it as the first argument to constructor:
```ts
import { StaticConfigLoader, HtmlValidate } from "html-validate";
import { FileSystemConfigLoader, HtmlValidate } from "html-validate";
const loader = new StaticConfigLoader();
const loader = new FileSystemConfigLoader();
const htmlvalidate = new HtmlValidate(loader);
```
......@@ -206,7 +208,7 @@ class MyCustomLoader extends ConfigLoader {
The custom loader is used the same as builtin loaders:
```diff
-const loader = new StaticConfigLoader();
-const loader = new FileSystemConfigLoader();
+const loader = new MyCustomLoader();
const htmlvalidate = new HtmlValidate(loader);
```
......@@ -221,15 +223,15 @@ htmlvalidate.validateString("..", "my-fancy-handle");
This will generate calls to `getConfigFor("foo.html")` and `getConfigFor("my-fancy-handle")` respectively.
While `validateFile` requires the file to be readable, the second argument to `validateString` can be any handle the API user wants as long as the loader can understand it.
### `FileSystemConfigLoader([config: ConfigData])` (default)
### `FileSystemConfigLoader([config: ConfigData])`
Default loader which traverses filesystem looking for `.htmlvalidate.json` configuration files, starting at the directory of the target filename.
Loader which traverses filesystem looking for `.htmlvalidate.json` configuration files, starting at the directory of the target filename.
The result from the configuration files are merged both with a global configuration and optionally explicit overrides from the calls to `validateFile`, `validateString` and `validateSource`.
### `StaticConfigLoader([config: ConfigData])`
### `StaticConfigLoader([config: ConfigData])` (default)
Loads configuration only from the configuration passed to the constructor or explicit overrides to `validateString(..)`.
Default loader which loads configuration only from the configuration passed to the constructor or explicit overrides to `validateString(..)`.
```ts
const loader = StaticConfigLoader({
......
......@@ -5,6 +5,10 @@ module.exports = function highlight() {
hljs.configure(options);
}
function registerAliases(alias, options) {
hljs.registerAliases(alias, options);
}
function render(code, lang) {
if (lang) {
return hljs.highlight(code, { language: lang }).value;
......@@ -14,6 +18,7 @@ module.exports = function highlight() {
}
render.configure = configure;
render.registerAliases = registerAliases;
return render;
};
......@@ -24,12 +24,15 @@ module.exports = new Package("html-validate-docs", [
highlight.configure({
languages: ["js", "json", "typescript", "html", "shell"],
});
highlight.registerAliases("jsonc", { languageName: "json" });
})
.factory(require("./changelog"))
.factory(require("./migration"))
.config(function (readFilesProcessor, changelogFileReader) {
.config(function (readFilesProcessor, changelogFileReader, migrationFileReader) {
readFilesProcessor.fileReaders.push(changelogFileReader);
readFilesProcessor.fileReaders.push(migrationFileReader);
})
.config(function (getLinkInfo) {
......@@ -52,6 +55,11 @@ module.exports = new Package("html-validate-docs", [
basePath: ".",
fileReader: "changelogFileReader",
},
{
include: "MIGRATION.md",
basePath: ".",
fileReader: "migrationFileReader",
},
];
copySchema.outputFolder = "schemas";
......@@ -116,7 +124,7 @@ module.exports = new Package("html-validate-docs", [
});
computeIdsProcessor.idTemplates.push({
docTypes: ["changelog"],
docTypes: ["changelog", "migration"],
getId: function (doc) {
return doc.fileInfo.baseName.toLowerCase();
},
......@@ -126,7 +134,7 @@ module.exports = new Package("html-validate-docs", [
});
computePathsProcessor.pathTemplates.push({
docTypes: ["changelog"],
docTypes: ["changelog", "migration"],
getPath: function (doc) {
const dirname = path.dirname(doc.fileInfo.relativePath);
return path.join(dirname, doc.fileInfo.baseName.toLowerCase(), "index.html");
......
module.exports = function migrationFileReader() {
return {
name: "migrationFileReader",
getDocs: function (fileInfo) {
return [
{
docType: "migration",
title: "Migration guide",
content: fileInfo.content,
startingLine: 1,
},
];
},
};
};
......@@ -40,6 +40,7 @@
<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>{@link usage Getting started}</li>
<li>{@link migration Migrating from old versions}</li>
<li>{@link usage/cli Using CLI}</li>
<li>{@link usage/elements Elements}</li>
<li>{@link rules/presets Presets}</li>
......
{% extends "base.template.html" %}
{% block content %}
{{ doc.description | marked }}
{% endblock %}
......@@ -21,7 +21,9 @@ Array [
Object {
"column": 23,
"context": Object {
"allowed": Array [],
"allowed": Object {
"boolean": true,
},
"attribute": "quacks",
"element": "my-component",
"value": "duck",
......@@ -78,11 +80,13 @@ Array [
Object {
"column": 21,
"context": Object {
"allowed": Array [
"huey",
"dewey",
"louie",
],
"allowed": Object {
"enum": Array [
"huey",
"dewey",
"louie",
],
},
"attribute": "duck",
"element": "my-component",
"value": "flintheart",
......@@ -104,6 +108,8 @@ Array [
]
`;
exports[`docs/guide/metadata/restrict-attributes.md inline validation: omit 1`] = `Array []`;
exports[`docs/guide/metadata/restrict-attributes.md inline validation: regexp 1`] = `
Array [
Object {
......@@ -113,9 +119,11 @@ Array [
Object {
"column": 22,
"context": Object {
"allowed": Array [
/\\^\\\\d\\+\\$/,
],
"allowed": Object {
"enum": Array [
/\\^\\\\d\\+\\$/,
],
},
"attribute": "ducks",
"element": "my-component",
"value": "huey",
......
......@@ -7,6 +7,8 @@ markup["regexp"] = `<my-component ducks="3">...</my-component>
<my-component ducks="huey">...</my-component>`;
markup["boolean"] = `<my-component quacks>...</my-component>
<my-component quacks="duck">...</my-component>`;
markup["omit"] = `<my-component quacks>...</my-component>
<my-component quacks="duck">...</my-component>`;
markup["required"] = `<my-component duck="dewey">...</my-component>
<my-component>...</my-component>`;
markup["deprecated"] = `<my-component duck="dewey">...</my-component>
......@@ -15,31 +17,37 @@ markup["deprecated"] = `<my-component duck="dewey">...</my-component>
describe("docs/guide/metadata/restrict-attributes.md", () => {
it("inline validation: enum", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"duck":["huey","dewey","louie"]}}}],"extends":["html-validate:recommended"]});
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"duck":{"enum":["huey","dewey","louie"]}}}}],"extends":["html-validate:recommended"]});
const report = htmlvalidate.validateString(markup["enum"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: regexp", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"ducks":["/\\d+/"]}}}],"extends":["html-validate:recommended"]});
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"ducks":{"enum":["/\\d+/"]}}}}],"extends":["html-validate:recommended"]});
const report = htmlvalidate.validateString(markup["regexp"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: boolean", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"quacks":[]}}}],"extends":["html-validate:recommended"]});
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"quacks":{"boolean":true}}}}],"extends":["html-validate:recommended"]});
const report = htmlvalidate.validateString(markup["boolean"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: omit", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"quacks":{"omit":true,"enum":["duck","dog"]}}}}],"extends":["html-validate:recommended"]});
const report = htmlvalidate.validateString(markup["omit"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: required", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"requiredAttributes":["duck"]}}],"extends":["html-validate:recommended"]});
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"duck":{"required":true}}}}],"extends":["html-validate:recommended"]});
const report = htmlvalidate.validateString(markup["required"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: deprecated", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"deprecatedAttributes":["duck"]}}],"extends":["html-validate:recommended"]});
const htmlvalidate = new HtmlValidate({"elements":["html5",{"my-component":{"flow":true,"attributes":{"duck":{"deprecated":true}}}}],"extends":["html-validate:recommended"]});
const report = htmlvalidate.validateString(markup["deprecated"]);
expect(report.results).toMatchSnapshot();
});
......
......@@ -2,7 +2,9 @@
"my-component": {
"flow": true,
"attributes": {
"quacks": []
"quacks": {
"boolean": true
}
}
}
}
{
"my-component": {
"flow": true,
"deprecatedAttributes": ["duck"]
"attributes": {
"duck": {
"deprecated": true
}
}
}
}
......@@ -2,7 +2,9 @@
"my-component": {
"flow": true,
"attributes": {
"duck": ["huey", "dewey", "louie"]
"duck": {
"enum": ["huey", "dewey", "louie"]
}
}
}
}
{
"my-component": {
"flow": true,
"attributes": {
"quacks": {
"omit": true,
"enum": ["duck", "dog"]
}
}
}
}
......@@ -2,7 +2,9 @@
"my-component": {
"flow": true,
"attributes": {
"ducks": ["/\\d+/"]
"ducks": {
"enum": ["/\\d+/"]
}
}
}
}
{
"my-component": {
"flow": true,
"requiredAttributes": ["duck"]
"attributes": {
"duck": {
"required": true
}
}
}
}
......@@ -17,7 +17,9 @@ Assuming our `<my-component>` element has a `duck` attribute which can take the
"my-component": {
"flow": true,
"attributes": {
"duck": ["huey", "dewey", "louie"]
"duck": {
"enum": ["huey", "dewey", "louie"]
}
}
}
}
......@@ -35,7 +37,9 @@ We can also specify regular expressions by surrounding the string with `/` (reme
"my-component": {
"flow": true,
"attributes": {
"ducks": ["/\\d+/"]
"ducks": {
"enum": ["/\\d+/"]
}
}
}
}
......@@ -51,18 +55,19 @@ We can also specify regular expressions by surrounding the string with `/` (reme
<strong>Tips</strong>
<ul>
<li>Regular expressions and enumeration can be used at the same time.</li>
<li>The empty string <code>""</code> is also valid and means that the value must be empty, e.g. <code>ducks=""</code></li>
</ul>
</div>
To force a boolean value similar to `disabled`, `selected` etc use an empty array `[]`:
To force a boolean value similar to `disabled`, `selected` etc instead set the `boolean` property to `true`.
```json
{
"my-component": {
"flow": true,
"attributes": {
"quacks": []
"quacks": {
"boolean": true
}
}
}
}
......@@ -73,15 +78,43 @@ To force a boolean value similar to `disabled`, `selected` etc use an empty arra
<my-component quacks="duck">...</my-component>
</validate>
## Define required attributes
If the value can be omitted (same as the empty value `""`) set the `omit` property to `true`.
This is often combined with `enum` but it should have a default value.
To define a list of required attributes use `requiredAttributes`:
For instance, to allow the `quacks` attribute to be set to either `duck` or `dog` but at the same time not require a value to be set at all `omit` can be used.
```json
{
"my-component": {
"flow": true,
"requiredAttributes": ["duck"]
"attributes": {
"quacks": {
"omit": true,
"enum": ["duck", "dog"]
}
}
}
}
```
<validate name="omit" elements="restrict-attributes-omit.json">
<my-component quacks>...</my-component>
<my-component quacks="duck">...</my-component>
</validate>
## Required attributes
Required attributes (attributes that must be set on an element) can be specified by setting `required` to `true`:
```json
{
"my-component": {
"flow": true,
"attributes": {
"duck": {
"required": true
}
}
}
}
```
......@@ -93,13 +126,17 @@ To define a list of required attributes use `requiredAttributes`:
## Deprecating attributes
Similar to required attribute we can use `deprecatedAttributes` to deprecate attributes:
Similar to required attribute we can set `deprecated` to true or a message to mark an attribute as deprecated:
```json
{
"my-component": {
"flow": true,
"deprecatedAttributes": ["duck"]
"attributes": {
"duck": {
"deprecated": true
}
}
}
}
```
......
......@@ -11,9 +11,11 @@ Array [
Object {
"column": 4,
"context": Object {
"allowed": Array [
/\\^\\.\\*\\$/,
],
"allowed": Object {
"enum": Array [
/\\^\\.\\*\\$/,
],
},
"attribute": "href",
"element": "a",
"value": "",
......@@ -30,30 +32,33 @@ Array [
Object {
"column": 14,
"context": Object {
"allowed": Array [
"button",
"checkbox",
"color",
"date",
"datetime-local",
"email",
"file",
"hidden",
"image",
"month",
"number",
"password",
"radio",
"range",
"reset",
"search",
"submit",
"tel",
"text",
"time",
"url",
"week",
],
"allowed": Object {
"enum": Array [
"button",
"checkbox",
"color",
"date",
"datetime-local",
"email",
"file",
"hidden",
"image",
"month",
"number",
"password",
"radio",
"range",
"reset",
"search",
"submit",
"tel",
"text",
"time",
"url",
"week",
],
"required": true,
},
"attribute": "type",
"element": "input",
"value": "foobar",
......