Skip to content

Instantly share code, notes, and snippets.

@DeveloperOfficeCom
Created July 19, 2025 20:00
Show Gist options
  • Select an option

  • Save DeveloperOfficeCom/9fa0199327827bbe20200bf2737fe67b to your computer and use it in GitHub Desktop.

Select an option

Save DeveloperOfficeCom/9fa0199327827bbe20200bf2737fe67b to your computer and use it in GitHub Desktop.
ColdFusion implementation of string slug generator - Creates URL-safe slugs from text with support for accented characters, custom separators, and max length
ColdFusion implementation of string slug generator - Creates URL-safe slugs from text with support for accented characters, custom separators, and max length
<!---
STRINGSLUG Function
Description: Generates a URL-safe slug from a string by converting to lowercase, replacing spaces
with hyphens, removing special characters, and handling accented characters. Similar to slug
generation in Django or other web frameworks.
Parameters:
- text: The text to convert to a slug (required)
- separator: Character to use as separator (optional, default: "-")
- maxLength: Maximum length of the slug (optional, default: 0 = no limit)
- allowUnicode: Allow unicode characters (optional, default: false)
Returns: URL-safe slug string
Usage:
<cfset slug = stringslug("Hello World!")>
<cfset slug = stringslug("This is a Test!", "_")>
<cfset slug = stringslug("Very long title here", "-", 20)>
Examples:
stringslug("Hello World!") returns "hello-world"
stringslug("This & That") returns "this-that"
stringslug("Café Münchën") returns "cafe-munchen"
Author: DeveloperOffice.com
Language: ColdFusion/Lucee
License: MIT (https://opensource.org/licenses/MIT)
Version: 1.0
--->
<cffunction name="stringslug" returntype="string" output="false">
<cfargument name="text" type="string" required="true">
<cfargument name="separator" type="string" required="false" default="-">
<cfargument name="maxLength" type="numeric" required="false" default="0">
<cfargument name="allowUnicode" type="boolean" required="false" default="false">
<cfset var slug = arguments.text>
<!--- Convert to lowercase --->
<cfset slug = lCase(slug)>
<!--- Replace accented characters with their non-accented equivalents --->
<cfif NOT arguments.allowUnicode>
<!--- Common accented characters mapping --->
<cfset var accents = {
"à": "a", "á": "a", "ä": "a", "â": "a", "ã": "a", "å": "a", "ą": "a",
"è": "e", "é": "e", "ë": "e", "ê": "e", "ę": "e", "ė": "e",
"ì": "i", "í": "i", "ï": "i", "î": "i", "į": "i",
"ò": "o", "ó": "o", "ö": "o", "ô": "o", "õ": "o", "ø": "o",
"ù": "u", "ú": "u", "ü": "u", "û": "u", "ų": "u",
"ñ": "n", "ň": "n", "ń": "n",
"ç": "c", "č": "c", "ć": "c",
"ğ": "g", "ģ": "g",
"ř": "r",
"ş": "s", "š": "s", "ś": "s",
"ť": "t", "ţ": "t",
"ý": "y", "ÿ": "y",
"ž": "z", "ź": "z", "ż": "z",
"đ": "d", "ď": "d",
"ľ": "l", "ļ": "l", "ł": "l",
"æ": "ae", "œ": "oe", "ß": "ss"
}>
<!--- Replace accented characters --->
<cfloop collection="#accents#" item="accent">
<cfset slug = replace(slug, accent, accents[accent], "all")>
</cfloop>
</cfif>
<!--- Replace spaces and underscores with separator --->
<cfset slug = reReplace(slug, "[\s_]+", arguments.separator, "all")>
<!--- Remove all non-alphanumeric characters except separator --->
<cfif arguments.allowUnicode>
<!--- Allow unicode letters and numbers --->
<cfset slug = reReplace(slug, "[^a-zA-Z0-9\u0080-\uFFFF#arguments.separator#]+", "", "all")>
<cfelse>
<!--- Only allow ASCII letters and numbers --->
<cfset slug = reReplace(slug, "[^a-zA-Z0-9#arguments.separator#]+", "", "all")>
</cfif>
<!--- Replace multiple separators with single separator --->
<cfset slug = reReplace(slug, "[#arguments.separator#]+", arguments.separator, "all")>
<!--- Trim separators from beginning and end --->
<cfset slug = reReplace(slug, "^[#arguments.separator#]+|[#arguments.separator#]+$", "", "all")>
<!--- Apply max length if specified --->
<cfif arguments.maxLength GT 0 AND len(slug) GT arguments.maxLength>
<cfset slug = left(slug, arguments.maxLength)>
<!--- If truncated at a separator, remove it --->
<cfif right(slug, 1) EQ arguments.separator>
<cfset slug = left(slug, len(slug) - 1)>
</cfif>
<!--- If truncated in middle of word, try to cut at last separator --->
<cfset var lastSeparator = findLast(arguments.separator, slug)>
<cfif lastSeparator GT 0 AND lastSeparator GT (arguments.maxLength * 0.7)>
<cfset slug = left(slug, lastSeparator - 1)>
</cfif>
</cfif>
<!--- Return empty string as fallback if slug is empty --->
<cfif len(trim(slug)) EQ 0>
<cfset slug = "">
</cfif>
<cfreturn slug>
</cffunction>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment