UNPKG

fullfiller

Version:
117 lines (92 loc) 3.84 kB
import { freqMapType, languageType } from 'fullfiller-common/src/types'; import { capitalize, getRandomArrayElement, last, isNumeric, } from 'fullfiller-common/src/utils'; import { isStopword as isStopwordBase } from 'stopwords-utils/src'; import weightedRandomness from 'weighted-randomness/src'; function capitalizeSentence(sentenceArray: string[]) { return [capitalize(sentenceArray[0]), ...sentenceArray.slice(1)]; } function getRandomPunctuation(location: 'end' | 'mid') { const freqMap: freqMapType = location === 'end' ? { 1: ['...'], 3: ['!', '?'], 16: ['.'] } : { 1: ['[]'], 2: [';', ':'], 4: ['""', '()', '— —'], 8: [','] }; // mid punctuation will be enclosing (quotes, parentheses, brackets, em dash) 1/3 of the time const punctuation = weightedRandomness(freqMap)(); return punctuation; } function addEndSentencePunctuation(arr: string[]) { const sentenceArray = [...arr]; if (!last(sentenceArray).endsWith('.')) { sentenceArray[sentenceArray.length - 1] += getRandomPunctuation('end'); } return sentenceArray; } function addMidSentencePunctuation(arr: string[], language: languageType) { const isStopword = (word: string) => isStopwordBase(word, language); const sentenceArray = [...arr]; if (sentenceArray.length > 8 && Math.random() < 0.8) { // punctuation will be placed at a minimum the fourth word // and at a maximum at the fourth to last word const subarray = sentenceArray.slice(3, sentenceArray.length - 3); const randomPunctuation = getRandomPunctuation('mid'); if (/,|:|;/.test(randomPunctuation)) { // simple punctuation won't be placed between stopwords or numbers const filtered = subarray.filter((word) => { const nextWord = sentenceArray[sentenceArray.indexOf(word) + 1]; return [word, nextWord].every((w) => !isStopword(w) && !isNumeric(w)); }); if (filtered.length > 0) { const randomWord = getRandomArrayElement(filtered); sentenceArray[sentenceArray.indexOf(randomWord)] += randomPunctuation; } } else { // enclosing punctuation won't be placed between stopwords const punctuationStartIndex = sentenceArray.indexOf( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion subarray.find((word) => { const previousWord = sentenceArray[sentenceArray.indexOf(word) - 1]; return !isStopword(previousWord) && !isStopword(word); })! ); const punctuationEndIndex = punctuationStartIndex === -1 ? -1 : sentenceArray.indexOf( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion [...subarray] .slice(subarray.indexOf(sentenceArray[punctuationStartIndex])) .reverse() .find((word) => { const nextWord = sentenceArray[sentenceArray.indexOf(word) + 1]; return !isStopword(word) && !isStopword(nextWord); })! ); if (punctuationStartIndex !== -1 && punctuationEndIndex !== -1) { const [, openingPunctuation, closingPunctuation] = /(\(|\[|"|—\s)(\)|]|"|\s—)/.exec(randomPunctuation) || []; sentenceArray[ punctuationStartIndex ] = `${openingPunctuation}${sentenceArray[punctuationStartIndex]}`; sentenceArray[punctuationEndIndex] += closingPunctuation; } } } return sentenceArray; } function capitalizeAndPunctuateSentence( arr: string[], language: languageType ): string[] { const sentenceArray = [...arr]; return capitalizeSentence( addEndSentencePunctuation( addMidSentencePunctuation(sentenceArray, language) ) ); } export default capitalizeAndPunctuateSentence;