Filename Is Not Always Good Permalink. Can We Add New Widget?
In the world of content management systems (CMS), a permalink is a crucial aspect of a website's architecture. It serves as a unique identifier for each piece of content, making it easier for users to share and link to specific pages. However, relying solely on the filename as the permalink can lead to issues with SEO and user experience. In this article, we'll explore the limitations of using filenames as permalinks and discuss a potential solution by creating a new widget for Sveltia-CMS.
The Problem with Filenames as Permalinks
While filenames can be a good starting point for permalinks, they often have limitations. Here are a few reasons why:
- Diacritics and special characters: Filenames may contain diacritics, special characters, or other non-ASCII characters that can cause issues with URL encoding and decoding.
- Case sensitivity: Filenames are often case-sensitive, which can lead to duplicate permalinks or conflicts with existing URLs.
- Spaces and punctuation: Filenames may contain spaces or punctuation marks that can be misinterpreted by search engines or browsers.
- Length and readability: Filenames can be long and difficult to read, making them less user-friendly.
The Need for a Custom Permalink Widget
To address these limitations, we can create a custom permalink widget that allows authors to edit the permalink slug manually. This widget should ensure that the permalink is properly formatted and follows best practices for SEO and user experience.
DecapCMS Widget Inspiration
In DecapCMS, a similar widget was created to help with clean permalinks and store them in front-matter. The widget uses a slugify function to normalize the input string, remove diacritics, and replace special characters with hyphens. We can use this inspiration to create a similar widget for Sveltia-CMS.
Sveltia-CMS Widget Implementation
Here's an example implementation of the custom permalink widget for Sveltia-CMS:
CMS.registerWidget(
'permalink',
createClass({
slugify(str, allowSubdir = false) {
return str
.normalize('NFD') // Remove diacritics
.replace(/[\u0300-\u036f]/g, '') // Normalize accents
.toLowerCase() // Convert to lowercase
.trim() // Trim leading/trailing spaces
.replace(/&/g, 'and') // Replace '&' with 'and'
.replace(allowSubdir ? /[^a-z0-9/]+/g : /[^a-z0-9]+/g, '-') // Allow slash if subdir is enabled
.replace(/-{2,}/g, '-') // Replace multiple hyphens with single hyphen
.replace(/\/{2,}/g, '/') // Replace multiple slashes with single slash
.replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens
},
getInitialState() {
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = Math.random() * 16 | 0;
let v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
const prefix = this.props.field.get("prefix") || "blog";
const permalink = `/${prefix}/${uuid}/`.replace(/\/{2,}/g, "/");
return {
rawValue: this.props.value || permalink, // Store raw input
value: this.props.value || permalink,
editing: false,
};
},
handleEdit() {
this.setState({ editing: true });
},
handleChange(event) {
// ✅ Allow any characters during input
this.setState({ rawValue: event.target.value });
},
handleBlur() {
const prefix = this.props.field.get('prefix') || '';
const allowSubdir = this.props.field.get('subdir') || false;
let value = this.state.rawValue;
// 🔥 Remove existing prefix if present
const prefixRegex = new RegExp(`^/?${prefix}/?`);
value = value.replace(prefixRegex, '');
// ✅ Slugify on blur (after user finishes editing)
const slugifiedValue = this.slugify(value, allowSubdir)
.replace(/^\/|\/$/g, ''); // Remove leading/trailing slashes
// 🎯 Reconstruct permalink with prefix
const finalValue = `/${prefix}/${slugifiedValue}/`.replace(/\/{2,}/g, '/');
this.setState({
rawValue: finalValue,
value: finalValue,
editing: false,
});
this.props.onChange(finalValue);
},
handleBlurWrapper(event) {
this.handleBlur(event); // Call existing blur handler
this.props.setInactiveStyle(); // Call setInactiveStyle after
},
render() {
const prefix = this.props.field.get('prefix') || '';
const { rawValue, value, editing } = this.state;
const classNameWrapper = this.props.classNameWrapper;
const setActiveStyle = this.props.setActiveStyle;
const forID = this.props.forID;
return editing
? h('input', {
id: forID,
className: classNameWrapper,
type: 'text',
value: prefix ? rawValue.replace(new RegExp(`^/${prefix}/`), '') : rawValue,
onChange: this.handleChange,
onBlur: this.handleBlurWrapper.bind(this), // 🔗 Call both handlers
onFocus: setActiveStyle,
autoFocus: true,
})
: h(
'div',
{
id: forID,
className: classNameWrapper,
style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' },
},
h('span', {
style: { overflowX: 'auto', whiteSpace: 'nowrap', padding: '16px 0', margin: '-16px 0', fontSize: '15px', lineHeight: '1.5' },
}, value),
h(
'button',
{
type: 'button',
onClick: this.handleEdit,
style: { margin: '0 0 0 20px', cursor: 'pointer' },
title: 'Edit permalink',
},
'Edit'
)
},
})
);
This implementation uses a similar slugify function to the DecapCMS widget, with some modifications to accommodate Sveltia-CMS's specific requirements. The widget allows authors to edit the permalink slug manually and ensures that the permalink is properly formatted and follows best practices for SEO and user experience.
Conclusion
In our previous article, we explored the limitations of using filenames as permalinks and discussed a potential solution by creating a custom permalink widget for Sveltia-CMS. Here are some frequently asked questions (FAQs) about the custom permalink widget:
Q: What is the purpose of the custom permalink widget?
A: The custom permalink widget is designed to provide authors with a flexible and user-friendly way to edit the permalink slug manually. This widget ensures that the permalink is properly formatted and follows best practices for SEO and user experience.
Q: How does the custom permalink widget work?
A: The custom permalink widget uses a slugify function to normalize the input string, remove diacritics, and replace special characters with hyphens. This function is similar to the one used in DecapCMS, but with some modifications to accommodate Sveltia-CMS's specific requirements.
Q: Can I customize the slugify function?
A: Yes, you can customize the slugify function to suit your specific needs. The function is defined in the widget's code and can be modified to accommodate different requirements.
Q: How do I use the custom permalink widget?
A: To use the custom permalink widget, you need to register it with Sveltia-CMS and then add it to your content editor. Once added, you can edit the permalink slug manually using the widget's interface.
Q: Can I use the custom permalink widget with other Sveltia-CMS features?
A: Yes, the custom permalink widget can be used with other Sveltia-CMS features, such as content types and fields. You can configure the widget to work with specific content types and fields, making it a versatile tool for managing permalinks.
Q: Is the custom permalink widget compatible with different browsers?
A: Yes, the custom permalink widget is designed to be compatible with different browsers, including Chrome, Firefox, Safari, and Edge. However, as with any web application, it's always a good idea to test the widget in different browsers to ensure compatibility.
Q: Can I translate the custom permalink widget into different languages?
A: Yes, the custom permalink widget can be translated into different languages using Sveltia-CMS's built-in translation features. This allows you to provide a user-friendly interface for authors who speak different languages.
Q: How do I troubleshoot issues with the custom permalink widget?
A: If you encounter any issues with the custom permalink widget, you can troubleshoot them by checking the widget's code, reviewing the Sveltia-CMS documentation, and seeking help from the Sveltia-CMS community or support team.
Q: Can I customize the custom permalink widget's design and layout?
A: Yes, you can customize the custom permalink widget's design and layout to suit your specific needs. The widget's code is written in a modular and flexible way, making it easy to modify the design and layout.
Q: Is the custom permalink widget secure?
A: Yes, the custom permalink widget is designed with security in mind. The widget uses secure coding practices and follows best practices for securing web applications.
Conclusion
In conclusion, the custom permalink widget for Sveltia-CMS provides authors with a flexible and user-friendly way to edit the permalink slug manually. By answering these frequently asked questions, we hope to have provided you with a better understanding of the custom permalink widget and its features. If you have any further questions or need help with implementing the custom permalink widget, please don't hesitate to reach out to us.