@unhead/schema-org 0.5.0 → 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 CHANGED
@@ -1,92 +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
- const PROTOCOL_STRICT_REGEX = /^\w{2,}:([/\\]{1,2})/;
10
- const PROTOCOL_REGEX = /^\w{2,}:([/\\]{2})?/;
11
- const PROTOCOL_RELATIVE_REGEX = /^[/\\]{2}[^/\\]+/;
12
- function hasProtocol(inputString, opts = {}) {
13
- if (typeof opts === "boolean") {
14
- opts = { acceptRelative: opts };
15
- }
16
- if (opts.strict) {
17
- return PROTOCOL_STRICT_REGEX.test(inputString);
18
- }
19
- return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
20
- }
21
- const TRAILING_SLASH_RE = /\/$|\/\?/;
22
- function hasTrailingSlash(input = "", queryParameters = false) {
23
- if (!queryParameters) {
24
- return input.endsWith("/");
25
- }
26
- return TRAILING_SLASH_RE.test(input);
27
- }
28
- function withoutTrailingSlash(input = "", queryParameters = false) {
29
- if (!queryParameters) {
30
- return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
31
- }
32
- if (!hasTrailingSlash(input, true)) {
33
- return input || "/";
34
- }
35
- const [s0, ...s] = input.split("?");
36
- return (s0.slice(0, -1) || "/") + (s.length > 0 ? `?${s.join("?")}` : "");
37
- }
38
- function withTrailingSlash(input = "", queryParameters = false) {
39
- if (!queryParameters) {
40
- return input.endsWith("/") ? input : input + "/";
41
- }
42
- if (hasTrailingSlash(input, true)) {
43
- return input || "/";
44
- }
45
- const [s0, ...s] = input.split("?");
46
- return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "");
47
- }
48
- function hasLeadingSlash(input = "") {
49
- return input.startsWith("/");
50
- }
51
- function withoutLeadingSlash(input = "") {
52
- return (hasLeadingSlash(input) ? input.slice(1) : input) || "/";
53
- }
54
- function withBase(input, base) {
55
- if (isEmptyURL(base) || hasProtocol(input)) {
56
- return input;
57
- }
58
- const _base = withoutTrailingSlash(base);
59
- if (input.startsWith(_base)) {
60
- return input;
61
- }
62
- return joinURL(_base, input);
63
- }
64
- function isEmptyURL(url) {
65
- return !url || url === "/";
66
- }
67
- function isNonEmptyURL(url) {
68
- return url && url !== "/";
69
- }
70
- function joinURL(base, ...input) {
71
- let url = base || "";
72
- for (const index of input.filter((url2) => isNonEmptyURL(url2))) {
73
- url = url ? withTrailingSlash(url) + withoutLeadingSlash(index) : index;
74
- }
75
- return url;
10
+ function idReference(node) {
11
+ return {
12
+ "@id": typeof node !== "string" ? node["@id"] : node
13
+ };
76
14
  }
77
-
78
- const idReference = (node) => ({
79
- "@id": typeof node !== "string" ? node["@id"] : node
80
- });
81
- const resolvableDateToDate = (val) => {
15
+ function resolvableDateToDate(val) {
82
16
  try {
83
17
  const date = val instanceof Date ? val : new Date(Date.parse(val));
84
18
  return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
85
19
  } catch (e) {
86
20
  }
87
21
  return typeof val === "string" ? val : val.toString();
88
- };
89
- const resolvableDateToIso = (val) => {
22
+ }
23
+ function resolvableDateToIso(val) {
90
24
  if (!val)
91
25
  return val;
92
26
  try {
@@ -97,29 +31,31 @@ const resolvableDateToIso = (val) => {
97
31
  } catch (e) {
98
32
  }
99
33
  return typeof val === "string" ? val : val.toString();
100
- };
34
+ }
101
35
  const IdentityId = "#identity";
102
- const setIfEmpty = (node, field, value) => {
36
+ function setIfEmpty(node, field, value) {
103
37
  if (!node?.[field] && value)
104
38
  node[field] = value;
105
- };
106
- const asArray = (input) => Array.isArray(input) ? input : [input];
107
- const dedupeMerge = (node, field, value) => {
39
+ }
40
+ function asArray(input) {
41
+ return Array.isArray(input) ? input : [input];
42
+ }
43
+ function dedupeMerge(node, field, value) {
108
44
  const dedupeMerge2 = [];
109
45
  const input = asArray(node[field]);
110
46
  dedupeMerge2.push(...input);
111
47
  const data = new Set(dedupeMerge2);
112
48
  data.add(value);
113
49
  node[field] = [...data.values()].filter(Boolean);
114
- };
115
- const prefixId = (url, id) => {
116
- if (hasProtocol(id))
50
+ }
51
+ function prefixId(url, id) {
52
+ if (ufo.hasProtocol(id))
117
53
  return url;
118
54
  if (!id.startsWith("#"))
119
55
  id = `#${id}`;
120
- return joinURL(url, id);
121
- };
122
- const trimLength = (val, length) => {
56
+ return ufo.joinURL(url, id);
57
+ }
58
+ function trimLength(val, length) {
123
59
  if (!val)
124
60
  return val;
125
61
  if (val.length > length) {
@@ -127,8 +63,8 @@ const trimLength = (val, length) => {
127
63
  return trimmedString.substring(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")));
128
64
  }
129
65
  return val;
130
- };
131
- const resolveDefaultType = (node, defaultType) => {
66
+ }
67
+ function resolveDefaultType(node, defaultType) {
132
68
  const val = node["@type"];
133
69
  if (val === defaultType)
134
70
  return;
@@ -137,18 +73,18 @@ const resolveDefaultType = (node, defaultType) => {
137
73
  ...asArray(val)
138
74
  ]);
139
75
  node["@type"] = types.size === 1 ? val : [...types.values()];
140
- };
141
- const resolveWithBase = (base, urlOrPath) => {
142
- if (!urlOrPath || hasProtocol(urlOrPath) || !urlOrPath.startsWith("/") && !urlOrPath.startsWith("#"))
76
+ }
77
+ function resolveWithBase(base, urlOrPath) {
78
+ if (!urlOrPath || ufo.hasProtocol(urlOrPath) || !urlOrPath.startsWith("/") && !urlOrPath.startsWith("#"))
143
79
  return urlOrPath;
144
- return withBase(urlOrPath, base);
145
- };
146
- const resolveAsGraphKey = (key) => {
80
+ return ufo.withBase(urlOrPath, base);
81
+ }
82
+ function resolveAsGraphKey(key) {
147
83
  if (!key)
148
84
  return key;
149
85
  return key.substring(key.lastIndexOf("#"));
150
- };
151
- const stripEmptyProperties = (obj) => {
86
+ }
87
+ function stripEmptyProperties(obj) {
152
88
  Object.keys(obj).forEach((k) => {
153
89
  if (obj[k] && typeof obj[k] === "object") {
154
90
  if (obj[k].__v_isReadonly || obj[k].__v_isRef)
@@ -160,7 +96,7 @@ const stripEmptyProperties = (obj) => {
160
96
  delete obj[k];
161
97
  });
162
98
  return obj;
163
- };
99
+ }
164
100
  function hashCode(s) {
165
101
  let h = 9;
166
102
  for (let i = 0; i < s.length; )
@@ -187,7 +123,7 @@ const offerResolver = defineSchemaOrgResolver({
187
123
  if (node.url)
188
124
  resolveWithBase(ctx.meta.host, node.url);
189
125
  if (node.availability)
190
- node.availability = withBase(node.availability, "https://schema.org/");
126
+ node.availability = ufo.withBase(node.availability, "https://schema.org/");
191
127
  if (node.priceValidUntil)
192
128
  node.priceValidUntil = resolvableDateToIso(node.priceValidUntil);
193
129
  return node;
@@ -428,7 +364,7 @@ const readActionResolver = defineSchemaOrgResolver({
428
364
  const PrimaryWebPageId = "#webpage";
429
365
  const webPageResolver = defineSchemaOrgResolver({
430
366
  defaults({ meta }) {
431
- const endPath = withoutTrailingSlash(meta.url.substring(meta.url.lastIndexOf("/") + 1));
367
+ const endPath = ufo.withoutTrailingSlash(meta.url.substring(meta.url.lastIndexOf("/") + 1));
432
368
  let type = "WebPage";
433
369
  switch (endPath) {
434
370
  case "about":
@@ -563,7 +499,7 @@ const bookEditionResolver = defineSchemaOrgResolver({
563
499
  ],
564
500
  resolve(node, ctx) {
565
501
  if (node.bookFormat)
566
- node.bookFormat = withBase(node.bookFormat, "https://schema.org/");
502
+ node.bookFormat = ufo.withBase(node.bookFormat, "https://schema.org/");
567
503
  if (node.datePublished)
568
504
  node.datePublished = resolvableDateToDate(node.datePublished);
569
505
  node.author = resolveRelation(node.author, ctx);
@@ -591,7 +527,7 @@ const bookResolver = defineSchemaOrgResolver({
591
527
  node.workExample = resolveRelation(node.workExample, ctx, bookEditionResolver);
592
528
  node.author = resolveRelation(node.author, ctx);
593
529
  if (node.url)
594
- withBase(node.url, ctx.meta.host);
530
+ ufo.withBase(node.url, ctx.meta.host);
595
531
  return node;
596
532
  },
597
533
  resolveRootNode(node, { find }) {
@@ -688,9 +624,9 @@ const eventResolver = defineSchemaOrgResolver({
688
624
  });
689
625
  node.offers = resolveRelation(node.offers, ctx, offerResolver);
690
626
  if (node.eventAttendanceMode)
691
- node.eventAttendanceMode = withBase(node.eventAttendanceMode, "https://schema.org/");
627
+ node.eventAttendanceMode = ufo.withBase(node.eventAttendanceMode, "https://schema.org/");
692
628
  if (node.eventStatus)
693
- node.eventStatus = withBase(node.eventStatus, "https://schema.org/");
629
+ node.eventStatus = ufo.withBase(node.eventStatus, "https://schema.org/");
694
630
  const isOnline = node.eventStatus === "https://schema.org/EventMovedOnline";
695
631
  const dates = ["startDate", "previousStartDate", "endDate"];
696
632
  dates.forEach((date) => {
@@ -977,6 +913,9 @@ function createHasher(options) {
977
913
  return this["_" + type](value);
978
914
  },
979
915
  _object(object) {
916
+ if (object && typeof object.toJSON === "function") {
917
+ return this._object(object.toJSON());
918
+ }
980
919
  const pattern = /\[object (.*)]/i;
981
920
  const objString = Object.prototype.toString.call(object);
982
921
  const _objType = pattern.exec(objString);
@@ -994,10 +933,8 @@ function createHasher(options) {
994
933
  if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
995
934
  if (this["_" + objType]) {
996
935
  this["_" + objType](object);
997
- } else if (options.ignoreUnknown) {
998
- return write("[" + objType + "]");
999
- } else {
1000
- throw new Error('Unknown object type "' + objType + '"');
936
+ } else if (!options.ignoreUnknown) {
937
+ this._unkown(object, objType);
1001
938
  }
1002
939
  } else {
1003
940
  let keys = Object.keys(object);
@@ -1049,6 +986,20 @@ function createHasher(options) {
1049
986
  _symbol(sym) {
1050
987
  return write("symbol:" + sym.toString());
1051
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
+ },
1052
1003
  _error(err) {
1053
1004
  return write("error:" + err.toString());
1054
1005
  },
@@ -1149,7 +1100,9 @@ function createHasher(options) {
1149
1100
  if (options.ignoreUnknown) {
1150
1101
  return write("[blob]");
1151
1102
  }
1152
- throw new Error('Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n');
1103
+ throw new Error(
1104
+ 'Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n'
1105
+ );
1153
1106
  },
1154
1107
  _domwindow() {
1155
1108
  return write("domwindow");
@@ -1157,6 +1110,7 @@ function createHasher(options) {
1157
1110
  _bigint(number) {
1158
1111
  return write("bigint:" + number.toString());
1159
1112
  },
1113
+ /* Node.js standard native objects */
1160
1114
  _process() {
1161
1115
  return write("process");
1162
1116
  },
@@ -1254,10 +1208,7 @@ const Hex = {
1254
1208
  const hexChars = [];
1255
1209
  for (let i = 0; i < wordArray.sigBytes; i++) {
1256
1210
  const bite = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
1257
- hexChars.push(
1258
- (bite >>> 4).toString(16),
1259
- (bite & 15).toString(16)
1260
- );
1211
+ hexChars.push((bite >>> 4).toString(16), (bite & 15).toString(16));
1261
1212
  }
1262
1213
  return hexChars.join("");
1263
1214
  }
@@ -1310,6 +1261,7 @@ class BufferedBlockAlgorithm {
1310
1261
  this._data.concat(data);
1311
1262
  this._nDataBytes += data.sigBytes;
1312
1263
  }
1264
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1313
1265
  _doProcessBlock(_dataWords, _offset) {
1314
1266
  }
1315
1267
  _process(doFlush) {
@@ -1345,8 +1297,82 @@ class Hasher extends BufferedBlockAlgorithm {
1345
1297
  }
1346
1298
  }
1347
1299
 
1348
- const H = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
1349
- const K = [1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998];
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
+ ];
1350
1376
  const W = [];
1351
1377
  class SHA256 extends Hasher {
1352
1378
  constructor() {
@@ -1406,7 +1432,9 @@ class SHA256 extends Hasher {
1406
1432
  const nBitsTotal = this._nDataBytes * 8;
1407
1433
  const nBitsLeft = this._data.sigBytes * 8;
1408
1434
  this._data.words[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32;
1409
- this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math.floor(nBitsTotal / 4294967296);
1435
+ this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math.floor(
1436
+ nBitsTotal / 4294967296
1437
+ );
1410
1438
  this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal;
1411
1439
  this._data.sigBytes = this._data.words.length * 4;
1412
1440
  this._process();
@@ -1610,7 +1638,7 @@ const resolver = {
1610
1638
  loadResolver: loadResolver
1611
1639
  };
1612
1640
 
1613
- const resolveMeta = (meta) => {
1641
+ function resolveMeta(meta) {
1614
1642
  if (!meta.host && meta.canonicalHost)
1615
1643
  meta.host = meta.canonicalHost;
1616
1644
  if (!meta.tagPosition && meta.position)
@@ -1626,12 +1654,12 @@ const resolveMeta = (meta) => {
1626
1654
  if (!meta.url && meta.canonicalUrl)
1627
1655
  meta.url = meta.canonicalUrl;
1628
1656
  if (meta.path !== "/") {
1629
- if (meta.trailingSlash && !hasTrailingSlash(meta.path))
1630
- meta.path = withTrailingSlash(meta.path);
1631
- else if (!meta.trailingSlash && hasTrailingSlash(meta.path))
1632
- 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);
1633
1661
  }
1634
- meta.url = joinURL(meta.host, meta.path);
1662
+ meta.url = ufo.joinURL(meta.host, meta.path);
1635
1663
  return {
1636
1664
  ...meta,
1637
1665
  host: meta.host,
@@ -1644,8 +1672,8 @@ const resolveMeta = (meta) => {
1644
1672
  datePublished: meta.datePublished,
1645
1673
  dateModified: meta.dateModified
1646
1674
  };
1647
- };
1648
- const resolveNode = (node, ctx, resolver) => {
1675
+ }
1676
+ function resolveNode(node, ctx, resolver) {
1649
1677
  if (resolver?.cast)
1650
1678
  node = resolver.cast(node, ctx);
1651
1679
  if (resolver?.defaults) {
@@ -1672,8 +1700,8 @@ const resolveNode = (node, ctx, resolver) => {
1672
1700
  }
1673
1701
  stripEmptyProperties(node);
1674
1702
  return node;
1675
- };
1676
- const resolveNodeId = (node, ctx, resolver, resolveAsRoot = false) => {
1703
+ }
1704
+ function resolveNodeId(node, ctx, resolver, resolveAsRoot = false) {
1677
1705
  const prefix = Array.isArray(resolver.idPrefix) ? resolver.idPrefix[0] : resolver.idPrefix;
1678
1706
  if (!prefix)
1679
1707
  return node;
@@ -1699,7 +1727,7 @@ const resolveNodeId = (node, ctx, resolver, resolveAsRoot = false) => {
1699
1727
  node["@id"] = prefixId(ctx.meta[prefix], `#/schema/${alias}/${hashCode(JSON.stringify(hashNodeData))}`);
1700
1728
  }
1701
1729
  return node;
1702
- };
1730
+ }
1703
1731
  function resolveRelation(input, ctx, fallbackResolver, options = {}) {
1704
1732
  if (!input)
1705
1733
  return input;
@@ -1733,14 +1761,70 @@ function resolveRelation(input, ctx, fallbackResolver, options = {}) {
1733
1761
  return ids;
1734
1762
  }
1735
1763
 
1736
- const groupBy = (array, predicate) => array.reduce((acc, value, index, array2) => {
1737
- const key = predicate(value, index, array2);
1738
- if (!acc[key])
1739
- acc[key] = [];
1740
- acc[key].push(value);
1741
- return acc;
1742
- }, {});
1743
- const dedupeNodes = (nodes) => {
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) {
1744
1828
  const sortedNodeKeys = nodes.keys();
1745
1829
  const dedupedNodes = {};
1746
1830
  for (const key of sortedNodeKeys) {
@@ -1758,15 +1842,17 @@ const dedupeNodes = (nodes) => {
1758
1842
  ...(groupedKeys.primitives || []).sort(),
1759
1843
  ...(groupedKeys.relations || []).sort()
1760
1844
  ];
1761
- const newNode = {};
1845
+ let newNode = {};
1762
1846
  for (const key2 of keys)
1763
1847
  newNode[key2] = n[key2];
1848
+ if (dedupedNodes[nodeKey])
1849
+ newNode = defu(newNode, dedupedNodes[nodeKey]);
1764
1850
  dedupedNodes[nodeKey] = newNode;
1765
1851
  }
1766
1852
  return Object.values(dedupedNodes);
1767
- };
1853
+ }
1768
1854
 
1769
- const createSchemaOrgGraph = () => {
1855
+ function createSchemaOrgGraph() {
1770
1856
  const ctx = {
1771
1857
  find(id) {
1772
1858
  const key = resolveAsGraphKey(id);
@@ -1788,6 +1874,7 @@ const createSchemaOrgGraph = () => {
1788
1874
  }
1789
1875
  ctx.nodes[key] = node;
1790
1876
  });
1877
+ ctx.nodes = dedupeNodes(ctx.nodes);
1791
1878
  ctx.nodes.forEach((node) => {
1792
1879
  if (node.image && typeof node.image === "string") {
1793
1880
  node.image = resolveRelation(node.image, ctx, imageResolver, {
@@ -1798,13 +1885,13 @@ const createSchemaOrgGraph = () => {
1798
1885
  node._resolver.resolveRootNode(node, ctx);
1799
1886
  delete node._resolver;
1800
1887
  });
1801
- return dedupeNodes(ctx.nodes);
1888
+ return normaliseNodes(ctx.nodes);
1802
1889
  },
1803
1890
  nodes: [],
1804
1891
  meta: {}
1805
1892
  };
1806
1893
  return ctx;
1807
- };
1894
+ }
1808
1895
 
1809
1896
  function SchemaOrgUnheadPlugin(config, meta) {
1810
1897
  config = resolveMeta({ ...config });
@@ -1852,46 +1939,114 @@ function SchemaOrgUnheadPlugin(config, meta) {
1852
1939
  };
1853
1940
  }
1854
1941
 
1855
- const provideResolver = (input, resolver) => {
1942
+ function provideResolver(input, resolver) {
1856
1943
  if (!input)
1857
1944
  input = {};
1858
1945
  input._resolver = resolver;
1859
1946
  return input;
1860
- };
1861
- const defineAddress = (input) => provideResolver(input, "address");
1862
- const defineAggregateOffer = (input) => provideResolver(input, "aggregateOffer");
1863
- const defineAggregateRating = (input) => provideResolver(input, "aggregateRating");
1864
- const defineArticle = (input) => provideResolver(input, "article");
1865
- const defineBreadcrumb = (input) => provideResolver(input, "breadcrumb");
1866
- const defineComment = (input) => provideResolver(input, "comment");
1867
- const defineEvent = (input) => provideResolver(input, "event");
1868
- const defineVirtualLocation = (input) => provideResolver(input, "virtualLocation");
1869
- const definePlace = (input) => provideResolver(input, "place");
1870
- const defineHowTo = (input) => provideResolver(input, "howTo");
1871
- const defineHowToStep = (input) => provideResolver(input, "howToStep");
1872
- const defineImage = (input) => provideResolver(input, "image");
1873
- const defineJobPosting = (input) => provideResolver(input, "jobPosting");
1874
- const defineLocalBusiness = (input) => provideResolver(input, "localBusiness");
1875
- const defineOffer = (input) => provideResolver(input, "offer");
1876
- const defineOpeningHours = (input) => provideResolver(input, "openingHours");
1877
- const defineOrganization = (input) => provideResolver(input, "organization");
1878
- const definePerson = (input) => provideResolver(input, "person");
1879
- const defineProduct = (input) => provideResolver(input, "product");
1880
- const defineQuestion = (input) => provideResolver(input, "question");
1881
- const defineRecipe = (input) => provideResolver(input, "recipe");
1882
- const defineReview = (input) => provideResolver(input, "review");
1883
- const defineVideo = (input) => provideResolver(input, "video");
1884
- const defineWebPage = (input) => provideResolver(input, "webPage");
1885
- const defineWebSite = (input) => provideResolver(input, "webSite");
1886
- const defineBook = (input) => provideResolver(input, "book");
1887
- const defineCourse = (input) => provideResolver(input, "course");
1888
- const defineItemList = (input) => provideResolver(input, "itemList");
1889
- const defineListItem = (input) => provideResolver(input, "listItem");
1890
- const defineMovie = (input) => provideResolver(input, "movie");
1891
- const defineSearchAction = (input) => provideResolver(input, "searchAction");
1892
- const defineReadAction = (input) => provideResolver(input, "readAction");
1893
- const defineSoftwareApp = (input) => provideResolver(input, "softwareApp");
1894
- const defineBookEdition = (input) => provideResolver(input, "bookEdition");
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
+ }
1895
2050
  function useSchemaOrg(input) {
1896
2051
  return unhead.useHead({
1897
2052
  script: [
@@ -1970,6 +2125,7 @@ exports.jobPostingResolver = jobPostingResolver;
1970
2125
  exports.listItemResolver = listItemResolver;
1971
2126
  exports.localBusinessResolver = localBusinessResolver;
1972
2127
  exports.movieResolver = movieResolver;
2128
+ exports.normaliseNodes = normaliseNodes;
1973
2129
  exports.offerResolver = offerResolver;
1974
2130
  exports.openingHoursResolver = openingHoursResolver;
1975
2131
  exports.organizationResolver = organizationResolver;