UNPKG

string-optimiser

Version:

A utility for generating strings that fall between certain length constraints, useful for website meta titles and meta descriptions.

116 lines 4.61 kB
export function optimiseString(input) { const { minimumLength, maximumLength, separator = ' ' } = input; if (maximumLength < minimumLength) { throw new Error('Maximum length cannot be less than minimum length'); } const bases = 'base' in input ? [input.base] : input.baseOptions; const { additionalPhraseOptions } = input; let bestResult = null; let bestScore = -1; for (const base of bases) { if (base.length > maximumLength) { continue; } let result; if (base.length >= minimumLength && additionalPhraseOptions.length === 0) { result = base; } else if (base.length >= minimumLength && base.length <= maximumLength) { const sortedPhrases = [...additionalPhraseOptions].sort((a, b) => { const lengthWithA = base.length + separator.length + a.length; const lengthWithB = base.length + separator.length + b.length; if (lengthWithA > maximumLength && lengthWithB > maximumLength) { return lengthWithA - lengthWithB; } if (lengthWithA > maximumLength) return 1; if (lengthWithB > maximumLength) return -1; return lengthWithB - lengthWithA; }); result = base; for (const phrase of sortedPhrases) { const combinedLength = base.length + separator.length + phrase.length; if (combinedLength <= maximumLength) { result = base + separator + phrase; break; } } } else { let bestPhrase = null; let bestPhraseLength = -1; for (const phrase of additionalPhraseOptions) { const combinedLength = base.length + separator.length + phrase.length; if (combinedLength >= minimumLength && combinedLength <= maximumLength) { if (combinedLength > bestPhraseLength) { bestPhrase = phrase; bestPhraseLength = combinedLength; } } else if (combinedLength < minimumLength && combinedLength > bestPhraseLength) { bestPhrase = phrase; bestPhraseLength = combinedLength; } } if (bestPhrase !== null) { result = base + separator + bestPhrase; } else if (base.length >= minimumLength) { result = base; } else { continue; } } const length = result.length; let score; if (length >= minimumLength && length <= maximumLength) { score = 1000 + length; } else if (length < minimumLength) { score = -(minimumLength - length); } else { score = -(length - maximumLength); } if (score > bestScore) { bestResult = result; bestScore = score; } } if (bestResult === null) { console.warn('⚠️ No combination can meet the minimum length requirement. Returning longest available option.', input); const longestBase = bases.reduce((longest, current) => (current.length > longest.length ? current : longest)); return longestBase; } const finalLength = bestResult.length; if (finalLength < minimumLength) { console.warn(`⚠️ Result is ${minimumLength - finalLength} characters shorter than minimum (${minimumLength}).`, 'input: ', input, 'Result: ', bestResult); } else if (finalLength > maximumLength) { console.warn(`⚠️ Result is ${finalLength - maximumLength} characters longer than maximum (${maximumLength}). Result: "${bestResult}"`); } return bestResult; } export function initialiseStringOptimiser({ minimumLength, maximumLength, separator = ' | ' }) { return (input) => { return optimiseString({ ...input, minimumLength, maximumLength, separator, }); }; } export const metaTitleConfig = { minimumLength: 50, maximumLength: 65, }; export const optimiseTitle = initialiseStringOptimiser(metaTitleConfig); export const metaDescriptionConfig = { minimumLength: 70, maximumLength: 155, }; export const optimiseDescription = initialiseStringOptimiser(metaDescriptionConfig); //# sourceMappingURL=index.js.map