@svelte-vitals/core 0.41.1 → 0.43.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/README.md +1 -1
- package/dist/index.d.ts +244 -28
- package/dist/index.js +1097 -1370
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,14 @@ var defaultProject = {
|
|
|
4
4
|
hasSitemap: false,
|
|
5
5
|
htmlLang: { presence: "none", value: "absent" }
|
|
6
6
|
};
|
|
7
|
-
var CATEGORIES = [
|
|
7
|
+
var CATEGORIES = [
|
|
8
|
+
"seo",
|
|
9
|
+
"performance",
|
|
10
|
+
"correctness",
|
|
11
|
+
"security",
|
|
12
|
+
"architecture",
|
|
13
|
+
"a11y"
|
|
14
|
+
];
|
|
8
15
|
var defaultConfig = {
|
|
9
16
|
treatDynamicAs: "pass",
|
|
10
17
|
metaComponents: [],
|
|
@@ -15,6 +22,71 @@ function defineConfig(config = {}) {
|
|
|
15
22
|
return { ...defaultConfig, ...config };
|
|
16
23
|
}
|
|
17
24
|
|
|
25
|
+
// src/a11y.ts
|
|
26
|
+
function foldOccurrences(nodes) {
|
|
27
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const node of nodes) {
|
|
29
|
+
if (node.repeatable) continue;
|
|
30
|
+
const list = byKey.get(node.key);
|
|
31
|
+
if (list) list.push(node);
|
|
32
|
+
else byKey.set(node.key, [node]);
|
|
33
|
+
}
|
|
34
|
+
const folded = /* @__PURE__ */ new Map();
|
|
35
|
+
for (const [key, list] of byKey) folded.set(key, foldAt(list, 0));
|
|
36
|
+
return folded;
|
|
37
|
+
}
|
|
38
|
+
function foldAt(nodes, depth) {
|
|
39
|
+
const unconditional = [];
|
|
40
|
+
const groups = /* @__PURE__ */ new Map();
|
|
41
|
+
for (const node of nodes) {
|
|
42
|
+
const step = node.path[depth];
|
|
43
|
+
if (!step) {
|
|
44
|
+
unconditional.push(node);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
let branches = groups.get(step.group);
|
|
48
|
+
if (!branches) groups.set(step.group, branches = /* @__PURE__ */ new Map());
|
|
49
|
+
const list = branches.get(step.branch);
|
|
50
|
+
if (list) list.push(node);
|
|
51
|
+
else branches.set(step.branch, [node]);
|
|
52
|
+
}
|
|
53
|
+
const representatives = [...unconditional];
|
|
54
|
+
for (const branches of groups.values()) {
|
|
55
|
+
let best = [];
|
|
56
|
+
let bestBranch = Number.POSITIVE_INFINITY;
|
|
57
|
+
for (const [branch, list] of branches) {
|
|
58
|
+
const arm = foldAt(list, depth + 1);
|
|
59
|
+
if (arm.length > best.length || arm.length === best.length && branch < bestBranch) {
|
|
60
|
+
best = arm;
|
|
61
|
+
bestBranch = branch;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
representatives.push(...best);
|
|
65
|
+
}
|
|
66
|
+
return representatives;
|
|
67
|
+
}
|
|
68
|
+
function decodeFragmentId(fragment) {
|
|
69
|
+
try {
|
|
70
|
+
return decodeURIComponent(fragment);
|
|
71
|
+
} catch {
|
|
72
|
+
return fragment;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function splitTokens(value) {
|
|
76
|
+
return value ? value.trim().split(/\s+/).filter(Boolean) : [];
|
|
77
|
+
}
|
|
78
|
+
var LANDMARK_ROLES = /* @__PURE__ */ new Set(["main", "banner", "contentinfo", "complementary"]);
|
|
79
|
+
var IDREF_ATTRS = [
|
|
80
|
+
"for",
|
|
81
|
+
"aria-labelledby",
|
|
82
|
+
"aria-describedby",
|
|
83
|
+
"aria-controls",
|
|
84
|
+
"aria-activedescendant"
|
|
85
|
+
];
|
|
86
|
+
function isTopFragment(id) {
|
|
87
|
+
return id.toLowerCase() === "top";
|
|
88
|
+
}
|
|
89
|
+
|
|
18
90
|
// src/component-parse.ts
|
|
19
91
|
import { parse } from "svelte/compiler";
|
|
20
92
|
|
|
@@ -35,36 +107,29 @@ var CHILD_NODE_KEYS = [
|
|
|
35
107
|
"catch",
|
|
36
108
|
"fallback"
|
|
37
109
|
];
|
|
110
|
+
var hasExpression = (nodes) => nodes.some((n) => n?.type === "ExpressionTag");
|
|
111
|
+
function joinText(nodes) {
|
|
112
|
+
return nodes.filter((n) => n?.type === "Text").map((n) => String(n.data ?? "")).join("");
|
|
113
|
+
}
|
|
38
114
|
function valueFromNodes(nodes) {
|
|
39
115
|
if (!Array.isArray(nodes)) return "absent";
|
|
40
|
-
if (nodes
|
|
41
|
-
|
|
42
|
-
return text.trim().length > 0 ? "static" : "absent";
|
|
116
|
+
if (hasExpression(nodes)) return "dynamic";
|
|
117
|
+
return joinText(nodes).trim().length > 0 ? "static" : "absent";
|
|
43
118
|
}
|
|
44
119
|
function textFromNodes(nodes) {
|
|
45
|
-
if (!Array.isArray(nodes) || nodes
|
|
46
|
-
const text = nodes
|
|
120
|
+
if (!Array.isArray(nodes) || hasExpression(nodes)) return void 0;
|
|
121
|
+
const text = joinText(nodes);
|
|
47
122
|
return text.trim().length > 0 ? text : void 0;
|
|
48
123
|
}
|
|
49
124
|
function attrText(attributes, name) {
|
|
50
|
-
const
|
|
51
|
-
if (!attr) return void 0;
|
|
52
|
-
const v = attr.value;
|
|
125
|
+
const v = findAttr(attributes, name)?.value;
|
|
53
126
|
if (v === true) return "";
|
|
54
|
-
if (Array.isArray(v))
|
|
55
|
-
|
|
56
|
-
return v.filter((n) => n?.type === "Text").map((n) => String(n.data ?? "")).join("");
|
|
57
|
-
}
|
|
58
|
-
return void 0;
|
|
127
|
+
if (!Array.isArray(v) || hasExpression(v)) return void 0;
|
|
128
|
+
return joinText(v);
|
|
59
129
|
}
|
|
60
130
|
function attrValue(attributes, name) {
|
|
61
131
|
const attr = findAttr(attributes, name);
|
|
62
|
-
|
|
63
|
-
const v = attr.value;
|
|
64
|
-
if (v === true) return "absent";
|
|
65
|
-
if (Array.isArray(v)) return valueFromNodes(v);
|
|
66
|
-
if (v && v.type === "ExpressionTag") return "dynamic";
|
|
67
|
-
return "absent";
|
|
132
|
+
return attr ? attrValueOf(attr) : "absent";
|
|
68
133
|
}
|
|
69
134
|
function lineOf(source, offset) {
|
|
70
135
|
if (typeof offset !== "number" || offset < 0) return 0;
|
|
@@ -86,9 +151,58 @@ function attrValueOf(attr) {
|
|
|
86
151
|
}
|
|
87
152
|
function attrTextOf(attr) {
|
|
88
153
|
const v = attr?.value;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
154
|
+
return Array.isArray(v) ? textFromNodes(v) : void 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/rules/a11y/interactive.ts
|
|
158
|
+
var ALWAYS_INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["button", "select", "textarea", "summary", "embed", "iframe"]);
|
|
159
|
+
var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
160
|
+
"button",
|
|
161
|
+
"link",
|
|
162
|
+
"checkbox",
|
|
163
|
+
"radio",
|
|
164
|
+
"switch",
|
|
165
|
+
"tab",
|
|
166
|
+
"menuitem",
|
|
167
|
+
"menuitemcheckbox",
|
|
168
|
+
"menuitemradio",
|
|
169
|
+
"option",
|
|
170
|
+
"slider",
|
|
171
|
+
"spinbutton",
|
|
172
|
+
"textbox",
|
|
173
|
+
"combobox",
|
|
174
|
+
"searchbox",
|
|
175
|
+
"scrollbar",
|
|
176
|
+
"gridcell"
|
|
177
|
+
]);
|
|
178
|
+
function literalOf(attrs, name) {
|
|
179
|
+
return attrs.find((a) => a.name === name)?.literal;
|
|
180
|
+
}
|
|
181
|
+
function hasInteractiveRole(attrs) {
|
|
182
|
+
const role = splitTokens(literalOf(attrs, "role"))[0];
|
|
183
|
+
return role !== void 0 && INTERACTIVE_ROLES.has(role);
|
|
184
|
+
}
|
|
185
|
+
function isInteractiveElement(tag, attrs) {
|
|
186
|
+
if (ALWAYS_INTERACTIVE_TAGS.has(tag)) return true;
|
|
187
|
+
if (tag === "a" && literalOf(attrs, "href") !== void 0) return true;
|
|
188
|
+
if (tag === "input") {
|
|
189
|
+
const typeAttr = attrs.find((a) => a.name === "type");
|
|
190
|
+
if (!typeAttr) return true;
|
|
191
|
+
if (typeAttr.literal !== void 0) return typeAttr.literal.toLowerCase() !== "hidden";
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
if ((tag === "audio" || tag === "video") && attrs.some((a) => a.name === "controls")) return true;
|
|
195
|
+
const tabindex = literalOf(attrs, "tabindex")?.trim();
|
|
196
|
+
if (tabindex) {
|
|
197
|
+
const n = Number(tabindex);
|
|
198
|
+
if (Number.isFinite(n) && n >= 0) return true;
|
|
199
|
+
}
|
|
200
|
+
return hasInteractiveRole(attrs);
|
|
201
|
+
}
|
|
202
|
+
function isInteractiveContainer(tag, attrs) {
|
|
203
|
+
if (tag === "button") return true;
|
|
204
|
+
if (tag === "a") return literalOf(attrs, "href") !== void 0;
|
|
205
|
+
return hasInteractiveRole(attrs);
|
|
92
206
|
}
|
|
93
207
|
|
|
94
208
|
// src/component-parse.ts
|
|
@@ -724,6 +838,304 @@ function collectCheckableBindValues(node, source, acc) {
|
|
|
724
838
|
if (key in node) collectCheckableBindValues(node[key], source, acc);
|
|
725
839
|
}
|
|
726
840
|
}
|
|
841
|
+
function classifyAttrValue(value) {
|
|
842
|
+
if (value === true) return { literal: "" };
|
|
843
|
+
if (Array.isArray(value) && value.length === 1 && value[0]?.type === "Text") {
|
|
844
|
+
return { literal: String(value[0].data ?? "") };
|
|
845
|
+
}
|
|
846
|
+
return { expression: true };
|
|
847
|
+
}
|
|
848
|
+
function collectAriaElements(node, source, acc) {
|
|
849
|
+
if (Array.isArray(node)) {
|
|
850
|
+
for (const child of node) collectAriaElements(child, source, acc);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (!node || typeof node !== "object") return;
|
|
854
|
+
if (node.type === "RegularElement" && Array.isArray(node.attributes)) {
|
|
855
|
+
const roleAttr = findAttr(node.attributes, "role");
|
|
856
|
+
const ariaAttrs = node.attributes.filter(
|
|
857
|
+
(a) => a?.type === "Attribute" && typeof a.name === "string" && a.name.startsWith("aria-")
|
|
858
|
+
);
|
|
859
|
+
if (roleAttr || ariaAttrs.length > 0) {
|
|
860
|
+
const inputType = node.name === "input" ? attrText(node.attributes, "type") : void 0;
|
|
861
|
+
const hasSpread = node.attributes.some((a) => a?.type === "SpreadAttribute");
|
|
862
|
+
acc.push({
|
|
863
|
+
tag: node.name,
|
|
864
|
+
line: lineOf(source, node.start),
|
|
865
|
+
...roleAttr ? { role: classifyAttrValue(roleAttr.value) } : {},
|
|
866
|
+
...inputType !== void 0 ? { inputType: inputType.toLowerCase() } : {},
|
|
867
|
+
...hasSpread ? { hasSpread: true } : {},
|
|
868
|
+
aria: ariaAttrs.map((a) => ({
|
|
869
|
+
name: a.name,
|
|
870
|
+
line: lineOf(source, a.start ?? node.start),
|
|
871
|
+
...classifyAttrValue(a.value)
|
|
872
|
+
}))
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
877
|
+
if (key in node) collectAriaElements(node[key], source, acc);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
function elementAttrs(attributes) {
|
|
881
|
+
return attributes.filter((a) => a?.type === "Attribute" && typeof a.name === "string").map((a) => ({ name: a.name, ...classifyAttrValue(a.value) }));
|
|
882
|
+
}
|
|
883
|
+
function collectInteractiveNestings(node, source, acc, stack) {
|
|
884
|
+
if (Array.isArray(node)) {
|
|
885
|
+
for (const child of node) collectInteractiveNestings(child, source, acc, stack);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
if (!node || typeof node !== "object") return;
|
|
889
|
+
if (node.type === "SnippetBlock") {
|
|
890
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
891
|
+
if (key in node) collectInteractiveNestings(node[key], source, acc, []);
|
|
892
|
+
}
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
let opened = false;
|
|
896
|
+
if (node.type === "RegularElement" && Array.isArray(node.attributes)) {
|
|
897
|
+
const attrs = elementAttrs(node.attributes);
|
|
898
|
+
if (stack.length > 0 && isInteractiveElement(node.name, attrs)) {
|
|
899
|
+
acc.push({
|
|
900
|
+
containerTag: stack[stack.length - 1],
|
|
901
|
+
descendantTag: node.name,
|
|
902
|
+
line: lineOf(source, node.start)
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
if (isInteractiveContainer(node.name, attrs)) {
|
|
906
|
+
stack.push(node.name);
|
|
907
|
+
opened = true;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
911
|
+
if (key in node) collectInteractiveNestings(node[key], source, acc, stack);
|
|
912
|
+
}
|
|
913
|
+
if (opened) stack.pop();
|
|
914
|
+
}
|
|
915
|
+
function hasNamingAttr(attributes) {
|
|
916
|
+
return ["aria-label", "aria-labelledby", "title"].some((name) => {
|
|
917
|
+
const attr = findAttr(attributes, name);
|
|
918
|
+
if (!attr) return false;
|
|
919
|
+
const v = classifyAttrValue(attr.value);
|
|
920
|
+
return "expression" in v || v.literal !== void 0 && v.literal.trim().length > 0;
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
function scanAccessibleNameSubtree(node) {
|
|
924
|
+
if (Array.isArray(node)) {
|
|
925
|
+
const acc2 = { named: false, unknowable: false };
|
|
926
|
+
for (const child of node) {
|
|
927
|
+
const r = scanAccessibleNameSubtree(child);
|
|
928
|
+
acc2.named ||= r.named;
|
|
929
|
+
acc2.unknowable ||= r.unknowable;
|
|
930
|
+
}
|
|
931
|
+
return acc2;
|
|
932
|
+
}
|
|
933
|
+
if (!node || typeof node !== "object") return { named: false, unknowable: false };
|
|
934
|
+
if (node.type === "SnippetBlock") return { named: false, unknowable: false };
|
|
935
|
+
if (node.type === "Text") return { named: String(node.data ?? "").trim().length > 0, unknowable: false };
|
|
936
|
+
if (node.type === "ExpressionTag" || node.type === "RenderTag" || node.type === "HtmlTag" || COMPONENT_LIKE_TYPES.has(node.type)) {
|
|
937
|
+
return { named: false, unknowable: true };
|
|
938
|
+
}
|
|
939
|
+
if (node.type === "RegularElement" && node.name === "img" && Array.isArray(node.attributes)) {
|
|
940
|
+
const alt = attrText(node.attributes, "alt");
|
|
941
|
+
if (alt !== void 0 && alt.trim().length > 0) return { named: true, unknowable: false };
|
|
942
|
+
}
|
|
943
|
+
const acc = { named: false, unknowable: false };
|
|
944
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
945
|
+
if (key in node) {
|
|
946
|
+
const r = scanAccessibleNameSubtree(node[key]);
|
|
947
|
+
acc.named ||= r.named;
|
|
948
|
+
acc.unknowable ||= r.unknowable;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return acc;
|
|
952
|
+
}
|
|
953
|
+
function accessibleNameTarget(node) {
|
|
954
|
+
if (node.name === "button") return "button";
|
|
955
|
+
if (node.name === "a") return attrText(node.attributes, "href") !== void 0 ? "a" : void 0;
|
|
956
|
+
if (node.name === "input") {
|
|
957
|
+
const type = attrText(node.attributes, "type");
|
|
958
|
+
return type?.toLowerCase() === "image" ? "input" : void 0;
|
|
959
|
+
}
|
|
960
|
+
return void 0;
|
|
961
|
+
}
|
|
962
|
+
function collectUnnamedInteractive(node, source, acc) {
|
|
963
|
+
if (Array.isArray(node)) {
|
|
964
|
+
for (const child of node) collectUnnamedInteractive(child, source, acc);
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
if (!node || typeof node !== "object") return;
|
|
968
|
+
if (node.type === "RegularElement" && Array.isArray(node.attributes)) {
|
|
969
|
+
const target = accessibleNameTarget(node);
|
|
970
|
+
const hasSpread = node.attributes.some((a) => a?.type === "SpreadAttribute");
|
|
971
|
+
if (target && !hasSpread) {
|
|
972
|
+
if (target === "input") {
|
|
973
|
+
const alt = attrText(node.attributes, "alt");
|
|
974
|
+
if (!hasNamingAttr(node.attributes) && !(alt !== void 0 && alt.trim().length > 0)) {
|
|
975
|
+
acc.push({ tag: node.name, line: lineOf(source, node.start) });
|
|
976
|
+
}
|
|
977
|
+
} else {
|
|
978
|
+
const scan = scanAccessibleNameSubtree(node);
|
|
979
|
+
if (!hasNamingAttr(node.attributes) && !scan.named && !scan.unknowable) {
|
|
980
|
+
acc.push({ tag: node.name, line: lineOf(source, node.start) });
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
986
|
+
if (key in node) collectUnnamedInteractive(node[key], source, acc);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
var LABELABLE_TAGS = /* @__PURE__ */ new Set(["input", "select", "textarea", "button", "meter", "output", "progress"]);
|
|
990
|
+
function isLabelableDescendant(node) {
|
|
991
|
+
if (node.type !== "RegularElement" || !LABELABLE_TAGS.has(node.name)) return false;
|
|
992
|
+
if (node.name !== "input") return true;
|
|
993
|
+
return attrText(node.attributes ?? [], "type")?.toLowerCase() !== "hidden";
|
|
994
|
+
}
|
|
995
|
+
function scanLabelSubtree(node) {
|
|
996
|
+
if (Array.isArray(node)) {
|
|
997
|
+
const acc2 = { hasControl: false, unknowable: false };
|
|
998
|
+
for (const child of node) {
|
|
999
|
+
const r = scanLabelSubtree(child);
|
|
1000
|
+
acc2.hasControl ||= r.hasControl;
|
|
1001
|
+
acc2.unknowable ||= r.unknowable;
|
|
1002
|
+
}
|
|
1003
|
+
return acc2;
|
|
1004
|
+
}
|
|
1005
|
+
if (!node || typeof node !== "object") return { hasControl: false, unknowable: false };
|
|
1006
|
+
if (node.type === "SnippetBlock") return { hasControl: false, unknowable: false };
|
|
1007
|
+
if (node.type === "ExpressionTag" || node.type === "RenderTag" || node.type === "HtmlTag" || COMPONENT_LIKE_TYPES.has(node.type)) {
|
|
1008
|
+
return { hasControl: false, unknowable: true };
|
|
1009
|
+
}
|
|
1010
|
+
if (isLabelableDescendant(node)) return { hasControl: true, unknowable: false };
|
|
1011
|
+
const acc = { hasControl: false, unknowable: false };
|
|
1012
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
1013
|
+
if (key in node) {
|
|
1014
|
+
const r = scanLabelSubtree(node[key]);
|
|
1015
|
+
acc.hasControl ||= r.hasControl;
|
|
1016
|
+
acc.unknowable ||= r.unknowable;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
return acc;
|
|
1020
|
+
}
|
|
1021
|
+
function collectUnassociatedLabels(node, source, acc) {
|
|
1022
|
+
if (Array.isArray(node)) {
|
|
1023
|
+
for (const child of node) collectUnassociatedLabels(child, source, acc);
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
if (!node || typeof node !== "object") return;
|
|
1027
|
+
if (node.type === "RegularElement" && node.name === "label" && Array.isArray(node.attributes)) {
|
|
1028
|
+
const hasFor = findAttr(node.attributes, "for") !== void 0;
|
|
1029
|
+
const hasSpread = node.attributes.some((a) => a?.type === "SpreadAttribute");
|
|
1030
|
+
if (!hasFor && !hasSpread) {
|
|
1031
|
+
const scan = scanLabelSubtree(node);
|
|
1032
|
+
if (!scan.hasControl && !scan.unknowable) {
|
|
1033
|
+
acc.push({ line: lineOf(source, node.start) });
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
1038
|
+
if (key in node) collectUnassociatedLabels(node[key], source, acc);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
var BULLET_TEXT_RE = /^[•・·\-*]\s/;
|
|
1042
|
+
function collectBulletTexts(node, source, acc, insideLi) {
|
|
1043
|
+
if (Array.isArray(node)) {
|
|
1044
|
+
for (const child of node) collectBulletTexts(child, source, acc, insideLi);
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
if (!node || typeof node !== "object") return;
|
|
1048
|
+
if (node.type === "Text") {
|
|
1049
|
+
const trimmed = String(node.data ?? "").trim();
|
|
1050
|
+
if (!insideLi && BULLET_TEXT_RE.test(trimmed)) {
|
|
1051
|
+
acc.push({ line: lineOf(source, node.start), char: trimmed[0] });
|
|
1052
|
+
}
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
if (node.type === "SnippetBlock") return;
|
|
1056
|
+
const nowInsideLi = insideLi || node.type === "RegularElement" && node.name === "li";
|
|
1057
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
1058
|
+
if (key in node) collectBulletTexts(node[key], source, acc, nowInsideLi);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
function selectNeedsPlaceholder(attributes) {
|
|
1062
|
+
const requiredAttr = findAttr(attributes, "required");
|
|
1063
|
+
if (!requiredAttr || attrValueOf(requiredAttr) === "dynamic") return false;
|
|
1064
|
+
if (findAttr(attributes, "multiple")) return false;
|
|
1065
|
+
const sizeAttr = findAttr(attributes, "size");
|
|
1066
|
+
if (sizeAttr) {
|
|
1067
|
+
if (attrValueOf(sizeAttr) === "dynamic") return false;
|
|
1068
|
+
const size = Number(attrText(attributes, "size"));
|
|
1069
|
+
if (!(Number.isFinite(size) && size <= 1)) return false;
|
|
1070
|
+
}
|
|
1071
|
+
return true;
|
|
1072
|
+
}
|
|
1073
|
+
function firstSignificantChild(nodes) {
|
|
1074
|
+
for (const child of nodes ?? []) {
|
|
1075
|
+
if (!child) continue;
|
|
1076
|
+
if (child.type === "Comment") continue;
|
|
1077
|
+
if (child.type === "Text" && !String(child.data ?? "").trim()) continue;
|
|
1078
|
+
return child;
|
|
1079
|
+
}
|
|
1080
|
+
return void 0;
|
|
1081
|
+
}
|
|
1082
|
+
function isPlaceholderOption(option) {
|
|
1083
|
+
const attributes = option.attributes ?? [];
|
|
1084
|
+
if (findAttr(attributes, "value")) {
|
|
1085
|
+
const literal = attrText(attributes, "value");
|
|
1086
|
+
return literal === void 0 || literal === "";
|
|
1087
|
+
}
|
|
1088
|
+
return textFromNodes(option.fragment?.nodes ?? []) === void 0;
|
|
1089
|
+
}
|
|
1090
|
+
function collectSelectsMissingPlaceholder(node, source, acc) {
|
|
1091
|
+
if (Array.isArray(node)) {
|
|
1092
|
+
for (const child of node) collectSelectsMissingPlaceholder(child, source, acc);
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
if (!node || typeof node !== "object") return;
|
|
1096
|
+
if (node.type === "RegularElement" && node.name === "select" && Array.isArray(node.attributes)) {
|
|
1097
|
+
const hasSpread = node.attributes.some((a) => a?.type === "SpreadAttribute");
|
|
1098
|
+
if (!hasSpread && selectNeedsPlaceholder(node.attributes)) {
|
|
1099
|
+
const first = firstSignificantChild(node.fragment?.nodes);
|
|
1100
|
+
if (!first) {
|
|
1101
|
+
acc.push({ line: lineOf(source, node.start) });
|
|
1102
|
+
} else if (first.type === "RegularElement" && first.name === "option") {
|
|
1103
|
+
const firstHasSpread = (first.attributes ?? []).some((a) => a?.type === "SpreadAttribute");
|
|
1104
|
+
if (!firstHasSpread && !isPlaceholderOption(first)) acc.push({ line: lineOf(source, node.start) });
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
1109
|
+
if (key in node) collectSelectsMissingPlaceholder(node[key], source, acc);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
var MACHINE_READABLE_TIME = [
|
|
1113
|
+
/^\d{4}(-\d{2}){0,2}$/,
|
|
1114
|
+
/^\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/,
|
|
1115
|
+
/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}/,
|
|
1116
|
+
/^\d{2}-\d{2}$/,
|
|
1117
|
+
/^P(?=\d|T)/i
|
|
1118
|
+
];
|
|
1119
|
+
function collectTimesMissingDatetime(node, source, acc) {
|
|
1120
|
+
if (Array.isArray(node)) {
|
|
1121
|
+
for (const child of node) collectTimesMissingDatetime(child, source, acc);
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
if (!node || typeof node !== "object") return;
|
|
1125
|
+
if (node.type === "RegularElement" && node.name === "time" && findAttr(node.attributes ?? [], "datetime") === void 0 && !(node.attributes ?? []).some((a) => a?.type === "SpreadAttribute")) {
|
|
1126
|
+
const nodes = node.fragment?.nodes ?? [];
|
|
1127
|
+
if (nodes.length > 0 && nodes.every((n) => n?.type === "Text")) {
|
|
1128
|
+
const text = nodes.map((n) => String(n.data ?? "")).join("");
|
|
1129
|
+
const trimmed = text.trim();
|
|
1130
|
+
if (trimmed.length > 0 && !MACHINE_READABLE_TIME.some((re) => re.test(trimmed))) {
|
|
1131
|
+
acc.push({ line: lineOf(source, node.start), text: trimmed });
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
for (const key of CHILD_NODE_KEYS) {
|
|
1136
|
+
if (key in node) collectTimesMissingDatetime(node[key], source, acc);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
727
1139
|
function collectHrefLinks(node, source, acc) {
|
|
728
1140
|
if (Array.isArray(node)) {
|
|
729
1141
|
for (const child of node) collectHrefLinks(child, source, acc);
|
|
@@ -1345,6 +1757,20 @@ function parseComponentFacts(source, filename) {
|
|
|
1345
1757
|
collectSecurityFacts(ast.fragment ?? ast, source, htmlTags, javascriptUrls);
|
|
1346
1758
|
const checkableBindValues = [];
|
|
1347
1759
|
collectCheckableBindValues(ast.fragment ?? ast, source, checkableBindValues);
|
|
1760
|
+
const ariaElements = [];
|
|
1761
|
+
collectAriaElements(ast.fragment ?? ast, source, ariaElements);
|
|
1762
|
+
const interactiveNestings = [];
|
|
1763
|
+
collectInteractiveNestings(ast.fragment ?? ast, source, interactiveNestings, []);
|
|
1764
|
+
const unnamedInteractive = [];
|
|
1765
|
+
collectUnnamedInteractive(ast.fragment ?? ast, source, unnamedInteractive);
|
|
1766
|
+
const unassociatedLabels = [];
|
|
1767
|
+
collectUnassociatedLabels(ast.fragment ?? ast, source, unassociatedLabels);
|
|
1768
|
+
const bulletTexts = [];
|
|
1769
|
+
collectBulletTexts(ast.fragment ?? ast, source, bulletTexts, false);
|
|
1770
|
+
const selectsMissingPlaceholder = [];
|
|
1771
|
+
collectSelectsMissingPlaceholder(ast.fragment ?? ast, source, selectsMissingPlaceholder);
|
|
1772
|
+
const timesMissingDatetime = [];
|
|
1773
|
+
collectTimesMissingDatetime(ast.fragment ?? ast, source, timesMissingDatetime);
|
|
1348
1774
|
const basePathLinks = [];
|
|
1349
1775
|
collectHrefLinks(ast.fragment ?? ast, source, basePathLinks);
|
|
1350
1776
|
const gotoPrograms = [ast.module?.content, ast.instance?.content].filter(Boolean);
|
|
@@ -1547,7 +1973,14 @@ function parseComponentFacts(source, filename) {
|
|
|
1547
1973
|
browserGlobalRefs,
|
|
1548
1974
|
moduleStateDecls: [],
|
|
1549
1975
|
suppressions,
|
|
1550
|
-
commentLinks: collectCommentLinks(source)
|
|
1976
|
+
commentLinks: collectCommentLinks(source),
|
|
1977
|
+
ariaElements,
|
|
1978
|
+
interactiveNestings,
|
|
1979
|
+
unnamedInteractive,
|
|
1980
|
+
unassociatedLabels,
|
|
1981
|
+
bulletTexts,
|
|
1982
|
+
selectsMissingPlaceholder,
|
|
1983
|
+
timesMissingDatetime
|
|
1551
1984
|
};
|
|
1552
1985
|
}
|
|
1553
1986
|
|
|
@@ -2417,10 +2850,10 @@ function findKitPathsBaseInViteConfig(source) {
|
|
|
2417
2850
|
}
|
|
2418
2851
|
function resolveKitPathsBase(viteConfig, svelteConfig) {
|
|
2419
2852
|
if (viteConfig) {
|
|
2420
|
-
const
|
|
2421
|
-
if (
|
|
2422
|
-
if (
|
|
2423
|
-
return
|
|
2853
|
+
const result3 = findKitPathsBaseInViteConfig(viteConfig.source);
|
|
2854
|
+
if (result3.kind === "unresolvable") return void 0;
|
|
2855
|
+
if (result3.kind === "resolved") {
|
|
2856
|
+
return result3.base ? { ...result3.base, file: viteConfig.file } : void 0;
|
|
2424
2857
|
}
|
|
2425
2858
|
}
|
|
2426
2859
|
if (!svelteConfig) return void 0;
|
|
@@ -2749,56 +3182,56 @@ var seoHtmlLang = {
|
|
|
2749
3182
|
}
|
|
2750
3183
|
};
|
|
2751
3184
|
|
|
3185
|
+
// src/rules/detection.ts
|
|
3186
|
+
var PENALIZED = { presence: "none", value: "absent" };
|
|
3187
|
+
var PASS = { presence: "own", value: "static" };
|
|
3188
|
+
|
|
2752
3189
|
// src/rules/perf/image-rule.ts
|
|
2753
|
-
function
|
|
2754
|
-
const docsUrl12 = docsUrlFor(
|
|
2755
|
-
const category = opts.category ?? "performance";
|
|
3190
|
+
function routeItemRule(spec) {
|
|
3191
|
+
const docsUrl12 = docsUrlFor(spec.id);
|
|
2756
3192
|
return {
|
|
2757
|
-
id:
|
|
2758
|
-
title:
|
|
2759
|
-
category,
|
|
2760
|
-
severity:
|
|
3193
|
+
id: spec.id,
|
|
3194
|
+
title: spec.title,
|
|
3195
|
+
category: spec.category,
|
|
3196
|
+
severity: spec.severity,
|
|
2761
3197
|
scope: "route",
|
|
2762
|
-
rationale:
|
|
2763
|
-
...
|
|
3198
|
+
rationale: spec.rationale,
|
|
3199
|
+
...spec.fix ? { fix: spec.fix } : {},
|
|
2764
3200
|
async check(ctx) {
|
|
2765
3201
|
const out = [];
|
|
2766
|
-
for (const
|
|
2767
|
-
if (
|
|
2768
|
-
const bad =
|
|
3202
|
+
for (const g of spec.groups(ctx)) {
|
|
3203
|
+
if (g.items.length === 0) continue;
|
|
3204
|
+
const bad = g.items.filter((item) => !spec.ok(item));
|
|
2769
3205
|
if (bad.length === 0) {
|
|
2770
3206
|
out.push({
|
|
2771
|
-
id:
|
|
2772
|
-
category,
|
|
2773
|
-
severity:
|
|
2774
|
-
detection:
|
|
2775
|
-
route:
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
// was missed by the design spike's grep and added to its blast-radius table
|
|
2780
|
-
// afterward, maintainer ruling, same date). `route.images.length === 0` already
|
|
2781
|
-
// continued above, so `[0]` is always defined here.
|
|
2782
|
-
location: route.images[0].file,
|
|
2783
|
-
message: opts.label,
|
|
2784
|
-
recommendation: opts.recommendation,
|
|
3207
|
+
id: spec.id,
|
|
3208
|
+
category: spec.category,
|
|
3209
|
+
severity: spec.severity,
|
|
3210
|
+
detection: PASS,
|
|
3211
|
+
route: g.route,
|
|
3212
|
+
location: g.passLocation,
|
|
3213
|
+
message: spec.label,
|
|
3214
|
+
recommendation: spec.recommendation,
|
|
2785
3215
|
docsUrl: docsUrl12
|
|
2786
3216
|
});
|
|
2787
3217
|
continue;
|
|
2788
3218
|
}
|
|
2789
|
-
for (const
|
|
3219
|
+
for (const item of bad) {
|
|
3220
|
+
const line = spec.line?.(item);
|
|
2790
3221
|
out.push({
|
|
2791
|
-
id:
|
|
2792
|
-
category,
|
|
2793
|
-
severity:
|
|
2794
|
-
detection:
|
|
2795
|
-
route:
|
|
2796
|
-
location:
|
|
2797
|
-
...
|
|
2798
|
-
message: `Missing ${
|
|
2799
|
-
recommendation:
|
|
3222
|
+
id: spec.id,
|
|
3223
|
+
category: spec.category,
|
|
3224
|
+
severity: spec.severity,
|
|
3225
|
+
detection: PENALIZED,
|
|
3226
|
+
route: g.route,
|
|
3227
|
+
location: spec.location(item, g.passLocation),
|
|
3228
|
+
...line !== void 0 && line > 0 ? { line } : {},
|
|
3229
|
+
message: `Missing ${spec.label}`,
|
|
3230
|
+
recommendation: spec.recommendation,
|
|
2800
3231
|
docsUrl: docsUrl12,
|
|
2801
|
-
|
|
3232
|
+
// Copy per finding: spec.fix is a rule-level template shared across all
|
|
3233
|
+
// results this rule emits; a fresh object keeps findings independent.
|
|
3234
|
+
...spec.fix ? { fix: { ...spec.fix } } : {}
|
|
2802
3235
|
});
|
|
2803
3236
|
}
|
|
2804
3237
|
}
|
|
@@ -2806,6 +3239,18 @@ function imageRule(opts) {
|
|
|
2806
3239
|
}
|
|
2807
3240
|
};
|
|
2808
3241
|
}
|
|
3242
|
+
function imageRule(opts) {
|
|
3243
|
+
return routeItemRule({
|
|
3244
|
+
...opts,
|
|
3245
|
+
category: opts.category ?? "performance",
|
|
3246
|
+
// No single route-level file exists here (unlike ResolvedHead.file) — the route's
|
|
3247
|
+
// first image stands in as its attributed file; empty routes are filtered first,
|
|
3248
|
+
// so `[0]` is always defined.
|
|
3249
|
+
groups: (ctx) => (ctx.images ?? []).filter((r) => r.images.length > 0).map((r) => ({ route: r.route, items: r.images, passLocation: r.images[0].file })),
|
|
3250
|
+
location: (img) => img.file,
|
|
3251
|
+
line: (img) => img.line
|
|
3252
|
+
});
|
|
3253
|
+
}
|
|
2809
3254
|
|
|
2810
3255
|
// src/rules/perf/image-dimensions.ts
|
|
2811
3256
|
var performanceImageDimensions = imageRule({
|
|
@@ -2857,62 +3302,19 @@ var performanceResponsiveImage = imageRule({
|
|
|
2857
3302
|
|
|
2858
3303
|
// src/rules/perf/link-rule.ts
|
|
2859
3304
|
function linkRule(opts) {
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
id: opts.id,
|
|
2863
|
-
title: opts.title,
|
|
3305
|
+
return routeItemRule({
|
|
3306
|
+
...opts,
|
|
2864
3307
|
category: "performance",
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
if (bad.length === 0) {
|
|
2876
|
-
out.push({
|
|
2877
|
-
id: opts.id,
|
|
2878
|
-
category: "performance",
|
|
2879
|
-
severity: opts.severity,
|
|
2880
|
-
detection: { presence: "own", value: "static" },
|
|
2881
|
-
route: head.route,
|
|
2882
|
-
// The route's own attributed file (design 2026-08-08-pass-result-location-design.md)
|
|
2883
|
-
// — this uncaught inline PASS literal was missed by the design spike's grep and
|
|
2884
|
-
// added to its blast-radius table afterward (maintainer ruling, same date). No
|
|
2885
|
-
// single per-tag location applies here (many links can back one pass), so the
|
|
2886
|
-
// route's own head file is the uniform attribution; per-tag penalized locations
|
|
2887
|
-
// above remain per-tag.
|
|
2888
|
-
location: head.file,
|
|
2889
|
-
message: opts.label,
|
|
2890
|
-
recommendation: opts.recommendation,
|
|
2891
|
-
docsUrl: docsUrl12
|
|
2892
|
-
});
|
|
2893
|
-
continue;
|
|
2894
|
-
}
|
|
2895
|
-
for (const tag of bad) {
|
|
2896
|
-
out.push({
|
|
2897
|
-
id: opts.id,
|
|
2898
|
-
category: "performance",
|
|
2899
|
-
severity: opts.severity,
|
|
2900
|
-
detection: { presence: "none", value: "absent" },
|
|
2901
|
-
route: head.route,
|
|
2902
|
-
// Point at the file the link actually came from (a layout in static
|
|
2903
|
-
// mode); fall back to the route's representative file when the tag
|
|
2904
|
-
// carries no file (rendered mode).
|
|
2905
|
-
location: tag.file ?? head.file,
|
|
2906
|
-
message: `Missing ${opts.label}`,
|
|
2907
|
-
recommendation: opts.recommendation,
|
|
2908
|
-
docsUrl: docsUrl12,
|
|
2909
|
-
...opts.fix ? { fix: { ...opts.fix } } : {}
|
|
2910
|
-
});
|
|
2911
|
-
}
|
|
2912
|
-
}
|
|
2913
|
-
return out;
|
|
2914
|
-
}
|
|
2915
|
-
};
|
|
3308
|
+
// The route's own head file is the PASS attribution (many links can back one pass).
|
|
3309
|
+
groups: (ctx) => ctx.heads.map((head) => ({
|
|
3310
|
+
route: head.route,
|
|
3311
|
+
items: head.tags.filter((t) => t.kind === "link" && opts.relevant(t)),
|
|
3312
|
+
passLocation: head.file
|
|
3313
|
+
})),
|
|
3314
|
+
// Point at the file the link actually came from (a layout in static mode); fall back
|
|
3315
|
+
// to the route's representative file when the tag carries no file (rendered mode).
|
|
3316
|
+
location: (tag, passLocation) => tag.file ?? passLocation
|
|
3317
|
+
});
|
|
2916
3318
|
}
|
|
2917
3319
|
|
|
2918
3320
|
// src/rules/perf/preload-missing-as.ts
|
|
@@ -3083,10 +3485,13 @@ function withFailedRulesOff(config, failedRuleIds) {
|
|
|
3083
3485
|
}
|
|
3084
3486
|
};
|
|
3085
3487
|
}
|
|
3488
|
+
function formatFailedRuleWarning(f) {
|
|
3489
|
+
return `rule ${f.id} failed and was skipped: ${f.message.split("\n")[0]}`;
|
|
3490
|
+
}
|
|
3086
3491
|
function applyRuleSeverities(results, config) {
|
|
3087
|
-
return results.map((
|
|
3088
|
-
const severity = settingSeverity(config.rules[
|
|
3089
|
-
return severity !== void 0 && severity !== "off" ? { ...
|
|
3492
|
+
return results.map((result3) => {
|
|
3493
|
+
const severity = settingSeverity(config.rules[result3.id]);
|
|
3494
|
+
return severity !== void 0 && severity !== "off" ? { ...result3, severity } : result3;
|
|
3090
3495
|
});
|
|
3091
3496
|
}
|
|
3092
3497
|
function routeGlobToRegExp(pattern) {
|
|
@@ -3113,15 +3518,15 @@ function applyOverrides(results, config) {
|
|
|
3113
3518
|
const compiled = compileOverrides(config);
|
|
3114
3519
|
if (compiled.length === 0) return results;
|
|
3115
3520
|
const out = [];
|
|
3116
|
-
for (const
|
|
3521
|
+
for (const result3 of results) {
|
|
3117
3522
|
let severity;
|
|
3118
3523
|
for (const o of compiled) {
|
|
3119
|
-
if (!overrideMatches(o, { route:
|
|
3120
|
-
const sev = settingSeverity(o.rules[
|
|
3524
|
+
if (!overrideMatches(o, { route: result3.route, file: result3.location })) continue;
|
|
3525
|
+
const sev = settingSeverity(o.rules[result3.id]) ?? settingSeverity(o.rules[result3.category ?? "seo"]);
|
|
3121
3526
|
if (sev !== void 0) severity = sev;
|
|
3122
3527
|
}
|
|
3123
|
-
if (severity === void 0) out.push(
|
|
3124
|
-
else if (severity !== "off") out.push({ ...
|
|
3528
|
+
if (severity === void 0) out.push(result3);
|
|
3529
|
+
else if (severity !== "off") out.push({ ...result3, severity });
|
|
3125
3530
|
}
|
|
3126
3531
|
return out;
|
|
3127
3532
|
}
|
|
@@ -3483,10 +3888,6 @@ var seoSitemapInRobots = {
|
|
|
3483
3888
|
}
|
|
3484
3889
|
};
|
|
3485
3890
|
|
|
3486
|
-
// src/rules/seo/detection.ts
|
|
3487
|
-
var PENALIZED = { presence: "none", value: "absent" };
|
|
3488
|
-
var PASS = { presence: "own", value: "static" };
|
|
3489
|
-
|
|
3490
3891
|
// src/rules/seo/jsonld-engine.ts
|
|
3491
3892
|
function parseJsonLd(raw) {
|
|
3492
3893
|
let data;
|
|
@@ -3700,1042 +4101,11 @@ function jsonldRule(opts) {
|
|
|
3700
4101
|
}
|
|
3701
4102
|
|
|
3702
4103
|
// src/rules/seo/schema-vocabulary.generated.ts
|
|
3703
|
-
var SCHEMA_ORG_TYPES =
|
|
3704
|
-
"3DModel",
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
"AcceptAction",
|
|
3709
|
-
"Accommodation",
|
|
3710
|
-
"AccountingService",
|
|
3711
|
-
"AchieveAction",
|
|
3712
|
-
"Action",
|
|
3713
|
-
"ActionAccessSpecification",
|
|
3714
|
-
"ActionStatusType",
|
|
3715
|
-
"ActivateAction",
|
|
3716
|
-
"AddAction",
|
|
3717
|
-
"AdministrativeArea",
|
|
3718
|
-
"AdultEntertainment",
|
|
3719
|
-
"AdultOrientedEnumeration",
|
|
3720
|
-
"AdvertiserContentArticle",
|
|
3721
|
-
"AggregateOffer",
|
|
3722
|
-
"AggregateRating",
|
|
3723
|
-
"AgreeAction",
|
|
3724
|
-
"Airline",
|
|
3725
|
-
"Airport",
|
|
3726
|
-
"AlignmentObject",
|
|
3727
|
-
"AllocateAction",
|
|
3728
|
-
"AmpStory",
|
|
3729
|
-
"AmusementPark",
|
|
3730
|
-
"AnalysisNewsArticle",
|
|
3731
|
-
"AnatomicalStructure",
|
|
3732
|
-
"AnatomicalSystem",
|
|
3733
|
-
"AnimalShelter",
|
|
3734
|
-
"Answer",
|
|
3735
|
-
"Apartment",
|
|
3736
|
-
"ApartmentComplex",
|
|
3737
|
-
"AppendAction",
|
|
3738
|
-
"ApplyAction",
|
|
3739
|
-
"ApprovedIndication",
|
|
3740
|
-
"Aquarium",
|
|
3741
|
-
"ArchiveComponent",
|
|
3742
|
-
"ArchiveOrganization",
|
|
3743
|
-
"ArriveAction",
|
|
3744
|
-
"ArtGallery",
|
|
3745
|
-
"Artery",
|
|
3746
|
-
"Article",
|
|
3747
|
-
"AskAction",
|
|
3748
|
-
"AskPublicNewsArticle",
|
|
3749
|
-
"AssessAction",
|
|
3750
|
-
"AssignAction",
|
|
3751
|
-
"Atlas",
|
|
3752
|
-
"Attorney",
|
|
3753
|
-
"Audience",
|
|
3754
|
-
"AudioObject",
|
|
3755
|
-
"AudioObjectSnapshot",
|
|
3756
|
-
"Audiobook",
|
|
3757
|
-
"AuthenticateAction",
|
|
3758
|
-
"AuthorizeAction",
|
|
3759
|
-
"AutoBodyShop",
|
|
3760
|
-
"AutoDealer",
|
|
3761
|
-
"AutoPartsStore",
|
|
3762
|
-
"AutoRental",
|
|
3763
|
-
"AutoRepair",
|
|
3764
|
-
"AutoWash",
|
|
3765
|
-
"AutomatedTeller",
|
|
3766
|
-
"AutomotiveBusiness",
|
|
3767
|
-
"BackgroundNewsArticle",
|
|
3768
|
-
"Bakery",
|
|
3769
|
-
"BankAccount",
|
|
3770
|
-
"BankOrCreditUnion",
|
|
3771
|
-
"BarOrPub",
|
|
3772
|
-
"Barcode",
|
|
3773
|
-
"Beach",
|
|
3774
|
-
"BeautySalon",
|
|
3775
|
-
"BedAndBreakfast",
|
|
3776
|
-
"BedDetails",
|
|
3777
|
-
"BedType",
|
|
3778
|
-
"BefriendAction",
|
|
3779
|
-
"BikeStore",
|
|
3780
|
-
"BioChemEntity",
|
|
3781
|
-
"Blog",
|
|
3782
|
-
"BlogPosting",
|
|
3783
|
-
"BloodTest",
|
|
3784
|
-
"BoardingPolicyType",
|
|
3785
|
-
"BoatReservation",
|
|
3786
|
-
"BoatTerminal",
|
|
3787
|
-
"BoatTrip",
|
|
3788
|
-
"BodyMeasurementTypeEnumeration",
|
|
3789
|
-
"BodyOfWater",
|
|
3790
|
-
"Bone",
|
|
3791
|
-
"Book",
|
|
3792
|
-
"BookFormatType",
|
|
3793
|
-
"BookSeries",
|
|
3794
|
-
"BookStore",
|
|
3795
|
-
"BookmarkAction",
|
|
3796
|
-
"Boolean",
|
|
3797
|
-
"BorrowAction",
|
|
3798
|
-
"BowlingAlley",
|
|
3799
|
-
"BrainStructure",
|
|
3800
|
-
"Brand",
|
|
3801
|
-
"BreadcrumbList",
|
|
3802
|
-
"Brewery",
|
|
3803
|
-
"Bridge",
|
|
3804
|
-
"BroadcastChannel",
|
|
3805
|
-
"BroadcastEvent",
|
|
3806
|
-
"BroadcastFrequencySpecification",
|
|
3807
|
-
"BroadcastService",
|
|
3808
|
-
"BrokerageAccount",
|
|
3809
|
-
"BuddhistTemple",
|
|
3810
|
-
"BusOrCoach",
|
|
3811
|
-
"BusReservation",
|
|
3812
|
-
"BusStation",
|
|
3813
|
-
"BusStop",
|
|
3814
|
-
"BusTrip",
|
|
3815
|
-
"BusinessAudience",
|
|
3816
|
-
"BusinessEntityType",
|
|
3817
|
-
"BusinessEvent",
|
|
3818
|
-
"BusinessFunction",
|
|
3819
|
-
"BuyAction",
|
|
3820
|
-
"CDCPMDRecord",
|
|
3821
|
-
"CableOrSatelliteService",
|
|
3822
|
-
"CafeOrCoffeeShop",
|
|
3823
|
-
"Campground",
|
|
3824
|
-
"CampingPitch",
|
|
3825
|
-
"Canal",
|
|
3826
|
-
"CancelAction",
|
|
3827
|
-
"Car",
|
|
3828
|
-
"CarUsageType",
|
|
3829
|
-
"Casino",
|
|
3830
|
-
"CategoryCode",
|
|
3831
|
-
"CategoryCodeSet",
|
|
3832
|
-
"CatholicChurch",
|
|
3833
|
-
"Cemetery",
|
|
3834
|
-
"Certification",
|
|
3835
|
-
"CertificationStatusEnumeration",
|
|
3836
|
-
"Chapter",
|
|
3837
|
-
"CheckAction",
|
|
3838
|
-
"CheckInAction",
|
|
3839
|
-
"CheckOutAction",
|
|
3840
|
-
"CheckoutPage",
|
|
3841
|
-
"ChemicalSubstance",
|
|
3842
|
-
"ChildCare",
|
|
3843
|
-
"ChildrensEvent",
|
|
3844
|
-
"ChooseAction",
|
|
3845
|
-
"Church",
|
|
3846
|
-
"City",
|
|
3847
|
-
"CityHall",
|
|
3848
|
-
"CivicStructure",
|
|
3849
|
-
"Claim",
|
|
3850
|
-
"ClaimReview",
|
|
3851
|
-
"Class",
|
|
3852
|
-
"Clip",
|
|
3853
|
-
"ClothingStore",
|
|
3854
|
-
"Code",
|
|
3855
|
-
"Collection",
|
|
3856
|
-
"CollectionPage",
|
|
3857
|
-
"CollegeOrUniversity",
|
|
3858
|
-
"ComedyClub",
|
|
3859
|
-
"ComedyEvent",
|
|
3860
|
-
"ComicCoverArt",
|
|
3861
|
-
"ComicIssue",
|
|
3862
|
-
"ComicSeries",
|
|
3863
|
-
"ComicStory",
|
|
3864
|
-
"Comment",
|
|
3865
|
-
"CommentAction",
|
|
3866
|
-
"CommunicateAction",
|
|
3867
|
-
"CommunityHealth",
|
|
3868
|
-
"CompleteDataFeed",
|
|
3869
|
-
"CompoundPriceSpecification",
|
|
3870
|
-
"ComputerLanguage",
|
|
3871
|
-
"ComputerStore",
|
|
3872
|
-
"ConferenceEvent",
|
|
3873
|
-
"ConfirmAction",
|
|
3874
|
-
"Consortium",
|
|
3875
|
-
"ConstraintNode",
|
|
3876
|
-
"ConsumeAction",
|
|
3877
|
-
"ContactPage",
|
|
3878
|
-
"ContactPoint",
|
|
3879
|
-
"ContactPointOption",
|
|
3880
|
-
"Continent",
|
|
3881
|
-
"ControlAction",
|
|
3882
|
-
"ConvenienceStore",
|
|
3883
|
-
"Conversation",
|
|
3884
|
-
"CookAction",
|
|
3885
|
-
"Cooperative",
|
|
3886
|
-
"Corporation",
|
|
3887
|
-
"CorrectionComment",
|
|
3888
|
-
"Country",
|
|
3889
|
-
"Course",
|
|
3890
|
-
"CourseInstance",
|
|
3891
|
-
"Courthouse",
|
|
3892
|
-
"CoverArt",
|
|
3893
|
-
"CovidTestingFacility",
|
|
3894
|
-
"CreateAction",
|
|
3895
|
-
"CreativeWork",
|
|
3896
|
-
"CreativeWorkSeason",
|
|
3897
|
-
"CreativeWorkSeries",
|
|
3898
|
-
"Credential",
|
|
3899
|
-
"CreditCard",
|
|
3900
|
-
"Crematorium",
|
|
3901
|
-
"CriticReview",
|
|
3902
|
-
"CssSelectorType",
|
|
3903
|
-
"CurrencyConversionService",
|
|
3904
|
-
"DDxElement",
|
|
3905
|
-
"DENonprofitType",
|
|
3906
|
-
"DanceEvent",
|
|
3907
|
-
"DanceGroup",
|
|
3908
|
-
"DataCatalog",
|
|
3909
|
-
"DataDownload",
|
|
3910
|
-
"DataFeed",
|
|
3911
|
-
"DataFeedItem",
|
|
3912
|
-
"DataType",
|
|
3913
|
-
"Dataset",
|
|
3914
|
-
"Date",
|
|
3915
|
-
"DateTime",
|
|
3916
|
-
"DatedMoneySpecification",
|
|
3917
|
-
"DayOfWeek",
|
|
3918
|
-
"DaySpa",
|
|
3919
|
-
"DeactivateAction",
|
|
3920
|
-
"DefenceEstablishment",
|
|
3921
|
-
"DefinedRegion",
|
|
3922
|
-
"DefinedTerm",
|
|
3923
|
-
"DefinedTermSet",
|
|
3924
|
-
"DeleteAction",
|
|
3925
|
-
"DeliveryChargeSpecification",
|
|
3926
|
-
"DeliveryEvent",
|
|
3927
|
-
"DeliveryMethod",
|
|
3928
|
-
"DeliveryTimeSettings",
|
|
3929
|
-
"Demand",
|
|
3930
|
-
"Dentist",
|
|
3931
|
-
"DepartAction",
|
|
3932
|
-
"DepartmentStore",
|
|
3933
|
-
"DepositAccount",
|
|
3934
|
-
"Dermatology",
|
|
3935
|
-
"DiagnosticLab",
|
|
3936
|
-
"DiagnosticProcedure",
|
|
3937
|
-
"Diet",
|
|
3938
|
-
"DietNutrition",
|
|
3939
|
-
"DietarySupplement",
|
|
3940
|
-
"DigitalDocument",
|
|
3941
|
-
"DigitalDocumentPermission",
|
|
3942
|
-
"DigitalDocumentPermissionType",
|
|
3943
|
-
"DigitalPlatformEnumeration",
|
|
3944
|
-
"DisagreeAction",
|
|
3945
|
-
"DiscoverAction",
|
|
3946
|
-
"DiscussionForumPosting",
|
|
3947
|
-
"DislikeAction",
|
|
3948
|
-
"Distance",
|
|
3949
|
-
"Distillery",
|
|
3950
|
-
"DonateAction",
|
|
3951
|
-
"DoseSchedule",
|
|
3952
|
-
"DownloadAction",
|
|
3953
|
-
"DrawAction",
|
|
3954
|
-
"Drawing",
|
|
3955
|
-
"DrinkAction",
|
|
3956
|
-
"DriveWheelConfigurationValue",
|
|
3957
|
-
"Drug",
|
|
3958
|
-
"DrugClass",
|
|
3959
|
-
"DrugCost",
|
|
3960
|
-
"DrugCostCategory",
|
|
3961
|
-
"DrugLegalStatus",
|
|
3962
|
-
"DrugPregnancyCategory",
|
|
3963
|
-
"DrugPrescriptionStatus",
|
|
3964
|
-
"DrugStrength",
|
|
3965
|
-
"DryCleaningOrLaundry",
|
|
3966
|
-
"Duration",
|
|
3967
|
-
"EUEnergyEfficiencyEnumeration",
|
|
3968
|
-
"EatAction",
|
|
3969
|
-
"EducationEvent",
|
|
3970
|
-
"EducationalAudience",
|
|
3971
|
-
"EducationalOccupationalCredential",
|
|
3972
|
-
"EducationalOccupationalProgram",
|
|
3973
|
-
"EducationalOrganization",
|
|
3974
|
-
"Electrician",
|
|
3975
|
-
"ElectronicsStore",
|
|
3976
|
-
"ElementarySchool",
|
|
3977
|
-
"EmailMessage",
|
|
3978
|
-
"Embassy",
|
|
3979
|
-
"Emergency",
|
|
3980
|
-
"EmergencyService",
|
|
3981
|
-
"EmployeeRole",
|
|
3982
|
-
"EmployerAggregateRating",
|
|
3983
|
-
"EmployerReview",
|
|
3984
|
-
"EmploymentAgency",
|
|
3985
|
-
"EndorseAction",
|
|
3986
|
-
"EndorsementRating",
|
|
3987
|
-
"Energy",
|
|
3988
|
-
"EnergyConsumptionDetails",
|
|
3989
|
-
"EnergyEfficiencyEnumeration",
|
|
3990
|
-
"EnergyStarEnergyEfficiencyEnumeration",
|
|
3991
|
-
"EngineSpecification",
|
|
3992
|
-
"EntertainmentBusiness",
|
|
3993
|
-
"EntryPoint",
|
|
3994
|
-
"Enumeration",
|
|
3995
|
-
"Episode",
|
|
3996
|
-
"Error",
|
|
3997
|
-
"Event",
|
|
3998
|
-
"EventAttendanceModeEnumeration",
|
|
3999
|
-
"EventReservation",
|
|
4000
|
-
"EventSeries",
|
|
4001
|
-
"EventStatusType",
|
|
4002
|
-
"EventVenue",
|
|
4003
|
-
"ExchangeRateSpecification",
|
|
4004
|
-
"ExerciseAction",
|
|
4005
|
-
"ExerciseGym",
|
|
4006
|
-
"ExercisePlan",
|
|
4007
|
-
"ExhibitionEvent",
|
|
4008
|
-
"FAQPage",
|
|
4009
|
-
"FMRadioChannel",
|
|
4010
|
-
"FastFoodRestaurant",
|
|
4011
|
-
"Festival",
|
|
4012
|
-
"FilmAction",
|
|
4013
|
-
"FinancialIncentive",
|
|
4014
|
-
"FinancialProduct",
|
|
4015
|
-
"FinancialService",
|
|
4016
|
-
"FindAction",
|
|
4017
|
-
"FireStation",
|
|
4018
|
-
"Flight",
|
|
4019
|
-
"FlightReservation",
|
|
4020
|
-
"Float",
|
|
4021
|
-
"FloorPlan",
|
|
4022
|
-
"Florist",
|
|
4023
|
-
"FollowAction",
|
|
4024
|
-
"FoodEstablishment",
|
|
4025
|
-
"FoodEstablishmentReservation",
|
|
4026
|
-
"FoodEvent",
|
|
4027
|
-
"FoodService",
|
|
4028
|
-
"FulfillmentTypeEnumeration",
|
|
4029
|
-
"FundingAgency",
|
|
4030
|
-
"FundingScheme",
|
|
4031
|
-
"FurnitureStore",
|
|
4032
|
-
"Game",
|
|
4033
|
-
"GameAvailabilityEnumeration",
|
|
4034
|
-
"GamePlayMode",
|
|
4035
|
-
"GameServer",
|
|
4036
|
-
"GameServerStatus",
|
|
4037
|
-
"GardenStore",
|
|
4038
|
-
"GasStation",
|
|
4039
|
-
"GatedResidenceCommunity",
|
|
4040
|
-
"GenderType",
|
|
4041
|
-
"Gene",
|
|
4042
|
-
"GeneralContractor",
|
|
4043
|
-
"GeoCircle",
|
|
4044
|
-
"GeoCoordinates",
|
|
4045
|
-
"GeoShape",
|
|
4046
|
-
"GeospatialGeometry",
|
|
4047
|
-
"Geriatric",
|
|
4048
|
-
"GiveAction",
|
|
4049
|
-
"GolfCourse",
|
|
4050
|
-
"GovernmentBenefitsType",
|
|
4051
|
-
"GovernmentBuilding",
|
|
4052
|
-
"GovernmentOffice",
|
|
4053
|
-
"GovernmentOrganization",
|
|
4054
|
-
"GovernmentPermit",
|
|
4055
|
-
"GovernmentService",
|
|
4056
|
-
"Grant",
|
|
4057
|
-
"GroceryStore",
|
|
4058
|
-
"Guide",
|
|
4059
|
-
"Gynecologic",
|
|
4060
|
-
"HVACBusiness",
|
|
4061
|
-
"Hackathon",
|
|
4062
|
-
"HairSalon",
|
|
4063
|
-
"HardwareStore",
|
|
4064
|
-
"HealthAndBeautyBusiness",
|
|
4065
|
-
"HealthAspectEnumeration",
|
|
4066
|
-
"HealthClub",
|
|
4067
|
-
"HealthInsurancePlan",
|
|
4068
|
-
"HealthPlanCostSharingSpecification",
|
|
4069
|
-
"HealthPlanFormulary",
|
|
4070
|
-
"HealthPlanNetwork",
|
|
4071
|
-
"HealthTopicContent",
|
|
4072
|
-
"HighSchool",
|
|
4073
|
-
"HinduTemple",
|
|
4074
|
-
"HobbyShop",
|
|
4075
|
-
"HomeAndConstructionBusiness",
|
|
4076
|
-
"HomeGoodsStore",
|
|
4077
|
-
"Hospital",
|
|
4078
|
-
"Hostel",
|
|
4079
|
-
"Hotel",
|
|
4080
|
-
"HotelRoom",
|
|
4081
|
-
"House",
|
|
4082
|
-
"HousePainter",
|
|
4083
|
-
"HowTo",
|
|
4084
|
-
"HowToDirection",
|
|
4085
|
-
"HowToItem",
|
|
4086
|
-
"HowToSection",
|
|
4087
|
-
"HowToStep",
|
|
4088
|
-
"HowToSupply",
|
|
4089
|
-
"HowToTip",
|
|
4090
|
-
"HowToTool",
|
|
4091
|
-
"HyperToc",
|
|
4092
|
-
"HyperTocEntry",
|
|
4093
|
-
"IPTCDigitalSourceEnumeration",
|
|
4094
|
-
"ITNonprofitType",
|
|
4095
|
-
"IceCreamShop",
|
|
4096
|
-
"IgnoreAction",
|
|
4097
|
-
"ImageGallery",
|
|
4098
|
-
"ImageObject",
|
|
4099
|
-
"ImageObjectSnapshot",
|
|
4100
|
-
"ImagingTest",
|
|
4101
|
-
"IncentiveQualifiedExpenseType",
|
|
4102
|
-
"IncentiveStatus",
|
|
4103
|
-
"IncentiveType",
|
|
4104
|
-
"IndividualPhysician",
|
|
4105
|
-
"IndividualProduct",
|
|
4106
|
-
"InfectiousAgentClass",
|
|
4107
|
-
"InfectiousDisease",
|
|
4108
|
-
"InformAction",
|
|
4109
|
-
"InsertAction",
|
|
4110
|
-
"InstallAction",
|
|
4111
|
-
"InstantaneousEvent",
|
|
4112
|
-
"InsuranceAgency",
|
|
4113
|
-
"Intangible",
|
|
4114
|
-
"Integer",
|
|
4115
|
-
"InteractAction",
|
|
4116
|
-
"InteractionCounter",
|
|
4117
|
-
"InternetCafe",
|
|
4118
|
-
"InvestmentFund",
|
|
4119
|
-
"InvestmentOrDeposit",
|
|
4120
|
-
"InviteAction",
|
|
4121
|
-
"Invoice",
|
|
4122
|
-
"ItemAvailability",
|
|
4123
|
-
"ItemList",
|
|
4124
|
-
"ItemListOrderType",
|
|
4125
|
-
"ItemPage",
|
|
4126
|
-
"JewelryStore",
|
|
4127
|
-
"JobPosting",
|
|
4128
|
-
"JoinAction",
|
|
4129
|
-
"Joint",
|
|
4130
|
-
"LakeBodyOfWater",
|
|
4131
|
-
"Landform",
|
|
4132
|
-
"LandmarksOrHistoricalBuildings",
|
|
4133
|
-
"Language",
|
|
4134
|
-
"LearningResource",
|
|
4135
|
-
"LeaveAction",
|
|
4136
|
-
"LegalForceStatus",
|
|
4137
|
-
"LegalService",
|
|
4138
|
-
"LegalValueLevel",
|
|
4139
|
-
"Legislation",
|
|
4140
|
-
"LegislationObject",
|
|
4141
|
-
"LegislativeBuilding",
|
|
4142
|
-
"LendAction",
|
|
4143
|
-
"Library",
|
|
4144
|
-
"LibrarySystem",
|
|
4145
|
-
"LifestyleModification",
|
|
4146
|
-
"Ligament",
|
|
4147
|
-
"LikeAction",
|
|
4148
|
-
"LinkRole",
|
|
4149
|
-
"LiquorStore",
|
|
4150
|
-
"ListItem",
|
|
4151
|
-
"ListenAction",
|
|
4152
|
-
"LiteraryEvent",
|
|
4153
|
-
"LiveBlogPosting",
|
|
4154
|
-
"LoanOrCredit",
|
|
4155
|
-
"LocalBusiness",
|
|
4156
|
-
"LocationFeatureSpecification",
|
|
4157
|
-
"Locksmith",
|
|
4158
|
-
"LodgingBusiness",
|
|
4159
|
-
"LodgingReservation",
|
|
4160
|
-
"LoginAction",
|
|
4161
|
-
"LoseAction",
|
|
4162
|
-
"LymphaticVessel",
|
|
4163
|
-
"Manuscript",
|
|
4164
|
-
"Map",
|
|
4165
|
-
"MapCategoryType",
|
|
4166
|
-
"MarryAction",
|
|
4167
|
-
"Mass",
|
|
4168
|
-
"MathSolver",
|
|
4169
|
-
"MaximumDoseSchedule",
|
|
4170
|
-
"MeasurementMethodEnum",
|
|
4171
|
-
"MeasurementTypeEnumeration",
|
|
4172
|
-
"MediaEnumeration",
|
|
4173
|
-
"MediaGallery",
|
|
4174
|
-
"MediaManipulationRatingEnumeration",
|
|
4175
|
-
"MediaObject",
|
|
4176
|
-
"MediaReview",
|
|
4177
|
-
"MediaReviewItem",
|
|
4178
|
-
"MediaSubscription",
|
|
4179
|
-
"MedicalAudience",
|
|
4180
|
-
"MedicalAudienceType",
|
|
4181
|
-
"MedicalBusiness",
|
|
4182
|
-
"MedicalCause",
|
|
4183
|
-
"MedicalClinic",
|
|
4184
|
-
"MedicalCode",
|
|
4185
|
-
"MedicalCondition",
|
|
4186
|
-
"MedicalConditionStage",
|
|
4187
|
-
"MedicalContraindication",
|
|
4188
|
-
"MedicalDevice",
|
|
4189
|
-
"MedicalDevicePurpose",
|
|
4190
|
-
"MedicalEntity",
|
|
4191
|
-
"MedicalEnumeration",
|
|
4192
|
-
"MedicalEvidenceLevel",
|
|
4193
|
-
"MedicalGuideline",
|
|
4194
|
-
"MedicalGuidelineContraindication",
|
|
4195
|
-
"MedicalGuidelineRecommendation",
|
|
4196
|
-
"MedicalImagingTechnique",
|
|
4197
|
-
"MedicalIndication",
|
|
4198
|
-
"MedicalIntangible",
|
|
4199
|
-
"MedicalObservationalStudy",
|
|
4200
|
-
"MedicalObservationalStudyDesign",
|
|
4201
|
-
"MedicalOrganization",
|
|
4202
|
-
"MedicalProcedure",
|
|
4203
|
-
"MedicalProcedureType",
|
|
4204
|
-
"MedicalRiskCalculator",
|
|
4205
|
-
"MedicalRiskEstimator",
|
|
4206
|
-
"MedicalRiskFactor",
|
|
4207
|
-
"MedicalRiskScore",
|
|
4208
|
-
"MedicalScholarlyArticle",
|
|
4209
|
-
"MedicalSign",
|
|
4210
|
-
"MedicalSignOrSymptom",
|
|
4211
|
-
"MedicalSpecialty",
|
|
4212
|
-
"MedicalStudy",
|
|
4213
|
-
"MedicalStudyStatus",
|
|
4214
|
-
"MedicalSymptom",
|
|
4215
|
-
"MedicalTest",
|
|
4216
|
-
"MedicalTestPanel",
|
|
4217
|
-
"MedicalTherapy",
|
|
4218
|
-
"MedicalTrial",
|
|
4219
|
-
"MedicalTrialDesign",
|
|
4220
|
-
"MedicalWebPage",
|
|
4221
|
-
"MedicineSystem",
|
|
4222
|
-
"MeetingRoom",
|
|
4223
|
-
"MemberProgram",
|
|
4224
|
-
"MemberProgramTier",
|
|
4225
|
-
"MensClothingStore",
|
|
4226
|
-
"Menu",
|
|
4227
|
-
"MenuItem",
|
|
4228
|
-
"MenuSection",
|
|
4229
|
-
"MerchantReturnEnumeration",
|
|
4230
|
-
"MerchantReturnPolicy",
|
|
4231
|
-
"MerchantReturnPolicySeasonalOverride",
|
|
4232
|
-
"Message",
|
|
4233
|
-
"MiddleSchool",
|
|
4234
|
-
"Midwifery",
|
|
4235
|
-
"MobileApplication",
|
|
4236
|
-
"MobilePhoneStore",
|
|
4237
|
-
"MolecularEntity",
|
|
4238
|
-
"MonetaryAmount",
|
|
4239
|
-
"MonetaryAmountDistribution",
|
|
4240
|
-
"MonetaryGrant",
|
|
4241
|
-
"MoneyTransfer",
|
|
4242
|
-
"MortgageLoan",
|
|
4243
|
-
"Mosque",
|
|
4244
|
-
"Motel",
|
|
4245
|
-
"Motorcycle",
|
|
4246
|
-
"MotorcycleDealer",
|
|
4247
|
-
"MotorcycleRepair",
|
|
4248
|
-
"MotorizedBicycle",
|
|
4249
|
-
"Mountain",
|
|
4250
|
-
"MoveAction",
|
|
4251
|
-
"Movie",
|
|
4252
|
-
"MovieClip",
|
|
4253
|
-
"MovieRentalStore",
|
|
4254
|
-
"MovieSeries",
|
|
4255
|
-
"MovieTheater",
|
|
4256
|
-
"MovingCompany",
|
|
4257
|
-
"Muscle",
|
|
4258
|
-
"Museum",
|
|
4259
|
-
"MusicAlbum",
|
|
4260
|
-
"MusicAlbumProductionType",
|
|
4261
|
-
"MusicAlbumReleaseType",
|
|
4262
|
-
"MusicComposition",
|
|
4263
|
-
"MusicEvent",
|
|
4264
|
-
"MusicGroup",
|
|
4265
|
-
"MusicPlaylist",
|
|
4266
|
-
"MusicRecording",
|
|
4267
|
-
"MusicRelease",
|
|
4268
|
-
"MusicReleaseFormatType",
|
|
4269
|
-
"MusicStore",
|
|
4270
|
-
"MusicVenue",
|
|
4271
|
-
"MusicVideoObject",
|
|
4272
|
-
"NGO",
|
|
4273
|
-
"NLNonprofitType",
|
|
4274
|
-
"NailSalon",
|
|
4275
|
-
"Nerve",
|
|
4276
|
-
"NewsArticle",
|
|
4277
|
-
"NewsMediaOrganization",
|
|
4278
|
-
"Newspaper",
|
|
4279
|
-
"NightClub",
|
|
4280
|
-
"NonprofitType",
|
|
4281
|
-
"Notary",
|
|
4282
|
-
"NoteDigitalDocument",
|
|
4283
|
-
"Number",
|
|
4284
|
-
"Nursing",
|
|
4285
|
-
"NutritionInformation",
|
|
4286
|
-
"Observation",
|
|
4287
|
-
"Obstetric",
|
|
4288
|
-
"Occupation",
|
|
4289
|
-
"OccupationalExperienceRequirements",
|
|
4290
|
-
"OccupationalTherapy",
|
|
4291
|
-
"OceanBodyOfWater",
|
|
4292
|
-
"Offer",
|
|
4293
|
-
"OfferCatalog",
|
|
4294
|
-
"OfferForLease",
|
|
4295
|
-
"OfferForPurchase",
|
|
4296
|
-
"OfferItemCondition",
|
|
4297
|
-
"OfferShippingDetails",
|
|
4298
|
-
"OfficeEquipmentStore",
|
|
4299
|
-
"OnDemandEvent",
|
|
4300
|
-
"Oncologic",
|
|
4301
|
-
"OnlineBusiness",
|
|
4302
|
-
"OnlineMarketplace",
|
|
4303
|
-
"OnlineStore",
|
|
4304
|
-
"OpeningHoursSpecification",
|
|
4305
|
-
"OperatingSystem",
|
|
4306
|
-
"OpinionNewsArticle",
|
|
4307
|
-
"Optician",
|
|
4308
|
-
"Optometric",
|
|
4309
|
-
"Order",
|
|
4310
|
-
"OrderAction",
|
|
4311
|
-
"OrderItem",
|
|
4312
|
-
"OrderStatus",
|
|
4313
|
-
"Organization",
|
|
4314
|
-
"OrganizationRole",
|
|
4315
|
-
"OrganizeAction",
|
|
4316
|
-
"Otolaryngologic",
|
|
4317
|
-
"OutletStore",
|
|
4318
|
-
"OwnershipInfo",
|
|
4319
|
-
"PaintAction",
|
|
4320
|
-
"Painting",
|
|
4321
|
-
"PalliativeProcedure",
|
|
4322
|
-
"ParcelDelivery",
|
|
4323
|
-
"ParentAudience",
|
|
4324
|
-
"Park",
|
|
4325
|
-
"ParkingFacility",
|
|
4326
|
-
"PathologyTest",
|
|
4327
|
-
"Patient",
|
|
4328
|
-
"PawnShop",
|
|
4329
|
-
"PayAction",
|
|
4330
|
-
"PaymentCard",
|
|
4331
|
-
"PaymentChargeSpecification",
|
|
4332
|
-
"PaymentMethod",
|
|
4333
|
-
"PaymentMethodType",
|
|
4334
|
-
"PaymentService",
|
|
4335
|
-
"PaymentStatusType",
|
|
4336
|
-
"Pediatric",
|
|
4337
|
-
"PeopleAudience",
|
|
4338
|
-
"PerformAction",
|
|
4339
|
-
"PerformanceRole",
|
|
4340
|
-
"PerformingArtsEvent",
|
|
4341
|
-
"PerformingArtsTheater",
|
|
4342
|
-
"PerformingGroup",
|
|
4343
|
-
"Periodical",
|
|
4344
|
-
"Permit",
|
|
4345
|
-
"Person",
|
|
4346
|
-
"PetStore",
|
|
4347
|
-
"Pharmacy",
|
|
4348
|
-
"Photograph",
|
|
4349
|
-
"PhotographAction",
|
|
4350
|
-
"PhysicalActivity",
|
|
4351
|
-
"PhysicalActivityCategory",
|
|
4352
|
-
"PhysicalExam",
|
|
4353
|
-
"PhysicalTherapy",
|
|
4354
|
-
"Physician",
|
|
4355
|
-
"PhysiciansOffice",
|
|
4356
|
-
"Physiotherapy",
|
|
4357
|
-
"Place",
|
|
4358
|
-
"PlaceOfWorship",
|
|
4359
|
-
"PlanAction",
|
|
4360
|
-
"PlasticSurgery",
|
|
4361
|
-
"Play",
|
|
4362
|
-
"PlayAction",
|
|
4363
|
-
"PlayGameAction",
|
|
4364
|
-
"Playground",
|
|
4365
|
-
"Plumber",
|
|
4366
|
-
"PodcastEpisode",
|
|
4367
|
-
"PodcastSeason",
|
|
4368
|
-
"PodcastSeries",
|
|
4369
|
-
"Podiatric",
|
|
4370
|
-
"PoliceStation",
|
|
4371
|
-
"PoliticalParty",
|
|
4372
|
-
"Pond",
|
|
4373
|
-
"PostOffice",
|
|
4374
|
-
"PostalAddress",
|
|
4375
|
-
"PostalCodeRangeSpecification",
|
|
4376
|
-
"Poster",
|
|
4377
|
-
"PreOrderAction",
|
|
4378
|
-
"PrependAction",
|
|
4379
|
-
"Preschool",
|
|
4380
|
-
"PresentationDigitalDocument",
|
|
4381
|
-
"PreventionIndication",
|
|
4382
|
-
"PriceComponentTypeEnumeration",
|
|
4383
|
-
"PriceSpecification",
|
|
4384
|
-
"PriceTypeEnumeration",
|
|
4385
|
-
"PrimaryCare",
|
|
4386
|
-
"Product",
|
|
4387
|
-
"ProductCollection",
|
|
4388
|
-
"ProductGroup",
|
|
4389
|
-
"ProductModel",
|
|
4390
|
-
"ProductReturnEnumeration",
|
|
4391
|
-
"ProductReturnPolicy",
|
|
4392
|
-
"ProfessionalService",
|
|
4393
|
-
"ProfilePage",
|
|
4394
|
-
"ProgramMembership",
|
|
4395
|
-
"Project",
|
|
4396
|
-
"PronounceableText",
|
|
4397
|
-
"Property",
|
|
4398
|
-
"PropertyValue",
|
|
4399
|
-
"PropertyValueSpecification",
|
|
4400
|
-
"Protein",
|
|
4401
|
-
"Psychiatric",
|
|
4402
|
-
"PsychologicalTreatment",
|
|
4403
|
-
"PublicHealth",
|
|
4404
|
-
"PublicSwimmingPool",
|
|
4405
|
-
"PublicToilet",
|
|
4406
|
-
"PublicationEvent",
|
|
4407
|
-
"PublicationIssue",
|
|
4408
|
-
"PublicationVolume",
|
|
4409
|
-
"PurchaseType",
|
|
4410
|
-
"QAPage",
|
|
4411
|
-
"QualitativeValue",
|
|
4412
|
-
"QuantitativeValue",
|
|
4413
|
-
"QuantitativeValueDistribution",
|
|
4414
|
-
"Quantity",
|
|
4415
|
-
"Question",
|
|
4416
|
-
"Quiz",
|
|
4417
|
-
"Quotation",
|
|
4418
|
-
"QuoteAction",
|
|
4419
|
-
"RVPark",
|
|
4420
|
-
"RadiationTherapy",
|
|
4421
|
-
"RadioBroadcastService",
|
|
4422
|
-
"RadioChannel",
|
|
4423
|
-
"RadioClip",
|
|
4424
|
-
"RadioEpisode",
|
|
4425
|
-
"RadioSeason",
|
|
4426
|
-
"RadioSeries",
|
|
4427
|
-
"RadioStation",
|
|
4428
|
-
"Rating",
|
|
4429
|
-
"ReactAction",
|
|
4430
|
-
"ReadAction",
|
|
4431
|
-
"RealEstateAgent",
|
|
4432
|
-
"RealEstateListing",
|
|
4433
|
-
"ReceiveAction",
|
|
4434
|
-
"Recipe",
|
|
4435
|
-
"Recommendation",
|
|
4436
|
-
"RecommendedDoseSchedule",
|
|
4437
|
-
"RecyclingCenter",
|
|
4438
|
-
"RefundTypeEnumeration",
|
|
4439
|
-
"RegisterAction",
|
|
4440
|
-
"RejectAction",
|
|
4441
|
-
"RentAction",
|
|
4442
|
-
"RentalCarReservation",
|
|
4443
|
-
"RepaymentSpecification",
|
|
4444
|
-
"ReplaceAction",
|
|
4445
|
-
"ReplyAction",
|
|
4446
|
-
"Report",
|
|
4447
|
-
"ReportageNewsArticle",
|
|
4448
|
-
"ReportedDoseSchedule",
|
|
4449
|
-
"ResearchOrganization",
|
|
4450
|
-
"ResearchProject",
|
|
4451
|
-
"Researcher",
|
|
4452
|
-
"Reservation",
|
|
4453
|
-
"ReservationPackage",
|
|
4454
|
-
"ReservationStatusType",
|
|
4455
|
-
"ReserveAction",
|
|
4456
|
-
"Reservoir",
|
|
4457
|
-
"ResetPasswordAction",
|
|
4458
|
-
"Residence",
|
|
4459
|
-
"Resort",
|
|
4460
|
-
"RespiratoryTherapy",
|
|
4461
|
-
"Restaurant",
|
|
4462
|
-
"RestrictedDiet",
|
|
4463
|
-
"ResumeAction",
|
|
4464
|
-
"ReturnAction",
|
|
4465
|
-
"ReturnFeesEnumeration",
|
|
4466
|
-
"ReturnLabelSourceEnumeration",
|
|
4467
|
-
"ReturnMethodEnumeration",
|
|
4468
|
-
"Review",
|
|
4469
|
-
"ReviewAction",
|
|
4470
|
-
"ReviewNewsArticle",
|
|
4471
|
-
"RiverBodyOfWater",
|
|
4472
|
-
"Role",
|
|
4473
|
-
"RoofingContractor",
|
|
4474
|
-
"Room",
|
|
4475
|
-
"RsvpAction",
|
|
4476
|
-
"RsvpResponseType",
|
|
4477
|
-
"RuntimePlatform",
|
|
4478
|
-
"SaleEvent",
|
|
4479
|
-
"SatiricalArticle",
|
|
4480
|
-
"Schedule",
|
|
4481
|
-
"ScheduleAction",
|
|
4482
|
-
"ScholarlyArticle",
|
|
4483
|
-
"School",
|
|
4484
|
-
"SchoolDistrict",
|
|
4485
|
-
"ScreeningEvent",
|
|
4486
|
-
"Sculpture",
|
|
4487
|
-
"SeaBodyOfWater",
|
|
4488
|
-
"SearchAction",
|
|
4489
|
-
"SearchRescueOrganization",
|
|
4490
|
-
"SearchResultsPage",
|
|
4491
|
-
"Season",
|
|
4492
|
-
"Seat",
|
|
4493
|
-
"SeekToAction",
|
|
4494
|
-
"SelfStorage",
|
|
4495
|
-
"SellAction",
|
|
4496
|
-
"SendAction",
|
|
4497
|
-
"SequentialArt",
|
|
4498
|
-
"Series",
|
|
4499
|
-
"Service",
|
|
4500
|
-
"ServiceChannel",
|
|
4501
|
-
"ServicePeriod",
|
|
4502
|
-
"ShareAction",
|
|
4503
|
-
"SheetMusic",
|
|
4504
|
-
"ShippingConditions",
|
|
4505
|
-
"ShippingDeliveryTime",
|
|
4506
|
-
"ShippingRateSettings",
|
|
4507
|
-
"ShippingService",
|
|
4508
|
-
"ShoeStore",
|
|
4509
|
-
"ShoppingCenter",
|
|
4510
|
-
"ShortStory",
|
|
4511
|
-
"SingleFamilyResidence",
|
|
4512
|
-
"SiteNavigationElement",
|
|
4513
|
-
"SizeGroupEnumeration",
|
|
4514
|
-
"SizeSpecification",
|
|
4515
|
-
"SizeSystemEnumeration",
|
|
4516
|
-
"SkiResort",
|
|
4517
|
-
"SocialEvent",
|
|
4518
|
-
"SocialMediaPosting",
|
|
4519
|
-
"SoftwareApplication",
|
|
4520
|
-
"SoftwareSourceCode",
|
|
4521
|
-
"SolveMathAction",
|
|
4522
|
-
"SomeProducts",
|
|
4523
|
-
"SpeakableSpecification",
|
|
4524
|
-
"SpecialAnnouncement",
|
|
4525
|
-
"Specialty",
|
|
4526
|
-
"SportingGoodsStore",
|
|
4527
|
-
"SportsActivityLocation",
|
|
4528
|
-
"SportsClub",
|
|
4529
|
-
"SportsEvent",
|
|
4530
|
-
"SportsOrganization",
|
|
4531
|
-
"SportsTeam",
|
|
4532
|
-
"SpreadsheetDigitalDocument",
|
|
4533
|
-
"StadiumOrArena",
|
|
4534
|
-
"State",
|
|
4535
|
-
"Statement",
|
|
4536
|
-
"StatisticalPopulation",
|
|
4537
|
-
"StatisticalVariable",
|
|
4538
|
-
"StatusEnumeration",
|
|
4539
|
-
"SteeringPositionValue",
|
|
4540
|
-
"Store",
|
|
4541
|
-
"StructuredValue",
|
|
4542
|
-
"StupidType",
|
|
4543
|
-
"SubscribeAction",
|
|
4544
|
-
"Substance",
|
|
4545
|
-
"SubwayStation",
|
|
4546
|
-
"Suite",
|
|
4547
|
-
"SuperficialAnatomy",
|
|
4548
|
-
"SurgicalProcedure",
|
|
4549
|
-
"SuspendAction",
|
|
4550
|
-
"Syllabus",
|
|
4551
|
-
"Synagogue",
|
|
4552
|
-
"TVClip",
|
|
4553
|
-
"TVEpisode",
|
|
4554
|
-
"TVSeason",
|
|
4555
|
-
"TVSeries",
|
|
4556
|
-
"Table",
|
|
4557
|
-
"TakeAction",
|
|
4558
|
-
"TattooParlor",
|
|
4559
|
-
"Taxi",
|
|
4560
|
-
"TaxiReservation",
|
|
4561
|
-
"TaxiService",
|
|
4562
|
-
"TaxiStand",
|
|
4563
|
-
"Taxon",
|
|
4564
|
-
"TechArticle",
|
|
4565
|
-
"TelevisionChannel",
|
|
4566
|
-
"TelevisionStation",
|
|
4567
|
-
"TennisComplex",
|
|
4568
|
-
"Text",
|
|
4569
|
-
"TextDigitalDocument",
|
|
4570
|
-
"TextObject",
|
|
4571
|
-
"TheaterEvent",
|
|
4572
|
-
"TheaterGroup",
|
|
4573
|
-
"TherapeuticProcedure",
|
|
4574
|
-
"Thesis",
|
|
4575
|
-
"Thing",
|
|
4576
|
-
"Ticket",
|
|
4577
|
-
"TieAction",
|
|
4578
|
-
"TierBenefitEnumeration",
|
|
4579
|
-
"Time",
|
|
4580
|
-
"TipAction",
|
|
4581
|
-
"TireShop",
|
|
4582
|
-
"TouristAttraction",
|
|
4583
|
-
"TouristDestination",
|
|
4584
|
-
"TouristInformationCenter",
|
|
4585
|
-
"TouristTrip",
|
|
4586
|
-
"ToyStore",
|
|
4587
|
-
"TrackAction",
|
|
4588
|
-
"TradeAction",
|
|
4589
|
-
"TrainReservation",
|
|
4590
|
-
"TrainStation",
|
|
4591
|
-
"TrainTrip",
|
|
4592
|
-
"TransferAction",
|
|
4593
|
-
"TravelAction",
|
|
4594
|
-
"TravelAgency",
|
|
4595
|
-
"TreatmentIndication",
|
|
4596
|
-
"Trip",
|
|
4597
|
-
"TypeAndQuantityNode",
|
|
4598
|
-
"UKNonprofitType",
|
|
4599
|
-
"URL",
|
|
4600
|
-
"USNonprofitType",
|
|
4601
|
-
"UnRegisterAction",
|
|
4602
|
-
"UnitPriceSpecification",
|
|
4603
|
-
"UpdateAction",
|
|
4604
|
-
"UseAction",
|
|
4605
|
-
"UserBlocks",
|
|
4606
|
-
"UserCheckins",
|
|
4607
|
-
"UserComments",
|
|
4608
|
-
"UserDownloads",
|
|
4609
|
-
"UserInteraction",
|
|
4610
|
-
"UserLikes",
|
|
4611
|
-
"UserPageVisits",
|
|
4612
|
-
"UserPlays",
|
|
4613
|
-
"UserPlusOnes",
|
|
4614
|
-
"UserReview",
|
|
4615
|
-
"UserTweets",
|
|
4616
|
-
"VacationRental",
|
|
4617
|
-
"Vehicle",
|
|
4618
|
-
"Vein",
|
|
4619
|
-
"Vessel",
|
|
4620
|
-
"VeterinaryCare",
|
|
4621
|
-
"VideoGallery",
|
|
4622
|
-
"VideoGame",
|
|
4623
|
-
"VideoGameClip",
|
|
4624
|
-
"VideoGameSeries",
|
|
4625
|
-
"VideoObject",
|
|
4626
|
-
"VideoObjectSnapshot",
|
|
4627
|
-
"ViewAction",
|
|
4628
|
-
"VirtualLocation",
|
|
4629
|
-
"VisualArtsEvent",
|
|
4630
|
-
"VisualArtwork",
|
|
4631
|
-
"VitalSign",
|
|
4632
|
-
"Volcano",
|
|
4633
|
-
"VoteAction",
|
|
4634
|
-
"WPAdBlock",
|
|
4635
|
-
"WPFooter",
|
|
4636
|
-
"WPHeader",
|
|
4637
|
-
"WPSideBar",
|
|
4638
|
-
"WantAction",
|
|
4639
|
-
"WarrantyPromise",
|
|
4640
|
-
"WarrantyScope",
|
|
4641
|
-
"WatchAction",
|
|
4642
|
-
"Waterfall",
|
|
4643
|
-
"WearAction",
|
|
4644
|
-
"WearableMeasurementTypeEnumeration",
|
|
4645
|
-
"WearableSizeGroupEnumeration",
|
|
4646
|
-
"WearableSizeSystemEnumeration",
|
|
4647
|
-
"WebAPI",
|
|
4648
|
-
"WebApplication",
|
|
4649
|
-
"WebContent",
|
|
4650
|
-
"WebPage",
|
|
4651
|
-
"WebPageElement",
|
|
4652
|
-
"WebSite",
|
|
4653
|
-
"WholesaleStore",
|
|
4654
|
-
"WinAction",
|
|
4655
|
-
"Winery",
|
|
4656
|
-
"WorkBasedProgram",
|
|
4657
|
-
"WorkersUnion",
|
|
4658
|
-
"WriteAction",
|
|
4659
|
-
"XPathType",
|
|
4660
|
-
"Zoo",
|
|
4661
|
-
"iflastandards_info_ns_lrm_lrmoo_F31_Performance",
|
|
4662
|
-
"purl_bioontology_org_ontology_SNOMEDCT_105590001",
|
|
4663
|
-
"purl_bioontology_org_ontology_SNOMEDCT_116154003",
|
|
4664
|
-
"purl_bioontology_org_ontology_SNOMEDCT_277132007",
|
|
4665
|
-
"purl_bioontology_org_ontology_SNOMEDCT_387713003",
|
|
4666
|
-
"purl_bioontology_org_ontology_SNOMEDCT_410942007",
|
|
4667
|
-
"purl_bioontology_org_ontology_SNOMEDCT_50731006",
|
|
4668
|
-
"purl_bioontology_org_ontology_SNOMEDCT_51114001",
|
|
4669
|
-
"purl_bioontology_org_ontology_SNOMEDCT_63653004",
|
|
4670
|
-
"purl_org_dc_dcmitype_Dataset",
|
|
4671
|
-
"purl_org_dc_dcmitype_Event",
|
|
4672
|
-
"purl_org_dc_dcmitype_Image",
|
|
4673
|
-
"purl_org_dc_dcmitype_Text",
|
|
4674
|
-
"purl_org_ontology_bibo_Issue",
|
|
4675
|
-
"purl_org_ontology_bibo_Periodical",
|
|
4676
|
-
"rdfs_org_ns_void_Dataset",
|
|
4677
|
-
"ref_gs1_org_voc_CertificationDetails",
|
|
4678
|
-
"ref_gs1_org_voc_ContactPoint",
|
|
4679
|
-
"ref_gs1_org_voc_Country",
|
|
4680
|
-
"ref_gs1_org_voc_Organization",
|
|
4681
|
-
"ref_gs1_org_voc_PostalAddress",
|
|
4682
|
-
"sarif_info_Result",
|
|
4683
|
-
"spec_edmcouncil_org_fibo_ontology_BE_Corporations_Corporations_Corporation",
|
|
4684
|
-
"spec_edmcouncil_org_fibo_ontology_BE_LegalEntities_CorporateBodies_CooperativeSociety",
|
|
4685
|
-
"spec_edmcouncil_org_fibo_ontology_BE_NotForProfitOrganizations_NotForProfitOrganizations_NonGovernmentalOrganization",
|
|
4686
|
-
"spec_edmcouncil_org_fibo_ontology_FBC_ProductsAndServices_FinancialProductsAndServices_BankAccount",
|
|
4687
|
-
"spec_edmcouncil_org_fibo_ontology_FBC_ProductsAndServices_FinancialProductsAndServices_PaymentMechanism",
|
|
4688
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Agreements_Contracts_MutualContractualAgreement",
|
|
4689
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Arrangements_Documents_Certificate",
|
|
4690
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Arrangements_Documents_Document",
|
|
4691
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Arrangements_Documents_LegalDocument",
|
|
4692
|
-
"spec_edmcouncil_org_fibo_ontology_FND_DatesAndTimes_Occurrences_Occurrence",
|
|
4693
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Organizations_Organizations_ContactPoint",
|
|
4694
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Organizations_Organizations_Organization",
|
|
4695
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Places_Addresses_PostalAddress",
|
|
4696
|
-
"spec_edmcouncil_org_fibo_ontology_FND_Places_Locations_Municipality",
|
|
4697
|
-
"spec_edmcouncil_org_fibo_ontology_FND_ProductsAndServices_ProductsAndServices_Offer",
|
|
4698
|
-
"spec_edmcouncil_org_fibo_ontology_FND_ProductsAndServices_ProductsAndServices_Price",
|
|
4699
|
-
"spec_edmcouncil_org_fibo_ontology_FND_ProductsAndServices_ProductsAndServices_Product",
|
|
4700
|
-
"spec_edmcouncil_org_fibo_ontology_PAY_PaymentServices_PaymentServices_PaymentService",
|
|
4701
|
-
"unece_org_vocab_AmountType",
|
|
4702
|
-
"unece_org_vocab_BrandName",
|
|
4703
|
-
"unece_org_vocab_Country",
|
|
4704
|
-
"unece_org_vocab_ElectronicDocument",
|
|
4705
|
-
"unece_org_vocab_FinancialCard",
|
|
4706
|
-
"unece_org_vocab_GeographicalCoordinate",
|
|
4707
|
-
"unece_org_vocab_Invoice",
|
|
4708
|
-
"unece_org_vocab_LineTradeAgreement",
|
|
4709
|
-
"unece_org_vocab_Offer",
|
|
4710
|
-
"unece_org_vocab_Order",
|
|
4711
|
-
"unece_org_vocab_PaymentMeans",
|
|
4712
|
-
"unece_org_vocab_RequestForQuotation",
|
|
4713
|
-
"unece_org_vocab_SpecifiedCertificate",
|
|
4714
|
-
"unece_org_vocab_SpecifiedTradeProduct",
|
|
4715
|
-
"unece_org_vocab_TradeAddress",
|
|
4716
|
-
"unece_org_vocab_TradeProduct",
|
|
4717
|
-
"unece_org_vocab_TransportMethod",
|
|
4718
|
-
"www_omg_org_spec_Commons_Classifiers_Classifier",
|
|
4719
|
-
"www_omg_org_spec_Commons_Collections_Collection",
|
|
4720
|
-
"www_omg_org_spec_Commons_DatesAndTimes_Date",
|
|
4721
|
-
"www_omg_org_spec_Commons_DatesAndTimes_DateTime",
|
|
4722
|
-
"www_omg_org_spec_Commons_DatesAndTimes_Duration",
|
|
4723
|
-
"www_omg_org_spec_Commons_GeopoliticalEntities_GeopoliticalEntity",
|
|
4724
|
-
"www_omg_org_spec_Commons_GeopoliticalEntities_Subdivision",
|
|
4725
|
-
"www_omg_org_spec_Commons_Locations_Address",
|
|
4726
|
-
"www_omg_org_spec_Commons_Locations_GeographicCoordinate",
|
|
4727
|
-
"www_omg_org_spec_Commons_Locations_Location",
|
|
4728
|
-
"www_omg_org_spec_LCC_Countries_CountryRepresentation_Continent",
|
|
4729
|
-
"www_omg_org_spec_LCC_Countries_CountryRepresentation_Country",
|
|
4730
|
-
"www_w3_org_2006_vcard_ns_VCard",
|
|
4731
|
-
"www_w3_org_ns_dcat_Catalog",
|
|
4732
|
-
"www_w3_org_ns_dcat_Dataset",
|
|
4733
|
-
"www_w3_org_ns_dcat_Distribution",
|
|
4734
|
-
"www_w3_org_ns_hydra_core_Error",
|
|
4735
|
-
"www_w3_org_ns_prov_InstantaneousEvent",
|
|
4736
|
-
"www_w3_org_ns_prov_atTime",
|
|
4737
|
-
"xmlns_com_foaf_0_1_Person"
|
|
4738
|
-
]);
|
|
4104
|
+
var SCHEMA_ORG_TYPES = new Set(
|
|
4105
|
+
"3DModel AMRadioChannel APIReference AboutPage AcceptAction Accommodation AccountingService AchieveAction Action ActionAccessSpecification ActionStatusType ActivateAction AddAction AdministrativeArea AdultEntertainment AdultOrientedEnumeration AdvertiserContentArticle AggregateOffer AggregateRating AgreeAction Airline Airport AlignmentObject AllocateAction AmpStory AmusementPark AnalysisNewsArticle AnatomicalStructure AnatomicalSystem AnimalShelter Answer Apartment ApartmentComplex AppendAction ApplyAction ApprovedIndication Aquarium ArchiveComponent ArchiveOrganization ArriveAction ArtGallery Artery Article AskAction AskPublicNewsArticle AssessAction AssignAction Atlas Attorney Audience AudioObject AudioObjectSnapshot Audiobook AuthenticateAction AuthorizeAction AutoBodyShop AutoDealer AutoPartsStore AutoRental AutoRepair AutoWash AutomatedTeller AutomotiveBusiness BackgroundNewsArticle Bakery BankAccount BankOrCreditUnion BarOrPub Barcode Beach BeautySalon BedAndBreakfast BedDetails BedType BefriendAction BikeStore BioChemEntity Blog BlogPosting BloodTest BoardingPolicyType BoatReservation BoatTerminal BoatTrip BodyMeasurementTypeEnumeration BodyOfWater Bone Book BookFormatType BookSeries BookStore BookmarkAction Boolean BorrowAction BowlingAlley BrainStructure Brand BreadcrumbList Brewery Bridge BroadcastChannel BroadcastEvent BroadcastFrequencySpecification BroadcastService BrokerageAccount BuddhistTemple BusOrCoach BusReservation BusStation BusStop BusTrip BusinessAudience BusinessEntityType BusinessEvent BusinessFunction BuyAction CDCPMDRecord CableOrSatelliteService CafeOrCoffeeShop Campground CampingPitch Canal CancelAction Car CarUsageType Casino CategoryCode CategoryCodeSet CatholicChurch Cemetery Certification CertificationStatusEnumeration Chapter CheckAction CheckInAction CheckOutAction CheckoutPage ChemicalSubstance ChildCare ChildrensEvent ChooseAction Church City CityHall CivicStructure Claim ClaimReview Class Clip ClothingStore Code Collection CollectionPage CollegeOrUniversity ComedyClub ComedyEvent ComicCoverArt ComicIssue ComicSeries ComicStory Comment CommentAction CommunicateAction CommunityHealth CompleteDataFeed CompoundPriceSpecification ComputerLanguage ComputerStore ConferenceEvent ConfirmAction Consortium ConstraintNode ConsumeAction ContactPage ContactPoint ContactPointOption Continent ControlAction ConvenienceStore Conversation CookAction Cooperative Corporation CorrectionComment Country Course CourseInstance Courthouse CoverArt CovidTestingFacility CreateAction CreativeWork CreativeWorkSeason CreativeWorkSeries Credential CreditCard Crematorium CriticReview CssSelectorType CurrencyConversionService DDxElement DENonprofitType DanceEvent DanceGroup DataCatalog DataDownload DataFeed DataFeedItem DataType Dataset Date DateTime DatedMoneySpecification DayOfWeek DaySpa DeactivateAction DefenceEstablishment DefinedRegion DefinedTerm DefinedTermSet DeleteAction DeliveryChargeSpecification DeliveryEvent DeliveryMethod DeliveryTimeSettings Demand Dentist DepartAction DepartmentStore DepositAccount Dermatology DiagnosticLab DiagnosticProcedure Diet DietNutrition DietarySupplement DigitalDocument DigitalDocumentPermission DigitalDocumentPermissionType DigitalPlatformEnumeration DisagreeAction DiscoverAction DiscussionForumPosting DislikeAction Distance Distillery DonateAction DoseSchedule DownloadAction DrawAction Drawing DrinkAction DriveWheelConfigurationValue Drug DrugClass DrugCost DrugCostCategory DrugLegalStatus DrugPregnancyCategory DrugPrescriptionStatus DrugStrength DryCleaningOrLaundry Duration EUEnergyEfficiencyEnumeration EatAction EducationEvent EducationalAudience EducationalOccupationalCredential EducationalOccupationalProgram EducationalOrganization Electrician ElectronicsStore ElementarySchool EmailMessage Embassy Emergency EmergencyService EmployeeRole EmployerAggregateRating EmployerReview EmploymentAgency EndorseAction EndorsementRating Energy EnergyConsumptionDetails EnergyEfficiencyEnumeration EnergyStarEnergyEfficiencyEnumeration EngineSpecification EntertainmentBusiness EntryPoint Enumeration Episode Error Event EventAttendanceModeEnumeration EventReservation EventSeries EventStatusType EventVenue ExchangeRateSpecification ExerciseAction ExerciseGym ExercisePlan ExhibitionEvent FAQPage FMRadioChannel FastFoodRestaurant Festival FilmAction FinancialIncentive FinancialProduct FinancialService FindAction FireStation Flight FlightReservation Float FloorPlan Florist FollowAction FoodEstablishment FoodEstablishmentReservation FoodEvent FoodService FulfillmentTypeEnumeration FundingAgency FundingScheme FurnitureStore Game GameAvailabilityEnumeration GamePlayMode GameServer GameServerStatus GardenStore GasStation GatedResidenceCommunity GenderType Gene GeneralContractor GeoCircle GeoCoordinates GeoShape GeospatialGeometry Geriatric GiveAction GolfCourse GovernmentBenefitsType GovernmentBuilding GovernmentOffice GovernmentOrganization GovernmentPermit GovernmentService Grant GroceryStore Guide Gynecologic HVACBusiness Hackathon HairSalon HardwareStore HealthAndBeautyBusiness HealthAspectEnumeration HealthClub HealthInsurancePlan HealthPlanCostSharingSpecification HealthPlanFormulary HealthPlanNetwork HealthTopicContent HighSchool HinduTemple HobbyShop HomeAndConstructionBusiness HomeGoodsStore Hospital Hostel Hotel HotelRoom House HousePainter HowTo HowToDirection HowToItem HowToSection HowToStep HowToSupply HowToTip HowToTool HyperToc HyperTocEntry IPTCDigitalSourceEnumeration ITNonprofitType IceCreamShop IgnoreAction ImageGallery ImageObject ImageObjectSnapshot ImagingTest IncentiveQualifiedExpenseType IncentiveStatus IncentiveType IndividualPhysician IndividualProduct InfectiousAgentClass InfectiousDisease InformAction InsertAction InstallAction InstantaneousEvent InsuranceAgency Intangible Integer InteractAction InteractionCounter InternetCafe InvestmentFund InvestmentOrDeposit InviteAction Invoice ItemAvailability ItemList ItemListOrderType ItemPage JewelryStore JobPosting JoinAction Joint LakeBodyOfWater Landform LandmarksOrHistoricalBuildings Language LearningResource LeaveAction LegalForceStatus LegalService LegalValueLevel Legislation LegislationObject LegislativeBuilding LendAction Library LibrarySystem LifestyleModification Ligament LikeAction LinkRole LiquorStore ListItem ListenAction LiteraryEvent LiveBlogPosting LoanOrCredit LocalBusiness LocationFeatureSpecification Locksmith LodgingBusiness LodgingReservation LoginAction LoseAction LymphaticVessel Manuscript Map MapCategoryType MarryAction Mass MathSolver MaximumDoseSchedule MeasurementMethodEnum MeasurementTypeEnumeration MediaEnumeration MediaGallery MediaManipulationRatingEnumeration MediaObject MediaReview MediaReviewItem MediaSubscription MedicalAudience MedicalAudienceType MedicalBusiness MedicalCause MedicalClinic MedicalCode MedicalCondition MedicalConditionStage MedicalContraindication MedicalDevice MedicalDevicePurpose MedicalEntity MedicalEnumeration MedicalEvidenceLevel MedicalGuideline MedicalGuidelineContraindication MedicalGuidelineRecommendation MedicalImagingTechnique MedicalIndication MedicalIntangible MedicalObservationalStudy MedicalObservationalStudyDesign MedicalOrganization MedicalProcedure MedicalProcedureType MedicalRiskCalculator MedicalRiskEstimator MedicalRiskFactor MedicalRiskScore MedicalScholarlyArticle MedicalSign MedicalSignOrSymptom MedicalSpecialty MedicalStudy MedicalStudyStatus MedicalSymptom MedicalTest MedicalTestPanel MedicalTherapy MedicalTrial MedicalTrialDesign MedicalWebPage MedicineSystem MeetingRoom MemberProgram MemberProgramTier MensClothingStore Menu MenuItem MenuSection MerchantReturnEnumeration MerchantReturnPolicy MerchantReturnPolicySeasonalOverride Message MiddleSchool Midwifery MobileApplication MobilePhoneStore MolecularEntity MonetaryAmount MonetaryAmountDistribution MonetaryGrant MoneyTransfer MortgageLoan Mosque Motel Motorcycle MotorcycleDealer MotorcycleRepair MotorizedBicycle Mountain MoveAction Movie MovieClip MovieRentalStore MovieSeries MovieTheater MovingCompany Muscle Museum MusicAlbum MusicAlbumProductionType MusicAlbumReleaseType MusicComposition MusicEvent MusicGroup MusicPlaylist MusicRecording MusicRelease MusicReleaseFormatType MusicStore MusicVenue MusicVideoObject NGO NLNonprofitType NailSalon Nerve NewsArticle NewsMediaOrganization Newspaper NightClub NonprofitType Notary NoteDigitalDocument Number Nursing NutritionInformation Observation Obstetric Occupation OccupationalExperienceRequirements OccupationalTherapy OceanBodyOfWater Offer OfferCatalog OfferForLease OfferForPurchase OfferItemCondition OfferShippingDetails OfficeEquipmentStore OnDemandEvent Oncologic OnlineBusiness OnlineMarketplace OnlineStore OpeningHoursSpecification OperatingSystem OpinionNewsArticle Optician Optometric Order OrderAction OrderItem OrderStatus Organization OrganizationRole OrganizeAction Otolaryngologic OutletStore OwnershipInfo PaintAction Painting PalliativeProcedure ParcelDelivery ParentAudience Park ParkingFacility PathologyTest Patient PawnShop PayAction PaymentCard PaymentChargeSpecification PaymentMethod PaymentMethodType PaymentService PaymentStatusType Pediatric PeopleAudience PerformAction PerformanceRole PerformingArtsEvent PerformingArtsTheater PerformingGroup Periodical Permit Person PetStore Pharmacy Photograph PhotographAction PhysicalActivity PhysicalActivityCategory PhysicalExam PhysicalTherapy Physician PhysiciansOffice Physiotherapy Place PlaceOfWorship PlanAction PlasticSurgery Play PlayAction PlayGameAction Playground Plumber PodcastEpisode PodcastSeason PodcastSeries Podiatric PoliceStation PoliticalParty Pond PostOffice PostalAddress PostalCodeRangeSpecification Poster PreOrderAction PrependAction Preschool PresentationDigitalDocument PreventionIndication PriceComponentTypeEnumeration PriceSpecification PriceTypeEnumeration PrimaryCare Product ProductCollection ProductGroup ProductModel ProductReturnEnumeration ProductReturnPolicy ProfessionalService ProfilePage ProgramMembership Project PronounceableText Property PropertyValue PropertyValueSpecification Protein Psychiatric PsychologicalTreatment PublicHealth PublicSwimmingPool PublicToilet PublicationEvent PublicationIssue PublicationVolume PurchaseType QAPage QualitativeValue QuantitativeValue QuantitativeValueDistribution Quantity Question Quiz Quotation QuoteAction RVPark RadiationTherapy RadioBroadcastService RadioChannel RadioClip RadioEpisode RadioSeason RadioSeries RadioStation Rating ReactAction ReadAction RealEstateAgent RealEstateListing ReceiveAction Recipe Recommendation RecommendedDoseSchedule RecyclingCenter RefundTypeEnumeration RegisterAction RejectAction RentAction RentalCarReservation RepaymentSpecification ReplaceAction ReplyAction Report ReportageNewsArticle ReportedDoseSchedule ResearchOrganization ResearchProject Researcher Reservation ReservationPackage ReservationStatusType ReserveAction Reservoir ResetPasswordAction Residence Resort RespiratoryTherapy Restaurant RestrictedDiet ResumeAction ReturnAction ReturnFeesEnumeration ReturnLabelSourceEnumeration ReturnMethodEnumeration Review ReviewAction ReviewNewsArticle RiverBodyOfWater Role RoofingContractor Room RsvpAction RsvpResponseType RuntimePlatform SaleEvent SatiricalArticle Schedule ScheduleAction ScholarlyArticle School SchoolDistrict ScreeningEvent Sculpture SeaBodyOfWater SearchAction SearchRescueOrganization SearchResultsPage Season Seat SeekToAction SelfStorage SellAction SendAction SequentialArt Series Service ServiceChannel ServicePeriod ShareAction SheetMusic ShippingConditions ShippingDeliveryTime ShippingRateSettings ShippingService ShoeStore ShoppingCenter ShortStory SingleFamilyResidence SiteNavigationElement SizeGroupEnumeration SizeSpecification SizeSystemEnumeration SkiResort SocialEvent SocialMediaPosting SoftwareApplication SoftwareSourceCode SolveMathAction SomeProducts SpeakableSpecification SpecialAnnouncement Specialty SportingGoodsStore SportsActivityLocation SportsClub SportsEvent SportsOrganization SportsTeam SpreadsheetDigitalDocument StadiumOrArena State Statement StatisticalPopulation StatisticalVariable StatusEnumeration SteeringPositionValue Store StructuredValue StupidType SubscribeAction Substance SubwayStation Suite SuperficialAnatomy SurgicalProcedure SuspendAction Syllabus Synagogue TVClip TVEpisode TVSeason TVSeries Table TakeAction TattooParlor Taxi TaxiReservation TaxiService TaxiStand Taxon TechArticle TelevisionChannel TelevisionStation TennisComplex Text TextDigitalDocument TextObject TheaterEvent TheaterGroup TherapeuticProcedure Thesis Thing Ticket TieAction TierBenefitEnumeration Time TipAction TireShop TouristAttraction TouristDestination TouristInformationCenter TouristTrip ToyStore TrackAction TradeAction TrainReservation TrainStation TrainTrip TransferAction TravelAction TravelAgency TreatmentIndication Trip TypeAndQuantityNode UKNonprofitType URL USNonprofitType UnRegisterAction UnitPriceSpecification UpdateAction UseAction UserBlocks UserCheckins UserComments UserDownloads UserInteraction UserLikes UserPageVisits UserPlays UserPlusOnes UserReview UserTweets VacationRental Vehicle Vein Vessel VeterinaryCare VideoGallery VideoGame VideoGameClip VideoGameSeries VideoObject VideoObjectSnapshot ViewAction VirtualLocation VisualArtsEvent VisualArtwork VitalSign Volcano VoteAction WPAdBlock WPFooter WPHeader WPSideBar WantAction WarrantyPromise WarrantyScope WatchAction Waterfall WearAction WearableMeasurementTypeEnumeration WearableSizeGroupEnumeration WearableSizeSystemEnumeration WebAPI WebApplication WebContent WebPage WebPageElement WebSite WholesaleStore WinAction Winery WorkBasedProgram WorkersUnion WriteAction XPathType Zoo iflastandards_info_ns_lrm_lrmoo_F31_Performance purl_bioontology_org_ontology_SNOMEDCT_105590001 purl_bioontology_org_ontology_SNOMEDCT_116154003 purl_bioontology_org_ontology_SNOMEDCT_277132007 purl_bioontology_org_ontology_SNOMEDCT_387713003 purl_bioontology_org_ontology_SNOMEDCT_410942007 purl_bioontology_org_ontology_SNOMEDCT_50731006 purl_bioontology_org_ontology_SNOMEDCT_51114001 purl_bioontology_org_ontology_SNOMEDCT_63653004 purl_org_dc_dcmitype_Dataset purl_org_dc_dcmitype_Event purl_org_dc_dcmitype_Image purl_org_dc_dcmitype_Text purl_org_ontology_bibo_Issue purl_org_ontology_bibo_Periodical rdfs_org_ns_void_Dataset ref_gs1_org_voc_CertificationDetails ref_gs1_org_voc_ContactPoint ref_gs1_org_voc_Country ref_gs1_org_voc_Organization ref_gs1_org_voc_PostalAddress sarif_info_Result spec_edmcouncil_org_fibo_ontology_BE_Corporations_Corporations_Corporation spec_edmcouncil_org_fibo_ontology_BE_LegalEntities_CorporateBodies_CooperativeSociety spec_edmcouncil_org_fibo_ontology_BE_NotForProfitOrganizations_NotForProfitOrganizations_NonGovernmentalOrganization spec_edmcouncil_org_fibo_ontology_FBC_ProductsAndServices_FinancialProductsAndServices_BankAccount spec_edmcouncil_org_fibo_ontology_FBC_ProductsAndServices_FinancialProductsAndServices_PaymentMechanism spec_edmcouncil_org_fibo_ontology_FND_Agreements_Contracts_MutualContractualAgreement spec_edmcouncil_org_fibo_ontology_FND_Arrangements_Documents_Certificate spec_edmcouncil_org_fibo_ontology_FND_Arrangements_Documents_Document spec_edmcouncil_org_fibo_ontology_FND_Arrangements_Documents_LegalDocument spec_edmcouncil_org_fibo_ontology_FND_DatesAndTimes_Occurrences_Occurrence spec_edmcouncil_org_fibo_ontology_FND_Organizations_Organizations_ContactPoint spec_edmcouncil_org_fibo_ontology_FND_Organizations_Organizations_Organization spec_edmcouncil_org_fibo_ontology_FND_Places_Addresses_PostalAddress spec_edmcouncil_org_fibo_ontology_FND_Places_Locations_Municipality spec_edmcouncil_org_fibo_ontology_FND_ProductsAndServices_ProductsAndServices_Offer spec_edmcouncil_org_fibo_ontology_FND_ProductsAndServices_ProductsAndServices_Price spec_edmcouncil_org_fibo_ontology_FND_ProductsAndServices_ProductsAndServices_Product spec_edmcouncil_org_fibo_ontology_PAY_PaymentServices_PaymentServices_PaymentService unece_org_vocab_AmountType unece_org_vocab_BrandName unece_org_vocab_Country unece_org_vocab_ElectronicDocument unece_org_vocab_FinancialCard unece_org_vocab_GeographicalCoordinate unece_org_vocab_Invoice unece_org_vocab_LineTradeAgreement unece_org_vocab_Offer unece_org_vocab_Order unece_org_vocab_PaymentMeans unece_org_vocab_RequestForQuotation unece_org_vocab_SpecifiedCertificate unece_org_vocab_SpecifiedTradeProduct unece_org_vocab_TradeAddress unece_org_vocab_TradeProduct unece_org_vocab_TransportMethod www_omg_org_spec_Commons_Classifiers_Classifier www_omg_org_spec_Commons_Collections_Collection www_omg_org_spec_Commons_DatesAndTimes_Date www_omg_org_spec_Commons_DatesAndTimes_DateTime www_omg_org_spec_Commons_DatesAndTimes_Duration www_omg_org_spec_Commons_GeopoliticalEntities_GeopoliticalEntity www_omg_org_spec_Commons_GeopoliticalEntities_Subdivision www_omg_org_spec_Commons_Locations_Address www_omg_org_spec_Commons_Locations_GeographicCoordinate www_omg_org_spec_Commons_Locations_Location www_omg_org_spec_LCC_Countries_CountryRepresentation_Continent www_omg_org_spec_LCC_Countries_CountryRepresentation_Country www_w3_org_2006_vcard_ns_VCard www_w3_org_ns_dcat_Catalog www_w3_org_ns_dcat_Dataset www_w3_org_ns_dcat_Distribution www_w3_org_ns_hydra_core_Error www_w3_org_ns_prov_InstantaneousEvent www_w3_org_ns_prov_atTime xmlns_com_foaf_0_1_Person".split(
|
|
4106
|
+
" "
|
|
4107
|
+
)
|
|
4108
|
+
);
|
|
4739
4109
|
|
|
4740
4110
|
// src/rules/seo/json-ld-validity.ts
|
|
4741
4111
|
var SCHEMA_ORG_CONTEXT_RE = /^https?:\/\/schema\.org\/?$/;
|
|
@@ -4994,7 +4364,7 @@ function lengthRule(opts) {
|
|
|
4994
4364
|
const o = resolveRuleOptions(opts.id, spec, ctx.config, { route: head.route, file: location }, compiled);
|
|
4995
4365
|
const min = intOption(o, "min", opts.min);
|
|
4996
4366
|
const max = intOption(o, "max", opts.max);
|
|
4997
|
-
const
|
|
4367
|
+
const recommendation12 = typeof opts.recommendation === "function" ? opts.recommendation(o) : opts.recommendation;
|
|
4998
4368
|
const len = visibleLength(tag.text);
|
|
4999
4369
|
let problem;
|
|
5000
4370
|
if (len < min) problem = `${opts.noun} is too short (${len} chars; aim for ${min}\u2013${max})`;
|
|
@@ -5008,7 +4378,7 @@ function lengthRule(opts) {
|
|
|
5008
4378
|
route: head.route,
|
|
5009
4379
|
location,
|
|
5010
4380
|
message: problem,
|
|
5011
|
-
recommendation:
|
|
4381
|
+
recommendation: recommendation12,
|
|
5012
4382
|
docsUrl: docsUrl12
|
|
5013
4383
|
} : {
|
|
5014
4384
|
id: opts.id,
|
|
@@ -5022,7 +4392,7 @@ function lengthRule(opts) {
|
|
|
5022
4392
|
// it to also apply `severity: 'off'`.
|
|
5023
4393
|
location,
|
|
5024
4394
|
message: opts.label,
|
|
5025
|
-
recommendation:
|
|
4395
|
+
recommendation: recommendation12,
|
|
5026
4396
|
docsUrl: docsUrl12
|
|
5027
4397
|
}
|
|
5028
4398
|
);
|
|
@@ -5355,57 +4725,56 @@ var seoHeadingLevelSkip = {
|
|
|
5355
4725
|
}
|
|
5356
4726
|
};
|
|
5357
4727
|
|
|
5358
|
-
// src/rules/
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
function isSuppressed(m, ruleId, line) {
|
|
5362
|
-
return (m.suppressions ?? []).some((s) => s.line === line && (!s.ruleIds || s.ruleIds.includes(ruleId)));
|
|
4728
|
+
// src/rules/component-rule.ts
|
|
4729
|
+
function isSuppressed(suppressions, ruleId, line) {
|
|
4730
|
+
return (suppressions ?? []).some((s) => s.line === line && (!s.ruleIds || s.ruleIds.includes(ruleId)));
|
|
5363
4731
|
}
|
|
5364
|
-
function
|
|
5365
|
-
const docsUrl12 = docsUrlFor(
|
|
5366
|
-
const severity = opts.severity ?? "warning";
|
|
4732
|
+
function fileRule(spec) {
|
|
4733
|
+
const docsUrl12 = docsUrlFor(spec.id);
|
|
5367
4734
|
return {
|
|
5368
|
-
id:
|
|
5369
|
-
title:
|
|
5370
|
-
category:
|
|
5371
|
-
severity,
|
|
4735
|
+
id: spec.id,
|
|
4736
|
+
title: spec.title,
|
|
4737
|
+
category: spec.category,
|
|
4738
|
+
severity: spec.severity,
|
|
5372
4739
|
scope: "component",
|
|
5373
|
-
rationale:
|
|
5374
|
-
...
|
|
4740
|
+
rationale: spec.rationale,
|
|
4741
|
+
...spec.fix ? { fix: spec.fix } : {},
|
|
4742
|
+
...spec.options ? { options: spec.options } : {},
|
|
5375
4743
|
async check(ctx) {
|
|
5376
4744
|
const out = [];
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
const
|
|
4745
|
+
const compiled = compileOverrides(ctx.config);
|
|
4746
|
+
for (const f of spec.facts(ctx) ?? []) {
|
|
4747
|
+
const o = resolveRuleOptions(spec.id, spec.options, ctx.config, { route: f.file, file: f.file }, compiled);
|
|
4748
|
+
if (!spec.applies(f, o, ctx)) continue;
|
|
4749
|
+
const recommendation12 = typeof spec.recommendation === "function" ? spec.recommendation(o) : spec.recommendation;
|
|
4750
|
+
const bad = spec.bad(f, o, ctx).filter((b) => !(b.line > 0 && isSuppressed(f.suppressions, spec.id, b.line)));
|
|
5380
4751
|
if (bad.length === 0) {
|
|
5381
4752
|
out.push({
|
|
5382
|
-
id:
|
|
5383
|
-
category:
|
|
5384
|
-
severity,
|
|
5385
|
-
detection:
|
|
5386
|
-
route:
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
message: opts.label,
|
|
5391
|
-
recommendation: opts.recommendation,
|
|
4753
|
+
id: spec.id,
|
|
4754
|
+
category: spec.category,
|
|
4755
|
+
severity: spec.severity,
|
|
4756
|
+
detection: PASS,
|
|
4757
|
+
route: f.file,
|
|
4758
|
+
location: f.file,
|
|
4759
|
+
message: spec.label,
|
|
4760
|
+
recommendation: recommendation12,
|
|
5392
4761
|
docsUrl: docsUrl12
|
|
5393
4762
|
});
|
|
5394
4763
|
continue;
|
|
5395
4764
|
}
|
|
5396
4765
|
for (const b of bad) {
|
|
5397
4766
|
out.push({
|
|
5398
|
-
id:
|
|
5399
|
-
category:
|
|
5400
|
-
severity,
|
|
5401
|
-
detection:
|
|
5402
|
-
route:
|
|
5403
|
-
location:
|
|
4767
|
+
id: spec.id,
|
|
4768
|
+
category: spec.category,
|
|
4769
|
+
severity: spec.severity,
|
|
4770
|
+
detection: PENALIZED,
|
|
4771
|
+
route: f.file,
|
|
4772
|
+
location: f.file,
|
|
5404
4773
|
...b.line > 0 ? { line: b.line } : {},
|
|
5405
4774
|
message: b.message,
|
|
5406
|
-
recommendation:
|
|
4775
|
+
recommendation: recommendation12,
|
|
5407
4776
|
docsUrl: docsUrl12,
|
|
5408
|
-
...
|
|
4777
|
+
...spec.fix ? { fix: { ...spec.fix } } : {}
|
|
5409
4778
|
});
|
|
5410
4779
|
}
|
|
5411
4780
|
}
|
|
@@ -5413,6 +4782,24 @@ function kitModuleRule(opts) {
|
|
|
5413
4782
|
}
|
|
5414
4783
|
};
|
|
5415
4784
|
}
|
|
4785
|
+
function componentRule(opts) {
|
|
4786
|
+
return fileRule({
|
|
4787
|
+
...opts,
|
|
4788
|
+
severity: opts.severity ?? "warning",
|
|
4789
|
+
facts: (ctx) => ctx.components
|
|
4790
|
+
});
|
|
4791
|
+
}
|
|
4792
|
+
|
|
4793
|
+
// src/rules/kit-module-rule.ts
|
|
4794
|
+
function kitModuleRule(opts) {
|
|
4795
|
+
return fileRule({
|
|
4796
|
+
...opts,
|
|
4797
|
+
severity: opts.severity ?? "warning",
|
|
4798
|
+
facts: (ctx) => ctx.kitModules,
|
|
4799
|
+
applies: (m, _o, ctx) => opts.applies(m, ctx),
|
|
4800
|
+
bad: (m, _o, ctx) => opts.bad(m, ctx)
|
|
4801
|
+
});
|
|
4802
|
+
}
|
|
5416
4803
|
|
|
5417
4804
|
// src/rules/seo/ssr-disabled.ts
|
|
5418
4805
|
var ROOT_LAYOUT_RE = /^src\/routes\/\+layout(\.server)?\.(ts|js)$/;
|
|
@@ -5433,69 +4820,6 @@ var seoSsrDisabled = kitModuleRule({
|
|
|
5433
4820
|
]
|
|
5434
4821
|
});
|
|
5435
4822
|
|
|
5436
|
-
// src/rules/component-rule.ts
|
|
5437
|
-
var PENALIZED3 = { presence: "none", value: "absent" };
|
|
5438
|
-
var PASS3 = { presence: "own", value: "static" };
|
|
5439
|
-
function isSuppressed2(c, ruleId, line) {
|
|
5440
|
-
return (c.suppressions ?? []).some((s) => s.line === line && (!s.ruleIds || s.ruleIds.includes(ruleId)));
|
|
5441
|
-
}
|
|
5442
|
-
function componentRule(opts) {
|
|
5443
|
-
const docsUrl12 = docsUrlFor(opts.id);
|
|
5444
|
-
const severity = opts.severity ?? "warning";
|
|
5445
|
-
return {
|
|
5446
|
-
id: opts.id,
|
|
5447
|
-
title: opts.title,
|
|
5448
|
-
category: opts.category,
|
|
5449
|
-
severity,
|
|
5450
|
-
scope: "component",
|
|
5451
|
-
rationale: opts.rationale,
|
|
5452
|
-
...opts.fix ? { fix: opts.fix } : {},
|
|
5453
|
-
...opts.options ? { options: opts.options } : {},
|
|
5454
|
-
async check(ctx) {
|
|
5455
|
-
const out = [];
|
|
5456
|
-
const compiled = compileOverrides(ctx.config);
|
|
5457
|
-
for (const c of ctx.components ?? []) {
|
|
5458
|
-
const o = resolveRuleOptions(opts.id, opts.options, ctx.config, { route: c.file, file: c.file }, compiled);
|
|
5459
|
-
const recommendation10 = typeof opts.recommendation === "function" ? opts.recommendation(o) : opts.recommendation;
|
|
5460
|
-
if (!opts.applies(c, o, ctx)) continue;
|
|
5461
|
-
const bad = opts.bad(c, o, ctx).filter((b) => !(b.line > 0 && isSuppressed2(c, opts.id, b.line)));
|
|
5462
|
-
if (bad.length === 0) {
|
|
5463
|
-
out.push({
|
|
5464
|
-
id: opts.id,
|
|
5465
|
-
category: opts.category,
|
|
5466
|
-
severity,
|
|
5467
|
-
detection: PASS3,
|
|
5468
|
-
route: c.file,
|
|
5469
|
-
// Uniform PASS-result attribution (design 2026-08-08-pass-result-location-design.md):
|
|
5470
|
-
// same location a penalized result for this file would carry.
|
|
5471
|
-
location: c.file,
|
|
5472
|
-
message: opts.label,
|
|
5473
|
-
recommendation: recommendation10,
|
|
5474
|
-
docsUrl: docsUrl12
|
|
5475
|
-
});
|
|
5476
|
-
continue;
|
|
5477
|
-
}
|
|
5478
|
-
for (const b of bad) {
|
|
5479
|
-
out.push({
|
|
5480
|
-
id: opts.id,
|
|
5481
|
-
category: opts.category,
|
|
5482
|
-
severity,
|
|
5483
|
-
detection: PENALIZED3,
|
|
5484
|
-
route: c.file,
|
|
5485
|
-
location: c.file,
|
|
5486
|
-
...b.line > 0 ? { line: b.line } : {},
|
|
5487
|
-
message: b.message,
|
|
5488
|
-
recommendation: recommendation10,
|
|
5489
|
-
docsUrl: docsUrl12,
|
|
5490
|
-
...opts.fix ? { fix: { ...opts.fix } } : {}
|
|
5491
|
-
});
|
|
5492
|
-
}
|
|
5493
|
-
}
|
|
5494
|
-
return out;
|
|
5495
|
-
}
|
|
5496
|
-
};
|
|
5497
|
-
}
|
|
5498
|
-
|
|
5499
4823
|
// src/rules/correctness/each-key.ts
|
|
5500
4824
|
var correctnessEachKey = componentRule({
|
|
5501
4825
|
id: "correctness/each-key",
|
|
@@ -5659,8 +4983,6 @@ var correctnessOrphanEffect = componentRule({
|
|
|
5659
4983
|
});
|
|
5660
4984
|
|
|
5661
4985
|
// src/rules/correctness/orphan-lifecycle.ts
|
|
5662
|
-
var PENALIZED4 = { presence: "none", value: "absent" };
|
|
5663
|
-
var PASS4 = { presence: "own", value: "static" };
|
|
5664
4986
|
var ID = "correctness/orphan-lifecycle";
|
|
5665
4987
|
var DOCS_URL = docsUrlFor(ID);
|
|
5666
4988
|
var LABEL = "Lifecycle-call context";
|
|
@@ -5674,17 +4996,14 @@ function kitLifecycleMessage(name, kind, inHandler) {
|
|
|
5674
4996
|
}
|
|
5675
4997
|
return inHandler ? `${name}() is called in a load/handler \u2014 it runs on every request, outside component initialisation, and throws lifecycle_outside_component at runtime` : `${name}() runs outside component initialisation (module evaluation or the init hook) \u2014 it throws lifecycle_outside_component at runtime`;
|
|
5676
4998
|
}
|
|
5677
|
-
function isSuppressed3(suppressions, line) {
|
|
5678
|
-
return (suppressions ?? []).some((s) => s.line === line && (!s.ruleIds || s.ruleIds.includes(ID)));
|
|
5679
|
-
}
|
|
5680
4999
|
function emitFile(out, file, issues, suppressions) {
|
|
5681
|
-
const bad = issues.filter((b) => !(b.line > 0 &&
|
|
5000
|
+
const bad = issues.filter((b) => !(b.line > 0 && isSuppressed(suppressions, ID, b.line)));
|
|
5682
5001
|
if (bad.length === 0) {
|
|
5683
5002
|
out.push({
|
|
5684
5003
|
id: ID,
|
|
5685
5004
|
category: "correctness",
|
|
5686
5005
|
severity: "critical",
|
|
5687
|
-
detection:
|
|
5006
|
+
detection: PASS,
|
|
5688
5007
|
route: file,
|
|
5689
5008
|
// Uniform PASS-result attribution (design 2026-08-08-pass-result-location-design.md):
|
|
5690
5009
|
// same location a penalized result for this file would carry.
|
|
@@ -5700,7 +5019,7 @@ function emitFile(out, file, issues, suppressions) {
|
|
|
5700
5019
|
id: ID,
|
|
5701
5020
|
category: "correctness",
|
|
5702
5021
|
severity: "critical",
|
|
5703
|
-
detection:
|
|
5022
|
+
detection: PENALIZED,
|
|
5704
5023
|
route: file,
|
|
5705
5024
|
location: file,
|
|
5706
5025
|
...b.line > 0 ? { line: b.line } : {},
|
|
@@ -5750,8 +5069,6 @@ var correctnessOrphanLifecycle = {
|
|
|
5750
5069
|
};
|
|
5751
5070
|
|
|
5752
5071
|
// src/rules/correctness/base-path-navigation.ts
|
|
5753
|
-
var PENALIZED5 = { presence: "none", value: "absent" };
|
|
5754
|
-
var PASS5 = { presence: "own", value: "static" };
|
|
5755
5072
|
var ID2 = "correctness/base-path-navigation";
|
|
5756
5073
|
var DOCS_URL2 = docsUrlFor(ID2);
|
|
5757
5074
|
var LABEL2 = "Base-path-aware navigation";
|
|
@@ -5768,17 +5085,14 @@ function messageFor2(link) {
|
|
|
5768
5085
|
}
|
|
5769
5086
|
return `redirect(\u2026, '${link.path}') is root-relative \u2014 the Location header points outside this project's kit.paths.base and 404s in production. Use resolve('${link.path}') from '$app/paths'.`;
|
|
5770
5087
|
}
|
|
5771
|
-
function isSuppressed4(suppressions, line) {
|
|
5772
|
-
return (suppressions ?? []).some((s) => s.line === line && (!s.ruleIds || s.ruleIds.includes(ID2)));
|
|
5773
|
-
}
|
|
5774
5088
|
function emitFile2(out, file, links, suppressions) {
|
|
5775
|
-
const bad = links.filter((l) => !(l.line > 0 &&
|
|
5089
|
+
const bad = links.filter((l) => !(l.line > 0 && isSuppressed(suppressions, ID2, l.line)));
|
|
5776
5090
|
if (bad.length === 0) {
|
|
5777
5091
|
out.push({
|
|
5778
5092
|
id: ID2,
|
|
5779
5093
|
category: "correctness",
|
|
5780
5094
|
severity: "warning",
|
|
5781
|
-
detection:
|
|
5095
|
+
detection: PASS,
|
|
5782
5096
|
route: file,
|
|
5783
5097
|
// Uniform PASS-result attribution (design 2026-08-08-pass-result-location-design.md):
|
|
5784
5098
|
// same location a penalized result for this file would carry.
|
|
@@ -5794,7 +5108,7 @@ function emitFile2(out, file, links, suppressions) {
|
|
|
5794
5108
|
id: ID2,
|
|
5795
5109
|
category: "correctness",
|
|
5796
5110
|
severity: "warning",
|
|
5797
|
-
detection:
|
|
5111
|
+
detection: PENALIZED,
|
|
5798
5112
|
route: file,
|
|
5799
5113
|
location: file,
|
|
5800
5114
|
...l.line > 0 ? { line: l.line } : {},
|
|
@@ -5831,24 +5145,19 @@ var correctnessBasePathNavigation = {
|
|
|
5831
5145
|
};
|
|
5832
5146
|
|
|
5833
5147
|
// src/rules/correctness/server-browser-global.ts
|
|
5834
|
-
var PENALIZED6 = { presence: "none", value: "absent" };
|
|
5835
|
-
var PASS6 = { presence: "own", value: "static" };
|
|
5836
5148
|
var ID3 = "correctness/server-browser-global";
|
|
5837
5149
|
var DOCS_URL3 = docsUrlFor(ID3);
|
|
5838
5150
|
var LABEL3 = "Server-safe module code";
|
|
5839
5151
|
var RECOMMENDATION3 = "Move browser-only code into onMount or $effect (they never run on the server), or guard it with browser from $app/environment (or a typeof check).";
|
|
5840
5152
|
var moduleMessage = (name) => `${name} is accessed at module scope \u2014 it does not exist on the server, so importing this file crashes SSR with "${name} is not defined"`;
|
|
5841
|
-
function isSuppressed5(suppressions, line) {
|
|
5842
|
-
return (suppressions ?? []).some((s) => s.line === line && (!s.ruleIds || s.ruleIds.includes(ID3)));
|
|
5843
|
-
}
|
|
5844
5153
|
function emitFile3(out, file, issues, suppressions) {
|
|
5845
|
-
const bad = issues.filter((b) => !(b.line > 0 &&
|
|
5154
|
+
const bad = issues.filter((b) => !(b.line > 0 && isSuppressed(suppressions, ID3, b.line)));
|
|
5846
5155
|
if (bad.length === 0) {
|
|
5847
5156
|
out.push({
|
|
5848
5157
|
id: ID3,
|
|
5849
5158
|
category: "correctness",
|
|
5850
5159
|
severity: "critical",
|
|
5851
|
-
detection:
|
|
5160
|
+
detection: PASS,
|
|
5852
5161
|
route: file,
|
|
5853
5162
|
// Uniform PASS-result attribution (design 2026-08-08-pass-result-location-design.md):
|
|
5854
5163
|
// same location a penalized result for this file would carry.
|
|
@@ -5864,7 +5173,7 @@ function emitFile3(out, file, issues, suppressions) {
|
|
|
5864
5173
|
id: ID3,
|
|
5865
5174
|
category: "correctness",
|
|
5866
5175
|
severity: "critical",
|
|
5867
|
-
detection:
|
|
5176
|
+
detection: PENALIZED,
|
|
5868
5177
|
route: file,
|
|
5869
5178
|
location: file,
|
|
5870
5179
|
...b.line > 0 ? { line: b.line } : {},
|
|
@@ -6122,7 +5431,7 @@ var architecturePrivateScopeImport = {
|
|
|
6122
5431
|
}
|
|
6123
5432
|
if (!sawScopedImport) continue;
|
|
6124
5433
|
const visible = violations.filter(
|
|
6125
|
-
(v) => !(v.line > 0 &&
|
|
5434
|
+
(v) => !(v.line > 0 && isSuppressed(c.suppressions, "architecture/private-scope-import", v.line))
|
|
6126
5435
|
);
|
|
6127
5436
|
if (visible.length === 0) {
|
|
6128
5437
|
out.push({
|
|
@@ -6837,7 +6146,7 @@ var architectureReservedNamePlacement = {
|
|
|
6837
6146
|
const inCapUnits = Object.hasOwn(capUnits, name);
|
|
6838
6147
|
const inAnyUnits = Object.hasOwn(anyUnits, name);
|
|
6839
6148
|
if (!inPlacements && !inCapUnits && !inAnyUnits) continue;
|
|
6840
|
-
const emptyValue = (
|
|
6149
|
+
const emptyValue = (present4, value) => present4 && globsOf(value ?? "").length === 0;
|
|
6841
6150
|
if (emptyValue(inPlacements, placements[name]) || emptyValue(inCapUnits, capUnits[name]) || emptyValue(inAnyUnits, anyUnits[name])) {
|
|
6842
6151
|
continue;
|
|
6843
6152
|
}
|
|
@@ -6954,9 +6263,9 @@ var routeEntryImportsCache = /* @__PURE__ */ new WeakMap();
|
|
|
6954
6263
|
function cachedRouteEntryImports(c, ctx) {
|
|
6955
6264
|
const cached = routeEntryImportsCache.get(c);
|
|
6956
6265
|
if (cached !== void 0 && cached.aliases === ctx.project.kitAliases) return cached.result;
|
|
6957
|
-
const
|
|
6958
|
-
routeEntryImportsCache.set(c, { aliases: ctx.project.kitAliases, result });
|
|
6959
|
-
return
|
|
6266
|
+
const result3 = routeEntryImports(c, ctx);
|
|
6267
|
+
routeEntryImportsCache.set(c, { aliases: ctx.project.kitAliases, result: result3 });
|
|
6268
|
+
return result3;
|
|
6960
6269
|
}
|
|
6961
6270
|
var architectureRouteComponentImport = componentRule({
|
|
6962
6271
|
id: ID8,
|
|
@@ -7092,7 +6401,7 @@ var performanceNamespaceImport = componentRule({
|
|
|
7092
6401
|
});
|
|
7093
6402
|
|
|
7094
6403
|
// src/rules/perf/minify-disabled.ts
|
|
7095
|
-
var
|
|
6404
|
+
var PENALIZED2 = { presence: "none", value: "absent" };
|
|
7096
6405
|
var MINIFY_DISABLED_FIX = {
|
|
7097
6406
|
description: "Remove the minify: false override from vite.config (Vite minifies by default), or scope it to non-production builds.",
|
|
7098
6407
|
snippet: "export default defineConfig({\n build: {\n // minify: false \u2014 removed; Vite minifies production builds by default\n }\n});",
|
|
@@ -7116,7 +6425,7 @@ var performanceMinifyDisabled = {
|
|
|
7116
6425
|
id: "performance/minify-disabled",
|
|
7117
6426
|
category: "performance",
|
|
7118
6427
|
severity: "warning",
|
|
7119
|
-
detection:
|
|
6428
|
+
detection: PENALIZED2,
|
|
7120
6429
|
...hit.file !== void 0 ? { location: hit.file } : {},
|
|
7121
6430
|
...hit.line !== void 0 ? { line: hit.line } : {},
|
|
7122
6431
|
message: "JS/CSS minification is disabled (build.minify: false) \u2014 production bundles ship unminified and several times larger." + provenance,
|
|
@@ -7185,6 +6494,386 @@ var performanceStateRaw = componentRule({
|
|
|
7185
6494
|
}))
|
|
7186
6495
|
});
|
|
7187
6496
|
|
|
6497
|
+
// src/rules/a11y/aria-data.ts
|
|
6498
|
+
import { roles, aria } from "aria-query";
|
|
6499
|
+
function isKnownRole(role) {
|
|
6500
|
+
return roles.has(role);
|
|
6501
|
+
}
|
|
6502
|
+
function isAbstractRole(role) {
|
|
6503
|
+
return roles.get(role)?.abstract === true;
|
|
6504
|
+
}
|
|
6505
|
+
function isKnownAriaAttribute(name) {
|
|
6506
|
+
return aria.has(name);
|
|
6507
|
+
}
|
|
6508
|
+
function requiredAriaProps(role) {
|
|
6509
|
+
const def = roles.get(role);
|
|
6510
|
+
return def ? Object.keys(def.requiredProps) : [];
|
|
6511
|
+
}
|
|
6512
|
+
function ariaValueKind(name) {
|
|
6513
|
+
const def = aria.get(name);
|
|
6514
|
+
if (!def) return void 0;
|
|
6515
|
+
return { type: def.type, ...def.values ? { values: def.values.map(String) } : {} };
|
|
6516
|
+
}
|
|
6517
|
+
|
|
6518
|
+
// src/rules/a11y/invalid-role.ts
|
|
6519
|
+
var a11yInvalidRole = componentRule({
|
|
6520
|
+
id: "a11y/invalid-role",
|
|
6521
|
+
title: "Invalid ARIA role",
|
|
6522
|
+
category: "a11y",
|
|
6523
|
+
label: "ARIA roles",
|
|
6524
|
+
rationale: "A role that does not exist in WAI-ARIA (or is abstract, reserved for the spec itself) is ignored or misread by assistive technology, silently breaking the element\u2019s announced semantics.",
|
|
6525
|
+
recommendation: "Use a concrete WAI-ARIA role; abstract roles and typos are ignored by assistive technology.",
|
|
6526
|
+
applies: (c) => (c.ariaElements ?? []).some((e) => e.role?.literal !== void 0),
|
|
6527
|
+
bad: (c) => (c.ariaElements ?? []).flatMap((e) => {
|
|
6528
|
+
const literal = e.role?.literal;
|
|
6529
|
+
if (literal === void 0) return [];
|
|
6530
|
+
const tokens = splitTokens(literal);
|
|
6531
|
+
const badTokens = tokens.filter((t) => !isKnownRole(t) || isAbstractRole(t));
|
|
6532
|
+
if (badTokens.length === 0) return [];
|
|
6533
|
+
return [
|
|
6534
|
+
{
|
|
6535
|
+
line: e.line,
|
|
6536
|
+
message: `role="${literal}" on <${e.tag}> is ${isAbstractRole(badTokens[0]) ? "an abstract role" : "not a WAI-ARIA role"}`
|
|
6537
|
+
}
|
|
6538
|
+
];
|
|
6539
|
+
})
|
|
6540
|
+
});
|
|
6541
|
+
|
|
6542
|
+
// src/rules/a11y/unknown-aria-attribute.ts
|
|
6543
|
+
var a11yUnknownAriaAttribute = componentRule({
|
|
6544
|
+
id: "a11y/unknown-aria-attribute",
|
|
6545
|
+
title: "Unknown ARIA attribute",
|
|
6546
|
+
category: "a11y",
|
|
6547
|
+
label: "Known ARIA attributes",
|
|
6548
|
+
rationale: "An `aria-*` name that does not exist in WAI-ARIA is not recognized by assistive technology, so the attribute is silently ignored instead of doing what the author intended.",
|
|
6549
|
+
recommendation: "Use a spec-defined `aria-*` attribute; unknown names are ignored by assistive technology.",
|
|
6550
|
+
applies: (c) => (c.ariaElements ?? []).some((e) => e.aria.length > 0),
|
|
6551
|
+
bad: (c) => (c.ariaElements ?? []).flatMap(
|
|
6552
|
+
(e) => e.aria.filter((a) => !isKnownAriaAttribute(a.name)).map((a) => ({ line: a.line, message: `\`${a.name}\` is not a WAI-ARIA attribute` }))
|
|
6553
|
+
)
|
|
6554
|
+
});
|
|
6555
|
+
|
|
6556
|
+
// src/rules/a11y/required-aria-props.ts
|
|
6557
|
+
var HOST_SUPPLIED = {
|
|
6558
|
+
"aria-checked": (e) => e.tag === "input" && (e.inputType === "checkbox" || e.inputType === "radio"),
|
|
6559
|
+
"aria-selected": (e) => e.tag === "option",
|
|
6560
|
+
"aria-level": (e) => /^h[1-6]$/.test(e.tag),
|
|
6561
|
+
"aria-valuenow": (e) => e.tag === "input" && e.inputType === "range" || e.tag === "progress" || e.tag === "meter"
|
|
6562
|
+
};
|
|
6563
|
+
var a11yRequiredAriaProps = componentRule({
|
|
6564
|
+
id: "a11y/required-aria-props",
|
|
6565
|
+
title: "Missing required ARIA props",
|
|
6566
|
+
category: "a11y",
|
|
6567
|
+
label: "Required ARIA props",
|
|
6568
|
+
rationale: 'Some WAI-ARIA roles are unusable to assistive technology without their required state/property attributes \u2014 a role="checkbox" with no way to know checked/unchecked announces a control with no discoverable state.',
|
|
6569
|
+
recommendation: "Add the role\u2019s required `aria-*` attribute(s), or rely on native host semantics that already supply them.",
|
|
6570
|
+
applies: (c) => (c.ariaElements ?? []).some((e) => e.role?.literal !== void 0 && !e.role.literal.includes(" ")),
|
|
6571
|
+
bad: (c) => (c.ariaElements ?? []).flatMap((e) => {
|
|
6572
|
+
if (e.hasSpread) return [];
|
|
6573
|
+
const literal = e.role?.literal;
|
|
6574
|
+
if (literal === void 0 || literal.includes(" ")) return [];
|
|
6575
|
+
const required = requiredAriaProps(literal);
|
|
6576
|
+
if (required.length === 0) return [];
|
|
6577
|
+
const present4 = new Set(e.aria.map((a) => a.name));
|
|
6578
|
+
const missing = required.filter((p) => !present4.has(p) && !HOST_SUPPLIED[p]?.(e));
|
|
6579
|
+
if (missing.length === 0) return [];
|
|
6580
|
+
return [{ line: e.line, message: `role="${literal}" on <${e.tag}> is missing required ${missing.join(", ")}` }];
|
|
6581
|
+
})
|
|
6582
|
+
});
|
|
6583
|
+
|
|
6584
|
+
// src/rules/a11y/invalid-aria-value.ts
|
|
6585
|
+
function isValid(type, values, literal) {
|
|
6586
|
+
switch (type) {
|
|
6587
|
+
case "boolean":
|
|
6588
|
+
return literal === "true" || literal === "false";
|
|
6589
|
+
case "tristate":
|
|
6590
|
+
return literal === "true" || literal === "false" || literal === "mixed";
|
|
6591
|
+
case "token":
|
|
6592
|
+
return (values ?? []).includes(literal);
|
|
6593
|
+
case "tokenlist":
|
|
6594
|
+
return splitTokens(literal).every((t) => (values ?? []).includes(t));
|
|
6595
|
+
case "integer":
|
|
6596
|
+
return /^-?\d+$/.test(literal);
|
|
6597
|
+
case "number":
|
|
6598
|
+
return literal.trim() !== "" && Number.isFinite(Number(literal));
|
|
6599
|
+
default:
|
|
6600
|
+
return true;
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
var a11yInvalidAriaValue = componentRule({
|
|
6604
|
+
id: "a11y/invalid-aria-value",
|
|
6605
|
+
title: "Invalid ARIA attribute value",
|
|
6606
|
+
category: "a11y",
|
|
6607
|
+
label: "ARIA attribute values",
|
|
6608
|
+
rationale: "An `aria-*` attribute whose value does not match its spec-defined type (e.g. a boolean given a non-`true`/`false` literal) is misread or ignored by assistive technology.",
|
|
6609
|
+
recommendation: "Use a value matching the attribute\u2019s WAI-ARIA type \u2014 see the spec for allowed values.",
|
|
6610
|
+
applies: (c) => (c.ariaElements ?? []).some((e) => e.aria.some((a) => a.literal !== void 0)),
|
|
6611
|
+
bad: (c) => (c.ariaElements ?? []).flatMap(
|
|
6612
|
+
(e) => e.aria.flatMap((a) => {
|
|
6613
|
+
if (a.literal === void 0) return [];
|
|
6614
|
+
const kind = ariaValueKind(a.name);
|
|
6615
|
+
if (kind === void 0) return [];
|
|
6616
|
+
if (isValid(kind.type, kind.values, a.literal)) return [];
|
|
6617
|
+
return [{ line: a.line, message: `\`${a.name}="${a.literal}"\` is not a valid ${kind.type} value` }];
|
|
6618
|
+
})
|
|
6619
|
+
)
|
|
6620
|
+
});
|
|
6621
|
+
|
|
6622
|
+
// src/rules/a11y/interactive-nesting.ts
|
|
6623
|
+
var a11yInteractiveNesting = componentRule({
|
|
6624
|
+
id: "a11y/interactive-nesting",
|
|
6625
|
+
title: "Interactive element nested in an interactive element",
|
|
6626
|
+
category: "a11y",
|
|
6627
|
+
label: "Interactive nesting",
|
|
6628
|
+
rationale: "A control nested inside another interactive element is unreachable or misannounced by keyboard and assistive technology, and violates the HTML content model.",
|
|
6629
|
+
recommendation: "Restructure the markup so each interactive control is a sibling, not a descendant, of another.",
|
|
6630
|
+
applies: (c) => (c.interactiveNestings ?? []).length > 0,
|
|
6631
|
+
bad: (c) => (c.interactiveNestings ?? []).map((f) => ({
|
|
6632
|
+
line: f.line,
|
|
6633
|
+
message: `<${f.descendantTag}> is nested inside interactive <${f.containerTag}>`
|
|
6634
|
+
}))
|
|
6635
|
+
});
|
|
6636
|
+
|
|
6637
|
+
// src/rules/a11y/accessible-name.ts
|
|
6638
|
+
var a11yAccessibleName = componentRule({
|
|
6639
|
+
id: "a11y/accessible-name",
|
|
6640
|
+
title: "Interactive element has no accessible name",
|
|
6641
|
+
category: "a11y",
|
|
6642
|
+
label: "Accessible names",
|
|
6643
|
+
rationale: 'A button, link, or image button with no accessible name is announced by assistive technology as its bare role ("button", "link") with nothing to distinguish it from any other control on the page.',
|
|
6644
|
+
recommendation: "Give the element visible text, an aria-label/aria-labelledby/title, or an alt on its icon image.",
|
|
6645
|
+
applies: (c) => (c.unnamedInteractive ?? []).length > 0,
|
|
6646
|
+
bad: (c) => (c.unnamedInteractive ?? []).map((f) => ({ line: f.line, message: `<${f.tag}> has no accessible name` }))
|
|
6647
|
+
});
|
|
6648
|
+
|
|
6649
|
+
// src/rules/a11y/label-has-control.ts
|
|
6650
|
+
var a11yLabelHasControl = componentRule({
|
|
6651
|
+
id: "a11y/label-has-control",
|
|
6652
|
+
title: "<label> has no associated control",
|
|
6653
|
+
category: "a11y",
|
|
6654
|
+
label: "Label associations",
|
|
6655
|
+
rationale: "A `<label>` with no associated control is announced by assistive technology as plain text \u2014 clicking or tapping it does not focus the field, and a screen reader gives no relationship between the label and its control.",
|
|
6656
|
+
recommendation: "Add a `for` attribute pointing at the control's `id`, or wrap the control inside the `<label>`.",
|
|
6657
|
+
applies: (c) => (c.unassociatedLabels ?? []).length > 0,
|
|
6658
|
+
bad: (c) => (c.unassociatedLabels ?? []).map((f) => ({ line: f.line, message: "<label> has no associated control" }))
|
|
6659
|
+
});
|
|
6660
|
+
|
|
6661
|
+
// src/rules/a11y/use-list.ts
|
|
6662
|
+
var a11yUseList = componentRule({
|
|
6663
|
+
id: "a11y/use-list",
|
|
6664
|
+
title: "Bullet text should be a list",
|
|
6665
|
+
category: "a11y",
|
|
6666
|
+
severity: "info",
|
|
6667
|
+
label: "List structure",
|
|
6668
|
+
rationale: "A screen reader announces a real `<ul>`/`<ol>` as a list \u2014 item count, position, and boundaries. A bullet character typed into plain text carries none of that, so the visual structure is lost on assistive technology.",
|
|
6669
|
+
recommendation: "Use a `<ul>`/`<ol>` with `<li>` items instead of a bullet character in plain text.",
|
|
6670
|
+
applies: (c) => (c.bulletTexts ?? []).length > 0,
|
|
6671
|
+
bad: (c) => (c.bulletTexts ?? []).map((b) => ({
|
|
6672
|
+
line: b.line,
|
|
6673
|
+
message: `Text starts with a bullet character ('${b.char}') \u2014 use a list element`
|
|
6674
|
+
}))
|
|
6675
|
+
});
|
|
6676
|
+
|
|
6677
|
+
// src/rules/a11y/placeholder-label-option.ts
|
|
6678
|
+
var a11yPlaceholderLabelOption = componentRule({
|
|
6679
|
+
id: "a11y/placeholder-label-option",
|
|
6680
|
+
title: "Missing placeholder label option",
|
|
6681
|
+
category: "a11y",
|
|
6682
|
+
label: "Select placeholder",
|
|
6683
|
+
rationale: "A required, single-selection `<select>` initially shows its first option as the chosen value \u2014 if that option is not an empty placeholder, users can submit the form without ever having made a real choice, and assistive technology announces a value as already selected.",
|
|
6684
|
+
recommendation: 'Make the first `<option>` a placeholder: an empty `value=""`, or no `value` attribute and no text.',
|
|
6685
|
+
applies: (c) => (c.selectsMissingPlaceholder ?? []).length > 0,
|
|
6686
|
+
bad: (c) => (c.selectsMissingPlaceholder ?? []).map((f) => ({
|
|
6687
|
+
line: f.line,
|
|
6688
|
+
message: "<select required> is missing a placeholder label option"
|
|
6689
|
+
}))
|
|
6690
|
+
});
|
|
6691
|
+
|
|
6692
|
+
// src/rules/a11y/require-datetime.ts
|
|
6693
|
+
var a11yRequireDatetime = componentRule({
|
|
6694
|
+
id: "a11y/require-datetime",
|
|
6695
|
+
title: "Missing datetime attribute",
|
|
6696
|
+
category: "a11y",
|
|
6697
|
+
label: "Time elements",
|
|
6698
|
+
rationale: 'A `<time>` element with no `datetime` attribute exposes its text content as the machine-readable value \u2014 text like "last Tuesday" cannot be parsed by assistive technology or user agents into an actual date, so its meaning is lost to anything that isn\'t a sighted reader.',
|
|
6699
|
+
recommendation: 'Add a `datetime` attribute with a machine-readable value, e.g. `<time datetime="2026-08-14">Aug 14</time>`.',
|
|
6700
|
+
applies: (c) => (c.timesMissingDatetime ?? []).length > 0,
|
|
6701
|
+
bad: (c) => (c.timesMissingDatetime ?? []).map((f) => ({
|
|
6702
|
+
line: f.line,
|
|
6703
|
+
message: `<time> content "${f.text}" is not machine-readable and has no datetime attribute`
|
|
6704
|
+
}))
|
|
6705
|
+
});
|
|
6706
|
+
|
|
6707
|
+
// src/rules/a11y/doctype.ts
|
|
6708
|
+
var present3 = { presence: "own", value: "static" };
|
|
6709
|
+
var absent3 = { presence: "none", value: "absent" };
|
|
6710
|
+
var FIX8 = {
|
|
6711
|
+
description: "Add <!doctype html> as the first line of src/app.html.",
|
|
6712
|
+
snippet: "<!doctype html>",
|
|
6713
|
+
lang: "html"
|
|
6714
|
+
};
|
|
6715
|
+
var a11yDoctype = {
|
|
6716
|
+
id: "a11y/doctype",
|
|
6717
|
+
title: "Doctype",
|
|
6718
|
+
category: "a11y",
|
|
6719
|
+
severity: "warning",
|
|
6720
|
+
scope: "project",
|
|
6721
|
+
rationale: "Without a doctype browsers render in quirks mode, breaking CSS and accessibility tree behavior.",
|
|
6722
|
+
fix: FIX8,
|
|
6723
|
+
async check(ctx) {
|
|
6724
|
+
const { appHtmlDoctype } = ctx.project;
|
|
6725
|
+
if (appHtmlDoctype === void 0) return [];
|
|
6726
|
+
return [
|
|
6727
|
+
{
|
|
6728
|
+
id: "a11y/doctype",
|
|
6729
|
+
category: "a11y",
|
|
6730
|
+
severity: "warning",
|
|
6731
|
+
detection: appHtmlDoctype ? present3 : absent3,
|
|
6732
|
+
location: "src/app.html",
|
|
6733
|
+
message: appHtmlDoctype ? "<!doctype html>" : "src/app.html is missing <!doctype html>",
|
|
6734
|
+
recommendation: "Add <!doctype html> as the first line of src/app.html.",
|
|
6735
|
+
docsUrl: docsUrlFor("a11y/doctype"),
|
|
6736
|
+
fix: { ...FIX8 }
|
|
6737
|
+
}
|
|
6738
|
+
];
|
|
6739
|
+
}
|
|
6740
|
+
};
|
|
6741
|
+
|
|
6742
|
+
// src/rules/a11y/route-rule.ts
|
|
6743
|
+
function resultFactory(id, recommendation12) {
|
|
6744
|
+
const docsUrl12 = docsUrlFor(id);
|
|
6745
|
+
return (route, detection, occ, message) => ({
|
|
6746
|
+
id,
|
|
6747
|
+
category: "a11y",
|
|
6748
|
+
severity: "warning",
|
|
6749
|
+
detection,
|
|
6750
|
+
route,
|
|
6751
|
+
location: occ.file,
|
|
6752
|
+
...occ.line > 0 ? { line: occ.line } : {},
|
|
6753
|
+
message,
|
|
6754
|
+
recommendation: recommendation12,
|
|
6755
|
+
docsUrl: docsUrl12
|
|
6756
|
+
});
|
|
6757
|
+
}
|
|
6758
|
+
function surplusRule(spec) {
|
|
6759
|
+
const result3 = resultFactory(spec.id, spec.recommendation);
|
|
6760
|
+
return {
|
|
6761
|
+
id: spec.id,
|
|
6762
|
+
title: spec.title,
|
|
6763
|
+
category: "a11y",
|
|
6764
|
+
severity: "warning",
|
|
6765
|
+
scope: "route",
|
|
6766
|
+
rationale: spec.rationale,
|
|
6767
|
+
async check(ctx) {
|
|
6768
|
+
const out = [];
|
|
6769
|
+
for (const route of ctx.a11y ?? []) {
|
|
6770
|
+
let first;
|
|
6771
|
+
let surplus = false;
|
|
6772
|
+
for (const [key, reps] of spec.map(route)) {
|
|
6773
|
+
first ??= reps[0];
|
|
6774
|
+
for (let i = 1; i < reps.length; i++) {
|
|
6775
|
+
surplus = true;
|
|
6776
|
+
out.push(result3(route.route, PENALIZED, reps[i], spec.message(key, i, reps.length)));
|
|
6777
|
+
}
|
|
6778
|
+
}
|
|
6779
|
+
if (first && !surplus) out.push(result3(route.route, PASS, { file: first.file, line: 0 }, spec.passMessage));
|
|
6780
|
+
}
|
|
6781
|
+
return out;
|
|
6782
|
+
}
|
|
6783
|
+
};
|
|
6784
|
+
}
|
|
6785
|
+
|
|
6786
|
+
// src/rules/a11y/duplicate-landmark.ts
|
|
6787
|
+
var KINDS = ["main", "banner", "contentinfo"];
|
|
6788
|
+
var a11yDuplicateLandmark = surplusRule({
|
|
6789
|
+
id: "a11y/duplicate-landmark",
|
|
6790
|
+
title: "Duplicate landmark",
|
|
6791
|
+
rationale: "Assistive tech users jump between landmarks to skip repeated content; more than one main, banner, or contentinfo per page leaves them guessing which one is the real one.",
|
|
6792
|
+
recommendation: "A route should have at most one main, banner, and contentinfo landmark.",
|
|
6793
|
+
map: (route) => KINDS.flatMap((kind) => {
|
|
6794
|
+
const reps = route.landmarks[kind];
|
|
6795
|
+
return reps?.length ? [[kind, reps]] : [];
|
|
6796
|
+
}),
|
|
6797
|
+
message: (kind, i, n) => `Duplicate ${kind} landmark (${i + 1} of ${n})`,
|
|
6798
|
+
passMessage: "No duplicate landmarks"
|
|
6799
|
+
});
|
|
6800
|
+
|
|
6801
|
+
// src/rules/a11y/top-level-landmark.ts
|
|
6802
|
+
var recommendation10 = "A banner, main, complementary, or contentinfo landmark should not be nested inside another landmark.";
|
|
6803
|
+
var result = resultFactory("a11y/top-level-landmark", recommendation10);
|
|
6804
|
+
var KINDS2 = ["main", "banner", "complementary", "contentinfo"];
|
|
6805
|
+
var a11yTopLevelLandmark = {
|
|
6806
|
+
id: "a11y/top-level-landmark",
|
|
6807
|
+
title: "Top-level landmark",
|
|
6808
|
+
category: "a11y",
|
|
6809
|
+
severity: "warning",
|
|
6810
|
+
scope: "route",
|
|
6811
|
+
rationale: "Assistive tech landmark navigation expects banner/main/complementary/contentinfo at the top level; nesting one inside another hides it from that navigation.",
|
|
6812
|
+
async check(ctx) {
|
|
6813
|
+
const out = [];
|
|
6814
|
+
for (const route of ctx.a11y ?? []) {
|
|
6815
|
+
for (const nested of route.nestedLandmarks) {
|
|
6816
|
+
out.push(result(route.route, PENALIZED, nested, `${nested.kind} landmark is nested inside ${nested.within}`));
|
|
6817
|
+
}
|
|
6818
|
+
if (route.nestedLandmarks.length === 0) {
|
|
6819
|
+
const first = KINDS2.map((kind) => route.landmarks[kind]?.[0]).find((rep) => rep !== void 0);
|
|
6820
|
+
if (first) out.push(result(route.route, PASS, { file: first.file, line: 0 }, "No nested landmarks"));
|
|
6821
|
+
}
|
|
6822
|
+
}
|
|
6823
|
+
return out;
|
|
6824
|
+
}
|
|
6825
|
+
};
|
|
6826
|
+
|
|
6827
|
+
// src/rules/a11y/id-duplication.ts
|
|
6828
|
+
var a11yIdDuplication = surplusRule({
|
|
6829
|
+
id: "a11y/id-duplication",
|
|
6830
|
+
title: "Id duplication",
|
|
6831
|
+
rationale: "A duplicate id breaks label/aria-labelledby associations and in-page fragment navigation: assistive tech resolves the first match, which may not be the one the author intended.",
|
|
6832
|
+
recommendation: "Every id in a route should be unique.",
|
|
6833
|
+
// Entries ordered by each id's first representative (file, then line): content-derived and
|
|
6834
|
+
// stable — a Record's own-key enumeration would pull integer-like ids ("1") to the front.
|
|
6835
|
+
map: (route) => Object.entries(route.ids).sort(([, a], [, b]) => a[0].file.localeCompare(b[0].file) || a[0].line - b[0].line),
|
|
6836
|
+
message: (id) => `Duplicate id "${id}"`,
|
|
6837
|
+
passMessage: "No duplicate ids"
|
|
6838
|
+
});
|
|
6839
|
+
|
|
6840
|
+
// src/rules/a11y/no-missing-id-ref.ts
|
|
6841
|
+
var recommendation11 = "An id reference should point to an id that exists somewhere in the composed route.";
|
|
6842
|
+
var result2 = resultFactory("a11y/no-missing-id-ref", recommendation11);
|
|
6843
|
+
var a11yNoMissingIdRef = {
|
|
6844
|
+
id: "a11y/no-missing-id-ref",
|
|
6845
|
+
title: "No missing id ref",
|
|
6846
|
+
category: "a11y",
|
|
6847
|
+
severity: "warning",
|
|
6848
|
+
scope: "route",
|
|
6849
|
+
rationale: 'A `for`/`aria-labelledby`/`aria-describedby`/`aria-controls`/`aria-activedescendant`/`href="#\u2026"` pointing at an id that does not exist leaves assistive tech with a broken association or the browser with a dead in-page link.',
|
|
6850
|
+
async check(ctx) {
|
|
6851
|
+
const out = [];
|
|
6852
|
+
for (const route of ctx.a11y ?? []) {
|
|
6853
|
+
if (!route.fullyResolved || route.idRefs.length === 0) continue;
|
|
6854
|
+
const candidates = new Set(route.idCandidates);
|
|
6855
|
+
let hasMissing = false;
|
|
6856
|
+
for (const ref of route.idRefs) {
|
|
6857
|
+
if (candidates.has(ref.id)) continue;
|
|
6858
|
+
hasMissing = true;
|
|
6859
|
+
out.push(
|
|
6860
|
+
result2(
|
|
6861
|
+
route.route,
|
|
6862
|
+
PENALIZED,
|
|
6863
|
+
ref,
|
|
6864
|
+
`${ref.attr}="${ref.attr === "href" ? "#" : ""}${ref.id}" references a missing id`
|
|
6865
|
+
)
|
|
6866
|
+
);
|
|
6867
|
+
}
|
|
6868
|
+
if (!hasMissing) {
|
|
6869
|
+
const first = route.idRefs[0];
|
|
6870
|
+
out.push(result2(route.route, PASS, { file: first.file, line: 0 }, "No missing id references"));
|
|
6871
|
+
}
|
|
6872
|
+
}
|
|
6873
|
+
return out;
|
|
6874
|
+
}
|
|
6875
|
+
};
|
|
6876
|
+
|
|
7188
6877
|
// src/rules/index.ts
|
|
7189
6878
|
var allRules = [
|
|
7190
6879
|
seoTitlePresence,
|
|
@@ -7259,7 +6948,22 @@ var allRules = [
|
|
|
7259
6948
|
performanceMinifyDisabled,
|
|
7260
6949
|
performanceLoadWaterfall,
|
|
7261
6950
|
performanceSequentialAwaits,
|
|
7262
|
-
performanceStateRaw
|
|
6951
|
+
performanceStateRaw,
|
|
6952
|
+
a11yInvalidRole,
|
|
6953
|
+
a11yUnknownAriaAttribute,
|
|
6954
|
+
a11yRequiredAriaProps,
|
|
6955
|
+
a11yInvalidAriaValue,
|
|
6956
|
+
a11yInteractiveNesting,
|
|
6957
|
+
a11yAccessibleName,
|
|
6958
|
+
a11yLabelHasControl,
|
|
6959
|
+
a11yUseList,
|
|
6960
|
+
a11yPlaceholderLabelOption,
|
|
6961
|
+
a11yRequireDatetime,
|
|
6962
|
+
a11yDoctype,
|
|
6963
|
+
a11yDuplicateLandmark,
|
|
6964
|
+
a11yTopLevelLandmark,
|
|
6965
|
+
a11yIdDuplication,
|
|
6966
|
+
a11yNoMissingIdRef
|
|
7263
6967
|
];
|
|
7264
6968
|
function optionInfos(spec) {
|
|
7265
6969
|
return Object.entries(spec).map(([name, s]) => ({
|
|
@@ -7286,21 +6990,21 @@ function explainRule(id) {
|
|
|
7286
6990
|
}
|
|
7287
6991
|
|
|
7288
6992
|
// src/summary.ts
|
|
7289
|
-
function classify(
|
|
7290
|
-
if (isPenalized(
|
|
7291
|
-
if (
|
|
6993
|
+
function classify(result3, config) {
|
|
6994
|
+
if (isPenalized(result3.detection, config.treatDynamicAs)) return "fail";
|
|
6995
|
+
if (result3.detection.value === "dynamic") return "dynamic";
|
|
7292
6996
|
return "pass";
|
|
7293
6997
|
}
|
|
7294
|
-
function effectiveSeverity(
|
|
7295
|
-
if (
|
|
7296
|
-
return
|
|
6998
|
+
function effectiveSeverity(result3, config) {
|
|
6999
|
+
if (result3.detection.value === "dynamic" && config.treatDynamicAs === "warn") return "warning";
|
|
7000
|
+
return result3.severity;
|
|
7297
7001
|
}
|
|
7298
7002
|
function summarize(results, config) {
|
|
7299
7003
|
const summary = { critical: 0, warning: 0, info: 0, passed: 0, dynamic: 0 };
|
|
7300
|
-
for (const
|
|
7301
|
-
const cls = classify(
|
|
7004
|
+
for (const result3 of results) {
|
|
7005
|
+
const cls = classify(result3, config);
|
|
7302
7006
|
if (cls === "fail") {
|
|
7303
|
-
summary[effectiveSeverity(
|
|
7007
|
+
summary[effectiveSeverity(result3, config)] += 1;
|
|
7304
7008
|
} else {
|
|
7305
7009
|
summary.passed += 1;
|
|
7306
7010
|
if (cls === "dynamic") summary.dynamic += 1;
|
|
@@ -7479,9 +7183,11 @@ var CATEGORY_LABEL = {
|
|
|
7479
7183
|
performance: "Performance",
|
|
7480
7184
|
correctness: "Correctness",
|
|
7481
7185
|
security: "Security",
|
|
7482
|
-
architecture: "Architecture"
|
|
7186
|
+
architecture: "Architecture",
|
|
7187
|
+
a11y: "Accessibility"
|
|
7483
7188
|
};
|
|
7484
|
-
var CATEGORY_ORDER =
|
|
7189
|
+
var CATEGORY_ORDER = Object.keys(CATEGORY_LABEL);
|
|
7190
|
+
var categoryLabel = (c) => CATEGORY_LABEL[c];
|
|
7485
7191
|
var MAX_RULE_GROUPS_PER_BUCKET = 5;
|
|
7486
7192
|
function groupByRule(results) {
|
|
7487
7193
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -7536,7 +7242,7 @@ function formatConsoleReport(results, config, options = {}) {
|
|
|
7536
7242
|
const p = options.palette ?? noColorPalette;
|
|
7537
7243
|
const summary = summarize(results, config);
|
|
7538
7244
|
const { health, categories: byCat } = computeHealth(results, config);
|
|
7539
|
-
const
|
|
7245
|
+
const present4 = CATEGORY_ORDER.filter((c) => byCat[c] !== void 0);
|
|
7540
7246
|
const lines = [];
|
|
7541
7247
|
if (!options.omitHeader) {
|
|
7542
7248
|
lines.push(
|
|
@@ -7545,8 +7251,8 @@ function formatConsoleReport(results, config, options = {}) {
|
|
|
7545
7251
|
`${p.bold("Health:")} ${scoreColor(p, health)(`${health}/100`)}`
|
|
7546
7252
|
);
|
|
7547
7253
|
}
|
|
7548
|
-
for (const c of
|
|
7549
|
-
lines.push(scoreLine(p,
|
|
7254
|
+
for (const c of present4) {
|
|
7255
|
+
lines.push(scoreLine(p, categoryLabel(c), byCat[c]));
|
|
7550
7256
|
}
|
|
7551
7257
|
lines.push("");
|
|
7552
7258
|
const SEVERITY_COLOR = {
|
|
@@ -7605,17 +7311,17 @@ function formatConsoleReport(results, config, options = {}) {
|
|
|
7605
7311
|
}
|
|
7606
7312
|
|
|
7607
7313
|
// src/reporter/json.ts
|
|
7608
|
-
function issueOf(
|
|
7314
|
+
function issueOf(result3) {
|
|
7609
7315
|
return {
|
|
7610
|
-
id:
|
|
7611
|
-
category:
|
|
7612
|
-
title:
|
|
7613
|
-
detection:
|
|
7614
|
-
location:
|
|
7615
|
-
...
|
|
7616
|
-
recommendation:
|
|
7617
|
-
...
|
|
7618
|
-
...
|
|
7316
|
+
id: result3.id,
|
|
7317
|
+
category: result3.category ?? "seo",
|
|
7318
|
+
title: result3.message,
|
|
7319
|
+
detection: result3.detection,
|
|
7320
|
+
location: result3.location,
|
|
7321
|
+
...result3.line !== void 0 ? { line: result3.line } : {},
|
|
7322
|
+
recommendation: result3.recommendation,
|
|
7323
|
+
...result3.docsUrl ? { docsUrl: result3.docsUrl } : {},
|
|
7324
|
+
...result3.fix ? { fix: result3.fix } : {}
|
|
7619
7325
|
};
|
|
7620
7326
|
}
|
|
7621
7327
|
function ruleEvidence(results, config, ruleIds) {
|
|
@@ -7675,8 +7381,25 @@ function formatJsonReport(results, config, meta, ruleIds, examined) {
|
|
|
7675
7381
|
return JSON.stringify(buildJsonReport(results, config, meta, ruleIds, examined), null, 2);
|
|
7676
7382
|
}
|
|
7677
7383
|
|
|
7678
|
-
// src/reporter/
|
|
7384
|
+
// src/reporter/shared.ts
|
|
7679
7385
|
var SEVERITY_RANK = { critical: 0, warning: 1, info: 2 };
|
|
7386
|
+
function severityToSarifLevel(sev) {
|
|
7387
|
+
return sev === "critical" ? "error" : sev === "warning" ? "warning" : "note";
|
|
7388
|
+
}
|
|
7389
|
+
function severityToGithubLevel(sev) {
|
|
7390
|
+
return sev === "critical" ? "error" : sev === "warning" ? "warning" : "notice";
|
|
7391
|
+
}
|
|
7392
|
+
function messageText(result3) {
|
|
7393
|
+
return result3.recommendation ? `${result3.message} ${result3.recommendation}` : result3.message;
|
|
7394
|
+
}
|
|
7395
|
+
var RULE_META = new Map(
|
|
7396
|
+
allRules.map((r) => [r.id, { title: r.title, severity: r.severity, docsUrl: docsUrlFor(r.id) }])
|
|
7397
|
+
);
|
|
7398
|
+
function ruleMetaById(id) {
|
|
7399
|
+
return RULE_META.get(id);
|
|
7400
|
+
}
|
|
7401
|
+
|
|
7402
|
+
// src/reporter/agent.ts
|
|
7680
7403
|
function formatAgentReport(results, config) {
|
|
7681
7404
|
const failing = results.filter((r) => classify(r, config) === "fail");
|
|
7682
7405
|
const { health } = computeHealth(results, config);
|
|
@@ -7719,23 +7442,6 @@ function formatAgentReport(results, config) {
|
|
|
7719
7442
|
return lines.join("\n").replace(/\n+$/, "\n");
|
|
7720
7443
|
}
|
|
7721
7444
|
|
|
7722
|
-
// src/reporter/shared.ts
|
|
7723
|
-
function severityToSarifLevel(sev) {
|
|
7724
|
-
return sev === "critical" ? "error" : sev === "warning" ? "warning" : "note";
|
|
7725
|
-
}
|
|
7726
|
-
function severityToGithubLevel(sev) {
|
|
7727
|
-
return sev === "critical" ? "error" : sev === "warning" ? "warning" : "notice";
|
|
7728
|
-
}
|
|
7729
|
-
function messageText(result) {
|
|
7730
|
-
return result.recommendation ? `${result.message} ${result.recommendation}` : result.message;
|
|
7731
|
-
}
|
|
7732
|
-
var RULE_META = new Map(
|
|
7733
|
-
allRules.map((r) => [r.id, { title: r.title, severity: r.severity, docsUrl: docsUrlFor(r.id) }])
|
|
7734
|
-
);
|
|
7735
|
-
function ruleMetaById(id) {
|
|
7736
|
-
return RULE_META.get(id);
|
|
7737
|
-
}
|
|
7738
|
-
|
|
7739
7445
|
// src/reporter/sarif.ts
|
|
7740
7446
|
function formatSarifReport(results, config, meta) {
|
|
7741
7447
|
const penalized = results.filter((r) => isPenalized(r.detection, config.treatDynamicAs));
|
|
@@ -7754,7 +7460,7 @@ function formatSarifReport(results, config, meta) {
|
|
|
7754
7460
|
defaultConfiguration: { level: severityToSarifLevel(m?.severity ?? r.severity) }
|
|
7755
7461
|
});
|
|
7756
7462
|
}
|
|
7757
|
-
const
|
|
7463
|
+
const result3 = {
|
|
7758
7464
|
ruleId: r.id,
|
|
7759
7465
|
ruleIndex: ruleIndex.get(r.id),
|
|
7760
7466
|
level: severityToSarifLevel(effectiveSeverity(r, config)),
|
|
@@ -7764,7 +7470,7 @@ function formatSarifReport(results, config, meta) {
|
|
|
7764
7470
|
}
|
|
7765
7471
|
};
|
|
7766
7472
|
if (r.location) {
|
|
7767
|
-
|
|
7473
|
+
result3.locations = [
|
|
7768
7474
|
{
|
|
7769
7475
|
physicalLocation: {
|
|
7770
7476
|
artifactLocation: { uri: r.location },
|
|
@@ -7773,7 +7479,7 @@ function formatSarifReport(results, config, meta) {
|
|
|
7773
7479
|
}
|
|
7774
7480
|
];
|
|
7775
7481
|
}
|
|
7776
|
-
return
|
|
7482
|
+
return result3;
|
|
7777
7483
|
});
|
|
7778
7484
|
const log = {
|
|
7779
7485
|
$schema: "https://json.schemastore.org/sarif-2.1.0.json",
|
|
@@ -7822,7 +7528,6 @@ function formatGithubReport(results, config) {
|
|
|
7822
7528
|
// src/reporter/markdown.ts
|
|
7823
7529
|
var MAX_FINDINGS = 50;
|
|
7824
7530
|
var SEVERITY_EMOJI = { critical: "\u{1F534}", warning: "\u{1F7E1}", info: "\u{1F535}" };
|
|
7825
|
-
var SEVERITY_RANK2 = { critical: 0, warning: 1, info: 2 };
|
|
7826
7531
|
function escapeCell(s) {
|
|
7827
7532
|
return mdEscape(s).replace(/(\\*)\|/g, (_, bs) => bs + bs + "\\|");
|
|
7828
7533
|
}
|
|
@@ -7853,7 +7558,7 @@ function flattenFindings(report) {
|
|
|
7853
7558
|
message: messageWithRecommendation(issue)
|
|
7854
7559
|
});
|
|
7855
7560
|
}
|
|
7856
|
-
return findings.map((f, index) => ({ f, index })).sort((a, b) =>
|
|
7561
|
+
return findings.map((f, index) => ({ f, index })).sort((a, b) => SEVERITY_RANK[a.f.severity] - SEVERITY_RANK[b.f.severity] || a.index - b.index).map(({ f }) => f);
|
|
7857
7562
|
}
|
|
7858
7563
|
function categoryRows(categories) {
|
|
7859
7564
|
const names = Object.keys(categories).sort();
|
|
@@ -7903,6 +7608,24 @@ function formatMarkdownReport(results, config, meta) {
|
|
|
7903
7608
|
}
|
|
7904
7609
|
|
|
7905
7610
|
// src/reporter/app-shell.ts
|
|
7611
|
+
var BAND_COLOR = {
|
|
7612
|
+
good: "#2FA968",
|
|
7613
|
+
warn: "#E8A317",
|
|
7614
|
+
poor: "#E5484D"
|
|
7615
|
+
};
|
|
7616
|
+
function scoreBand(score) {
|
|
7617
|
+
return score >= 90 ? "good" : score >= 50 ? "warn" : "poor";
|
|
7618
|
+
}
|
|
7619
|
+
function escapeHtml(s) {
|
|
7620
|
+
return s.replace(
|
|
7621
|
+
/[&<>"']/g,
|
|
7622
|
+
(c) => c === "&" ? "&" : c === "<" ? "<" : c === ">" ? ">" : c === '"' ? """ : "'"
|
|
7623
|
+
);
|
|
7624
|
+
}
|
|
7625
|
+
function safeHref(url) {
|
|
7626
|
+
const normalized = url.replace(/\s/g, "").toLowerCase();
|
|
7627
|
+
return /^https?:\/\//.test(normalized) ? url : null;
|
|
7628
|
+
}
|
|
7906
7629
|
function embedJson(value) {
|
|
7907
7630
|
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
7908
7631
|
}
|
|
@@ -8022,6 +7745,7 @@ body{background:var(--ground);color:var(--ink);font-family:var(--sans);line-heig
|
|
|
8022
7745
|
var APP_SCRIPT = `
|
|
8023
7746
|
(function(){
|
|
8024
7747
|
var BAND_COLOR = { good: '#2fa968', warn: '#e8a317', poor: '#e5484d' };
|
|
7748
|
+
var CATEGORY_NAMES = ${JSON.stringify(CATEGORY_LABEL)};
|
|
8025
7749
|
function scoreBand(score) { return score >= 90 ? 'good' : score >= 50 ? 'warn' : 'poor'; }
|
|
8026
7750
|
|
|
8027
7751
|
// Same mark as the docs site's hero wordmark (docs/public/wordmark.svg) \u2014 an inline
|
|
@@ -8368,7 +8092,7 @@ var APP_SCRIPT = `
|
|
|
8368
8092
|
}, []);
|
|
8369
8093
|
};
|
|
8370
8094
|
var catChips = Object.keys(categories).map(function (cat) {
|
|
8371
|
-
var name = cat
|
|
8095
|
+
var name = CATEGORY_NAMES[cat] || cat;
|
|
8372
8096
|
return chip(cat, name);
|
|
8373
8097
|
});
|
|
8374
8098
|
return h('div', { class: 'dv-filters', role: 'group', 'aria-label': 'Filter findings' },
|
|
@@ -8440,7 +8164,7 @@ var APP_SCRIPT = `
|
|
|
8440
8164
|
var c = s.report.categories[cat];
|
|
8441
8165
|
var band = scoreBand(c.score);
|
|
8442
8166
|
var weight = s.report.weights[cat];
|
|
8443
|
-
var name = cat
|
|
8167
|
+
var name = CATEGORY_NAMES[cat] || cat;
|
|
8444
8168
|
// keys/affectedKeys are absent on hand-built snapshots (older fixtures, tests) \u2014
|
|
8445
8169
|
// render nothing rather than "undefined of undefined". 0 affected of N keys is still
|
|
8446
8170
|
// rendered: on a real project that's the signal a thin score can't give, that the
|
|
@@ -8575,36 +8299,33 @@ function buildHtmlDocument(report, meta) {
|
|
|
8575
8299
|
function formatHtmlReport(results, config, meta) {
|
|
8576
8300
|
return buildHtmlDocument(buildJsonReport(results, config, meta), meta);
|
|
8577
8301
|
}
|
|
8578
|
-
|
|
8579
|
-
// src/reporter/html.ts
|
|
8580
|
-
var BAND_COLOR = {
|
|
8581
|
-
good: "#2FA968",
|
|
8582
|
-
warn: "#E8A317",
|
|
8583
|
-
poor: "#E5484D"
|
|
8584
|
-
};
|
|
8585
|
-
function scoreBand(score) {
|
|
8586
|
-
return score >= 90 ? "good" : score >= 50 ? "warn" : "poor";
|
|
8587
|
-
}
|
|
8588
|
-
function escapeHtml(s) {
|
|
8589
|
-
return s.replace(
|
|
8590
|
-
/[&<>"']/g,
|
|
8591
|
-
(c) => c === "&" ? "&" : c === "<" ? "<" : c === ">" ? ">" : c === '"' ? """ : "'"
|
|
8592
|
-
);
|
|
8593
|
-
}
|
|
8594
|
-
function safeHref(url) {
|
|
8595
|
-
const normalized = url.replace(/\s/g, "").toLowerCase();
|
|
8596
|
-
return /^https?:\/\//.test(normalized) ? url : null;
|
|
8597
|
-
}
|
|
8598
8302
|
export {
|
|
8599
8303
|
APP_SCRIPT,
|
|
8600
8304
|
APP_STYLE,
|
|
8601
8305
|
BAND_COLOR,
|
|
8602
8306
|
CATEGORIES,
|
|
8603
8307
|
CHILD_NODE_KEYS,
|
|
8308
|
+
IDREF_ATTRS,
|
|
8309
|
+
LANDMARK_ROLES,
|
|
8604
8310
|
ROBOTS_SOURCE_PATHS,
|
|
8605
8311
|
SITEMAP_SOURCE_PATHS,
|
|
8606
8312
|
SVELTE_CONFIG_FILES,
|
|
8607
8313
|
VITE_CONFIG_FILES,
|
|
8314
|
+
a11yAccessibleName,
|
|
8315
|
+
a11yDoctype,
|
|
8316
|
+
a11yDuplicateLandmark,
|
|
8317
|
+
a11yIdDuplication,
|
|
8318
|
+
a11yInteractiveNesting,
|
|
8319
|
+
a11yInvalidAriaValue,
|
|
8320
|
+
a11yInvalidRole,
|
|
8321
|
+
a11yLabelHasControl,
|
|
8322
|
+
a11yNoMissingIdRef,
|
|
8323
|
+
a11yPlaceholderLabelOption,
|
|
8324
|
+
a11yRequireDatetime,
|
|
8325
|
+
a11yRequiredAriaProps,
|
|
8326
|
+
a11yTopLevelLandmark,
|
|
8327
|
+
a11yUnknownAriaAttribute,
|
|
8328
|
+
a11yUseList,
|
|
8608
8329
|
allRules,
|
|
8609
8330
|
applyOverrides,
|
|
8610
8331
|
applyRuleSeverities,
|
|
@@ -8644,6 +8365,7 @@ export {
|
|
|
8644
8365
|
correctnessServerBrowserGlobal,
|
|
8645
8366
|
correctnessStalePropDerivation,
|
|
8646
8367
|
correctnessUnmutatedState,
|
|
8368
|
+
decodeFragmentId,
|
|
8647
8369
|
defaultConfig,
|
|
8648
8370
|
defaultProject,
|
|
8649
8371
|
defineConfig,
|
|
@@ -8658,8 +8380,10 @@ export {
|
|
|
8658
8380
|
findKitPathsBaseInSvelteConfig,
|
|
8659
8381
|
findKitPathsBaseInViteConfig,
|
|
8660
8382
|
findMinifyDisabled,
|
|
8383
|
+
foldOccurrences,
|
|
8661
8384
|
formatAgentReport,
|
|
8662
8385
|
formatConsoleReport,
|
|
8386
|
+
formatFailedRuleWarning,
|
|
8663
8387
|
formatGithubReport,
|
|
8664
8388
|
formatHtmlReport,
|
|
8665
8389
|
formatJsonReport,
|
|
@@ -8671,6 +8395,7 @@ export {
|
|
|
8671
8395
|
intOption,
|
|
8672
8396
|
isMentionedAnywhere,
|
|
8673
8397
|
isPenalized,
|
|
8398
|
+
isTopFragment,
|
|
8674
8399
|
lineOf,
|
|
8675
8400
|
linkRule,
|
|
8676
8401
|
listOption,
|
|
@@ -8744,7 +8469,9 @@ export {
|
|
|
8744
8469
|
settingOptions,
|
|
8745
8470
|
settingSeverity,
|
|
8746
8471
|
shouldSkipRangeCheck,
|
|
8472
|
+
splitTokens,
|
|
8747
8473
|
summarize,
|
|
8474
|
+
terminalSafe,
|
|
8748
8475
|
textFromNodes,
|
|
8749
8476
|
validateRuleOptions,
|
|
8750
8477
|
validateRuleSetting,
|