In Contentful, when creating a new field, one of the choices is Text. Here you can choose either a short text, or long text, which again contains a couple of appearances you can choose from.
Here, we will use a short text with the slug appearance. This will enable the editors to get a slug generated from a chosen field, in this case its the entry title.
One thing I noticed about this though, is that the slug is only auto-generated before the first publish, which is fine - since you don't want to accidentally change your slug when editor other fields. When auto-generating the slug from my entry title, the value is slugified. Meaning, if I write a title with capital letters, spaces and Norwegian characters, this is converted to a appropriate slug.
What I didn't think about, was what would happen if you went back, after publishing the article and tried adding a slug with all sorts of characters? It turns out the default slug field doesn't have any validations on it, so I can update my slug to be "th!5 is æ slug" if I wanted. Maybe someone want that.. but as a web developer I do not.
In my case, the damage has already happened, where a few editors had updated some of the slugs. Luckily this was before production, but I still need to add validations to all slug fields across all content type, and update all the values that doesn't match this validations.
Contentful migrations scripts to the rescue!
Using Contentful migration scripts and the Contentful CLI we can quickly update all fields for all content types, and update the values for all fields that are necessary.
Now I can run my new script using the Contentful CLI
contentful space migration --environment-id 'update-validations-and-slugs' .\migrations\update-validations-for-slug-types.js
Now that that is done, I need to update my data for the slug fields that doesn't match the new validations.
In the code below, im first checking if the slug is a match to my validation pattern. If it matches, return null and I dont need to update the existing value. If however, the value needs to be updated I need to do a couple of steps to remove unwanted characters, removing whitespace and setting all characters to lowercase.
// return null if slug is valid, otherwise return a new slug
function getSlug(slug) {
const match = slug.match(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/)
if (match) return null
const newSlug = slugify(slug)
return newSlug
}
function slugify(inputStr) {
// Remove diacritics
inputStr = inputStr.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
inputStr = inputStr.toLowerCase()
// Replace Norwegian characters
inputStr = inputStr.replace(/ø/g, 'o')
inputStr = inputStr.replace(/æ/g, 'ae')
inputStr = inputStr.replace(/å/g, 'a')
// Replace any character that is not a lowercase letter or hyphen with a hyphen
inputStr = inputStr.replace(/[^a-z0-9-]/g, '-')
// Replace consecutive hyphens with a single one
inputStr = inputStr.replace(/-+/g, '-')
// Remove leading and trailing hyphens
inputStr = inputStr.replace(/^-+|-+$/g, '')
// If string is empty or consists only of hyphens, return a default slug
if (!inputStr) {
return ''
}
return inputStr
}
module.exports = { getSlug }
Just as before, we can now run the same CLI command for the new script as well.
contentful space migration --environment-id 'update-validations-and-slugs' .\migrations\update-slug-values.js
Now we have validations for all our slug fields, and all values that didnt match our pattern is now updated!