@unhead/schema-org-vue
Version:
Vue Schema.org for Simple and Automated Google Rich Results for everyone
1,829 lines (1,785 loc) • 68.9 kB
JavaScript
'use strict';
const vue = require('@unhead/vue');
const vue$1 = require('vue');
const name = "@unhead/schema-org-vue";
const schemaAutoImports = [
"defineAddress",
"defineAggregateOffer",
"defineAggregateRating",
"defineArticle",
"defineBook",
"defineBookEdition",
"defineBreadcrumb",
"defineComment",
"defineCourse",
"defineEvent",
"defineHowTo",
"defineHowToStep",
"defineImage",
"defineItemList",
"defineJobPosting",
"defineListItem",
"defineLocalBusiness",
"defineMovie",
"defineOffer",
"defineOpeningHours",
"defineOrganization",
"definePerson",
"definePlace",
"defineProduct",
"defineQuestion",
"defineReadAction",
"defineRecipe",
"defineReview",
"defineSearchAction",
"defineSoftwareApp",
"defineVideo",
"defineVirtualLocation",
"defineWebPage",
"defineWebSite",
"useSchemaOrg"
];
const schemaOrgAutoImports = [
{
from: name,
imports: schemaAutoImports
}
];
const schemaOrgComponents = [
"SchemaOrgDebug",
"SchemaOrgArticle",
"SchemaOrgBreadcrumb",
"SchemaOrgComment",
"SchemaOrgEvent",
"SchemaOrgHowTo",
"SchemaOrgImage",
"SchemaOrgJobPosting",
"SchemaOrgLocalBusiness",
"SchemaOrgOrganization",
"SchemaOrgPerson",
"SchemaOrgProduct",
"SchemaOrgQuestion",
"SchemaOrgRecipe",
"SchemaOrgReview",
"SchemaOrgVideo",
"SchemaOrgWebPage",
"SchemaOrgWebSite",
"SchemaOrgMovie",
"SchemaOrgCourse",
"SchemaOrgItemList",
"SchemaOrgBook",
"SchemaOrgSoftwareApp"
];
function SchemaOrgResolver(options = {}) {
const { prefix = "" } = options;
return {
type: "component",
resolve: (name$1) => {
if (name$1.startsWith(prefix)) {
const componentName = name$1.substring(prefix.length);
if (schemaOrgComponents.includes(componentName)) {
return {
name: componentName,
from: name
};
}
}
}
};
}
function provideResolver(input, resolver) {
if (!input)
input = {};
input._resolver = resolver;
return input;
}
function defineAddress(input) {
return provideResolver(input, "address");
}
function defineAggregateOffer(input) {
return provideResolver(input, "aggregateOffer");
}
function defineAggregateRating(input) {
return provideResolver(input, "aggregateRating");
}
function defineArticle(input) {
return provideResolver(input, "article");
}
function defineBreadcrumb(input) {
return provideResolver(input, "breadcrumb");
}
function defineComment(input) {
return provideResolver(input, "comment");
}
function defineEvent(input) {
return provideResolver(input, "event");
}
function defineVirtualLocation(input) {
return provideResolver(input, "virtualLocation");
}
function definePlace(input) {
return provideResolver(input, "place");
}
function defineHowTo(input) {
return provideResolver(input, "howTo");
}
function defineHowToStep(input) {
return provideResolver(input, "howToStep");
}
function defineImage(input) {
return provideResolver(input, "image");
}
function defineJobPosting(input) {
return provideResolver(input, "jobPosting");
}
function defineLocalBusiness(input) {
return provideResolver(input, "localBusiness");
}
function defineOffer(input) {
return provideResolver(input, "offer");
}
function defineOpeningHours(input) {
return provideResolver(input, "openingHours");
}
function defineOrganization(input) {
return provideResolver(input, "organization");
}
function definePerson(input) {
return provideResolver(input, "person");
}
function defineProduct(input) {
return provideResolver(input, "product");
}
function defineQuestion(input) {
return provideResolver(input, "question");
}
function defineRecipe(input) {
return provideResolver(input, "recipe");
}
function defineReview(input) {
return provideResolver(input, "review");
}
function defineVideo(input) {
return provideResolver(input, "video");
}
function defineWebPage(input) {
return provideResolver(input, "webPage");
}
function defineWebSite(input) {
return provideResolver(input, "webSite");
}
function defineBook(input) {
return provideResolver(input, "book");
}
function defineCourse(input) {
return provideResolver(input, "course");
}
function defineItemList(input) {
return provideResolver(input, "itemList");
}
function defineListItem(input) {
return provideResolver(input, "listItem");
}
function defineMovie(input) {
return provideResolver(input, "movie");
}
function defineSearchAction(input) {
return provideResolver(input, "searchAction");
}
function defineReadAction(input) {
return provideResolver(input, "readAction");
}
function defineSoftwareApp(input) {
return provideResolver(input, "softwareApp");
}
function defineBookEdition(input) {
return provideResolver(input, "bookEdition");
}
let isSPA = null;
function useSchemaOrg(input) {
if (process.env.NODE_ENV !== "development" && typeof window !== "undefined") {
if (isSPA === null && !window.document.querySelector("#schema-org-graph"))
isSPA = true;
if (!isSPA)
return;
}
return vue.useHead({
script: [
{
type: "application/ld+json",
id: "schema-org-graph",
key: "schema-org-graph",
// @ts-expect-error runtime type
nodes: input
}
]
}, { mode: isSPA ? "all" : "server" });
}
function shallowVNodesToText(nodes) {
let text = "";
for (const node of nodes) {
if (typeof node.children === "string")
text += node.children.trim();
}
return text;
}
function fixKey(s) {
let key = s.replace(/-./g, (x) => x[1].toUpperCase());
if (key === "type" || key === "id")
key = `@${key}`;
return key;
}
function ignoreKey(s) {
if (s.startsWith("aria-") || s.startsWith("data-"))
return false;
return ["class", "style"].includes(s);
}
function defineSchemaOrgComponent(name, defineFn) {
return vue$1.defineComponent({
name,
props: {
as: String
},
setup(props, { slots, attrs }) {
const node = vue$1.ref(null);
const nodePartial = vue$1.computed(() => {
const val = {};
Object.entries(vue$1.unref(attrs)).forEach(([key, value]) => {
if (!ignoreKey(key)) {
val[fixKey(key)] = vue$1.unref(value);
}
});
if (!node.value) {
for (const [key, slot] of Object.entries(slots)) {
if (!slot || key === "default")
continue;
val[fixKey(key)] = shallowVNodesToText(slot(props));
}
}
return val;
});
if (defineFn) {
useSchemaOrg(defineFn(vue$1.unref(nodePartial)));
}
return () => {
const data = vue$1.unref(nodePartial);
if (!slots.default)
return null;
const childSlots = [];
if (slots.default)
childSlots.push(slots.default(data));
return vue$1.h(props.as || "div", {}, childSlots);
};
}
});
}
const SchemaOrgArticle = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgArticle", defineArticle);
const SchemaOrgBreadcrumb = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgBreadcrumb", defineBreadcrumb);
const SchemaOrgComment = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgComment", defineComment);
const SchemaOrgEvent = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgEvent", defineEvent);
const SchemaOrgHowTo = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgHowTo", defineHowTo);
const SchemaOrgImage = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgImage", defineImage);
const SchemaOrgJobPosting = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgJobPosting", defineJobPosting);
const SchemaOrgLocalBusiness = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgLocalBusiness", defineLocalBusiness);
const SchemaOrgOrganization = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgOrganization", defineOrganization);
const SchemaOrgPerson = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgPerson", definePerson);
const SchemaOrgProduct = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgProduct", defineProduct);
const SchemaOrgQuestion = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgQuestion", defineQuestion);
const SchemaOrgRecipe = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgRecipe", defineRecipe);
const SchemaOrgReview = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgReview", defineReview);
const SchemaOrgVideo = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgVideo", defineVideo);
const SchemaOrgWebPage = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgWebPage", defineWebPage);
const SchemaOrgWebSite = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgWebSite", defineWebSite);
const SchemaOrgMovie = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgMovie", defineMovie);
const SchemaOrgCourse = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgCourse", defineCourse);
const SchemaOrgItemList = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgItemList", defineItemList);
const SchemaOrgBook = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgBook", defineBook);
const SchemaOrgSoftwareApp = /* @__PURE__ */ defineSchemaOrgComponent("SchemaOrgSoftwareApp", defineSoftwareApp);
const SchemaOrgDebug = vue$1.defineComponent({
name: "SchemaOrgDebug",
props: {
console: {
type: Boolean,
default: false
}
},
setup(props) {
const schemaRaw = vue$1.ref("");
let observer;
vue$1.onMounted(() => {
vue$1.nextTick(() => {
let $el = document.querySelector('script[type="application/ld+json"]');
if (!$el)
return;
const fetchSchema = () => {
$el = document.querySelector('script[type="application/ld+json"]');
schemaRaw.value = $el?.textContent || "";
};
observer = new MutationObserver(fetchSchema);
observer.observe(document.body, {
childList: true,
characterData: true,
attributes: true,
subtree: true
});
fetchSchema();
});
});
if (props.console) {
vue$1.watch(schemaRaw, (val) => {
console.info("[SchemaOrgDebug]", JSON.parse(vue$1.unref(val)));
});
}
vue$1.onBeforeUnmount(() => {
observer?.disconnect();
});
return () => {
return vue$1.h("div", {
style: {
display: "inline-block"
}
}, [vue$1.h("div", {
style: {
backgroundColor: "#282839",
color: "#c5c6c9",
padding: "5px",
borderRadius: "5px",
width: "900px",
height: "600px",
overflowY: "auto",
boxShadow: "3px 4px 15px rgb(0 0 0 / 10%)"
}
}, [
vue$1.h("pre", { style: { textAlign: "left" } }, schemaRaw.value)
])]);
};
}
});
const PROTOCOL_STRICT_REGEX = /^\w{2,}:([/\\]{1,2})/;
const PROTOCOL_REGEX = /^\w{2,}:([/\\]{2})?/;
const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
function hasProtocol(inputString, opts = {}) {
if (typeof opts === "boolean") {
opts = { acceptRelative: opts };
}
if (opts.strict) {
return PROTOCOL_STRICT_REGEX.test(inputString);
}
return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
}
const TRAILING_SLASH_RE = /\/$|\/\?/;
function hasTrailingSlash(input = "", queryParameters = false) {
if (!queryParameters) {
return input.endsWith("/");
}
return TRAILING_SLASH_RE.test(input);
}
function withoutTrailingSlash(input = "", queryParameters = false) {
if (!queryParameters) {
return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
}
if (!hasTrailingSlash(input, true)) {
return input || "/";
}
const [s0, ...s] = input.split("?");
return (s0.slice(0, -1) || "/") + (s.length > 0 ? `?${s.join("?")}` : "");
}
function withTrailingSlash(input = "", queryParameters = false) {
if (!queryParameters) {
return input.endsWith("/") ? input : input + "/";
}
if (hasTrailingSlash(input, true)) {
return input || "/";
}
const [s0, ...s] = input.split("?");
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "");
}
function hasLeadingSlash(input = "") {
return input.startsWith("/");
}
function withoutLeadingSlash(input = "") {
return (hasLeadingSlash(input) ? input.slice(1) : input) || "/";
}
function withBase(input, base) {
if (isEmptyURL(base) || hasProtocol(input)) {
return input;
}
const _base = withoutTrailingSlash(base);
if (input.startsWith(_base)) {
return input;
}
return joinURL(_base, input);
}
function isEmptyURL(url) {
return !url || url === "/";
}
function isNonEmptyURL(url) {
return url && url !== "/";
}
function joinURL(base, ...input) {
let url = base || "";
for (const index of input.filter((url2) => isNonEmptyURL(url2))) {
url = url ? withTrailingSlash(url) + withoutLeadingSlash(index) : index;
}
return url;
}
function defineSchemaOrgResolver(schema) {
return schema;
}
function idReference(node) {
return {
"@id": typeof node !== "string" ? node["@id"] : node
};
}
function resolvableDateToDate(val) {
try {
const date = val instanceof Date ? val : new Date(Date.parse(val));
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
} catch (e) {
}
return typeof val === "string" ? val : val.toString();
}
function resolvableDateToIso(val) {
if (!val)
return val;
try {
if (val instanceof Date)
return val.toISOString();
else
return new Date(Date.parse(val)).toISOString();
} catch (e) {
}
return typeof val === "string" ? val : val.toString();
}
const IdentityId = "#identity";
function setIfEmpty(node, field, value) {
if (!node?.[field] && value)
node[field] = value;
}
function asArray(input) {
return Array.isArray(input) ? input : [input];
}
function dedupeMerge(node, field, value) {
const dedupeMerge2 = [];
const input = asArray(node[field]);
dedupeMerge2.push(...input);
const data = new Set(dedupeMerge2);
data.add(value);
node[field] = [...data.values()].filter(Boolean);
}
function prefixId(url, id) {
if (hasProtocol(id))
return url;
if (!id.startsWith("#"))
id = `#${id}`;
return joinURL(url, id);
}
function trimLength(val, length) {
if (!val)
return val;
if (val.length > length) {
const trimmedString = val.substring(0, length);
return trimmedString.substring(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")));
}
return val;
}
function resolveDefaultType(node, defaultType) {
const val = node["@type"];
if (val === defaultType)
return;
const types = /* @__PURE__ */ new Set([
...asArray(defaultType),
...asArray(val)
]);
node["@type"] = types.size === 1 ? val : [...types.values()];
}
function resolveWithBase(base, urlOrPath) {
if (!urlOrPath || hasProtocol(urlOrPath) || !urlOrPath.startsWith("/") && !urlOrPath.startsWith("#"))
return urlOrPath;
return withBase(urlOrPath, base);
}
function resolveAsGraphKey(key) {
if (!key)
return key;
return key.substring(key.lastIndexOf("#"));
}
function stripEmptyProperties(obj) {
Object.keys(obj).forEach((k) => {
if (obj[k] && typeof obj[k] === "object") {
if (obj[k].__v_isReadonly || obj[k].__v_isRef)
return;
stripEmptyProperties(obj[k]);
return;
}
if (obj[k] === "" || obj[k] === null || typeof obj[k] === "undefined")
delete obj[k];
});
return obj;
}
function hashCode(s) {
let h = 9;
for (let i = 0; i < s.length; )
h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
}
const offerResolver = defineSchemaOrgResolver({
cast(node) {
if (typeof node === "number" || typeof node === "string") {
return {
price: node
};
}
return node;
},
defaults: {
"@type": "Offer",
"availability": "InStock"
},
resolve(node, ctx) {
setIfEmpty(node, "priceCurrency", ctx.meta.currency);
setIfEmpty(node, "priceValidUntil", new Date(Date.UTC((/* @__PURE__ */ new Date()).getFullYear() + 1, 12, -1, 0, 0, 0)));
if (node.url)
resolveWithBase(ctx.meta.host, node.url);
if (node.availability)
node.availability = withBase(node.availability, "https://schema.org/");
if (node.priceValidUntil)
node.priceValidUntil = resolvableDateToIso(node.priceValidUntil);
return node;
}
});
const aggregateOfferResolver = defineSchemaOrgResolver({
defaults: {
"@type": "AggregateOffer"
},
inheritMeta: [
{ meta: "currency", key: "priceCurrency" }
],
resolve(node, ctx) {
node.offers = resolveRelation(node.offers, ctx, offerResolver);
if (node.offers)
setIfEmpty(node, "offerCount", asArray(node.offers).length);
return node;
}
});
const aggregateRatingResolver = defineSchemaOrgResolver({
defaults: {
"@type": "AggregateRating"
}
});
const searchActionResolver = defineSchemaOrgResolver({
defaults: {
"@type": "SearchAction",
"target": {
"@type": "EntryPoint"
},
"query-input": {
"@type": "PropertyValueSpecification",
"valueRequired": true,
"valueName": "search_term_string"
}
},
resolve(node, ctx) {
if (typeof node.target === "string") {
node.target = {
"@type": "EntryPoint",
"urlTemplate": resolveWithBase(ctx.meta.host, node.target)
};
}
return node;
}
});
const PrimaryWebSiteId = "#website";
const webSiteResolver = defineSchemaOrgResolver({
defaults: {
"@type": "WebSite"
},
inheritMeta: [
"inLanguage",
{ meta: "host", key: "url" }
],
idPrefix: ["host", PrimaryWebSiteId],
resolve(node, ctx) {
node.potentialAction = resolveRelation(node.potentialAction, ctx, searchActionResolver, {
array: true
});
node.publisher = resolveRelation(node.publisher, ctx);
return node;
},
resolveRootNode(node, { find }) {
if (resolveAsGraphKey(node["@id"]) === PrimaryWebSiteId) {
const identity = find(IdentityId);
if (identity)
setIfEmpty(node, "publisher", idReference(identity));
const webPage = find(PrimaryWebPageId);
if (webPage)
setIfEmpty(webPage, "isPartOf", idReference(node));
}
return node;
}
});
const listItemResolver = defineSchemaOrgResolver({
cast(node) {
if (typeof node === "string") {
node = {
name: node
};
}
return node;
},
defaults: {
"@type": "ListItem"
},
resolve(node, ctx) {
if (typeof node.item === "string")
node.item = resolveWithBase(ctx.meta.host, node.item);
else if (typeof node.item === "object")
node.item = resolveRelation(node.item, ctx);
return node;
}
});
const PrimaryBreadcrumbId = "#breadcrumb";
const breadcrumbResolver = defineSchemaOrgResolver({
defaults: {
"@type": "BreadcrumbList"
},
idPrefix: ["url", PrimaryBreadcrumbId],
resolve(breadcrumb, ctx) {
if (breadcrumb.itemListElement) {
let index = 1;
breadcrumb.itemListElement = resolveRelation(breadcrumb.itemListElement, ctx, listItemResolver, {
array: true,
afterResolve(node) {
setIfEmpty(node, "position", index++);
}
});
}
return breadcrumb;
},
resolveRootNode(node, { find }) {
const webPage = find(PrimaryWebPageId);
if (webPage)
setIfEmpty(webPage, "breadcrumb", idReference(node));
}
});
const imageResolver = defineSchemaOrgResolver({
alias: "image",
cast(input) {
if (typeof input === "string") {
input = {
url: input
};
}
return input;
},
defaults: {
"@type": "ImageObject"
},
inheritMeta: [
// @todo possibly only do if there's a caption
"inLanguage"
],
idPrefix: "host",
resolve(image, { meta }) {
image.url = resolveWithBase(meta.host, image.url);
setIfEmpty(image, "contentUrl", image.url);
if (image.height && !image.width)
delete image.height;
if (image.width && !image.height)
delete image.width;
return image;
}
});
const addressResolver = defineSchemaOrgResolver({
defaults: {
"@type": "PostalAddress"
}
});
const organizationResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Organization"
},
idPrefix: ["host", IdentityId],
inheritMeta: [
{ meta: "host", key: "url" }
],
resolve(node, ctx) {
resolveDefaultType(node, "Organization");
node.address = resolveRelation(node.address, ctx, addressResolver);
return node;
},
resolveRootNode(node, ctx) {
const isIdentity = resolveAsGraphKey(node["@id"]) === IdentityId;
const webPage = ctx.find(PrimaryWebPageId);
if (node.logo) {
node.logo = resolveRelation(node.logo, ctx, imageResolver, {
root: true,
afterResolve(logo) {
if (isIdentity)
logo["@id"] = prefixId(ctx.meta.host, "#logo");
setIfEmpty(logo, "caption", node.name);
}
});
if (webPage)
setIfEmpty(webPage, "primaryImageOfPage", idReference(node.logo));
}
if (isIdentity && webPage)
setIfEmpty(webPage, "about", idReference(node));
const webSite = ctx.find(PrimaryWebSiteId);
if (webSite)
setIfEmpty(webSite, "publisher", idReference(node));
}
});
const personResolver = defineSchemaOrgResolver({
cast(node) {
if (typeof node === "string") {
return {
name: node
};
}
return node;
},
defaults: {
"@type": "Person"
},
idPrefix: ["host", IdentityId],
resolveRootNode(node, { find, meta }) {
if (resolveAsGraphKey(node["@id"]) === IdentityId) {
setIfEmpty(node, "url", meta.host);
const webPage = find(PrimaryWebPageId);
if (webPage)
setIfEmpty(webPage, "about", idReference(node));
const webSite = find(PrimaryWebSiteId);
if (webSite)
setIfEmpty(webSite, "publisher", idReference(node));
}
const article = find(PrimaryArticleId);
if (article)
setIfEmpty(article, "author", idReference(node));
}
});
const readActionResolver = defineSchemaOrgResolver({
defaults: {
"@type": "ReadAction"
},
resolve(node, ctx) {
if (!node.target.includes(ctx.meta.url))
node.target.unshift(ctx.meta.url);
return node;
}
});
const PrimaryWebPageId = "#webpage";
const webPageResolver = defineSchemaOrgResolver({
defaults({ meta }) {
const endPath = withoutTrailingSlash(meta.url.substring(meta.url.lastIndexOf("/") + 1));
let type = "WebPage";
switch (endPath) {
case "about":
case "about-us":
type = "AboutPage";
break;
case "search":
type = "SearchResultsPage";
break;
case "checkout":
type = "CheckoutPage";
break;
case "contact":
case "get-in-touch":
case "contact-us":
type = "ContactPage";
break;
case "faq":
type = "FAQPage";
break;
}
const defaults = {
"@type": type
};
return defaults;
},
idPrefix: ["url", PrimaryWebPageId],
inheritMeta: [
{ meta: "title", key: "name" },
"description",
"datePublished",
"dateModified",
"url"
],
resolve(node, ctx) {
node.dateModified = resolvableDateToIso(node.dateModified);
node.datePublished = resolvableDateToIso(node.datePublished);
resolveDefaultType(node, "WebPage");
node.about = resolveRelation(node.about, ctx, organizationResolver);
node.breadcrumb = resolveRelation(node.breadcrumb, ctx, breadcrumbResolver);
node.author = resolveRelation(node.author, ctx, personResolver);
node.primaryImageOfPage = resolveRelation(node.primaryImageOfPage, ctx, imageResolver);
node.potentialAction = resolveRelation(node.potentialAction, ctx, readActionResolver);
if (node["@type"] === "WebPage") {
setIfEmpty(node, "potentialAction", [
{
"@type": "ReadAction",
"target": [ctx.meta.url]
}
]);
}
return node;
},
resolveRootNode(webPage, { find, meta }) {
const identity = find(IdentityId);
const webSite = find(PrimaryWebSiteId);
const logo = find("#logo");
if (identity && meta.url === meta.host)
setIfEmpty(webPage, "about", idReference(identity));
if (logo)
setIfEmpty(webPage, "primaryImageOfPage", idReference(logo));
if (webSite)
setIfEmpty(webPage, "isPartOf", idReference(webSite));
const breadcrumb = find(PrimaryBreadcrumbId);
if (breadcrumb)
setIfEmpty(webPage, "breadcrumb", idReference(breadcrumb));
return webPage;
}
});
const PrimaryArticleId = "#article";
const articleResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Article"
},
inheritMeta: [
"inLanguage",
"description",
"image",
"dateModified",
"datePublished",
{ meta: "title", key: "headline" }
],
idPrefix: ["url", PrimaryArticleId],
resolve(node, ctx) {
node.author = resolveRelation(node.author, ctx, personResolver, {
root: true
});
node.publisher = resolveRelation(node.publisher, ctx);
node.dateModified = resolvableDateToIso(node.dateModified);
node.datePublished = resolvableDateToIso(node.datePublished);
resolveDefaultType(node, "Article");
node.headline = trimLength(node.headline, 110);
return node;
},
resolveRootNode(node, { find, meta }) {
const webPage = find(PrimaryWebPageId);
const identity = find(IdentityId);
if (node.image && !node.thumbnailUrl) {
const firstImage = asArray(node.image)[0];
if (typeof firstImage === "string")
setIfEmpty(node, "thumbnailUrl", resolveWithBase(meta.host, firstImage));
else if (firstImage?.["@id"])
setIfEmpty(node, "thumbnailUrl", find(firstImage["@id"])?.url);
}
if (identity) {
setIfEmpty(node, "publisher", idReference(identity));
setIfEmpty(node, "author", idReference(identity));
}
if (webPage) {
setIfEmpty(node, "isPartOf", idReference(webPage));
setIfEmpty(node, "mainEntityOfPage", idReference(webPage));
setIfEmpty(webPage, "potentialAction", [
{
"@type": "ReadAction",
"target": [meta.url]
}
]);
setIfEmpty(webPage, "dateModified", node.dateModified);
setIfEmpty(webPage, "datePublished", node.datePublished);
}
return node;
}
});
const bookEditionResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Book"
},
inheritMeta: [
"inLanguage"
],
resolve(node, ctx) {
if (node.bookFormat)
node.bookFormat = withBase(node.bookFormat, "https://schema.org/");
if (node.datePublished)
node.datePublished = resolvableDateToDate(node.datePublished);
node.author = resolveRelation(node.author, ctx);
return node;
},
resolveRootNode(node, { find }) {
const identity = find(IdentityId);
if (identity)
setIfEmpty(node, "provider", idReference(identity));
return node;
}
});
const PrimaryBookId = "#book";
const bookResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Book"
},
inheritMeta: [
"description",
"url",
{ meta: "title", key: "name" }
],
idPrefix: ["url", PrimaryBookId],
resolve(node, ctx) {
node.workExample = resolveRelation(node.workExample, ctx, bookEditionResolver);
node.author = resolveRelation(node.author, ctx);
if (node.url)
withBase(node.url, ctx.meta.host);
return node;
},
resolveRootNode(node, { find }) {
const identity = find(IdentityId);
if (identity)
setIfEmpty(node, "author", idReference(identity));
return node;
}
});
const commentResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Comment"
},
idPrefix: "url",
resolve(node, ctx) {
node.author = resolveRelation(node.author, ctx, personResolver, {
root: true
});
return node;
},
resolveRootNode(node, { find }) {
const article = find(PrimaryArticleId);
if (article)
setIfEmpty(node, "about", idReference(article));
}
});
const courseResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Course"
},
resolve(node, ctx) {
node.provider = resolveRelation(node.provider, ctx, organizationResolver, {
root: true
});
return node;
},
resolveRootNode(node, { find }) {
const identity = find(IdentityId);
if (identity)
setIfEmpty(node, "provider", idReference(identity));
return node;
}
});
const placeResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Place"
},
resolve(node, ctx) {
if (typeof node.address !== "string")
node.address = resolveRelation(node.address, ctx, addressResolver);
return node;
}
});
const virtualLocationResolver = defineSchemaOrgResolver({
cast(node) {
if (typeof node === "string") {
return {
url: node
};
}
return node;
},
defaults: {
"@type": "VirtualLocation"
}
});
const PrimaryEventId = "#event";
const eventResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Event"
},
inheritMeta: [
"inLanguage",
"description",
"image",
{ meta: "title", key: "name" }
],
idPrefix: ["url", PrimaryEventId],
resolve(node, ctx) {
if (node.location) {
const isVirtual = node.location === "string" || node.location?.url !== "undefined";
node.location = resolveRelation(node.location, ctx, isVirtual ? virtualLocationResolver : placeResolver);
}
node.performer = resolveRelation(node.performer, ctx, personResolver, {
root: true
});
node.organizer = resolveRelation(node.organizer, ctx, organizationResolver, {
root: true
});
node.offers = resolveRelation(node.offers, ctx, offerResolver);
if (node.eventAttendanceMode)
node.eventAttendanceMode = withBase(node.eventAttendanceMode, "https://schema.org/");
if (node.eventStatus)
node.eventStatus = withBase(node.eventStatus, "https://schema.org/");
const isOnline = node.eventStatus === "https://schema.org/EventMovedOnline";
const dates = ["startDate", "previousStartDate", "endDate"];
dates.forEach((date) => {
if (!isOnline) {
if (node[date] instanceof Date && node[date].getHours() === 0 && node[date].getMinutes() === 0)
node[date] = resolvableDateToDate(node[date]);
} else {
node[date] = resolvableDateToIso(node[date]);
}
});
setIfEmpty(node, "endDate", node.startDate);
return node;
},
resolveRootNode(node, { find }) {
const identity = find(IdentityId);
if (identity)
setIfEmpty(node, "organizer", idReference(identity));
}
});
const howToStepDirectionResolver = defineSchemaOrgResolver({
cast(node) {
if (typeof node === "string") {
return {
text: node
};
}
return node;
},
defaults: {
"@type": "HowToDirection"
}
});
const howToStepResolver = defineSchemaOrgResolver({
cast(node) {
if (typeof node === "string") {
return {
text: node
};
}
return node;
},
defaults: {
"@type": "HowToStep"
},
resolve(step, ctx) {
if (step.url)
step.url = resolveWithBase(ctx.meta.url, step.url);
if (step.image) {
step.image = resolveRelation(step.image, ctx, imageResolver, {
root: true
});
}
if (step.itemListElement)
step.itemListElement = resolveRelation(step.itemListElement, ctx, howToStepDirectionResolver);
return step;
}
});
const HowToId = "#howto";
const howToResolver = defineSchemaOrgResolver({
defaults: {
"@type": "HowTo"
},
inheritMeta: [
"description",
"image",
"inLanguage",
{ meta: "title", key: "name" }
],
idPrefix: ["url", HowToId],
resolve(node, ctx) {
node.step = resolveRelation(node.step, ctx, howToStepResolver);
return node;
},
resolveRootNode(node, { find }) {
const webPage = find(PrimaryWebPageId);
if (webPage)
setIfEmpty(node, "mainEntityOfPage", idReference(webPage));
}
});
const itemListResolver = defineSchemaOrgResolver({
defaults: {
"@type": "ItemList"
},
resolve(node, ctx) {
if (node.itemListElement) {
let index = 1;
node.itemListElement = resolveRelation(node.itemListElement, ctx, listItemResolver, {
array: true,
afterResolve(node2) {
setIfEmpty(node2, "position", index++);
}
});
}
return node;
}
});
const quantitativeValueResolver = defineSchemaOrgResolver({
defaults: {
"@type": "QuantitativeValue"
}
});
const monetaryAmountResolver = defineSchemaOrgResolver({
defaults: {
"@type": "MonetaryAmount"
},
resolve(node, ctx) {
node.value = resolveRelation(node.value, ctx, quantitativeValueResolver);
return node;
}
});
const jobPostingResolver = defineSchemaOrgResolver({
defaults: {
"@type": "JobPosting"
},
resolve(node, ctx) {
node.datePosted = resolvableDateToIso(node.datePosted);
node.hiringOrganization = resolveRelation(node.hiringOrganization, ctx, organizationResolver);
node.jobLocation = resolveRelation(node.jobLocation, ctx, placeResolver);
node.baseSalary = resolveRelation(node.baseSalary, ctx, monetaryAmountResolver);
node.validThrough = resolvableDateToIso(node.validThrough);
return node;
}
});
const openingHoursResolver = defineSchemaOrgResolver({
defaults: {
"@type": "OpeningHoursSpecification",
"opens": "00:00",
"closes": "23:59"
}
});
const localBusinessResolver = defineSchemaOrgResolver({
defaults: {
"@type": ["Organization", "LocalBusiness"]
},
inheritMeta: [
{ key: "url", meta: "host" },
{ key: "currenciesAccepted", meta: "currency" }
],
idPrefix: ["host", IdentityId],
resolve(node, ctx) {
resolveDefaultType(node, ["Organization", "LocalBusiness"]);
node.address = resolveRelation(node.address, ctx, addressResolver);
node.openingHoursSpecification = resolveRelation(node.openingHoursSpecification, ctx, openingHoursResolver);
node.logo = resolveRelation(node.logo, ctx, imageResolver, {
afterResolve(logo) {
const hasLogo = !!ctx.find("#logo");
if (!hasLogo)
logo["@id"] = prefixId(ctx.meta.host, "#logo");
setIfEmpty(logo, "caption", node.name);
}
});
return node;
}
});
const ratingResolver = defineSchemaOrgResolver({
cast(node) {
if (node === "number") {
return {
ratingValue: node
};
}
return node;
},
defaults: {
"@type": "Rating",
"bestRating": 5,
"worstRating": 1
}
});
const reviewResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Review"
},
inheritMeta: [
"inLanguage"
],
resolve(review, ctx) {
review.reviewRating = resolveRelation(review.reviewRating, ctx, ratingResolver);
review.author = resolveRelation(review.author, ctx, personResolver);
return review;
}
});
const videoResolver = defineSchemaOrgResolver({
cast(input) {
if (typeof input === "string") {
input = {
url: input
};
}
return input;
},
alias: "video",
defaults: {
"@type": "VideoObject"
},
inheritMeta: [
{ meta: "title", key: "name" },
"description",
"image",
"inLanguage",
{ meta: "datePublished", key: "uploadDate" }
],
idPrefix: "host",
resolve(video, ctx) {
if (video.uploadDate)
video.uploadDate = resolvableDateToIso(video.uploadDate);
video.url = resolveWithBase(ctx.meta.host, video.url);
if (video.caption && !video.description)
video.description = video.caption;
if (!video.description)
video.description = "No description";
if (video.thumbnailUrl)
video.thumbnailUrl = resolveRelation(video.thumbnailUrl, ctx, imageResolver);
return video;
},
resolveRootNode(video, { find }) {
if (video.image && !video.thumbnailUrl) {
const firstImage = asArray(video.image)[0];
setIfEmpty(video, "thumbnailUrl", find(firstImage["@id"])?.url);
}
}
});
const movieResolver = defineSchemaOrgResolver({
defaults: {
"@type": "Movie"
},
resolve(node, ctx) {
node.aggregateRating = resolveRelation(node.aggregateRating, ctx, aggregateRatingResolver);
node.review = resolveRelation(node.review, ctx, reviewResolver);
node.director = resolveRelation(node.director, ctx, personResolver);
node.actor = resolveRelation(node.actor, ctx, personResolver);
node.trailer = resolveRelation(node.trailer, ctx, videoResolver);
if (node.dateCreated)
node.dateCreated = resolvableDateToDate(node.dateCreated);
return node;
}
});
const defaults = {
ignoreUnknown: false,
respectType: false,
respectFunctionNames: false,
respectFunctionProperties: false,
unorderedObjects: true,
unorderedArrays: false,
unorderedSets: false
};
function objectHash(object, options = {}) {
options = { ...defaults, ...options };
const hasher = createHasher(options);
hasher.dispatch(object);
return hasher.toString();
}
function createHasher(options) {
const buff = [];
let context = [];
const write = (str) => {
buff.push(str);
};
return {
toString() {
return buff.join("");
},
getContext() {
return context;
},
dispatch(value) {
if (options.replacer) {
value = options.replacer(value);
}
const type = value === null ? "null" : typeof value;
return this["_" + type](value);
},
_object(object) {
if (object && typeof object.toJSON === "function") {
return this._object(object.toJSON());
}
const pattern = /\[object (.*)]/i;
const objString = Object.prototype.toString.call(object);
const _objType = pattern.exec(objString);
const objType = _objType ? _objType[1].toLowerCase() : "unknown:[" + objString.toLowerCase() + "]";
let objectNumber = null;
if ((objectNumber = context.indexOf(object)) >= 0) {
return this.dispatch("[CIRCULAR:" + objectNumber + "]");
} else {
context.push(object);
}
if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
write("buffer:");
return write(object.toString("utf8"));
}
if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
if (this["_" + objType]) {
this["_" + objType](object);
} else if (!options.ignoreUnknown) {
this._unkown(object, objType);
}
} else {
let keys = Object.keys(object);
if (options.unorderedObjects) {
keys = keys.sort();
}
if (options.respectType !== false && !isNativeFunction(object)) {
keys.splice(0, 0, "prototype", "__proto__", "letructor");
}
if (options.excludeKeys) {
keys = keys.filter(function(key) {
return !options.excludeKeys(key);
});
}
write("object:" + keys.length + ":");
for (const key of keys) {
this.dispatch(key);
write(":");
if (!options.excludeValues) {
this.dispatch(object[key]);
}
write(",");
}
}
},
_array(arr, unordered) {
unordered = typeof unordered !== "undefined" ? unordered : options.unorderedArrays !== false;
write("array:" + arr.length + ":");
if (!unordered || arr.length <= 1) {
for (const entry of arr) {
this.dispatch(entry);
}
return;
}
const contextAdditions = [];
const entries = arr.map((entry) => {
const hasher = createHasher(options);
hasher.dispatch(entry);
contextAdditions.push(hasher.getContext());
return hasher.toString();
});
context = [...context, ...contextAdditions];
entries.sort();
return this._array(entries, false);
},
_date(date) {
return write("date:" + date.toJSON());
},
_symbol(sym) {
return write("symbol:" + sym.toString());
},
_unkown(value, type) {
write(type);
if (!value) {
return;
}
write(":");
if (value && typeof value.entries === "function") {
return this._array(
Array.from(value.entries()),
true
/* ordered */
);
}
},
_error(err) {
return write("error:" + err.toString());
},
_boolean(bool) {
return write("bool:" + bool.toString());
},
_string(string) {
write("string:" + string.length + ":");
write(string.toString());
},
_function(fn) {
write("fn:");
if (isNativeFunction(fn)) {
this.dispatch("[native]");
} else {
this.dispatch(fn.toString());
}
if (options.respectFunctionNames !== false) {
this.dispatch("function-name:" + String(fn.name));
}
if (options.respectFunctionProperties) {
this._object(fn);
}
},
_number(number) {
return write("number:" + number.toString());
},
_xml(xml) {
return write("xml:" + xml.toString());
},
_null() {
return write("Null");
},
_undefined() {
return write("Undefined");
},
_regexp(regex) {
return write("regex:" + regex.toString());
},
_uint8array(arr) {
write("uint8array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_uint8clampedarray(arr) {
write("uint8clampedarray:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_int8array(arr) {
write("int8array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_uint16array(arr) {
write("uint16array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_int16array(arr) {
write("int16array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_uint32array(arr) {
write("uint32array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_int32array(arr) {
write("int32array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_float32array(arr) {
write("float32array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_float64array(arr) {
write("float64array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
_arraybuffer(arr) {
write("arraybuffer:");
return this.dispatch(new Uint8Array(arr));
},
_url(url) {
return write("url:" + url.toString());
},
_map(map) {
write("map:");
const arr = [...map];
return this._array(arr, options.unorderedSets !== false);
},
_set(set) {
write("set:");
const arr = [...set];
return this._array(arr, options.unorderedSets !== false);
},
_file(file) {
write("file:");
return this.dispatch([file.name, file.size, file.type, file.lastModfied]);
},
_blob() {
if (options.ignoreUnknown) {
return write("[blob]");
}
throw new Error(
'Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n'
);
},
_domwindow() {
return write("domwindow");
},
_bigint(number) {
return write("bigint:" + number.toString());
},
/* Node.js standard native objects */
_process() {
return write("process");
},
_timer() {
return write("timer");
},
_pipe() {
return write("pipe");
},
_tcp() {
return write("tcp");
},
_udp() {
return write("udp");
},
_tty() {
return write("tty");
},
_statwatcher() {
return write("statwatcher");
},
_securecontext() {
return write("securecontext");
},
_connection() {
return write("connection");
},
_zlib() {
return write("zlib");
},
_context() {
return write("context");
},
_nodescript() {
return write("nodescript");
},
_httpparser() {
return write("httpparser");
},
_dataview() {
return write("dataview");
},
_signal() {
return write("signal");
},
_fsevent() {
return write("fsevent");
},
_tlswrap() {
return write("tlswrap");
}
};
}
function isNativeFunction(f) {
if (typeof f !== "function") {
return false;
}
const exp = /^function\s+\w*\s*\(\s*\)\s*{\s+\[native code]\s+}$/i;
return exp.exec(Function.prototype.toString.call(f)) != null;
}
class WordArray {
constructor(words, sigBytes) {
words = this.words = words || [];
this.sigBytes = sigBytes !== void 0 ? sigBytes : words.length * 4;
}
toString(encoder) {
return (encoder || Hex).stringify(this);
}
concat(wordArray) {
this.clamp();
if (this.sigBytes % 4) {
for (let i = 0; i < wordArray.sigBytes; i++) {
const thatByte = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
this.words[this.sigBytes + i >>> 2] |= thatByte << 24 - (this.sigBytes + i) % 4 * 8;
}
} else {
for (let j = 0; j < wordArray.sigBytes; j += 4) {
this.words[this.sigBytes + j >>> 2] = wordArray.words[j >>> 2];
}
}
this.sigBytes += wordArray.sigBytes;
return this;
}
clamp() {
this.words[this.sigBytes >>> 2] &= 4294967295 << 32 - this.sigBytes % 4 * 8;
this.words.length = Math.ceil(this.sigBytes / 4);
}
clone() {
return new WordArray([...this.words]);
}
}
const Hex = {
stringify(wordArray) {
const hexChars = [];
for (let i = 0; i < wordArray.sigBytes; i++) {
const bite = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
hexChars.push((bite >>> 4).toString(16), (bite & 15).toString(16));
}
return hexChars.join("");
}
};
const Base64 = {
stringify(wordArray) {
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const base64Chars = [];
for (let i = 0; i < wordArray.sigBytes; i += 3) {
const byte1 = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
const byte2 = wordArray.words[i + 1 >>> 2] >>> 24 - (i + 1) % 4 * 8 & 255;
const byte3 = wordArray.words[i + 2 >>> 2] >>> 24 - (i + 2) % 4 * 8 & 255;
const triplet = byte1 << 16 | byte2 << 8 | byte3;
for (let j = 0; j < 4 && i * 8 + j * 6 < wordArray.sigBytes * 8; j++) {
base64Chars.push(keyStr.charAt(triplet >>> 6 * (3 - j) & 63));
}
}
return base64Chars.join("");
}
};
const Latin1 = {
parse(latin1Str) {
const latin1StrLength = latin1Str.length;
const words = [];
for (let i = 0; i < latin1StrLength; i++) {
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << 24 - i % 4 * 8;
}
return new WordArray(words, latin1StrLength);
}
};
const Utf8 = {
parse(utf8Str) {
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
}
};
class BufferedBlockAlgorithm {
constructor() {
this._minBufferSize = 0;
this.blockSize = 512 / 32;
this.reset();
}
reset() {
this._data = new WordArray();
this._nDataBytes = 0;
}
_append(data) {
if (typeof data === "string") {
data = Utf8.parse(data);
}
this._data.concat(data);
this._nDataBytes += data.sigBytes;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_doProcessBlock(_dataWords, _offset) {
}
_process(doFlush) {
let processedWords;
let nBlocksReady = this._data.sigBytes / (this.blockSize * 4);
if (doFlush) {
nBlocksReady = Math.ceil(nBlocksReady);
} else {
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
}
const nWordsReady = nBlocksReady * this.blockSize;
const nBytesReady = Math.min(nWordsReady * 4, this._data.sigBytes);
if (nWordsReady) {
for (let offset = 0; offset < nWordsReady; offset += this.blockSize) {
this._doProcessBlock(this._data.words, offset);
}
processedWords = this._data.words.splice(0, nWordsReady);
this._data.sigBytes -= nBytesReady;
}
return new WordArray(processedWords, nBytesReady);
}
}
class Hasher extends BufferedBlockAlgorithm {
update(messageUpdate) {
this._append(messageUpdate);
this._process();
return this;
}
finalize(messageUpdate) {
if (messageUpdate) {
this._append(messageUpdate);
}
}
}
const H = [
1779033703,
-1150833019,
1013904242,
-1521486534,
1359893119,
-1694144372,
528734635,
1541459225
];
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
];
const W = [];
class SHA256 extends Hasher {
constructor() {
super();
this.reset();
}
reset() {
super.reset();
this._hash = new WordArray([...H]);
}
_doProcessBlock(M, offset) {
const H2 = this._hash.words;
let a = H2[0];
let b = H2[1];
let c = H2[2];
let d = H2[3];
let e = H2[4];
let f = H2[5];
let g = H2[6];
let h = H2[7];
for (let i = 0; i < 64; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0;
} else {
const gamma0x = W[i - 15];
const gamma0 = (gamma0x << 25 | gamma0x >>> 7