Skip to content

Instantly share code, notes, and snippets.

@DeveloperOfficeCom
Created July 19, 2025 22:25
Show Gist options
  • Select an option

  • Save DeveloperOfficeCom/7c6f5f340e572a2170da5f21f118b302 to your computer and use it in GitHub Desktop.

Select an option

Save DeveloperOfficeCom/7c6f5f340e572a2170da5f21f118b302 to your computer and use it in GitHub Desktop.
ColdFusion implementation of intelligent string truncation - Smart truncation with word boundaries, custom suffixes, and multiple truncation positions (start, middle, end)
<!---
STRINGTRUNCATE Function
Description: Intelligently truncates a string to a specified length while preserving word boundaries.
Can add ellipsis or custom suffix, and optionally truncate from different positions (start, middle, end).
Parameters:
- text: The text to truncate (required)
- maxLength: Maximum length of the result including suffix (required)
- suffix: String to append when truncated (optional, default: "...")
- position: Where to truncate - "end", "start", or "middle" (optional, default: "end")
- breakWords: Allow breaking in middle of words (optional, default: false)
- minWordLength: Minimum word length to preserve when not breaking words (optional, default: 4)
Returns: Truncated string
Usage:
<cfset result = stringtruncate("Long text here", 10)>
<cfset result = stringtruncate("Long text", 10, "…")>
<cfset result = stringtruncate("Long text", 10, "...", "middle")>
Examples:
stringtruncate("Hello World", 8) returns "Hello..."
stringtruncate("Hello World", 11, " →") returns "Hello →"
stringtruncate("LongFilename.txt", 12, "...", "middle") returns "Long...txt"
Author: DeveloperOffice.com
Language: ColdFusion/Lucee
License: MIT (https://opensource.org/licenses/MIT)
Version: 1.0
--->
<cffunction name="stringtruncate" returntype="string" output="false">
<cfargument name="text" type="string" required="true">
<cfargument name="maxLength" type="numeric" required="true">
<cfargument name="suffix" type="string" required="false" default="...">
<cfargument name="position" type="string" required="false" default="end">
<cfargument name="breakWords" type="boolean" required="false" default="false">
<cfargument name="minWordLength" type="numeric" required="false" default="4">
<cfset var result = arguments.text>
<cfset var textLen = len(result)>
<cfset var suffixLen = len(arguments.suffix)>
<!--- If text is already short enough, return as-is --->
<cfif textLen LTE arguments.maxLength>
<cfreturn result>
</cfif>
<!--- Calculate available space for text --->
<cfset var availableLength = arguments.maxLength - suffixLen>
<!--- Ensure we have reasonable space for text --->
<cfif availableLength LT 1>
<!--- If suffix is longer than max length, just return truncated suffix --->
<cfreturn left(arguments.suffix, arguments.maxLength)>
</cfif>
<!--- Handle different truncation positions --->
<cfswitch expression="#lCase(arguments.position)#">
<cfcase value="start">
<!--- Truncate from start --->
<cfif arguments.breakWords>
<cfset result = arguments.suffix & right(result, availableLength)>
<cfelse>
<!--- Find word boundary from the start --->
<cfset var startText = right(result, availableLength + 20)>
<cfset var spacePos = find(" ", startText)>
<cfif spacePos GT 0 AND spacePos LTE 20>
<cfset result = arguments.suffix & mid(startText, spacePos + 1, len(startText))>
<cfelse>
<cfset result = arguments.suffix & right(result, availableLength)>
</cfif>
</cfif>
</cfcase>
<cfcase value="middle">
<!--- Truncate from middle --->
<cfset var halfLength = int(availableLength / 2)>
<cfset var startPart = left(result, halfLength)>
<cfset var endPart = right(result, halfLength)>
<cfif NOT arguments.breakWords>
<!--- Try to find word boundaries --->
<cfset var startBoundary = len(startPart)>
<cfset var endBoundary = 1>
<!--- Find last space in start part --->
<cfloop from="#len(startPart)#" to="1" index="i" step="-1">
<cfif mid(startPart, i, 1) EQ " ">
<cfset startBoundary = i - 1>
<cfbreak>
</cfif>
</cfloop>
<!--- Find first space in end part --->
<cfloop from="1" to="#len(endPart)#" index="i">
<cfif mid(endPart, i, 1) EQ " ">
<cfset endBoundary = i + 1>
<cfbreak>
</cfif>
</cfloop>
<cfset startPart = left(startPart, startBoundary)>
<cfset endPart = mid(endPart, endBoundary, len(endPart))>
</cfif>
<cfset result = startPart & arguments.suffix & endPart>
</cfcase>
<cfdefaultcase>
<!--- Default: truncate from end --->
<cfif arguments.breakWords>
<cfset result = left(result, availableLength) & arguments.suffix>
<cfelse>
<!--- Find last complete word that fits --->
<cfset var truncated = left(result, availableLength)>
<cfset var lastSpace = 0>
<!--- Look for last space --->
<cfloop from="#len(truncated)#" to="1" index="i" step="-1">
<cfif mid(truncated, i, 1) EQ " ">
<cfset lastSpace = i>
<cfbreak>
</cfif>
</cfloop>
<!--- If we found a space and the remaining word is long enough --->
<cfif lastSpace GT 0 AND lastSpace GTE arguments.minWordLength>
<cfset result = trim(left(result, lastSpace - 1)) & arguments.suffix>
<cfelse>
<!--- No good break point found, check if we should break the word --->
<cfif availableLength GTE arguments.minWordLength>
<cfset result = left(result, availableLength) & arguments.suffix>
<cfelse>
<!--- Very short space, just use suffix --->
<cfset result = arguments.suffix>
</cfif>
</cfif>
</cfif>
</cfdefaultcase>
</cfswitch>
<!--- Ensure result doesn't exceed max length --->
<cfif len(result) GT arguments.maxLength>
<cfset result = left(result, arguments.maxLength)>
</cfif>
<cfreturn result>
</cffunction>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment