diff --git a/docs/configuration/overview.mdx b/docs/configuration/overview.mdx index dd697723cd6..b5ed2f23b0d 100644 --- a/docs/configuration/overview.mdx +++ b/docs/configuration/overview.mdx @@ -101,6 +101,7 @@ The following options are available: | **`i18n`** | Internationalization configuration. Pass all i18n languages you'd like the admin UI to support. Defaults to English-only. [More details](./i18n). | | **`secret`** \* | A secure, unguessable string that Payload will use for any encryption workflows - for example, password salt / hashing. | | **`sharp`** | If you would like Payload to offer cropping, focal point selection, and automatic media resizing, install and pass the Sharp module to the config here. | +| **`slugify`** | Override the default slugify function for all slug fields. Can be overridden at field level. [More details](#custom-slugify-function). | | **`typescript`** | Configure TypeScript settings here. [More details](#typescript). | _\* An asterisk denotes that a property is required._ @@ -250,6 +251,45 @@ export default buildConfig({ }) ``` +## Custom Slugify Function + +You can override the default slugify function for all slug fields across your application. This is useful when you need special character encoding, additional language support, or consistent slug formatting across all collections. + +The config-level `slugify` function can be overridden at the field level if needed. + +```ts +import { buildConfig } from 'payload' +import slugify from 'slugify' + +export default buildConfig({ + // ... + // highlight-start + slugify: ({ valueToSlugify }) => + slugify(valueToSlugify, { + lower: true, + strict: true, + // ...additional `slugify` options here + }), + // highlight-end +}) +``` + +The following args are provided to the custom `slugify` function: + +| Argument | Type | Description | +| ---------------- | ---------------- | ------------------------------------------------ | +| `valueToSlugify` | `string` | The value of the field specified in `useAsSlug`. | +| `data` | `object` | The full document data being saved. | +| `req` | `PayloadRequest` | The Payload request object. | + +**Priority order:** + +1. Field-level `slugify` (if defined) +2. Config-level `slugify` (if defined) +3. Default `slugify` function + +For more details on field-level overrides, see the [Slug Field documentation](../fields/text#custom-slugify-function). + ## TypeScript You can import types from Payload to help make writing your config easier and type-safe. There are two main types that represent the Payload Config, `Config` and `SanitizedConfig`. diff --git a/docs/fields/text.mdx b/docs/fields/text.mdx index d42bbc95a34..0ea69cebfbf 100644 --- a/docs/fields/text.mdx +++ b/docs/fields/text.mdx @@ -249,9 +249,11 @@ export const ExampleCollection: CollectionConfig = { ### Custom Slugify Function -You can also override the default slugify function of the slug field. This is necessary if the slug requires special treatment, such as character encoding, additional language support, etc. +You can override the default slugify function of the slug field. This is necessary if the slug requires special treatment, such as character encoding, additional language support, etc. -This functions receives the value of the `useAsSlug` field as `valueToSlugify` and must return a string. +You can also set a global default slugify function in the [Payload Config](../configuration/overview#custom-slugify-function) that will apply to all slug fields across your application. Field-level slugify will override the config-level setting. + +This function receives the value of the `useAsSlug` field as `valueToSlugify` and must return a string. For example, if you wanted to use the [`slugify`](https://www.npmjs.com/package/slugify) package, you could do something like this: diff --git a/packages/next/src/utilities/slugify.ts b/packages/next/src/utilities/slugify.ts index fa64c640bca..21fece32a27 100644 --- a/packages/next/src/utilities/slugify.ts +++ b/packages/next/src/utilities/slugify.ts @@ -46,12 +46,16 @@ export const slugifyHandler: ServerFunction< path, }) - const customSlugify = ( + const fieldLevelSlugify = ( typeof field?.custom?.slugify === 'function' ? field.custom.slugify : undefined ) as Slugify - const result = customSlugify - ? await customSlugify({ data, req, valueToSlugify }) + const configLevelSlugify = req.payload.config.slugify + + const slugifyToUse = fieldLevelSlugify || configLevelSlugify + + const result = slugifyToUse + ? await slugifyToUse({ data, req, valueToSlugify }) : defaultSlugify(valueToSlugify) return result diff --git a/packages/payload/src/config/client.ts b/packages/payload/src/config/client.ts index 6f09d5a3a76..f480214494f 100644 --- a/packages/payload/src/config/client.ts +++ b/packages/payload/src/config/client.ts @@ -38,6 +38,7 @@ export type ServerOnlyRootProperties = keyof Pick< | 'queryPresets' | 'secret' | 'sharp' + | 'slugify' | 'typescript' > @@ -80,6 +81,7 @@ export const serverOnlyConfigProperties: readonly Partial> const slugify = ({ - customSlugify, + customSlugify: fieldLevelSlugify, data, req, valueToSlugify, @@ -21,6 +21,9 @@ const slugify = ({ req: PayloadRequest valueToSlugify?: string }) => { + const configLevelSlugify = req.payload.config.slugify + const customSlugify = fieldLevelSlugify || configLevelSlugify + if (customSlugify) { return customSlugify({ data, req, valueToSlugify }) }