@payloadcms/plugin-seo
Version:
SEO plugin for Payload
232 lines (231 loc) • 11 kB
JavaScript
import { deepMergeSimple } from 'payload/shared';
import { MetaDescriptionField } from './fields/MetaDescription/index.js';
import { MetaImageField } from './fields/MetaImage/index.js';
import { MetaTitleField } from './fields/MetaTitle/index.js';
import { OverviewField } from './fields/Overview/index.js';
import { PreviewField } from './fields/Preview/index.js';
import { translations } from './translations/index.js';
export const seoPlugin = (pluginConfig)=>(config)=>{
const defaultFields = [
OverviewField({}),
MetaTitleField({
hasGenerateFn: typeof pluginConfig?.generateTitle === 'function'
}),
MetaDescriptionField({
hasGenerateFn: typeof pluginConfig?.generateDescription === 'function'
}),
...pluginConfig?.uploadsCollection ? [
MetaImageField({
hasGenerateFn: typeof pluginConfig?.generateImage === 'function',
relationTo: pluginConfig.uploadsCollection
})
] : [],
PreviewField({
hasGenerateFn: typeof pluginConfig?.generateURL === 'function'
})
];
const seoFields = [
{
name: 'meta',
type: 'group',
fields: [
...pluginConfig?.fields && typeof pluginConfig.fields === 'function' ? pluginConfig.fields({
defaultFields
}) : defaultFields
],
interfaceName: pluginConfig.interfaceName,
label: 'SEO'
}
];
return {
...config,
collections: config.collections?.map((collection)=>{
const { slug } = collection;
const isEnabled = pluginConfig?.collections?.includes(slug);
if (isEnabled) {
if (pluginConfig?.tabbedUI) {
// prevent issues with auth enabled collections having an email field that shouldn't be moved to the SEO tab
const emailField = collection.auth && !(typeof collection.auth === 'object' && collection.auth.disableLocalStrategy) && collection.fields?.find((field)=>'name' in field && field.name === 'email');
const hasOnlyEmailField = collection.fields?.length === 1 && emailField;
const seoTabs = hasOnlyEmailField ? [
{
type: 'tabs',
tabs: [
{
fields: seoFields,
label: 'SEO'
}
]
}
] : [
{
type: 'tabs',
tabs: [
// append a new tab onto the end of the tabs array, if there is one at the first index
// if needed, create a new `Content` tab in the first index for this collection's base fields
...collection?.fields?.[0]?.type === 'tabs' && collection?.fields?.[0]?.tabs ? collection.fields[0].tabs : [
{
fields: [
...emailField ? collection.fields.filter((field)=>'name' in field && field.name !== 'email') : collection.fields
],
label: collection?.labels?.singular || 'Content'
}
],
{
fields: seoFields,
label: 'SEO'
}
]
}
];
return {
...collection,
fields: [
...emailField ? [
emailField
] : [],
...seoTabs,
...collection?.fields?.[0]?.type === 'tabs' ? collection.fields.slice(1) : []
]
};
}
return {
...collection,
fields: [
...collection?.fields || [],
...seoFields
]
};
}
return collection;
}) || [],
endpoints: [
...config.endpoints ?? [],
{
handler: async (req)=>{
const data = await req.json?.();
const reqData = data ?? req.data;
const result = pluginConfig.generateTitle ? await pluginConfig.generateTitle({
...data,
collectionConfig: config.collections?.find((c)=>c.slug === reqData.collectionSlug),
globalConfig: config.globals?.find((g)=>g.slug === reqData.globalSlug),
req
}) : '';
return new Response(JSON.stringify({
result
}), {
status: 200
});
},
method: 'post',
path: '/plugin-seo/generate-title'
},
{
handler: async (req)=>{
const data = await req.json?.();
const reqData = data ?? req.data;
const result = pluginConfig.generateDescription ? await pluginConfig.generateDescription({
...data,
collectionConfig: config.collections?.find((c)=>c.slug === reqData.collectionSlug),
globalConfig: config.globals?.find((g)=>g.slug === reqData.globalSlug),
req
}) : '';
return new Response(JSON.stringify({
result
}), {
status: 200
});
},
method: 'post',
path: '/plugin-seo/generate-description'
},
{
handler: async (req)=>{
const data = await req.json?.();
const reqData = data ?? req.data;
const result = pluginConfig.generateURL ? await pluginConfig.generateURL({
...data,
collectionConfig: config.collections?.find((c)=>c.slug === reqData.collectionSlug),
globalConfig: config.globals?.find((g)=>g.slug === reqData.globalSlug),
req
}) : '';
return new Response(JSON.stringify({
result
}), {
status: 200
});
},
method: 'post',
path: '/plugin-seo/generate-url'
},
{
handler: async (req)=>{
const data = await req.json?.();
const reqData = data ?? req.data;
const result = pluginConfig.generateImage ? await pluginConfig.generateImage({
...data,
collectionConfig: config.collections?.find((c)=>c.slug === reqData.collectionSlug),
globalConfig: config.globals?.find((g)=>g.slug === reqData.globalSlug),
req
}) : '';
return new Response(JSON.stringify({
result
}), {
status: 200
});
},
method: 'post',
path: '/plugin-seo/generate-image'
}
],
globals: config.globals?.map((global)=>{
const { slug } = global;
const isEnabled = pluginConfig?.globals?.includes(slug);
if (isEnabled) {
if (pluginConfig?.tabbedUI) {
const seoTabs = [
{
type: 'tabs',
tabs: [
// append a new tab onto the end of the tabs array, if there is one at the first index
// if needed, create a new `Content` tab in the first index for this global's base fields
...global?.fields?.[0]?.type === 'tabs' && global?.fields?.[0].tabs ? global.fields[0].tabs : [
{
fields: [
...global?.fields || []
],
label: global?.label || 'Content'
}
],
{
fields: seoFields,
label: 'SEO'
}
]
}
];
return {
...global,
fields: [
...seoTabs,
...global?.fields?.[0]?.type === 'tabs' ? global.fields.slice(1) : []
]
};
}
return {
...global,
fields: [
...global?.fields || [],
...seoFields
]
};
}
return global;
}) || [],
i18n: {
...config.i18n,
translations: deepMergeSimple(translations, config.i18n?.translations ?? {})
}
};
};
//# sourceMappingURL=index.js.map