@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 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
- const PROTOCOL_REGEX = /^\w{2,}:(\/\/)?/;
10
- const PROTOCOL_RELATIVE_REGEX = /^\/\/[^/]+/;
11
- function hasProtocol(inputString, acceptProtocolRelative = false) {
12
- return PROTOCOL_REGEX.test(inputString) || acceptProtocolRelative && PROTOCOL_RELATIVE_REGEX.test(inputString);
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
- const resolvableDateToIso = (val) => {
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
- const setIfEmpty = (node, field, value) => {
36
+ function setIfEmpty(node, field, value) {
96
37
  if (!node?.[field] && value)
97
38
  node[field] = value;
98
- };
99
- const asArray = (input) => Array.isArray(input) ? input : [input];
100
- const dedupeMerge = (node, field, value) => {
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
- const prefixId = (url, id) => {
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
- const trimLength = (val, length) => {
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
- const resolveDefaultType = (node, defaultType) => {
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
- const resolveWithBase = (base, urlOrPath) => {
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
- const resolveAsGraphKey = (key) => {
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
- const stripEmptyProperties = (obj) => {
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
- return write("[" + objType + "]");
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('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
+ );
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 = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
1342
- 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
+ ];
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(nBitsTotal / 4294967296);
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
- const resolveMeta = (meta) => {
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
- const resolveNode = (node, ctx, resolver) => {
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
- const resolveNodeId = (node, ctx, resolver, resolveAsRoot = false) => {
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
- const groupBy = (array, predicate) => array.reduce((acc, value, index, array2) => {
1730
- const key = predicate(value, index, array2);
1731
- if (!acc[key])
1732
- acc[key] = [];
1733
- acc[key].push(value);
1734
- return acc;
1735
- }, {});
1736
- 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) {
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
- const newNode = {};
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
- const createSchemaOrgGraph = () => {
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 dedupeNodes(ctx.nodes);
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.children;
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.children = JSON.stringify({
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
- const provideResolver = (input, resolver) => {
1942
+ function provideResolver(input, resolver) {
1849
1943
  if (!input)
1850
1944
  input = {};
1851
1945
  input._resolver = resolver;
1852
1946
  return input;
1853
- };
1854
- const defineAddress = (input) => provideResolver(input, "address");
1855
- const defineAggregateOffer = (input) => provideResolver(input, "aggregateOffer");
1856
- const defineAggregateRating = (input) => provideResolver(input, "aggregateRating");
1857
- const defineArticle = (input) => provideResolver(input, "article");
1858
- const defineBreadcrumb = (input) => provideResolver(input, "breadcrumb");
1859
- const defineComment = (input) => provideResolver(input, "comment");
1860
- const defineEvent = (input) => provideResolver(input, "event");
1861
- const defineVirtualLocation = (input) => provideResolver(input, "virtualLocation");
1862
- const definePlace = (input) => provideResolver(input, "place");
1863
- const defineHowTo = (input) => provideResolver(input, "howTo");
1864
- const defineHowToStep = (input) => provideResolver(input, "howToStep");
1865
- const defineImage = (input) => provideResolver(input, "image");
1866
- const defineJobPosting = (input) => provideResolver(input, "jobPosting");
1867
- const defineLocalBusiness = (input) => provideResolver(input, "localBusiness");
1868
- const defineOffer = (input) => provideResolver(input, "offer");
1869
- const defineOpeningHours = (input) => provideResolver(input, "openingHours");
1870
- const defineOrganization = (input) => provideResolver(input, "organization");
1871
- const definePerson = (input) => provideResolver(input, "person");
1872
- const defineProduct = (input) => provideResolver(input, "product");
1873
- const defineQuestion = (input) => provideResolver(input, "question");
1874
- const defineRecipe = (input) => provideResolver(input, "recipe");
1875
- const defineReview = (input) => provideResolver(input, "review");
1876
- const defineVideo = (input) => provideResolver(input, "video");
1877
- const defineWebPage = (input) => provideResolver(input, "webPage");
1878
- const defineWebSite = (input) => provideResolver(input, "webSite");
1879
- const defineBook = (input) => provideResolver(input, "book");
1880
- const defineCourse = (input) => provideResolver(input, "course");
1881
- const defineItemList = (input) => provideResolver(input, "itemList");
1882
- const defineListItem = (input) => provideResolver(input, "listItem");
1883
- const defineMovie = (input) => provideResolver(input, "movie");
1884
- const defineSearchAction = (input) => provideResolver(input, "searchAction");
1885
- const defineReadAction = (input) => provideResolver(input, "readAction");
1886
- const defineSoftwareApp = (input) => provideResolver(input, "softwareApp");
1887
- 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
+ }
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;