init commit for iPAL-kit plugin
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import type { Field, FieldHook, TextField } from 'payload'
|
||||
|
||||
import slugify from 'slugify'
|
||||
|
||||
/**
|
||||
* Normalizes a string into a URL slug. slugify handles diacritics out of the
|
||||
* box (Polish included: "Strona główna" → "strona-glowna").
|
||||
*/
|
||||
export function toSlug(input: string): string {
|
||||
return slugify(input, {
|
||||
lower: true,
|
||||
strict: true, // drop characters that aren't url-safe
|
||||
trim: true,
|
||||
})
|
||||
}
|
||||
|
||||
type BuildSlugFieldOptions = {
|
||||
/** Source field to derive the slug from. Default: 'title'. */
|
||||
from?: string
|
||||
/** Whether the slug is localized (per-locale). Default: true. */
|
||||
localized?: boolean
|
||||
/** Field name for the slug. Default: 'slug'. */
|
||||
name?: string
|
||||
/** Override or extend the generated field config. */
|
||||
overrides?: Partial<TextField>
|
||||
/** Whether the slug is required. Default: true. */
|
||||
required?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a slug field that auto-generates from a source field (default 'title')
|
||||
* only when left empty — an editor's manual slug is never overwritten (mode 4a).
|
||||
*
|
||||
* Localized-safe: on a localized field Payload runs the hook per locale, so
|
||||
* `value` is the slug for the active locale and `siblingData[from]` is the
|
||||
* source in that same locale. Editing the doc in 'pl' fills slug.pl from
|
||||
* title.pl; editing in 'en' fills slug.en from title.en — giving genuinely
|
||||
* per-locale slugs (strona-glowna / homepage) that the language switcher needs.
|
||||
*/
|
||||
export function buildSlugField(options: BuildSlugFieldOptions = {}): Field {
|
||||
const {
|
||||
name = 'slug',
|
||||
from = 'title',
|
||||
localized = true,
|
||||
overrides = {},
|
||||
required = true,
|
||||
} = options
|
||||
|
||||
const autoGenerate: FieldHook = ({ originalDoc, siblingData, value }) => {
|
||||
// Respect a manually entered slug — only generate when empty (mode 4a).
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
return toSlug(value) // still normalize what the editor typed
|
||||
}
|
||||
|
||||
// Derive from the source field in the current locale.
|
||||
const source =
|
||||
(siblingData as Record<string, unknown>)?.[from] ??
|
||||
(originalDoc as Record<string, unknown>)?.[from]
|
||||
|
||||
if (typeof source === 'string' && source.trim()) {
|
||||
return toSlug(source)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
type: 'text',
|
||||
admin: {
|
||||
description: 'Auto-generated from the title when left empty. You can override it.',
|
||||
...overrides.admin,
|
||||
},
|
||||
hooks: {
|
||||
beforeValidate: [autoGenerate],
|
||||
},
|
||||
index: true,
|
||||
localized,
|
||||
required,
|
||||
...overrides,
|
||||
} as TextField
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { buildSlugField, toSlug } from './buildSlugField.js'
|
||||
Reference in New Issue
Block a user