UNPKG

fullfiller

Version:
149 lines (129 loc) 4.21 kB
import CustomError from 'fullfiller-common/src/CustomError'; import { sentencesPerParagraphDefault, wordsPerSentenceDefault, } from 'fullfiller-common/src/constants'; import { invalidInput } from 'fullfiller-common/src/errorMessages'; import { inputType, queryInputType, textInputType, wordsArrayInputType, optionsType, freqMapInputType, articleType, DeepRequired, fillerType, } from 'fullfiller-common/src/types'; import generateFreqMap from 'generate-words-freqmap/src'; import getWikipediaArticle from 'get-wikipedia-article/src'; import { isStopword } from 'stopwords-utils/src'; import tokenizeWords from 'tokenize-words/src'; import distribute from './distribute'; import populateDistribution from './populateDistribution'; import stringifyBodyArray from './stringifyBodyArray'; import validate from './validate'; function getInputType( input: inputType ): 'query' | 'text' | 'wordsArray' | 'freqMap' | undefined { if (typeof input === 'string') return 'query'; if ('body' in input) return 'text'; if ('words' in input) return 'wordsArray'; if ('map' in input) return 'freqMap'; return undefined; } /** merge default options with options passed as argument */ function mergeOptions(optionsArg: optionsType): DeepRequired<optionsType> { return { language: optionsArg.language ?? 'en', unit: optionsArg.unit ?? 'paragraphs', quantity: optionsArg.quantity ?? (optionsArg.unit === 'words' ? 200 : 5), format: optionsArg.format ?? 'plain', stringify: optionsArg.stringify ?? true, include: optionsArg.include ?? ['title'], sentencesPerParagraph: { ...sentencesPerParagraphDefault, ...optionsArg.sentencesPerParagraph, }, wordsPerSentence: { ...wordsPerSentenceDefault, ...optionsArg.wordsPerSentence, }, }; } /** * Feature-rich filler text generator. * @param input Filler text will be generated from this parameter. * @param optionsArg Miscellaneous options. * @throws Array of errors if arguments validation fails. * @returns Filler object containing body and maybe (depending on `include`) title and freqMap. */ async function fullfiller( input: inputType, optionsArg: optionsType = {} ): Promise<fillerType> { const options = mergeOptions(optionsArg); validate(input, options); /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion, no-case-declarations, no-fallthrough */ switch (getInputType(input)) { case 'query': const article = (await getWikipediaArticle(input as queryInputType, { language: options.language, })) as Required<Pick<articleType, 'title' | 'body'>>; case 'text': const wordsArray = tokenizeWords( (input as textInputType).body ?? article!.body ).filter((w) => !isStopword(w, options.language)); case 'wordsArray': const freqMap = generateFreqMap( (input as wordsArrayInputType).words ?? wordsArray! ); case 'freqMap': const fm = (input as freqMapInputType).map ?? freqMap!; const distribution = distribute( options.quantity, options.unit, options.sentencesPerParagraph, options.wordsPerSentence ); const bodyArray = populateDistribution( fm, options.language, distribution ); const body = options.stringify ? stringifyBodyArray(bodyArray, options.format) : bodyArray; return { ...(options.include.includes('title') ? { title: ( input as | textInputType | wordsArrayInputType | freqMapInputType ).title ?? article!.title, } : {}), body, ...(options.include.includes('freqMap') ? { freqMap: fm } : {}), }; default: throw new CustomError(invalidInput, 'fullfiller'); } /* eslint-enable @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion, no-case-declarations, no-fallthrough */ } export default fullfiller;