@nuxtjs/prismic
Version:
Easily connect your Nuxt application to your content hosted on Prismic
303 lines (299 loc) • 9.49 kB
JavaScript
import { existsSync } from 'node:fs';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { useLogger, defineNuxtModule, createResolver, addPlugin, addComponent, addImports, extendPages, getNuxtVersion, addTemplate } from '@nuxt/kit';
import { defu } from 'defu';
import { addDependency } from 'nypm';
import { readPackage } from 'pkg-types';
const name = "@nuxtjs/prismic";
const version = "5.2.0";
const logger = useLogger("nuxt:prismic");
async function addPrismicClient() {
try {
const pkg = await readPackage();
if (!pkg.dependencies?.["@prismicio/client"] && !pkg.devDependencies?.["@prismicio/client"]) {
await addDependency("@prismicio/client");
logger.info("Added `@prismicio/client` required peer dependency");
}
} catch {
}
}
const module$1 = defineNuxtModule({
meta: {
name,
version,
configKey: "prismic",
compatibility: { nuxt: ">=3.7.0" }
},
onInstall() {
return addPrismicClient();
},
onUpgrade(_options, _nuxt, previousVersion) {
const previousMajor = parseInt(previousVersion.split(".")[0]);
if (previousMajor < 4) {
return addPrismicClient();
}
},
defaults: (nuxt) => {
const nuxt3flavor = getNuxtVersion(nuxt).startsWith("3") && !nuxt.options?.future?.compatibilityVersion;
if (nuxt3flavor) {
return {
endpoint: "",
environment: "",
clientConfig: {},
client: "~/app/prismic/client",
linkResolver: "~/app/prismic/linkResolver",
preview: "/preview",
toolbar: true,
imports: ["vue"],
components: {
richTextComponents: "~/app/prismic/richTextComponents "
}
};
}
return {
endpoint: "",
environment: "",
client: "~/prismic/client",
linkResolver: "~/prismic/linkResolver",
clientConfig: {},
preview: "/preview",
toolbar: true,
imports: ["vue"],
components: {
richTextComponents: "~/prismic/richTextComponents"
}
};
},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url);
const moduleOptions = defu(
nuxt.options.runtimeConfig.public?.prismic,
options
);
exposeRuntimeConfig();
transpileDependencies();
const ok = proxyUserFiles();
if (!ok) return;
addRuntimePlugins();
addAutoImports();
addPreviewRoute();
extendESLintConfig();
function exposeRuntimeConfig() {
nuxt.options.runtimeConfig.public ||= {};
nuxt.options.runtimeConfig.public.prismic = moduleOptions;
}
function transpileDependencies() {
nuxt.options.build.transpile.push(
resolver.resolve("runtime"),
"@nuxtjs/prismic",
"@prismicio/vue"
);
nuxt.options.vite.optimizeDeps ||= {};
nuxt.options.vite.optimizeDeps.exclude ||= [];
nuxt.options.vite.optimizeDeps.exclude.push("@prismicio/vue");
}
function proxyUserFiles() {
const proxyUserFileWithUndefinedFallback = (filename, path) => {
const resolvedFilename = `prismic/proxy/${filename}.ts`;
const resolvedPath = path.replace(/^(~~|@@)/, nuxt.options.rootDir).replace(/^(~|@)/, nuxt.options.srcDir);
const maybeUserFile = fileExists(resolvedPath, [
"js",
"mjs",
"ts",
"vue"
]);
if (maybeUserFile) {
logger.info(
`Using user-defined \`${filename}\` at \`${maybeUserFile.replace(nuxt.options.srcDir, "~").replace(nuxt.options.rootDir, "~~").replace(/\\/g, "/")}\``
);
addTemplate({
filename: resolvedFilename,
getContents: () => `export { default } from '${path}'`
});
return true;
} else {
addTemplate({
filename: resolvedFilename,
getContents: () => "export default undefined"
});
return false;
}
};
const proxiedUserClient = proxyUserFileWithUndefinedFallback(
"client",
moduleOptions.client
);
if (!moduleOptions.endpoint && !proxiedUserClient && !process.env.NUXT_PUBLIC_PRISMIC_ENDPOINT) {
logger.warn(
`\`endpoint\` option is missing and \`${moduleOptions.client}\` was not found. At least one of them is required for the module to run. Disabling module...`
);
return false;
}
proxyUserFileWithUndefinedFallback(
"linkResolver",
moduleOptions.linkResolver
);
proxyUserFileWithUndefinedFallback(
"richTextComponents",
moduleOptions.components.richTextComponents
);
return true;
}
function addRuntimePlugins() {
addPlugin(resolver.resolve("runtime/plugin"));
addPlugin(resolver.resolve("runtime/plugin.client"));
}
function addAutoImports() {
if (!moduleOptions.imports) return;
if (moduleOptions.imports === "all" || moduleOptions.imports.includes("vue")) {
[
"PrismicImage",
"PrismicLink",
"PrismicText",
"PrismicRichText",
"PrismicTable",
"SliceZone",
"SliceSimulator"
].forEach((entry) => {
addComponent({
name: entry,
export: entry,
filePath: "@prismicio/vue"
});
});
addImports(
[
"usePrismic",
"getSliceComponentProps",
"defineSliceZoneComponents",
"getRichTextComponentProps",
"getTableComponentProps"
].map((entry) => ({
name: entry,
as: entry,
from: "@prismicio/vue"
}))
);
addImports({
name: "usePrismicPreview",
as: "usePrismicPreview",
from: resolver.resolve("runtime/usePrismicPreview")
});
}
if (moduleOptions.imports === "all" || moduleOptions.imports.includes("javascript")) {
addImports(
[
"asDate",
"asLink",
"asLinkAttrs",
"asText",
"asHTML",
"asImageSrc",
"asImageWidthSrcSet",
"asImagePixelDensitySrcSet",
"isFilled"
].map((entry) => ({
name: entry,
as: entry,
from: "@prismicio/client"
}))
);
}
if (moduleOptions.imports === "all" || moduleOptions.imports.includes("content")) {
addImports({
name: "Content",
from: "@prismicio/client",
typeFrom: "@prismicio/client",
type: true
});
}
}
function addPreviewRoute() {
if (moduleOptions.preview) {
const maybeUserPreviewPage = fileExists(
join(
nuxt.options.srcDir,
nuxt.options.dir.pages,
moduleOptions.preview
),
["js", "ts", "vue"]
);
if (maybeUserPreviewPage) {
logger.info(
`Using user-defined preview page at \`${maybeUserPreviewPage.replace(join(nuxt.options.srcDir), "~").replace(nuxt.options.rootDir, "~~").replace(
/\\/g,
"/"
)}\`, available at \`${moduleOptions.preview}\``
);
} else {
logger.info(
`Using default preview page, available at \`${moduleOptions.preview}\``
);
extendPages((pages) => {
pages.unshift({
name: "prismic-preview",
path: moduleOptions.preview,
// Checked before
file: resolver.resolve("runtime/PrismicPreview.vue")
});
});
}
if (!moduleOptions.toolbar) {
logger.warn(
"`toolbar` option is disabled but `preview` is enabled. Previews won't work unless you manually load the toolbar."
);
}
}
}
function extendESLintConfig() {
nuxt.hook(
// @ts-expect-error 3rd party hook
"eslint:config:addons",
(addons) => {
addons.push({
name: "@nuxtjs/prismic",
async getConfigs() {
const configPath = resolver.resolve(
nuxt.options.rootDir,
"slicemachine.config.json"
);
const configs = [];
try {
if (existsSync(configPath)) {
const config = JSON.parse(await readFile(configPath, "utf-8"));
if (config && "libraries" in config && Array.isArray(config.libraries)) {
configs.push(
JSON.stringify({
files: config.libraries.map(
(library) => `${library.replace("./", "")}/**/index.vue`
),
rules: {
"vue/multi-word-component-names": "off"
}
})
);
}
}
} catch {
}
return { configs };
}
});
}
);
}
}
});
function fileExists(path, extensions = ["js", "ts"]) {
if (!path) {
return null;
} else if (existsSync(path)) {
return path;
}
const extension = extensions.find(
(extension2) => existsSync(`${path}.${extension2}`)
);
return extension ? `${path}.${extension}` : null;
}
export { module$1 as default };