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
JavaScript
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