Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions docs/configuration/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down Expand Up @@ -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`.
Expand Down
6 changes: 4 additions & 2 deletions docs/fields/text.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
10 changes: 7 additions & 3 deletions packages/next/src/utilities/slugify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions packages/payload/src/config/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type ServerOnlyRootProperties = keyof Pick<
| 'queryPresets'
| 'secret'
| 'sharp'
| 'slugify'
| 'typescript'
>

Expand Down Expand Up @@ -80,6 +81,7 @@ export const serverOnlyConfigProperties: readonly Partial<ServerOnlyRootProperti
'editor',
'plugins',
'sharp',
'slugify',
'onInit',
'secret',
'hooks',
Expand Down
8 changes: 8 additions & 0 deletions packages/payload/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import type {
import type { DatabaseAdapterResult } from '../database/types.js'
import type { EmailAdapter, SendEmailOptions } from '../email/types.js'
import type { ErrorName } from '../errors/types.js'
import type { Slugify } from '../fields/baseFields/slug/index.js'
import type { RootFoldersConfiguration } from '../folders/types.js'
import type { GlobalConfig, Globals, SanitizedGlobalConfig } from '../globals/config/types.js'
import type {
Expand Down Expand Up @@ -1305,6 +1306,13 @@ export type Config = {
*
*/
sharp?: SharpDependency
/**
* Provide a custom slugify function to be used as the default for all slug fields.
* Can be overridden at the field level by passing a `slugify` function to `slugField()`.
*
* @see https://payloadcms.com/docs/fields/text#slug-field
*/
slugify?: Slugify
/** Send anonymous telemetry data about general usage. */
telemetry?: boolean
/** Control how typescript interfaces are generated from your collections. */
Expand Down
5 changes: 4 additions & 1 deletion packages/payload/src/fields/baseFields/slug/generateSlug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type HookArgs = {
Required<Pick<SlugFieldArgs, 'useAsSlug'>>

const slugify = ({
customSlugify,
customSlugify: fieldLevelSlugify,
data,
req,
valueToSlugify,
Expand All @@ -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 })
}
Expand Down
Loading