html-validate 8.12.0 → 8.13.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.
@@ -33,6 +33,29 @@ function isInsideLandmark(node) {
33
33
  ];
34
34
  return Boolean(node.closest(selectors.join(",")));
35
35
  }
36
+ function linkBodyOk(node) {
37
+ if (node.hasAttribute("itemprop")) {
38
+ return true;
39
+ }
40
+ const rel = node.getAttribute("rel");
41
+ if (!rel) {
42
+ return false;
43
+ }
44
+ if (typeof rel !== "string") {
45
+ return false;
46
+ }
47
+ const bodyOk = [
48
+ "dns-prefetch",
49
+ "modulepreload",
50
+ "pingback",
51
+ "preconnect",
52
+ "prefetch",
53
+ "preload",
54
+ "stylesheet"
55
+ ];
56
+ const tokens = rel.toLowerCase().split(/\s+/);
57
+ return tokens.some((keyword) => bodyOk.includes(keyword));
58
+ }
36
59
  var html5 = defineMetadata({
37
60
  "*": {
38
61
  attributes: {
@@ -109,7 +132,74 @@ var html5 = defineMetadata({
109
132
  enum: ReferrerPolicy
110
133
  },
111
134
  rel: {
112
- allowed: allowedIfAttributeIsPresent("href")
135
+ allowed(node, attr) {
136
+ if (!node.hasAttribute("href")) {
137
+ return `requires "href" attribute to be present`;
138
+ }
139
+ if (!attr || attr === "" || typeof attr !== "string") {
140
+ return null;
141
+ }
142
+ const disallowed = [
143
+ /* whatwg */
144
+ "canonical",
145
+ "dns-prefetch",
146
+ "expect",
147
+ "icon",
148
+ "manifest",
149
+ "modulepreload",
150
+ "pingback",
151
+ "preconnect",
152
+ "prefetch",
153
+ "preload",
154
+ "stylesheet",
155
+ /* microformats.org */
156
+ "apple-touch-icon",
157
+ "apple-touch-icon-precomposed",
158
+ "apple-touch-startup-image",
159
+ "authorization_endpoint",
160
+ "component",
161
+ "chrome-webstore-item",
162
+ "dns-prefetch",
163
+ "edit",
164
+ "gbfs",
165
+ "gtfs-static",
166
+ "gtfs-realtime",
167
+ "import",
168
+ "mask-icon",
169
+ "meta",
170
+ "micropub",
171
+ "openid.delegate",
172
+ "openid.server",
173
+ "openid2.local_id",
174
+ "openid2.provider",
175
+ "p3pv1",
176
+ "pgpkey",
177
+ "schema.dcterms",
178
+ "service",
179
+ "shortlink",
180
+ "sitemap",
181
+ "subresource",
182
+ "sword",
183
+ "timesheet",
184
+ "token_endpoint",
185
+ "wlwmanifest",
186
+ "stylesheet/less",
187
+ "token_endpoint",
188
+ "yandex-tableau-widget"
189
+ ];
190
+ const tokens = attr.toLowerCase().split(/\s+/);
191
+ for (const keyword of tokens) {
192
+ if (disallowed.includes(keyword)) {
193
+ return `<a> does not allow rel="${keyword}"`;
194
+ }
195
+ if (keyword.startsWith("dcterms.")) {
196
+ return `<a> does not allow rel="${keyword}"`;
197
+ }
198
+ }
199
+ return null;
200
+ },
201
+ list: true,
202
+ enum: ["/.+/"]
113
203
  },
114
204
  shape: {
115
205
  deprecated: true
@@ -207,7 +297,72 @@ var html5 = defineMetadata({
207
297
  enum: ReferrerPolicy
208
298
  },
209
299
  rel: {
210
- allowed: allowedIfAttributeIsPresent("href")
300
+ allowed(node, attr) {
301
+ if (!node.hasAttribute("href")) {
302
+ return `requires "href" attribute to be present`;
303
+ }
304
+ if (!attr || attr === "" || typeof attr !== "string") {
305
+ return null;
306
+ }
307
+ const disallowed = [
308
+ /* whatwg */
309
+ "canonical",
310
+ "dns-prefetch",
311
+ "expect",
312
+ "icon",
313
+ "manifest",
314
+ "modulepreload",
315
+ "pingback",
316
+ "preconnect",
317
+ "prefetch",
318
+ "preload",
319
+ "stylesheet",
320
+ /* microformats.org */
321
+ "apple-touch-icon",
322
+ "apple-touch-icon-precomposed",
323
+ "apple-touch-startup-image",
324
+ "authorization_endpoint",
325
+ "component",
326
+ "chrome-webstore-item",
327
+ "dns-prefetch",
328
+ "edit",
329
+ "gbfs",
330
+ "gtfs-static",
331
+ "gtfs-realtime",
332
+ "import",
333
+ "mask-icon",
334
+ "meta",
335
+ "micropub",
336
+ "openid.delegate",
337
+ "openid.server",
338
+ "openid2.local_id",
339
+ "openid2.provider",
340
+ "p3pv1",
341
+ "pgpkey",
342
+ "schema.dcterms",
343
+ "service",
344
+ "shortlink",
345
+ "sitemap",
346
+ "subresource",
347
+ "sword",
348
+ "timesheet",
349
+ "token_endpoint",
350
+ "wlwmanifest",
351
+ "stylesheet/less",
352
+ "token_endpoint",
353
+ "yandex-tableau-widget"
354
+ ];
355
+ const tokens = attr.toLowerCase().split(/\s+/);
356
+ for (const keyword of tokens) {
357
+ if (disallowed.includes(keyword)) {
358
+ return `<area> does not allow rel="${keyword}"`;
359
+ }
360
+ if (keyword.startsWith("dcterms.")) {
361
+ return `<area> does not allow rel="${keyword}"`;
362
+ }
363
+ }
364
+ return null;
365
+ }
211
366
  },
212
367
  shape: {
213
368
  allowed(node, attr) {
@@ -766,6 +921,42 @@ var html5 = defineMetadata({
766
921
  novalidate: {
767
922
  boolean: true
768
923
  },
924
+ rel: {
925
+ allowed(_, attr) {
926
+ if (!attr || attr === "" || typeof attr !== "string") {
927
+ return null;
928
+ }
929
+ const disallowed = [
930
+ /* whatwg */
931
+ "alternate",
932
+ "canonical",
933
+ "author",
934
+ "bookmark",
935
+ "dns-prefetch",
936
+ "expect",
937
+ "icon",
938
+ "manifest",
939
+ "modulepreload",
940
+ "pingback",
941
+ "preconnect",
942
+ "prefetch",
943
+ "preload",
944
+ "privacy-policy",
945
+ "stylesheet",
946
+ "tag",
947
+ "terms-of-service"
948
+ ];
949
+ const tokens = attr.toLowerCase().split(/\s+/);
950
+ for (const keyword of tokens) {
951
+ if (disallowed.includes(keyword)) {
952
+ return `<form> does not allow rel="${keyword}"`;
953
+ }
954
+ }
955
+ return null;
956
+ },
957
+ list: true,
958
+ enum: ["/.+/"]
959
+ },
769
960
  target: {
770
961
  enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"]
771
962
  }
@@ -1369,6 +1560,12 @@ var html5 = defineMetadata({
1369
1560
  },
1370
1561
  link: {
1371
1562
  metadata: true,
1563
+ flow(node) {
1564
+ return linkBodyOk(node);
1565
+ },
1566
+ phrasing(node) {
1567
+ return linkBodyOk(node);
1568
+ },
1372
1569
  void: true,
1373
1570
  attributes: {
1374
1571
  as: {
@@ -1428,6 +1625,37 @@ var html5 = defineMetadata({
1428
1625
  referrerpolicy: {
1429
1626
  enum: ReferrerPolicy
1430
1627
  },
1628
+ rel: {
1629
+ allowed(_, attr) {
1630
+ if (!attr || attr === "" || typeof attr !== "string") {
1631
+ return null;
1632
+ }
1633
+ const disallowed = [
1634
+ /* whatwg */
1635
+ "bookmark",
1636
+ "external",
1637
+ "nofollow",
1638
+ "noopener",
1639
+ "noreferrer",
1640
+ "opener",
1641
+ "tag",
1642
+ /* microformats.org */
1643
+ "disclosure",
1644
+ "entry-content",
1645
+ "lightbox",
1646
+ "lightvideo"
1647
+ ];
1648
+ const tokens = attr.toLowerCase().split(/\s+/);
1649
+ for (const keyword of tokens) {
1650
+ if (disallowed.includes(keyword)) {
1651
+ return `<link> does not allow rel="${keyword}"`;
1652
+ }
1653
+ }
1654
+ return null;
1655
+ },
1656
+ list: true,
1657
+ enum: ["/.+/"]
1658
+ },
1431
1659
  target: {
1432
1660
  deprecated: true
1433
1661
  },