html-validate 10.3.1 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core.js +49 -16
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js +40 -2
- package/dist/cjs/elements.js.map +1 -1
- package/dist/cjs/meta-helper.js +5 -1
- package/dist/cjs/meta-helper.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/esm/core.js +49 -16
- package/dist/esm/core.js.map +1 -1
- package/dist/esm/elements.js +40 -2
- package/dist/esm/elements.js.map +1 -1
- package/dist/esm/meta-helper.js +5 -1
- package/dist/esm/meta-helper.js.map +1 -1
- package/dist/schema/elements.json +2 -2
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +23 -1
- package/dist/types/index.d.ts +23 -1
- package/package.json +2 -2
package/dist/cjs/meta-helper.js
CHANGED
|
@@ -45,11 +45,15 @@ function allowedIfParentIsPresent(...tags) {
|
|
|
45
45
|
return `requires ${expected} as parent`;
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
function hasKeyword(attr, keyword) {
|
|
49
|
+
return attr.toLowerCase().split(/\s+/).includes(keyword);
|
|
50
|
+
}
|
|
48
51
|
const metadataHelper = {
|
|
49
52
|
allowedIfAttributeIsPresent,
|
|
50
53
|
allowedIfAttributeIsAbsent,
|
|
51
54
|
allowedIfAttributeHasValue,
|
|
52
|
-
allowedIfParentIsPresent
|
|
55
|
+
allowedIfParentIsPresent,
|
|
56
|
+
hasKeyword
|
|
53
57
|
};
|
|
54
58
|
|
|
55
59
|
function defineMetadata(metatable) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta-helper.js","sources":["../../src/meta/helper.ts","../../src/meta/define-metadata.ts"],"sourcesContent":["import { naturalJoin } from \"../utils/natural-join\";\nimport { type MetaAttributeAllowedCallback } from \"./element\";\nimport { type HtmlElementLike } from \"./html-element-like\";\n\n/**\n * Helpers when writing element metadata.\n *\n * @public\n */\nexport interface MetadataHelper {\n\t/** Returns an error if another attribute is omitted, i.e. it requires another attribute to be present to pass. */\n\tallowedIfAttributeIsPresent(this: void, ...attr: string[]): MetaAttributeAllowedCallback;\n\n\t/** Returns an error if another attribute is present, i.e. it requires another attribute to be omitted to pass. */\n\tallowedIfAttributeIsAbsent(this: void, ...attr: string[]): MetaAttributeAllowedCallback;\n\n\t/** Returns an error if another attribute does not have one of the listed values */\n\tallowedIfAttributeHasValue(\n\t\tthis: void,\n\t\tattr: string,\n\t\tvalue: string[],\n\t\toptions?: { defaultValue?: string | null },\n\t): MetaAttributeAllowedCallback;\n\n\t/**\n\t * Returns an error if the node doesn't have any of the given elements as parent\n\t *\n\t * @since 8.2.0\n\t **/\n\tallowedIfParentIsPresent(this: void, ...tags: string[]): MetaAttributeAllowedCallback;\n}\n\n/**\n * @internal\n */\nexport function allowedIfAttributeIsPresent(...attr: string[]) {\n\treturn (node: HtmlElementLike) => {\n\t\tif (attr.some((it) => node.hasAttribute(it))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(attr.map((it) => `\"${it}\"`));\n\t\treturn `requires ${expected} attribute to be present`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function allowedIfAttributeIsAbsent(...attr: string[]): MetaAttributeAllowedCallback {\n\treturn (node: HtmlElementLike) => {\n\t\tconst present = attr.filter((it) => node.hasAttribute(it));\n\t\tif (present.length === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(present.map((it) => `\"${it}\"`));\n\t\treturn `cannot be used at the same time as ${expected}`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function allowedIfAttributeHasValue(\n\tkey: string,\n\texpectedValue: string[],\n\t{ defaultValue }: { defaultValue?: string | null } = {},\n): MetaAttributeAllowedCallback {\n\treturn (node: HtmlElementLike) => {\n\t\tconst attr = node.getAttribute(key);\n\t\tif (attr && typeof attr !== \"string\") {\n\t\t\treturn null;\n\t\t}\n\t\tconst actualValue = attr ?? defaultValue;\n\t\tif (actualValue && expectedValue.includes(actualValue.toLocaleLowerCase())) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(expectedValue.map((it) => `\"${it}\"`));\n\t\treturn `\"${key}\" attribute must be ${expected}`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function allowedIfParentIsPresent(\n\tthis: void,\n\t...tags: string[]\n): MetaAttributeAllowedCallback {\n\treturn (node: HtmlElementLike) => {\n\t\tconst match = tags.some((it) => node.closest(it));\n\t\tif (match) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(tags.map((it) => `<${it}>`));\n\t\treturn `requires ${expected} as parent`;\n\t};\n}\n\n/**\n * @public\n */\nexport const metadataHelper: MetadataHelper = {\n\tallowedIfAttributeIsPresent,\n\tallowedIfAttributeIsAbsent,\n\tallowedIfAttributeHasValue,\n\tallowedIfParentIsPresent,\n};\n","import { type MetaDataTable } from \"./element\";\n\n/**\n * Helper function to assist IDE with completion and type-checking.\n *\n * @public\n */\nexport function defineMetadata(metatable: MetaDataTable): MetaDataTable {\n\treturn metatable;\n}\n"],"names":["naturalJoin"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"meta-helper.js","sources":["../../src/meta/helper.ts","../../src/meta/define-metadata.ts"],"sourcesContent":["import { naturalJoin } from \"../utils/natural-join\";\nimport { type MetaAttributeAllowedCallback } from \"./element\";\nimport { type HtmlElementLike } from \"./html-element-like\";\n\n/**\n * Helpers when writing element metadata.\n *\n * @public\n */\nexport interface MetadataHelper {\n\t/** Returns an error if another attribute is omitted, i.e. it requires another attribute to be present to pass. */\n\tallowedIfAttributeIsPresent(this: void, ...attr: string[]): MetaAttributeAllowedCallback;\n\n\t/** Returns an error if another attribute is present, i.e. it requires another attribute to be omitted to pass. */\n\tallowedIfAttributeIsAbsent(this: void, ...attr: string[]): MetaAttributeAllowedCallback;\n\n\t/** Returns an error if another attribute does not have one of the listed values */\n\tallowedIfAttributeHasValue(\n\t\tthis: void,\n\t\tattr: string,\n\t\tvalue: string[],\n\t\toptions?: { defaultValue?: string | null },\n\t): MetaAttributeAllowedCallback;\n\n\t/**\n\t * Returns an error if the node doesn't have any of the given elements as parent\n\t *\n\t * @since 8.2.0\n\t **/\n\tallowedIfParentIsPresent(this: void, ...tags: string[]): MetaAttributeAllowedCallback;\n\n\t/**\n\t * Returns true if an attribute with space-separated tokens includes given\n\t * keyword.\n\t *\n\t * @since 10.4.0\n\t * @param attr - Attribute value.\n\t * @param keyword - Keyword to look for.\n\t */\n\thasKeyword(this: void, attr: string, keyword: string): boolean;\n}\n\n/**\n * @internal\n */\nexport function allowedIfAttributeIsPresent(...attr: string[]) {\n\treturn (node: HtmlElementLike) => {\n\t\tif (attr.some((it) => node.hasAttribute(it))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(attr.map((it) => `\"${it}\"`));\n\t\treturn `requires ${expected} attribute to be present`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function allowedIfAttributeIsAbsent(...attr: string[]): MetaAttributeAllowedCallback {\n\treturn (node: HtmlElementLike) => {\n\t\tconst present = attr.filter((it) => node.hasAttribute(it));\n\t\tif (present.length === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(present.map((it) => `\"${it}\"`));\n\t\treturn `cannot be used at the same time as ${expected}`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function allowedIfAttributeHasValue(\n\tkey: string,\n\texpectedValue: string[],\n\t{ defaultValue }: { defaultValue?: string | null } = {},\n): MetaAttributeAllowedCallback {\n\treturn (node: HtmlElementLike) => {\n\t\tconst attr = node.getAttribute(key);\n\t\tif (attr && typeof attr !== \"string\") {\n\t\t\treturn null;\n\t\t}\n\t\tconst actualValue = attr ?? defaultValue;\n\t\tif (actualValue && expectedValue.includes(actualValue.toLocaleLowerCase())) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(expectedValue.map((it) => `\"${it}\"`));\n\t\treturn `\"${key}\" attribute must be ${expected}`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function allowedIfParentIsPresent(\n\tthis: void,\n\t...tags: string[]\n): MetaAttributeAllowedCallback {\n\treturn (node: HtmlElementLike) => {\n\t\tconst match = tags.some((it) => node.closest(it));\n\t\tif (match) {\n\t\t\treturn null;\n\t\t}\n\t\tconst expected = naturalJoin(tags.map((it) => `<${it}>`));\n\t\treturn `requires ${expected} as parent`;\n\t};\n}\n\n/**\n * @internal\n */\nexport function hasKeyword(attr: string, keyword: string): boolean {\n\treturn attr.toLowerCase().split(/\\s+/).includes(keyword);\n}\n\n/**\n * @public\n */\nexport const metadataHelper: MetadataHelper = {\n\tallowedIfAttributeIsPresent,\n\tallowedIfAttributeIsAbsent,\n\tallowedIfAttributeHasValue,\n\tallowedIfParentIsPresent,\n\thasKeyword,\n};\n","import { type MetaDataTable } from \"./element\";\n\n/**\n * Helper function to assist IDE with completion and type-checking.\n *\n * @public\n */\nexport function defineMetadata(metatable: MetaDataTable): MetaDataTable {\n\treturn metatable;\n}\n"],"names":["naturalJoin"],"mappings":";;;;AA6CO,SAAS,+BAA+B,IAAA,EAAgB;AAC9D,EAAA,OAAO,CAAC,IAAA,KAA0B;AACjC,IAAA,IAAI,IAAA,CAAK,KAAK,CAAC,EAAA,KAAO,KAAK,YAAA,CAAa,EAAE,CAAC,CAAA,EAAG;AAC7C,MAAA,OAAO,IAAA;AAAA,IACR;AACA,IAAA,MAAM,QAAA,GAAWA,8BAAY,IAAA,CAAK,GAAA,CAAI,CAAC,EAAA,KAAO,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,CAAG,CAAC,CAAA;AACxD,IAAA,OAAO,YAAY,QAAQ,CAAA,wBAAA,CAAA;AAAA,EAC5B,CAAA;AACD;AAKO,SAAS,8BAA8B,IAAA,EAA8C;AAC3F,EAAA,OAAO,CAAC,IAAA,KAA0B;AACjC,IAAA,MAAM,OAAA,GAAU,KAAK,MAAA,CAAO,CAAC,OAAO,IAAA,CAAK,YAAA,CAAa,EAAE,CAAC,CAAA;AACzD,IAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACzB,MAAA,OAAO,IAAA;AAAA,IACR;AACA,IAAA,MAAM,QAAA,GAAWA,8BAAY,OAAA,CAAQ,GAAA,CAAI,CAAC,EAAA,KAAO,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,CAAG,CAAC,CAAA;AAC3D,IAAA,OAAO,sCAAsC,QAAQ,CAAA,CAAA;AAAA,EACtD,CAAA;AACD;AAKO,SAAS,2BACf,GAAA,EACA,aAAA,EACA,EAAE,YAAA,EAAa,GAAsC,EAAC,EACvB;AAC/B,EAAA,OAAO,CAAC,IAAA,KAA0B;AACjC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,YAAA,CAAa,GAAG,CAAA;AAClC,IAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,MAAA,OAAO,IAAA;AAAA,IACR;AACA,IAAA,MAAM,cAAc,IAAA,IAAQ,YAAA;AAC5B,IAAA,IAAI,eAAe,aAAA,CAAc,QAAA,CAAS,WAAA,CAAY,iBAAA,EAAmB,CAAA,EAAG;AAC3E,MAAA,OAAO,IAAA;AAAA,IACR;AACA,IAAA,MAAM,QAAA,GAAWA,8BAAY,aAAA,CAAc,GAAA,CAAI,CAAC,EAAA,KAAO,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,CAAG,CAAC,CAAA;AACjE,IAAA,OAAO,CAAA,CAAA,EAAI,GAAG,CAAA,oBAAA,EAAuB,QAAQ,CAAA,CAAA;AAAA,EAC9C,CAAA;AACD;AAKO,SAAS,4BAEZ,IAAA,EAC4B;AAC/B,EAAA,OAAO,CAAC,IAAA,KAA0B;AACjC,IAAA,MAAM,KAAA,GAAQ,KAAK,IAAA,CAAK,CAAC,OAAO,IAAA,CAAK,OAAA,CAAQ,EAAE,CAAC,CAAA;AAChD,IAAA,IAAI,KAAA,EAAO;AACV,MAAA,OAAO,IAAA;AAAA,IACR;AACA,IAAA,MAAM,QAAA,GAAWA,8BAAY,IAAA,CAAK,GAAA,CAAI,CAAC,EAAA,KAAO,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,CAAG,CAAC,CAAA;AACxD,IAAA,OAAO,YAAY,QAAQ,CAAA,UAAA,CAAA;AAAA,EAC5B,CAAA;AACD;AAKO,SAAS,UAAA,CAAW,MAAc,OAAA,EAA0B;AAClE,EAAA,OAAO,KAAK,WAAA,EAAY,CAAE,MAAM,KAAK,CAAA,CAAE,SAAS,OAAO,CAAA;AACxD;AAKO,MAAM,cAAA,GAAiC;AAAA,EAC7C,2BAAA;AAAA,EACA,0BAAA;AAAA,EACA,0BAAA;AAAA,EACA,wBAAA;AAAA,EACA;AACD;;ACrHO,SAAS,eAAe,SAAA,EAAyC;AACvE,EAAA,OAAO,SAAA;AACR;;;;;"}
|
package/dist/esm/core.js
CHANGED
|
@@ -854,8 +854,15 @@ const definitions = {
|
|
|
854
854
|
title: "Set to true if this attribute can optionally omit its value"
|
|
855
855
|
},
|
|
856
856
|
required: {
|
|
857
|
-
|
|
858
|
-
|
|
857
|
+
title: "Set to true or a function to evaluate if this attribute is required",
|
|
858
|
+
oneOf: [
|
|
859
|
+
{
|
|
860
|
+
type: "boolean"
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
"function": true
|
|
864
|
+
}
|
|
865
|
+
]
|
|
859
866
|
}
|
|
860
867
|
}
|
|
861
868
|
},
|
|
@@ -6278,10 +6285,30 @@ class ElementRequiredAncestor extends Rule {
|
|
|
6278
6285
|
}
|
|
6279
6286
|
}
|
|
6280
6287
|
|
|
6288
|
+
const defaultMessage = `{{ tagName }} is missing required "{{ attr }}" attribute`;
|
|
6289
|
+
function normalizeRequired(element, attr) {
|
|
6290
|
+
const { required } = attr;
|
|
6291
|
+
if (typeof required === "function") {
|
|
6292
|
+
const result = required(element._adapter);
|
|
6293
|
+
switch (result) {
|
|
6294
|
+
case void 0:
|
|
6295
|
+
case null:
|
|
6296
|
+
case false:
|
|
6297
|
+
case "":
|
|
6298
|
+
return false;
|
|
6299
|
+
case true:
|
|
6300
|
+
return defaultMessage;
|
|
6301
|
+
default:
|
|
6302
|
+
return result;
|
|
6303
|
+
}
|
|
6304
|
+
} else {
|
|
6305
|
+
return required ? defaultMessage : false;
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6281
6308
|
class ElementRequiredAttributes extends Rule {
|
|
6282
6309
|
documentation(context) {
|
|
6283
6310
|
return {
|
|
6284
|
-
description: `The
|
|
6311
|
+
description: `The \`${context.tagName}\` element is required to have a \`${context.attr}\` attribute.`,
|
|
6285
6312
|
url: "https://html-validate.org/rules/element-required-attributes.html"
|
|
6286
6313
|
};
|
|
6287
6314
|
}
|
|
@@ -6293,23 +6320,29 @@ class ElementRequiredAttributes extends Rule {
|
|
|
6293
6320
|
return;
|
|
6294
6321
|
}
|
|
6295
6322
|
for (const [key, attr] of Object.entries(meta.attributes)) {
|
|
6296
|
-
|
|
6323
|
+
const required = normalizeRequired(node, attr);
|
|
6324
|
+
if (!required) {
|
|
6297
6325
|
continue;
|
|
6298
6326
|
}
|
|
6299
|
-
|
|
6300
|
-
const context = {
|
|
6301
|
-
element: node.tagName,
|
|
6302
|
-
attribute: key
|
|
6303
|
-
};
|
|
6304
|
-
this.report(
|
|
6305
|
-
node,
|
|
6306
|
-
`${node.annotatedName} is missing required "${key}" attribute`,
|
|
6307
|
-
node.location,
|
|
6308
|
-
context
|
|
6309
|
-
);
|
|
6327
|
+
this.validateRequiredAttribute(node, key, required);
|
|
6310
6328
|
}
|
|
6311
6329
|
});
|
|
6312
6330
|
}
|
|
6331
|
+
validateRequiredAttribute(node, attr, message) {
|
|
6332
|
+
if (node.hasAttribute(attr)) {
|
|
6333
|
+
return;
|
|
6334
|
+
}
|
|
6335
|
+
const context = {
|
|
6336
|
+
tagName: node.annotatedName,
|
|
6337
|
+
attr
|
|
6338
|
+
};
|
|
6339
|
+
this.report({
|
|
6340
|
+
node,
|
|
6341
|
+
message,
|
|
6342
|
+
location: node.location,
|
|
6343
|
+
context
|
|
6344
|
+
});
|
|
6345
|
+
}
|
|
6313
6346
|
}
|
|
6314
6347
|
|
|
6315
6348
|
function isCategory(value) {
|
|
@@ -11936,7 +11969,7 @@ class EventHandler {
|
|
|
11936
11969
|
}
|
|
11937
11970
|
|
|
11938
11971
|
const name = "html-validate";
|
|
11939
|
-
const version = "10.
|
|
11972
|
+
const version = "10.4.0";
|
|
11940
11973
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11941
11974
|
|
|
11942
11975
|
function freeze(src) {
|