nuxt-schema-org
Version:
The quickest and easiest way to build Schema.org graphs for Nuxt.
100 lines (99 loc) • 3.19 kB
JavaScript
import { injectHead, useHead } from "#imports";
import {
useSiteConfig
} from "#site-config/app/composables/useSiteConfig";
import { createSitePathResolver } from "#site-config/app/composables/utils";
import { SchemaOrgUnheadPlugin } from "@unhead/schema-org/vue";
import { useRoute } from "nuxt/app";
import { camelCase } from "scule";
import { withTrailingSlash } from "ufo";
import { computed, toValue, watch } from "vue";
import { useSchemaOrg } from "../composables/useSchemaOrg.js";
import { useSchemaOrgConfig } from "./config.js";
export function initPlugin(nuxtApp) {
const head = injectHead();
const config = useSchemaOrgConfig();
const route = useRoute();
const siteConfig = useSiteConfig();
const resolvePath = createSitePathResolver({
absolute: false,
withBase: true
});
const resolveUrl = createSitePathResolver({
canonical: true,
absolute: true,
withBase: true
});
const schemaOrg = computed(() => {
const siteConfigResolved = {};
for (const key in siteConfig) {
if (key.startsWith("_")) {
continue;
}
siteConfigResolved[key] = toValue(siteConfig[key]);
if (typeof siteConfigResolved[key] === "object") {
for (const k in siteConfigResolved[key]) {
siteConfigResolved[key][k] = toValue(siteConfigResolved[key][k]);
}
}
}
return {
...route.meta?.schemaOrg || {},
...siteConfigResolved,
url: toValue(resolveUrl(route.path)),
host: withTrailingSlash(siteConfigResolved.url),
inLanguage: toValue(siteConfigResolved.currentLocale) || toValue(siteConfigResolved.defaultLocale),
path: toValue(resolvePath(route.path))
};
});
const templateParamEntry = useHead({
templateParams: { schemaOrg: schemaOrg.value }
});
watch(() => siteConfig, () => {
templateParamEntry.patch({
templateParams: { schemaOrg: schemaOrg.value }
});
}, { deep: true });
head.use(
SchemaOrgUnheadPlugin({}, async () => {
const meta = {};
await nuxtApp.hooks.callHook("schema-org:meta", meta);
return meta;
}, {
minify: config.minify,
trailingSlash: siteConfig.trailingSlash
})
);
}
export function maybeAddIdentitySchemaOrg() {
const config = useSchemaOrgConfig();
const siteConfig = useSiteConfig({
resolveRefs: true
});
if (config.identity || siteConfig.identity) {
const identity = config.identity || siteConfig.identity;
let identityPayload = {
name: () => toValue(siteConfig.name),
url: () => toValue(siteConfig.url)
};
let identityType;
if (typeof identity !== "string") {
identityPayload = {
...identityPayload,
...identity
};
identityType = identity.type;
delete identityPayload.type;
} else {
identityType = identity;
}
if (siteConfig.twitter) {
const id = siteConfig.twitter.startsWith("@") ? siteConfig.twitter.slice(1) : siteConfig.twitter;
identityPayload.sameAs = [
`https://twitter.com/${id}`
];
}
identityPayload._resolver = identityPayload._resolver || camelCase(identityType);
useSchemaOrg([identityPayload]);
}
}