Created
July 19, 2025 22:25
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!--- | |
| 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