@unhead/schema-org 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +333 -170
- package/dist/index.d.ts +41 -40
- package/dist/index.mjs +318 -156
- package/package.json +6 -5
package/dist/index.cjs
CHANGED
|
@@ -1,85 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const ufo = require('ufo');
|
|
3
4
|
const unhead = require('unhead');
|
|
4
5
|
|
|
5
6
|
function defineSchemaOrgResolver(schema) {
|
|
6
7
|
return schema;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
const TRAILING_SLASH_RE = /\/$|\/\?/;
|
|
15
|
-
function hasTrailingSlash(input = "", queryParameters = false) {
|
|
16
|
-
if (!queryParameters) {
|
|
17
|
-
return input.endsWith("/");
|
|
18
|
-
}
|
|
19
|
-
return TRAILING_SLASH_RE.test(input);
|
|
20
|
-
}
|
|
21
|
-
function withoutTrailingSlash(input = "", queryParameters = false) {
|
|
22
|
-
if (!queryParameters) {
|
|
23
|
-
return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
|
|
24
|
-
}
|
|
25
|
-
if (!hasTrailingSlash(input, true)) {
|
|
26
|
-
return input || "/";
|
|
27
|
-
}
|
|
28
|
-
const [s0, ...s] = input.split("?");
|
|
29
|
-
return (s0.slice(0, -1) || "/") + (s.length > 0 ? `?${s.join("?")}` : "");
|
|
30
|
-
}
|
|
31
|
-
function withTrailingSlash(input = "", queryParameters = false) {
|
|
32
|
-
if (!queryParameters) {
|
|
33
|
-
return input.endsWith("/") ? input : input + "/";
|
|
34
|
-
}
|
|
35
|
-
if (hasTrailingSlash(input, true)) {
|
|
36
|
-
return input || "/";
|
|
37
|
-
}
|
|
38
|
-
const [s0, ...s] = input.split("?");
|
|
39
|
-
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "");
|
|
40
|
-
}
|
|
41
|
-
function hasLeadingSlash(input = "") {
|
|
42
|
-
return input.startsWith("/");
|
|
43
|
-
}
|
|
44
|
-
function withoutLeadingSlash(input = "") {
|
|
45
|
-
return (hasLeadingSlash(input) ? input.slice(1) : input) || "/";
|
|
46
|
-
}
|
|
47
|
-
function withBase(input, base) {
|
|
48
|
-
if (isEmptyURL(base) || hasProtocol(input)) {
|
|
49
|
-
return input;
|
|
50
|
-
}
|
|
51
|
-
const _base = withoutTrailingSlash(base);
|
|
52
|
-
if (input.startsWith(_base)) {
|
|
53
|
-
return input;
|
|
54
|
-
}
|
|
55
|
-
return joinURL(_base, input);
|
|
56
|
-
}
|
|
57
|
-
function isEmptyURL(url) {
|
|
58
|
-
return !url || url === "/";
|
|
59
|
-
}
|
|
60
|
-
function isNonEmptyURL(url) {
|
|
61
|
-
return url && url !== "/";
|
|
62
|
-
}
|
|
63
|
-
function joinURL(base, ...input) {
|
|
64
|
-
let url = base || "";
|
|
65
|
-
for (const index of input.filter((url2) => isNonEmptyURL(url2))) {
|
|
66
|
-
url = url ? withTrailingSlash(url) + withoutLeadingSlash(index) : index;
|
|
67
|
-
}
|
|
68
|
-
return url;
|
|
10
|
+
function idReference(node) {
|
|
11
|
+
return {
|
|
12
|
+
"@id": typeof node !== "string" ? node["@id"] : node
|
|
13
|
+
};
|
|
69
14
|
}
|
|
70
|
-
|
|
71
|
-
const idReference = (node) => ({
|
|
72
|
-
"@id": typeof node !== "string" ? node["@id"] : node
|
|
73
|
-
});
|
|
74
|
-
const resolvableDateToDate = (val) => {
|
|
15
|
+
function resolvableDateToDate(val) {
|
|
75
16
|
try {
|
|
76
17
|
const date = val instanceof Date ? val : new Date(Date.parse(val));
|
|
77
18
|
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
|
|
78
19
|
} catch (e) {
|
|
79
20
|
}
|
|
80
21
|
return typeof val === "string" ? val : val.toString();
|
|
81
|
-
}
|
|
82
|
-
|
|
22
|
+
}
|
|
23
|
+
function resolvableDateToIso(val) {
|
|
83
24
|
if (!val)
|
|
84
25
|
return val;
|
|
85
26
|
try {
|
|
@@ -90,29 +31,31 @@ const resolvableDateToIso = (val) => {
|
|
|
90
31
|
} catch (e) {
|
|
91
32
|
}
|
|
92
33
|
return typeof val === "string" ? val : val.toString();
|
|
93
|
-
}
|
|
34
|
+
}
|
|
94
35
|
const IdentityId = "#identity";
|
|
95
|
-
|
|
36
|
+
function setIfEmpty(node, field, value) {
|
|
96
37
|
if (!node?.[field] && value)
|
|
97
38
|
node[field] = value;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
39
|
+
}
|
|
40
|
+
function asArray(input) {
|
|
41
|
+
return Array.isArray(input) ? input : [input];
|
|
42
|
+
}
|
|
43
|
+
function dedupeMerge(node, field, value) {
|
|
101
44
|
const dedupeMerge2 = [];
|
|
102
45
|
const input = asArray(node[field]);
|
|
103
46
|
dedupeMerge2.push(...input);
|
|
104
47
|
const data = new Set(dedupeMerge2);
|
|
105
48
|
data.add(value);
|
|
106
49
|
node[field] = [...data.values()].filter(Boolean);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (hasProtocol(id))
|
|
50
|
+
}
|
|
51
|
+
function prefixId(url, id) {
|
|
52
|
+
if (ufo.hasProtocol(id))
|
|
110
53
|
return url;
|
|
111
54
|
if (!id.startsWith("#"))
|
|
112
55
|
id = `#${id}`;
|
|
113
|
-
return joinURL(url, id);
|
|
114
|
-
}
|
|
115
|
-
|
|
56
|
+
return ufo.joinURL(url, id);
|
|
57
|
+
}
|
|
58
|
+
function trimLength(val, length) {
|
|
116
59
|
if (!val)
|
|
117
60
|
return val;
|
|
118
61
|
if (val.length > length) {
|
|
@@ -120,8 +63,8 @@ const trimLength = (val, length) => {
|
|
|
120
63
|
return trimmedString.substring(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")));
|
|
121
64
|
}
|
|
122
65
|
return val;
|
|
123
|
-
}
|
|
124
|
-
|
|
66
|
+
}
|
|
67
|
+
function resolveDefaultType(node, defaultType) {
|
|
125
68
|
const val = node["@type"];
|
|
126
69
|
if (val === defaultType)
|
|
127
70
|
return;
|
|
@@ -130,18 +73,18 @@ const resolveDefaultType = (node, defaultType) => {
|
|
|
130
73
|
...asArray(val)
|
|
131
74
|
]);
|
|
132
75
|
node["@type"] = types.size === 1 ? val : [...types.values()];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (!urlOrPath || hasProtocol(urlOrPath) || !urlOrPath.startsWith("/") && !urlOrPath.startsWith("#"))
|
|
76
|
+
}
|
|
77
|
+
function resolveWithBase(base, urlOrPath) {
|
|
78
|
+
if (!urlOrPath || ufo.hasProtocol(urlOrPath) || !urlOrPath.startsWith("/") && !urlOrPath.startsWith("#"))
|
|
136
79
|
return urlOrPath;
|
|
137
|
-
return withBase(urlOrPath, base);
|
|
138
|
-
}
|
|
139
|
-
|
|
80
|
+
return ufo.withBase(urlOrPath, base);
|
|
81
|
+
}
|
|
82
|
+
function resolveAsGraphKey(key) {
|
|
140
83
|
if (!key)
|
|
141
84
|
return key;
|
|
142
85
|
return key.substring(key.lastIndexOf("#"));
|
|
143
|
-
}
|
|
144
|
-
|
|
86
|
+
}
|
|
87
|
+
function stripEmptyProperties(obj) {
|
|
145
88
|
Object.keys(obj).forEach((k) => {
|
|
146
89
|
if (obj[k] && typeof obj[k] === "object") {
|
|
147
90
|
if (obj[k].__v_isReadonly || obj[k].__v_isRef)
|
|
@@ -153,7 +96,7 @@ const stripEmptyProperties = (obj) => {
|
|
|
153
96
|
delete obj[k];
|
|
154
97
|
});
|
|
155
98
|
return obj;
|
|
156
|
-
}
|
|
99
|
+
}
|
|
157
100
|
function hashCode(s) {
|
|
158
101
|
let h = 9;
|
|
159
102
|
for (let i = 0; i < s.length; )
|
|
@@ -176,11 +119,11 @@ const offerResolver = defineSchemaOrgResolver({
|
|
|
176
119
|
},
|
|
177
120
|
resolve(node, ctx) {
|
|
178
121
|
setIfEmpty(node, "priceCurrency", ctx.meta.currency);
|
|
179
|
-
setIfEmpty(node, "priceValidUntil", new Date(Date.UTC(new Date().getFullYear() + 1, 12, -1, 0, 0, 0)));
|
|
122
|
+
setIfEmpty(node, "priceValidUntil", new Date(Date.UTC((/* @__PURE__ */ new Date()).getFullYear() + 1, 12, -1, 0, 0, 0)));
|
|
180
123
|
if (node.url)
|
|
181
124
|
resolveWithBase(ctx.meta.host, node.url);
|
|
182
125
|
if (node.availability)
|
|
183
|
-
node.availability = withBase(node.availability, "https://schema.org/");
|
|
126
|
+
node.availability = ufo.withBase(node.availability, "https://schema.org/");
|
|
184
127
|
if (node.priceValidUntil)
|
|
185
128
|
node.priceValidUntil = resolvableDateToIso(node.priceValidUntil);
|
|
186
129
|
return node;
|
|
@@ -421,7 +364,7 @@ const readActionResolver = defineSchemaOrgResolver({
|
|
|
421
364
|
const PrimaryWebPageId = "#webpage";
|
|
422
365
|
const webPageResolver = defineSchemaOrgResolver({
|
|
423
366
|
defaults({ meta }) {
|
|
424
|
-
const endPath = withoutTrailingSlash(meta.url.substring(meta.url.lastIndexOf("/") + 1));
|
|
367
|
+
const endPath = ufo.withoutTrailingSlash(meta.url.substring(meta.url.lastIndexOf("/") + 1));
|
|
425
368
|
let type = "WebPage";
|
|
426
369
|
switch (endPath) {
|
|
427
370
|
case "about":
|
|
@@ -556,7 +499,7 @@ const bookEditionResolver = defineSchemaOrgResolver({
|
|
|
556
499
|
],
|
|
557
500
|
resolve(node, ctx) {
|
|
558
501
|
if (node.bookFormat)
|
|
559
|
-
node.bookFormat = withBase(node.bookFormat, "https://schema.org/");
|
|
502
|
+
node.bookFormat = ufo.withBase(node.bookFormat, "https://schema.org/");
|
|
560
503
|
if (node.datePublished)
|
|
561
504
|
node.datePublished = resolvableDateToDate(node.datePublished);
|
|
562
505
|
node.author = resolveRelation(node.author, ctx);
|
|
@@ -584,7 +527,7 @@ const bookResolver = defineSchemaOrgResolver({
|
|
|
584
527
|
node.workExample = resolveRelation(node.workExample, ctx, bookEditionResolver);
|
|
585
528
|
node.author = resolveRelation(node.author, ctx);
|
|
586
529
|
if (node.url)
|
|
587
|
-
withBase(node.url, ctx.meta.host);
|
|
530
|
+
ufo.withBase(node.url, ctx.meta.host);
|
|
588
531
|
return node;
|
|
589
532
|
},
|
|
590
533
|
resolveRootNode(node, { find }) {
|
|
@@ -681,9 +624,9 @@ const eventResolver = defineSchemaOrgResolver({
|
|
|
681
624
|
});
|
|
682
625
|
node.offers = resolveRelation(node.offers, ctx, offerResolver);
|
|
683
626
|
if (node.eventAttendanceMode)
|
|
684
|
-
node.eventAttendanceMode = withBase(node.eventAttendanceMode, "https://schema.org/");
|
|
627
|
+
node.eventAttendanceMode = ufo.withBase(node.eventAttendanceMode, "https://schema.org/");
|
|
685
628
|
if (node.eventStatus)
|
|
686
|
-
node.eventStatus = withBase(node.eventStatus, "https://schema.org/");
|
|
629
|
+
node.eventStatus = ufo.withBase(node.eventStatus, "https://schema.org/");
|
|
687
630
|
const isOnline = node.eventStatus === "https://schema.org/EventMovedOnline";
|
|
688
631
|
const dates = ["startDate", "previousStartDate", "endDate"];
|
|
689
632
|
dates.forEach((date) => {
|
|
@@ -970,6 +913,9 @@ function createHasher(options) {
|
|
|
970
913
|
return this["_" + type](value);
|
|
971
914
|
},
|
|
972
915
|
_object(object) {
|
|
916
|
+
if (object && typeof object.toJSON === "function") {
|
|
917
|
+
return this._object(object.toJSON());
|
|
918
|
+
}
|
|
973
919
|
const pattern = /\[object (.*)]/i;
|
|
974
920
|
const objString = Object.prototype.toString.call(object);
|
|
975
921
|
const _objType = pattern.exec(objString);
|
|
@@ -987,10 +933,8 @@ function createHasher(options) {
|
|
|
987
933
|
if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
|
|
988
934
|
if (this["_" + objType]) {
|
|
989
935
|
this["_" + objType](object);
|
|
990
|
-
} else if (options.ignoreUnknown) {
|
|
991
|
-
|
|
992
|
-
} else {
|
|
993
|
-
throw new Error('Unknown object type "' + objType + '"');
|
|
936
|
+
} else if (!options.ignoreUnknown) {
|
|
937
|
+
this._unkown(object, objType);
|
|
994
938
|
}
|
|
995
939
|
} else {
|
|
996
940
|
let keys = Object.keys(object);
|
|
@@ -1042,6 +986,20 @@ function createHasher(options) {
|
|
|
1042
986
|
_symbol(sym) {
|
|
1043
987
|
return write("symbol:" + sym.toString());
|
|
1044
988
|
},
|
|
989
|
+
_unkown(value, type) {
|
|
990
|
+
write(type);
|
|
991
|
+
if (!value) {
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
write(":");
|
|
995
|
+
if (value && typeof value.entries === "function") {
|
|
996
|
+
return this._array(
|
|
997
|
+
Array.from(value.entries()),
|
|
998
|
+
true
|
|
999
|
+
/* ordered */
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
},
|
|
1045
1003
|
_error(err) {
|
|
1046
1004
|
return write("error:" + err.toString());
|
|
1047
1005
|
},
|
|
@@ -1142,7 +1100,9 @@ function createHasher(options) {
|
|
|
1142
1100
|
if (options.ignoreUnknown) {
|
|
1143
1101
|
return write("[blob]");
|
|
1144
1102
|
}
|
|
1145
|
-
throw new Error(
|
|
1103
|
+
throw new Error(
|
|
1104
|
+
'Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n'
|
|
1105
|
+
);
|
|
1146
1106
|
},
|
|
1147
1107
|
_domwindow() {
|
|
1148
1108
|
return write("domwindow");
|
|
@@ -1150,6 +1110,7 @@ function createHasher(options) {
|
|
|
1150
1110
|
_bigint(number) {
|
|
1151
1111
|
return write("bigint:" + number.toString());
|
|
1152
1112
|
},
|
|
1113
|
+
/* Node.js standard native objects */
|
|
1153
1114
|
_process() {
|
|
1154
1115
|
return write("process");
|
|
1155
1116
|
},
|
|
@@ -1247,10 +1208,7 @@ const Hex = {
|
|
|
1247
1208
|
const hexChars = [];
|
|
1248
1209
|
for (let i = 0; i < wordArray.sigBytes; i++) {
|
|
1249
1210
|
const bite = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
|
|
1250
|
-
hexChars.push(
|
|
1251
|
-
(bite >>> 4).toString(16),
|
|
1252
|
-
(bite & 15).toString(16)
|
|
1253
|
-
);
|
|
1211
|
+
hexChars.push((bite >>> 4).toString(16), (bite & 15).toString(16));
|
|
1254
1212
|
}
|
|
1255
1213
|
return hexChars.join("");
|
|
1256
1214
|
}
|
|
@@ -1303,6 +1261,7 @@ class BufferedBlockAlgorithm {
|
|
|
1303
1261
|
this._data.concat(data);
|
|
1304
1262
|
this._nDataBytes += data.sigBytes;
|
|
1305
1263
|
}
|
|
1264
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1306
1265
|
_doProcessBlock(_dataWords, _offset) {
|
|
1307
1266
|
}
|
|
1308
1267
|
_process(doFlush) {
|
|
@@ -1338,8 +1297,82 @@ class Hasher extends BufferedBlockAlgorithm {
|
|
|
1338
1297
|
}
|
|
1339
1298
|
}
|
|
1340
1299
|
|
|
1341
|
-
const H = [
|
|
1342
|
-
|
|
1300
|
+
const H = [
|
|
1301
|
+
1779033703,
|
|
1302
|
+
-1150833019,
|
|
1303
|
+
1013904242,
|
|
1304
|
+
-1521486534,
|
|
1305
|
+
1359893119,
|
|
1306
|
+
-1694144372,
|
|
1307
|
+
528734635,
|
|
1308
|
+
1541459225
|
|
1309
|
+
];
|
|
1310
|
+
const K = [
|
|
1311
|
+
1116352408,
|
|
1312
|
+
1899447441,
|
|
1313
|
+
-1245643825,
|
|
1314
|
+
-373957723,
|
|
1315
|
+
961987163,
|
|
1316
|
+
1508970993,
|
|
1317
|
+
-1841331548,
|
|
1318
|
+
-1424204075,
|
|
1319
|
+
-670586216,
|
|
1320
|
+
310598401,
|
|
1321
|
+
607225278,
|
|
1322
|
+
1426881987,
|
|
1323
|
+
1925078388,
|
|
1324
|
+
-2132889090,
|
|
1325
|
+
-1680079193,
|
|
1326
|
+
-1046744716,
|
|
1327
|
+
-459576895,
|
|
1328
|
+
-272742522,
|
|
1329
|
+
264347078,
|
|
1330
|
+
604807628,
|
|
1331
|
+
770255983,
|
|
1332
|
+
1249150122,
|
|
1333
|
+
1555081692,
|
|
1334
|
+
1996064986,
|
|
1335
|
+
-1740746414,
|
|
1336
|
+
-1473132947,
|
|
1337
|
+
-1341970488,
|
|
1338
|
+
-1084653625,
|
|
1339
|
+
-958395405,
|
|
1340
|
+
-710438585,
|
|
1341
|
+
113926993,
|
|
1342
|
+
338241895,
|
|
1343
|
+
666307205,
|
|
1344
|
+
773529912,
|
|
1345
|
+
1294757372,
|
|
1346
|
+
1396182291,
|
|
1347
|
+
1695183700,
|
|
1348
|
+
1986661051,
|
|
1349
|
+
-2117940946,
|
|
1350
|
+
-1838011259,
|
|
1351
|
+
-1564481375,
|
|
1352
|
+
-1474664885,
|
|
1353
|
+
-1035236496,
|
|
1354
|
+
-949202525,
|
|
1355
|
+
-778901479,
|
|
1356
|
+
-694614492,
|
|
1357
|
+
-200395387,
|
|
1358
|
+
275423344,
|
|
1359
|
+
430227734,
|
|
1360
|
+
506948616,
|
|
1361
|
+
659060556,
|
|
1362
|
+
883997877,
|
|
1363
|
+
958139571,
|
|
1364
|
+
1322822218,
|
|
1365
|
+
1537002063,
|
|
1366
|
+
1747873779,
|
|
1367
|
+
1955562222,
|
|
1368
|
+
2024104815,
|
|
1369
|
+
-2067236844,
|
|
1370
|
+
-1933114872,
|
|
1371
|
+
-1866530822,
|
|
1372
|
+
-1538233109,
|
|
1373
|
+
-1090935817,
|
|
1374
|
+
-965641998
|
|
1375
|
+
];
|
|
1343
1376
|
const W = [];
|
|
1344
1377
|
class SHA256 extends Hasher {
|
|
1345
1378
|
constructor() {
|
|
@@ -1399,7 +1432,9 @@ class SHA256 extends Hasher {
|
|
|
1399
1432
|
const nBitsTotal = this._nDataBytes * 8;
|
|
1400
1433
|
const nBitsLeft = this._data.sigBytes * 8;
|
|
1401
1434
|
this._data.words[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32;
|
|
1402
|
-
this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math.floor(
|
|
1435
|
+
this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math.floor(
|
|
1436
|
+
nBitsTotal / 4294967296
|
|
1437
|
+
);
|
|
1403
1438
|
this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal;
|
|
1404
1439
|
this._data.sigBytes = this._data.words.length * 4;
|
|
1405
1440
|
this._process();
|
|
@@ -1603,7 +1638,7 @@ const resolver = {
|
|
|
1603
1638
|
loadResolver: loadResolver
|
|
1604
1639
|
};
|
|
1605
1640
|
|
|
1606
|
-
|
|
1641
|
+
function resolveMeta(meta) {
|
|
1607
1642
|
if (!meta.host && meta.canonicalHost)
|
|
1608
1643
|
meta.host = meta.canonicalHost;
|
|
1609
1644
|
if (!meta.tagPosition && meta.position)
|
|
@@ -1619,12 +1654,12 @@ const resolveMeta = (meta) => {
|
|
|
1619
1654
|
if (!meta.url && meta.canonicalUrl)
|
|
1620
1655
|
meta.url = meta.canonicalUrl;
|
|
1621
1656
|
if (meta.path !== "/") {
|
|
1622
|
-
if (meta.trailingSlash && !hasTrailingSlash(meta.path))
|
|
1623
|
-
meta.path = withTrailingSlash(meta.path);
|
|
1624
|
-
else if (!meta.trailingSlash && hasTrailingSlash(meta.path))
|
|
1625
|
-
meta.path = withoutTrailingSlash(meta.path);
|
|
1657
|
+
if (meta.trailingSlash && !ufo.hasTrailingSlash(meta.path))
|
|
1658
|
+
meta.path = ufo.withTrailingSlash(meta.path);
|
|
1659
|
+
else if (!meta.trailingSlash && ufo.hasTrailingSlash(meta.path))
|
|
1660
|
+
meta.path = ufo.withoutTrailingSlash(meta.path);
|
|
1626
1661
|
}
|
|
1627
|
-
meta.url = joinURL(meta.host, meta.path);
|
|
1662
|
+
meta.url = ufo.joinURL(meta.host, meta.path);
|
|
1628
1663
|
return {
|
|
1629
1664
|
...meta,
|
|
1630
1665
|
host: meta.host,
|
|
@@ -1637,8 +1672,8 @@ const resolveMeta = (meta) => {
|
|
|
1637
1672
|
datePublished: meta.datePublished,
|
|
1638
1673
|
dateModified: meta.dateModified
|
|
1639
1674
|
};
|
|
1640
|
-
}
|
|
1641
|
-
|
|
1675
|
+
}
|
|
1676
|
+
function resolveNode(node, ctx, resolver) {
|
|
1642
1677
|
if (resolver?.cast)
|
|
1643
1678
|
node = resolver.cast(node, ctx);
|
|
1644
1679
|
if (resolver?.defaults) {
|
|
@@ -1665,8 +1700,8 @@ const resolveNode = (node, ctx, resolver) => {
|
|
|
1665
1700
|
}
|
|
1666
1701
|
stripEmptyProperties(node);
|
|
1667
1702
|
return node;
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1703
|
+
}
|
|
1704
|
+
function resolveNodeId(node, ctx, resolver, resolveAsRoot = false) {
|
|
1670
1705
|
const prefix = Array.isArray(resolver.idPrefix) ? resolver.idPrefix[0] : resolver.idPrefix;
|
|
1671
1706
|
if (!prefix)
|
|
1672
1707
|
return node;
|
|
@@ -1692,7 +1727,7 @@ const resolveNodeId = (node, ctx, resolver, resolveAsRoot = false) => {
|
|
|
1692
1727
|
node["@id"] = prefixId(ctx.meta[prefix], `#/schema/${alias}/${hashCode(JSON.stringify(hashNodeData))}`);
|
|
1693
1728
|
}
|
|
1694
1729
|
return node;
|
|
1695
|
-
}
|
|
1730
|
+
}
|
|
1696
1731
|
function resolveRelation(input, ctx, fallbackResolver, options = {}) {
|
|
1697
1732
|
if (!input)
|
|
1698
1733
|
return input;
|
|
@@ -1726,14 +1761,70 @@ function resolveRelation(input, ctx, fallbackResolver, options = {}) {
|
|
|
1726
1761
|
return ids;
|
|
1727
1762
|
}
|
|
1728
1763
|
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
}
|
|
1736
|
-
const
|
|
1764
|
+
function isObject(value) {
|
|
1765
|
+
return value !== null && typeof value === "object";
|
|
1766
|
+
}
|
|
1767
|
+
function _defu(baseObject, defaults, namespace = ".", merger) {
|
|
1768
|
+
if (!isObject(defaults)) {
|
|
1769
|
+
return _defu(baseObject, {}, namespace, merger);
|
|
1770
|
+
}
|
|
1771
|
+
const object = Object.assign({}, defaults);
|
|
1772
|
+
for (const key in baseObject) {
|
|
1773
|
+
if (key === "__proto__" || key === "constructor") {
|
|
1774
|
+
continue;
|
|
1775
|
+
}
|
|
1776
|
+
const value = baseObject[key];
|
|
1777
|
+
if (value === null || value === void 0) {
|
|
1778
|
+
continue;
|
|
1779
|
+
}
|
|
1780
|
+
if (merger && merger(object, key, value, namespace)) {
|
|
1781
|
+
continue;
|
|
1782
|
+
}
|
|
1783
|
+
if (Array.isArray(value) && Array.isArray(object[key])) {
|
|
1784
|
+
object[key] = [...value, ...object[key]];
|
|
1785
|
+
} else if (isObject(value) && isObject(object[key])) {
|
|
1786
|
+
object[key] = _defu(
|
|
1787
|
+
value,
|
|
1788
|
+
object[key],
|
|
1789
|
+
(namespace ? `${namespace}.` : "") + key.toString(),
|
|
1790
|
+
merger
|
|
1791
|
+
);
|
|
1792
|
+
} else {
|
|
1793
|
+
object[key] = value;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
return object;
|
|
1797
|
+
}
|
|
1798
|
+
function createDefu(merger) {
|
|
1799
|
+
return (...arguments_) => (
|
|
1800
|
+
// eslint-disable-next-line unicorn/no-array-reduce
|
|
1801
|
+
arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
const defu = createDefu();
|
|
1805
|
+
|
|
1806
|
+
function groupBy(array, predicate) {
|
|
1807
|
+
return array.reduce((acc, value, index, array2) => {
|
|
1808
|
+
const key = predicate(value, index, array2);
|
|
1809
|
+
if (!acc[key])
|
|
1810
|
+
acc[key] = [];
|
|
1811
|
+
acc[key].push(value);
|
|
1812
|
+
return acc;
|
|
1813
|
+
}, {});
|
|
1814
|
+
}
|
|
1815
|
+
function dedupeNodes(nodes) {
|
|
1816
|
+
const dedupedNodes = {};
|
|
1817
|
+
for (const key of nodes.keys()) {
|
|
1818
|
+
const n = nodes[key];
|
|
1819
|
+
const nodeKey = resolveAsGraphKey(n["@id"] || hash(n));
|
|
1820
|
+
if (dedupedNodes[nodeKey])
|
|
1821
|
+
dedupedNodes[nodeKey] = defu(nodes[key], dedupedNodes[nodeKey]);
|
|
1822
|
+
else
|
|
1823
|
+
dedupedNodes[nodeKey] = nodes[key];
|
|
1824
|
+
}
|
|
1825
|
+
return Object.values(dedupedNodes);
|
|
1826
|
+
}
|
|
1827
|
+
function normaliseNodes(nodes) {
|
|
1737
1828
|
const sortedNodeKeys = nodes.keys();
|
|
1738
1829
|
const dedupedNodes = {};
|
|
1739
1830
|
for (const key of sortedNodeKeys) {
|
|
@@ -1751,15 +1842,17 @@ const dedupeNodes = (nodes) => {
|
|
|
1751
1842
|
...(groupedKeys.primitives || []).sort(),
|
|
1752
1843
|
...(groupedKeys.relations || []).sort()
|
|
1753
1844
|
];
|
|
1754
|
-
|
|
1845
|
+
let newNode = {};
|
|
1755
1846
|
for (const key2 of keys)
|
|
1756
1847
|
newNode[key2] = n[key2];
|
|
1848
|
+
if (dedupedNodes[nodeKey])
|
|
1849
|
+
newNode = defu(newNode, dedupedNodes[nodeKey]);
|
|
1757
1850
|
dedupedNodes[nodeKey] = newNode;
|
|
1758
1851
|
}
|
|
1759
1852
|
return Object.values(dedupedNodes);
|
|
1760
|
-
}
|
|
1853
|
+
}
|
|
1761
1854
|
|
|
1762
|
-
|
|
1855
|
+
function createSchemaOrgGraph() {
|
|
1763
1856
|
const ctx = {
|
|
1764
1857
|
find(id) {
|
|
1765
1858
|
const key = resolveAsGraphKey(id);
|
|
@@ -1781,6 +1874,7 @@ const createSchemaOrgGraph = () => {
|
|
|
1781
1874
|
}
|
|
1782
1875
|
ctx.nodes[key] = node;
|
|
1783
1876
|
});
|
|
1877
|
+
ctx.nodes = dedupeNodes(ctx.nodes);
|
|
1784
1878
|
ctx.nodes.forEach((node) => {
|
|
1785
1879
|
if (node.image && typeof node.image === "string") {
|
|
1786
1880
|
node.image = resolveRelation(node.image, ctx, imageResolver, {
|
|
@@ -1791,13 +1885,13 @@ const createSchemaOrgGraph = () => {
|
|
|
1791
1885
|
node._resolver.resolveRootNode(node, ctx);
|
|
1792
1886
|
delete node._resolver;
|
|
1793
1887
|
});
|
|
1794
|
-
return
|
|
1888
|
+
return normaliseNodes(ctx.nodes);
|
|
1795
1889
|
},
|
|
1796
1890
|
nodes: [],
|
|
1797
1891
|
meta: {}
|
|
1798
1892
|
};
|
|
1799
1893
|
return ctx;
|
|
1800
|
-
}
|
|
1894
|
+
}
|
|
1801
1895
|
|
|
1802
1896
|
function SchemaOrgUnheadPlugin(config, meta) {
|
|
1803
1897
|
config = resolveMeta({ ...config });
|
|
@@ -1822,7 +1916,7 @@ function SchemaOrgUnheadPlugin(config, meta) {
|
|
|
1822
1916
|
tag.tagPosition = config.tagPosition === "head" ? "head" : "bodyClose";
|
|
1823
1917
|
}
|
|
1824
1918
|
if (tag.tag === "title")
|
|
1825
|
-
resolvedMeta.title = tag.
|
|
1919
|
+
resolvedMeta.title = tag.textContent;
|
|
1826
1920
|
else if (tag.tag === "meta" && tag.props.name === "description")
|
|
1827
1921
|
resolvedMeta.description = tag.props.content;
|
|
1828
1922
|
else if (tag.tag === "link" && tag.props.rel === "canonical")
|
|
@@ -1833,7 +1927,7 @@ function SchemaOrgUnheadPlugin(config, meta) {
|
|
|
1833
1927
|
"tags:resolve": async function(ctx) {
|
|
1834
1928
|
for (const tag of ctx.tags) {
|
|
1835
1929
|
if (tag.tag === "script" && tag.key === "schema-org-graph") {
|
|
1836
|
-
tag.
|
|
1930
|
+
tag.innerHTML = JSON.stringify({
|
|
1837
1931
|
"@context": "https://schema.org",
|
|
1838
1932
|
"@graph": graph.resolveGraph({ ...config, ...resolvedMeta, ...await meta() })
|
|
1839
1933
|
}, null, 2);
|
|
@@ -1845,46 +1939,114 @@ function SchemaOrgUnheadPlugin(config, meta) {
|
|
|
1845
1939
|
};
|
|
1846
1940
|
}
|
|
1847
1941
|
|
|
1848
|
-
|
|
1942
|
+
function provideResolver(input, resolver) {
|
|
1849
1943
|
if (!input)
|
|
1850
1944
|
input = {};
|
|
1851
1945
|
input._resolver = resolver;
|
|
1852
1946
|
return input;
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1947
|
+
}
|
|
1948
|
+
function defineAddress(input) {
|
|
1949
|
+
return provideResolver(input, "address");
|
|
1950
|
+
}
|
|
1951
|
+
function defineAggregateOffer(input) {
|
|
1952
|
+
return provideResolver(input, "aggregateOffer");
|
|
1953
|
+
}
|
|
1954
|
+
function defineAggregateRating(input) {
|
|
1955
|
+
return provideResolver(input, "aggregateRating");
|
|
1956
|
+
}
|
|
1957
|
+
function defineArticle(input) {
|
|
1958
|
+
return provideResolver(input, "article");
|
|
1959
|
+
}
|
|
1960
|
+
function defineBreadcrumb(input) {
|
|
1961
|
+
return provideResolver(input, "breadcrumb");
|
|
1962
|
+
}
|
|
1963
|
+
function defineComment(input) {
|
|
1964
|
+
return provideResolver(input, "comment");
|
|
1965
|
+
}
|
|
1966
|
+
function defineEvent(input) {
|
|
1967
|
+
return provideResolver(input, "event");
|
|
1968
|
+
}
|
|
1969
|
+
function defineVirtualLocation(input) {
|
|
1970
|
+
return provideResolver(input, "virtualLocation");
|
|
1971
|
+
}
|
|
1972
|
+
function definePlace(input) {
|
|
1973
|
+
return provideResolver(input, "place");
|
|
1974
|
+
}
|
|
1975
|
+
function defineHowTo(input) {
|
|
1976
|
+
return provideResolver(input, "howTo");
|
|
1977
|
+
}
|
|
1978
|
+
function defineHowToStep(input) {
|
|
1979
|
+
return provideResolver(input, "howToStep");
|
|
1980
|
+
}
|
|
1981
|
+
function defineImage(input) {
|
|
1982
|
+
return provideResolver(input, "image");
|
|
1983
|
+
}
|
|
1984
|
+
function defineJobPosting(input) {
|
|
1985
|
+
return provideResolver(input, "jobPosting");
|
|
1986
|
+
}
|
|
1987
|
+
function defineLocalBusiness(input) {
|
|
1988
|
+
return provideResolver(input, "localBusiness");
|
|
1989
|
+
}
|
|
1990
|
+
function defineOffer(input) {
|
|
1991
|
+
return provideResolver(input, "offer");
|
|
1992
|
+
}
|
|
1993
|
+
function defineOpeningHours(input) {
|
|
1994
|
+
return provideResolver(input, "openingHours");
|
|
1995
|
+
}
|
|
1996
|
+
function defineOrganization(input) {
|
|
1997
|
+
return provideResolver(input, "organization");
|
|
1998
|
+
}
|
|
1999
|
+
function definePerson(input) {
|
|
2000
|
+
return provideResolver(input, "person");
|
|
2001
|
+
}
|
|
2002
|
+
function defineProduct(input) {
|
|
2003
|
+
return provideResolver(input, "product");
|
|
2004
|
+
}
|
|
2005
|
+
function defineQuestion(input) {
|
|
2006
|
+
return provideResolver(input, "question");
|
|
2007
|
+
}
|
|
2008
|
+
function defineRecipe(input) {
|
|
2009
|
+
return provideResolver(input, "recipe");
|
|
2010
|
+
}
|
|
2011
|
+
function defineReview(input) {
|
|
2012
|
+
return provideResolver(input, "review");
|
|
2013
|
+
}
|
|
2014
|
+
function defineVideo(input) {
|
|
2015
|
+
return provideResolver(input, "video");
|
|
2016
|
+
}
|
|
2017
|
+
function defineWebPage(input) {
|
|
2018
|
+
return provideResolver(input, "webPage");
|
|
2019
|
+
}
|
|
2020
|
+
function defineWebSite(input) {
|
|
2021
|
+
return provideResolver(input, "webSite");
|
|
2022
|
+
}
|
|
2023
|
+
function defineBook(input) {
|
|
2024
|
+
return provideResolver(input, "book");
|
|
2025
|
+
}
|
|
2026
|
+
function defineCourse(input) {
|
|
2027
|
+
return provideResolver(input, "course");
|
|
2028
|
+
}
|
|
2029
|
+
function defineItemList(input) {
|
|
2030
|
+
return provideResolver(input, "itemList");
|
|
2031
|
+
}
|
|
2032
|
+
function defineListItem(input) {
|
|
2033
|
+
return provideResolver(input, "listItem");
|
|
2034
|
+
}
|
|
2035
|
+
function defineMovie(input) {
|
|
2036
|
+
return provideResolver(input, "movie");
|
|
2037
|
+
}
|
|
2038
|
+
function defineSearchAction(input) {
|
|
2039
|
+
return provideResolver(input, "searchAction");
|
|
2040
|
+
}
|
|
2041
|
+
function defineReadAction(input) {
|
|
2042
|
+
return provideResolver(input, "readAction");
|
|
2043
|
+
}
|
|
2044
|
+
function defineSoftwareApp(input) {
|
|
2045
|
+
return provideResolver(input, "softwareApp");
|
|
2046
|
+
}
|
|
2047
|
+
function defineBookEdition(input) {
|
|
2048
|
+
return provideResolver(input, "bookEdition");
|
|
2049
|
+
}
|
|
1888
2050
|
function useSchemaOrg(input) {
|
|
1889
2051
|
return unhead.useHead({
|
|
1890
2052
|
script: [
|
|
@@ -1963,6 +2125,7 @@ exports.jobPostingResolver = jobPostingResolver;
|
|
|
1963
2125
|
exports.listItemResolver = listItemResolver;
|
|
1964
2126
|
exports.localBusinessResolver = localBusinessResolver;
|
|
1965
2127
|
exports.movieResolver = movieResolver;
|
|
2128
|
+
exports.normaliseNodes = normaliseNodes;
|
|
1966
2129
|
exports.offerResolver = offerResolver;
|
|
1967
2130
|
exports.openingHoursResolver = openingHoursResolver;
|
|
1968
2131
|
exports.organizationResolver = organizationResolver;
|