Files
web/apps/scandic-web/server/routers/contentstack/metadata/utils/truncate.ts
Erik Tiekstra 4ae5da8a04 Feat/SW-2152 seo descriptions
* feat(SW-2152): Added improved meta descriptions for hotel pages
* feat(SW-2152): Added improved meta descriptions for destination pages
* feat(SW-2152): Refactoring metadata description functionality
* feat(SW-2152): Improved truncate function and added cities check to country page description

Approved-by: Michael Zetterberg
Approved-by: Matilda Landström
2025-04-29 06:52:04 +00:00

61 lines
2.4 KiB
TypeScript

/**
* Truncates the given text "intelligently" based on the last period found near the max length.
*
* - If a period exists within the extended range (`maxLength` to `maxLength + maxExtension`),
* the function truncates after the closest period to `maxLength`.
* - If no period is found in the range, it truncates the text after the last period found in the max length of the text.
* - If no periods exist at all, it truncates at `maxLength` and appends ellipsis (`...`).
*
* @param {string} text - The input text to be truncated.
* @param {number} [maxLength=150] - The desired maximum length of the truncated text.
* @param {number} [minLength=120] - The minimum allowable length for the truncated text.
* @param {number} [maxExtension=10] - The maximum number of characters to extend beyond `maxLength` to find a period.
* @returns {string} - The truncated text.
*/
export function truncateTextAfterLastPeriod(
text: string,
maxLength: number = 160,
minLength: number = 120,
maxExtension: number = 10
): string {
if (text.length <= maxLength) {
return text
}
// Define the extended range
const extendedEnd = Math.min(text.length, maxLength + maxExtension)
const extendedText = text.slice(0, extendedEnd)
// Find all periods within the extended range and filter after minLength to get valid periods
const periodsInRange = [...extendedText.matchAll(/\./g)].map(
({ index }) => index
)
const validPeriods = periodsInRange.filter((index) => index + 1 >= minLength)
if (validPeriods.length > 0) {
// Find the period closest to maxLength
const closestPeriod = validPeriods.reduce((closest, currentIndex) => {
const distanceFromCurrentToMaxLength = Math.abs(
currentIndex + 1 - maxLength
)
const distanceFromClosestToMaxLength = Math.abs(closest + 1 - maxLength)
return distanceFromCurrentToMaxLength < distanceFromClosestToMaxLength
? currentIndex
: closest
}, validPeriods[0])
return extendedText.slice(0, closestPeriod + 1)
}
// Fallback: If no period is found within the valid range, look for the last period in the truncated text
const maxLengthText = text.slice(0, maxLength)
const lastPeriodIndex = maxLengthText.lastIndexOf(".")
if (lastPeriodIndex !== -1) {
return text.slice(0, lastPeriodIndex + 1)
}
// Final fallback: Return maxLength text including ellipsis
return `${maxLengthText}...`
}