From 2100e17f7ab2f6080fbf676d8759df9dca4ffcd8 Mon Sep 17 00:00:00 2001 From: Juan Villela <13276705+fourjuaneight@users.noreply.github.com> Date: Tue, 7 Jan 2025 13:45:51 -0500 Subject: [PATCH] chore: Update helpers with cleaner comments and less dependencies. --- templates/helpers/animationInterval.ts | 2 - templates/helpers/arithmeticProgression.ts | 5 - templates/helpers/arrayContainsObject.ts | 6 - templates/helpers/arrayDiff.ts | 7 - templates/helpers/arrayToObject.ts | 6 - templates/helpers/arrayUniqueCount.ts | 8 - templates/helpers/assetsToSW.ts | 87 --------- templates/helpers/binarySearch.ts | 6 - templates/helpers/bufferToFile.ts | 6 - templates/helpers/cacheAssets.ts | 62 ------ templates/helpers/cleanObject.ts | 4 - templates/helpers/comparison.ts | 36 ---- templates/helpers/cookies.ts | 7 - templates/helpers/countSubstrings.ts | 5 - templates/helpers/createBuffer.ts | 5 - templates/helpers/dashToCamelCase.ts | 7 +- templates/helpers/deleteFile.ts | 4 - templates/helpers/emojiUnicode.ts | 10 - templates/helpers/expandShortLink.ts | 13 +- templates/helpers/fmtAddress.ts | 14 +- templates/helpers/fmtCurrency.ts | 15 +- templates/helpers/fmtTime.ts | 17 -- templates/helpers/geometricProgression.ts | 6 - templates/helpers/imagePipeline.ts | 213 +++++++++++---------- templates/helpers/isFloat.ts | 4 - templates/helpers/isInteger.ts | 4 - templates/helpers/isLocalHost.ts | 8 + templates/helpers/isPositiveNumber.ts | 12 +- templates/helpers/linearSearch.ts | 6 - templates/helpers/luhnCheck.ts | 5 +- templates/helpers/mergeSort.ts | 13 +- templates/helpers/multiplyArray.ts | 8 +- templates/helpers/mutationObservable.ts | 26 +-- templates/helpers/numbRange.ts | 10 +- templates/helpers/objToQueryString.ts | 6 +- templates/helpers/objectDiff.ts | 6 - templates/helpers/objectsEqual.ts | 19 +- templates/helpers/permutations.ts | 4 - templates/helpers/powerset.ts | 4 - templates/helpers/quickSort.ts | 7 +- templates/helpers/roundTo.ts | 7 +- templates/helpers/shuffleArrs.ts | 6 +- templates/helpers/sortArr.ts | 7 - templates/helpers/sortObjectByKey.ts | 8 +- templates/helpers/states.ts | 3 + templates/helpers/streamToBuffer.ts | 5 - templates/helpers/stringToFilename.ts | 5 - templates/helpers/stringifySchema.ts | 5 - templates/helpers/sw.ts | 3 + templates/helpers/toCapitalized.ts | 5 - templates/helpers/toOrdinal.ts | 15 +- templates/helpers/uploadContentB2.ts | 18 +- templates/helpers/uploadContentS3.ts | 12 +- templates/helpers/uuid.ts | 11 +- templates/helpers/withinRange.ts | 9 +- 55 files changed, 181 insertions(+), 631 deletions(-) delete mode 100644 templates/helpers/assetsToSW.ts delete mode 100644 templates/helpers/cacheAssets.ts diff --git a/templates/helpers/animationInterval.ts b/templates/helpers/animationInterval.ts index 0e8b3ef..fcb6d1a 100644 --- a/templates/helpers/animationInterval.ts +++ b/templates/helpers/animationInterval.ts @@ -1,11 +1,9 @@ /** * Corss-browser, time perfect, animation interval. - * @function * * @param {number} ms when to ship animation; interval * @param {AbortSignal} signal performant abort of interval * @param {function} callback get time for next frame - * @return {void} */ export const animationInterval = ( ms: number, diff --git a/templates/helpers/arithmeticProgression.ts b/templates/helpers/arithmeticProgression.ts index c0b15bb..899f88f 100644 --- a/templates/helpers/arithmeticProgression.ts +++ b/templates/helpers/arithmeticProgression.ts @@ -1,10 +1,5 @@ /** * Creates an array of numbers in the arithmetic progression, starting with the given positive integer and up to the specified limit. - * @function - * - * @param {number} number - * @param {number} limit - * @returns {number[]} */ export const arithmeticProgression = ( number: number, diff --git a/templates/helpers/arrayContainsObject.ts b/templates/helpers/arrayContainsObject.ts index 615e271..8e6c84f 100644 --- a/templates/helpers/arrayContainsObject.ts +++ b/templates/helpers/arrayContainsObject.ts @@ -2,12 +2,6 @@ import { deepCheck } from './objectsEqual'; /** * Determine if object is found in given array. - * @function - * - * @param {array} arr array to lookup against - * @param {object} obj object to search for - * - * @returns {boolean} is obj in array */ export const arrayContainsObject = (arr: A[], obj: O): boolean => arr.some((elem) => deepCheck(elem, obj)); diff --git a/templates/helpers/arrayDiff.ts b/templates/helpers/arrayDiff.ts index a6eb204..3d70115 100644 --- a/templates/helpers/arrayDiff.ts +++ b/templates/helpers/arrayDiff.ts @@ -1,12 +1,5 @@ /** * Diff two arrays of objects by key. - * @function - * - * @param {array} arr1 first array to compare - * @param {array} arr2 second array to comprare - * @param {string} key objecy key (in arrays) to compare against - * - * @returns {array} diff between two arrays */ export const arrayDiff = (arr1: A[], arr2: B[], key: string): : any[] => arr1.filter((item1) => !arr2.some((item2) => item1[key] === item2[key])); diff --git a/templates/helpers/arrayToObject.ts b/templates/helpers/arrayToObject.ts index 3b5602a..e54e55c 100644 --- a/templates/helpers/arrayToObject.ts +++ b/templates/helpers/arrayToObject.ts @@ -1,11 +1,5 @@ /** * Convert array to object sorted by given key value. - * @function - * - * @param {array} array raw data source - * @param {string} key kay-value to re-organize by - * - * @returns {object} record by title key */ export const arrayToObject = (array: A[], key = "title"): Type => { const initialValue = {}; diff --git a/templates/helpers/arrayUniqueCount.ts b/templates/helpers/arrayUniqueCount.ts index 4389832..e8d2c26 100644 --- a/templates/helpers/arrayUniqueCount.ts +++ b/templates/helpers/arrayUniqueCount.ts @@ -4,10 +4,6 @@ interface Aggregate { /** * Aggregates unique values in an array. - * @function - * - * @param {array} iterable array of items to count - * @returns {object} object with unique items and their count */ export const countUnique = (iterable: string[]) => iterable.reduce((acc: Aggregate, item) => { @@ -18,10 +14,6 @@ export const countUnique = (iterable: string[]) => /** * Aggregates unique values in an array. * Sorted by count descending. - * @function - * - * @param {array} iterable array of items to count - * @returns {object} object with unique items and their count */ export const countUniqueSorted = (iterable: string[]) => Object.entries(countUnique(iterable)) diff --git a/templates/helpers/assetsToSW.ts b/templates/helpers/assetsToSW.ts deleted file mode 100644 index 11b9c42..0000000 --- a/templates/helpers/assetsToSW.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { resolve } from "path"; -import glob from "glob"; -import replace from "replace-in-file"; - -import { siteUrl, title } from "./siteConfig"; - -// Glob options. Pass directory to search and files to ignore -const cwd = resolve(__dirname, "public"); -const ignore: string[] = ["sw.js"]; - -/** - * Generate alphanumeric hash. - * @function - * - * @param {number} length hash size - * - * @return {string} alphanumeric hash - */ -const makeHash = (length: number): string => { - let result: string = ""; - const characters: string = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - const charactersLength: number = characters.length; - - for (let i = 0; i < length; i += 1) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - - return result; -}; - -/** - * Find all JS, CSS, and font assets and create list of their paths. - * @function - * - * @return {string} assets path list - */ -const getFiles = (): string => { - const files: string[] = glob.sync("**/*.{js,css,woff,woff2}", { - cwd, - ignore, - }); - const filesList: string = files.map((toCache) => `'/${toCache}'`).toString(); - - return filesList; -}; - -/** - * String to camel case. - * @function - * - * @param {string} str space separate string - * - * @returns {string} camelCased string - */ -const toCamelCase = (str: string): string => - str - .toLowerCase() - .replace(/\s(.)/g, (match: string, group1: string) => group1.toUpperCase()); - -(async () => { - // find and replace options; add hash ID, files to cache array, and site base URL - const replaceOptions = { - files: resolve(cwd, "sw.js"), - from: [ - /(const)\s(staticAssets)\s=\s?\[\];/g, - /const\sversion\s=\s'';/g, - /const\cacheName\s=\s'';/g, - /baseURL/g, - ], - to: [ - `const staticAssets = [${getFiles()}];`, - `const version = '${makeHash(6)}';`, - `const cacheName = '${toCamelCase(title)}';`, - `${siteUrl}`, - ], - }; - - // update sw.js in _public dir - try { - await replace(replaceOptions); - // eslint-disable-next-line no-console - console.info("SW updated."); - } catch (error) { - throw new Error("Error occurred:", error); - } -})(); diff --git a/templates/helpers/binarySearch.ts b/templates/helpers/binarySearch.ts index e42b17f..53c1aff 100644 --- a/templates/helpers/binarySearch.ts +++ b/templates/helpers/binarySearch.ts @@ -9,12 +9,6 @@ const lessThan = (a: : string | number, b: : string | number): boolean => compar /** * Binary search implementation. - * @function - * - * @param {*[]} sortedArray - * @param {*} seekElement - * - * @return {number} */ export const binarySearch = (sortedArray: A[], seekElement: : string | number): number => { // These two indices will contain current array (sub-array) boundaries. diff --git a/templates/helpers/bufferToFile.ts b/templates/helpers/bufferToFile.ts index 918d25c..ce58820 100644 --- a/templates/helpers/bufferToFile.ts +++ b/templates/helpers/bufferToFile.ts @@ -4,12 +4,6 @@ const { writeFile } = promises; /** * Save buffer as local file. - * @function - * - * @param {Buffer} data media buffer to save - * @param {string} name file name - * - * @returns {Promise} */ export const bufferToFile = async (data: Buffer, name: string): Promise => { try { diff --git a/templates/helpers/cacheAssets.ts b/templates/helpers/cacheAssets.ts deleted file mode 100644 index b51a11d..0000000 --- a/templates/helpers/cacheAssets.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { resolve } from 'path'; - -import chalk from 'chalk'; -import glob from 'glob'; -import { replaceInFile, ReplaceInFileConfig } from 'replace-in-file'; - -const globSync = glob.sync; - -const SITE_URL: string = 'https://www.thepancake.house'; - -// Glob options. Pass directory to search and files to ignore -const cwd = resolve(__dirname, '..', 'dist'); -const ignore = ['sw.js']; - -// Generate alphanumeric hash -const makeId = (length: number): string => { - let result = ''; - const characters: string = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - const charactersLength = characters.length; - - for (let i = 0; i < length; i += 1) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - - return result; -}; - -// Find all JS, CSS, and font files in rendered output -(async () => { - console.info( - chalk.cyan('[INFO]'), - 'Generating cache list for Service Worker.' - ); - - // create matched files array - const files = globSync('**/*.{js,css,woff,woff2}', { cwd, ignore }); - const newFiles = files.map(toCache => `'/${toCache}'`).toString(); - - // find and replace options; add hash ID, files to cache array, and site base URL - const replaceOptions: ReplaceInFileConfig = { - files: resolve(cwd, 'sw.min.js'), - from: [ - /(const)\s(staticAssets)\s=\s?\[\];/g, - /const\sversion\s=\s'';/g, - /baseURL/g, - ], - to: [ - `const staticAssets = [${newFiles}];`, - `const version = '${makeId(6)}';`, - `${SITE_URL}`, - ], - }; - - try { - await replaceInFile(replaceOptions); - - console.info(chalk.green('[SUCCESS]'), 'Service Worker updated.'); - } catch (error) { - throw new Error(`${chalk.red('[ERROR]')} ${error}`); - } -})(); diff --git a/templates/helpers/cleanObject.ts b/templates/helpers/cleanObject.ts index 000fd57..428f2ed 100644 --- a/templates/helpers/cleanObject.ts +++ b/templates/helpers/cleanObject.ts @@ -1,9 +1,5 @@ /** * Remove null or undefined values from an object. - * @function - * - * @param {*} obj entry object to cleanup - * @returns clean object */ export const cleanObject = (obj: O): T => Object.fromEntries( diff --git a/templates/helpers/comparison.ts b/templates/helpers/comparison.ts index eae0d5f..baf3fc2 100644 --- a/templates/helpers/comparison.ts +++ b/templates/helpers/comparison.ts @@ -1,11 +1,5 @@ /** * Default comparison function. It just assumes that "a" and "b" are strings or numbers. - * @function - * - * @param {(string|number)} a - * @param {(string|number)} b - * - * @returns {number} */ export const compare = (a: string | number, b: string | number): number => { if (a === b) { @@ -17,57 +11,27 @@ export const compare = (a: string | number, b: string | number): number => { /** * Checks if two variables are equal. - * @function - * - * @param {*} a - * @param {*} b - * - * @return {boolean} */ export const equal = (a: A, b: B): boolean => compare(a, b) === 0; /** * Checks if variable "a" is less than "b". - * @function - * - * @param {*} a - * @param {*} b - * - * @return {boolean} */ export const lessThan = (a: A, b: B): boolean => compare(a, b) < 0; /** * Checks if variable "a" is less than or equal to "b". - * @function - * - * @param {*} a - * @param {*} b - * - * @return {boolean} */ export const lessThanOrEqual = (a: A, b: B): boolean => lessThan(a, b) || equal(a, b); /** * Checks if variable "a" is greater than "b". - * @function - * - * @param {*} a - * @param {*} b - * - * @return {boolean} */ export const greaterThan = (a: A, b: B): boolean => compare(a, b) > 0; /** * Checks if variable "a" is greater than or equal to "b". - * @function - * - * @param {*} a - * @param {*} b - * - * @return {boolean} */ export const greaterThanOrEqual = (a: A, b: B): boolean => greaterThan(a, b) || equal(a, b); diff --git a/templates/helpers/cookies.ts b/templates/helpers/cookies.ts index ec3d2f3..b5fdf29 100644 --- a/templates/helpers/cookies.ts +++ b/templates/helpers/cookies.ts @@ -1,9 +1,5 @@ /** * Sets a cookie with an optional expiration time. - * - * @param name - The name of the cookie. - * @param value - The value of the cookie. - * @param expires - The expiration time in seconds or a specific Date object. */ export const setCookie = ( name: string, @@ -29,9 +25,6 @@ export const setCookie = ( /** * Retrieves the value of a specified cookie. - * - * @param name - The name of the cookie to retrieve. - * @returns The value of the cookie, or null if not found. */ export const getCookie = (name: string): string | null => { const nameEQ = `${name}=` diff --git a/templates/helpers/countSubstrings.ts b/templates/helpers/countSubstrings.ts index 9197059..0806b87 100644 --- a/templates/helpers/countSubstrings.ts +++ b/templates/helpers/countSubstrings.ts @@ -1,10 +1,5 @@ /** * Counts the occurrences of a substring in a given string. - * @function - * - * @param {string} str string to search - * @param {string} searchValue value to search for - * @returns {number} found occurrences */ export const countSubstrings = (str: string, searchValue: string): number => { let count = 0; diff --git a/templates/helpers/createBuffer.ts b/templates/helpers/createBuffer.ts index e88c5ab..8fe866c 100644 --- a/templates/helpers/createBuffer.ts +++ b/templates/helpers/createBuffer.ts @@ -2,11 +2,6 @@ import { Readable } from 'stream'; /** * Create buffer from readable stream. - * @function - * @async - * - * @param {Readable} stream - * @returns {Buffer} video buffer */ export const createBuffer = async (stream: Readable): Promise => { const chunks = []; diff --git a/templates/helpers/dashToCamelCase.ts b/templates/helpers/dashToCamelCase.ts index 20e4ce2..1f9d273 100644 --- a/templates/helpers/dashToCamelCase.ts +++ b/templates/helpers/dashToCamelCase.ts @@ -1,10 +1,5 @@ /** - * Dashed string to camel case. - * @function - * - * @param {string} str dash separate string - * - * @returns {string} camelCased string + * Convert dashed string to camel case. */ export const dashToCamelCase = (str: string): string => str diff --git a/templates/helpers/deleteFile.ts b/templates/helpers/deleteFile.ts index abd1350..bed290a 100644 --- a/templates/helpers/deleteFile.ts +++ b/templates/helpers/deleteFile.ts @@ -4,10 +4,6 @@ const { unlink } = promises; /** * Delete list of files. - * @function - * - * @param files array of file paths to delete - * @returns {Promise} */ export const deleteFiles = async (files: string[]): Promise => { const delCmds = files.map((fl) => unlink(fl)); diff --git a/templates/helpers/emojiUnicode.ts b/templates/helpers/emojiUnicode.ts index 34f2d7f..1ac91f8 100644 --- a/templates/helpers/emojiUnicode.ts +++ b/templates/helpers/emojiUnicode.ts @@ -5,11 +5,6 @@ export const range = new RegExp( /** * Get the unicode code of an emoji in base 16. - * @function - * - * @param {string} emojiString the string containing emoji characters - * - * @returns {string} the unicode code */ export const convertEmoji = (emojiString: string): string => { let comp: string | number; @@ -35,11 +30,6 @@ export const convertEmoji = (emojiString: string): string => { /** * Takes a string and replaces unicode. - * @function - * - * @param {string} str string string with emojies - * - * @return {string} string with unicode emojies */ export const emojiUnicode = (str: string): string => str.replace(range, (p1: string) => `${convertEmoji(p1)}`); diff --git a/templates/helpers/expandShortLink.ts b/templates/helpers/expandShortLink.ts index 36fd14e..7715fda 100644 --- a/templates/helpers/expandShortLink.ts +++ b/templates/helpers/expandShortLink.ts @@ -1,11 +1,6 @@ /* eslint-disable sort-keys */ /** - * Expand shortend URLs. - * @function - * - * @param {string} url shortned url string - * - * @returns {Promise} expanded URL + * Expand shortend URLs via Fetch. */ export const expandLinks = async (url: string): Promise => { try { @@ -27,12 +22,6 @@ export const expandLinks = async (url: string): Promise => { /** * Get expanded URLs. - * @function - * - * @param {string} str string to replace - * @param {RegExp} regex pattern to match - * - * @returns {Promise} list of expanded URLs from str */ export const expandShortLink = async (str: string, regex: RegExp): Promise => { const promises: Promise[] = []; diff --git a/templates/helpers/fmtAddress.ts b/templates/helpers/fmtAddress.ts index 4f289e2..6a57878 100644 --- a/templates/helpers/fmtAddress.ts +++ b/templates/helpers/fmtAddress.ts @@ -8,12 +8,7 @@ export interface AddressValues { } /** - * Address string to itemized object. - * @function - * - * @param {string} address coma separated address string - * - * @returns {AddressValues} itemized address object + * Convert address string to itemized object. */ export const separateAddress = (address: string): AddressValues => { const arr: string[] = address.split(','); @@ -38,12 +33,7 @@ export const separateAddress = (address: string): AddressValues => { }; /** - * Itemized address object to comma separated string. - * @function - * - * @param {AddressValues} address itemized object - * - * @returns {string} comma separated address + * Convert itemized address object to comma separated string. */ export const joinAddress = (address: AddressValues): string => { // object to array (removes null values) diff --git a/templates/helpers/fmtCurrency.ts b/templates/helpers/fmtCurrency.ts index ee4619e..986512a 100644 --- a/templates/helpers/fmtCurrency.ts +++ b/templates/helpers/fmtCurrency.ts @@ -1,12 +1,6 @@ /* eslint-disable sort-keys */ /** - * Formate float to USD currency. - * @function - * - * @param {number} num float number to convert - * @param {boolean} includeCurrency include currency type - * - * @return {string} dollar amount + * Convert float to USD currency. */ export const formatCurrency = ( num: number | null, @@ -32,12 +26,7 @@ export const formatCurrency = ( }; /** - * Format number to comma-separate. - * @function - * - * @param {number} num number to convert - * - * @return {string} comma-separate number + * Convert number to comma-separate. */ export const numberWithCommas = (num: number): string => { if (!num) { diff --git a/templates/helpers/fmtTime.ts b/templates/helpers/fmtTime.ts index 875777b..ed26a69 100644 --- a/templates/helpers/fmtTime.ts +++ b/templates/helpers/fmtTime.ts @@ -2,12 +2,6 @@ import { format } from "date-fns"; /** * Convert time string to locale format. - * @function - * - * @param {string} time time string - * @param {string} localePattern conversion pattern - * - * @return {string} datetime */ export const timeToLocale = (time: string, localePattern: string): string => { const pattern: string = localePattern || "HH:mm a"; @@ -23,12 +17,6 @@ export const timeToLocale = (time: string, localePattern: string): string => { /** * Convert time string to ISO format. - * @function - * - * @param {string} time time string - * @param {string} timePattern conversion pattern - * - * @return {string} ISO timestamp */ export const localeToTime = (time: string, timePattern: string): string => { const pattern: string = timePattern || "HH:mm:ss"; @@ -44,11 +32,6 @@ export const localeToTime = (time: string, timePattern: string): string => { /** * Remove timezone from date string. - * @function - * - * @param {string} date date string - * - * @return {Date} UTC date */ export const removeTimeZone = (date: string | Date): Date => { let locDate: Date; diff --git a/templates/helpers/geometricProgression.ts b/templates/helpers/geometricProgression.ts index ee626e9..30756a7 100644 --- a/templates/helpers/geometricProgression.ts +++ b/templates/helpers/geometricProgression.ts @@ -1,11 +1,5 @@ /** * Initializes an array containing the numbers in the specified range where start and end are inclusive and the ratio between two terms is step. - * @function - * - * @param {number} end - * @param {number} start - * @param {number} step - * @returns {number[]} */ const geometricProgression = (end: number, start = 1, step = 2): number[] => // create an array of the desired length diff --git a/templates/helpers/imagePipeline.ts b/templates/helpers/imagePipeline.ts index c63d3a5..87a1a3b 100644 --- a/templates/helpers/imagePipeline.ts +++ b/templates/helpers/imagePipeline.ts @@ -1,7 +1,6 @@ import { resolve } from 'path'; import * as yargs from 'yargs'; -import chalk from 'chalk'; import sharp from 'sharp'; interface VOptions { @@ -19,111 +18,115 @@ interface Variants { type Assets = 'favicon' | 'logo' | 'hero' | 'about' | 'post'; -const asset: ReadonlyArray = [ - 'favicon', - 'logo', - 'hero', - 'about', - 'post', -]; -const argv = yargs.option('asset', { - choices: asset, - demandOption: true, -}).argv; -const dir = resolve(__dirname, '..', 'public'); -const variants: Variants = { - favicon: [ - { name: 'favicon', resize: [16, 16] }, - { name: 'favicon', resize: [32, 32] }, - { name: 'icon', resize: [120, 120] }, - { name: 'icon', resize: [180, 180] }, - { name: 'icon', resize: [152, 152] }, - { name: 'icon', resize: [167, 167] }, - { name: 'icon', resize: [256, 256] }, - { name: 'icon', resize: [512, 512] }, - ], - logo: [ - { name: 'logo', resize: 250 }, - { name: 'logo', resize: 250, ext: 'webp' }, - { name: 'logo', resize: 250, ext: 'avif' }, - ], - hero: [ - { name: 'hero', resize: 500 }, - { name: 'hero', resize: 500, ext: 'webp' }, - { name: 'hero', resize: 500, ext: 'avif' }, - ], - about: [ - { name: 'about', resize: 350 }, - { name: 'about', resize: 350, ext: 'webp' }, - { name: 'about', resize: 350, ext: 'avif' }, - ], -}; /** - * Create various size and format variants of an image. - * @function - * - * @param {VOptions[]} data Variants options - * @param {string} src Image to format and convert - * @param {string} dest Where to save image - * - * @returns {Promise} + * Create various size and format variants of an image based on the asset type. */ -const fmtImage = async ( - data: VOptions[], - src: string, - dest: string -): Promise => { - const input = resolve(__dirname, src); - - // map array to promises - const promises = data.map(async img => { - // image options - const sizes = Array.isArray(img.resize) - ? { height: img.resize[0], width: img.resize[1] } - : { width: img.resize }; - const type: any = img.ext || 'png'; - const fileName: string = Array.isArray(img.resize) - ? `${img.name}-${img.resize[0]}x${img.resize[1]}.${type}` - : `${img.name}.${type}`; - const output = `${dir}/${dest}/${fileName}`; - const image = sharp(input); - - // create variants - await image - .resize(sizes) - .toFormat(type) - .toFile(output) - .then(() => { - console.info(chalk.green('[SUCCESS]'), `${fileName} created.`); - }) - .catch(err => { - console.error(chalk.red('[ERROR]'), { - input, - output, - err, +(() => { + const asset: ReadonlyArray = [ + 'favicon', + 'logo', + 'hero', + 'about', + 'post', + ]; + const argv = yargs.option('asset', { + choices: asset, + demandOption: true, + }).argv; + const dir = resolve(__dirname, '..', 'public'); + const variants: Variants = { + favicon: [ + { name: 'favicon', resize: [16, 16] }, + { name: 'favicon', resize: [32, 32] }, + { name: 'icon', resize: [120, 120] }, + { name: 'icon', resize: [180, 180] }, + { name: 'icon', resize: [152, 152] }, + { name: 'icon', resize: [167, 167] }, + { name: 'icon', resize: [256, 256] }, + { name: 'icon', resize: [512, 512] }, + ], + logo: [ + { name: 'logo', resize: 250 }, + { name: 'logo', resize: 250, ext: 'webp' }, + { name: 'logo', resize: 250, ext: 'avif' }, + ], + hero: [ + { name: 'hero', resize: 500 }, + { name: 'hero', resize: 500, ext: 'webp' }, + { name: 'hero', resize: 500, ext: 'avif' }, + ], + about: [ + { name: 'about', resize: 350 }, + { name: 'about', resize: 350, ext: 'webp' }, + { name: 'about', resize: 350, ext: 'avif' }, + ], + }; + + /** + * Create various size and format variants of an image. + * + * @param data Variants options + * @param src Image to format and convert + * @param dest Where to save image + */ + const fmtImage = async ( + data: VOptions[], + src: string, + dest: string + ): Promise => { + const input = resolve(__dirname, src); + + // map array to promises + const promises = data.map(async img => { + // image options + const sizes = Array.isArray(img.resize) + ? { height: img.resize[0], width: img.resize[1] } + : { width: img.resize }; + const type: any = img.ext || 'png'; + const fileName: string = Array.isArray(img.resize) + ? `${img.name}-${img.resize[0]}x${img.resize[1]}.${type}` + : `${img.name}.${type}`; + const output = `${dir}/${dest}/${fileName}`; + const image = sharp(input); + + // create variants + await image + .resize(sizes) + .toFormat(type) + .toFile(output) + .then(() => { + console.info('[SUCCESS]', `${fileName} created.`); + }) + .catch(err => { + console.error('[ERROR]', { + input, + output, + err, + }); }); - }); - }); - - // wait until all promises are resolved - await Promise.all(promises); -}; - -switch (argv.asset) { - case 'favicon': - fmtImage(variants.favicon, 'favicon.png', 'icons'); - break; - case 'logo': - fmtImage(variants.logo, 'logo.png', 'img'); - break; - case 'hero': - fmtImage(variants.hero, 'hero.png', 'img'); - break; - case 'about': - fmtImage(variants.about, 'about.png', 'img'); - break; - default: - console.info(chalk.blue('[INFO]'), 'No images converted.'); - break; -} + }); + + // wait until all promises are resolved + await Promise.all(promises); + }; + + // run script based on asset type + switch (argv.asset) { + case 'favicon': + fmtImage(variants.favicon, 'favicon.png', 'icons'); + break; + case 'logo': + fmtImage(variants.logo, 'logo.png', 'img'); + break; + case 'hero': + fmtImage(variants.hero, 'hero.png', 'img'); + break; + case 'about': + fmtImage(variants.about, 'about.png', 'img'); + break; + default: + console.info('[INFO]', 'No images converted.'); + break; + } +})(); diff --git a/templates/helpers/isFloat.ts b/templates/helpers/isFloat.ts index 23cea4c..0c23429 100644 --- a/templates/helpers/isFloat.ts +++ b/templates/helpers/isFloat.ts @@ -1,9 +1,5 @@ /** * Checks if the given value is a float. - * @function - * - * @param val - possible float - * @returns {boolean} - true if value is float */ export const isFloat = (val: string): boolean => { let newVal: any = val; diff --git a/templates/helpers/isInteger.ts b/templates/helpers/isInteger.ts index 5189a03..eebd5e9 100644 --- a/templates/helpers/isInteger.ts +++ b/templates/helpers/isInteger.ts @@ -1,9 +1,5 @@ /** * Checks if the given value is an integer. - * @function - * - * @param {string} val - possible integer - * @returns {boolean} - true if value is integer */ export const isInteger = (val: string): boolean => { if (isNaN(val as unknown as number)) { diff --git a/templates/helpers/isLocalHost.ts b/templates/helpers/isLocalHost.ts index 7f5552c..5b10d61 100644 --- a/templates/helpers/isLocalHost.ts +++ b/templates/helpers/isLocalHost.ts @@ -1,3 +1,11 @@ +/** + * Determines if the current hostname is localhost. + * + * Checks for: + * - 'localhost' (standard hostname) + * - '[::1]' (IPv6 localhost address) + * - Any IPv4 address in the range 127.0.0.0/8 + */ export const isLocalhost: boolean = Boolean( window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. diff --git a/templates/helpers/isPositiveNumber.ts b/templates/helpers/isPositiveNumber.ts index 1108a2c..803a47c 100644 --- a/templates/helpers/isPositiveNumber.ts +++ b/templates/helpers/isPositiveNumber.ts @@ -1,13 +1,9 @@ /** * Checks if the given value is a positive number. - * @summary !isNaN(parseFloat(val)) is used to filter pure string values - * @summary ~~val >= 0 filters negative and large non-number values - * @summary (!isNaN(parseFloat(val)) && ~~val >= 0) returns true if value is both numeric and positive - * @summary val % (...) === 0 checks if value is non-float - * @function - * - * @param val - possible positive number - * @returns {boolean} - true if value is positive number + * `!isNaN(parseFloat(val))` is used to filter pure string values. + * `~~val >= 0` filters negative and large non-number values. + * `(!isNaN(parseFloat(val)) && ~~val >= 0)` returns true if value is both numeric and positive. + * `val % (...) === 0` checks if value is non-float. */ export const isPositiveNumber = (val: string): boolean => val % (!isNaN(parseFloat(val)) && ~~val >= 0) === 0; diff --git a/templates/helpers/linearSearch.ts b/templates/helpers/linearSearch.ts index 0cea446..3657ae8 100644 --- a/templates/helpers/linearSearch.ts +++ b/templates/helpers/linearSearch.ts @@ -8,12 +8,6 @@ const equal = (a: : string | number, b: : string | number): boolean => compare(a /** * Linear search implementation. - * @function - * - * @param {*[]} array - * @param {*} seekElement - * - * @return {number[]} */ export const linearSearch = (array: A[], seekElement: : string | number): number[] => { const foundIndices: any[] = []; diff --git a/templates/helpers/luhnCheck.ts b/templates/helpers/luhnCheck.ts index 21352fd..fec9b76 100644 --- a/templates/helpers/luhnCheck.ts +++ b/templates/helpers/luhnCheck.ts @@ -1,9 +1,6 @@ /** * Implementation of the Luhn Algorithm used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers, National Provider Identifier numbers etc. - * @function - * - * @param {number | string} num - * @returns {boolean} true if sum is divisible by 10, false otherwise + * https://w.wiki/HD5 */ export const luhnCheck = (num: number | string): boolean => { // obtain array of digits diff --git a/templates/helpers/mergeSort.ts b/templates/helpers/mergeSort.ts index 3eb9f3e..dda657e 100644 --- a/templates/helpers/mergeSort.ts +++ b/templates/helpers/mergeSort.ts @@ -3,13 +3,7 @@ const lessThanOrEqual = (a: any, b: any): boolean => lessThan(a, b) || equal(a, b); /** - * Merge arrays. - * @function - * - * @param {number[]} leftArray - * @param {number[]} rightArray - * - * @return {number[]} + * Merge sorted arrays. */ export const mergeSortedArrays = ( leftArray: number[], @@ -47,11 +41,6 @@ export const mergeSortedArrays = ( /** * Merge sort. - * @function - * - * @param {number[]} originalArray - * - * @return {number[]} */ export const mergeSort = (originalArray: number[]): number[] => { // If array is empty or consists of one element then return this array since it is sorted. diff --git a/templates/helpers/multiplyArray.ts b/templates/helpers/multiplyArray.ts index de042f8..7bc8369 100644 --- a/templates/helpers/multiplyArray.ts +++ b/templates/helpers/multiplyArray.ts @@ -1,11 +1,5 @@ /** - * Copy array by given n times. - * @function - * - * @param {array} arr data to multiply - * @param {number} copies number of copies - * - * @returns {array} array with copies of data + * Copy array by given number times. */ export const multiplyArray = (arr: T[], copies: number): T[] => { const array: any[] = Array(copies) diff --git a/templates/helpers/mutationObservable.ts b/templates/helpers/mutationObservable.ts index 568337f..b895185 100644 --- a/templates/helpers/mutationObservable.ts +++ b/templates/helpers/mutationObservable.ts @@ -1,25 +1,29 @@ -import { Observable } from "rxjs"; +import { Observable } from 'rxjs' +/** + * Observe the target node for mutations and emit the mutation records. + * Uses MutationObserver API. + */ export const observeOnMutation = ( - target: Node + target: Node, ): Observable => { const config = { attributes: true, childList: false, characterData: false, - }; + } return new Observable((observer) => { const mutation = new MutationObserver((mutations, instance) => { - observer.next(mutations); - }); + observer.next(mutations) + }) - mutation.observe(target, config); + mutation.observe(target, config) const unsubscribe = () => { - mutation.disconnect(); - }; + mutation.disconnect() + } - return unsubscribe; - }); -}; + return unsubscribe + }) +} diff --git a/templates/helpers/numbRange.ts b/templates/helpers/numbRange.ts index 67de636..4ca7577 100644 --- a/templates/helpers/numbRange.ts +++ b/templates/helpers/numbRange.ts @@ -1,13 +1,7 @@ /** * Generate array of numbers based on given range. - * @function - * - * @param {number} length amount of numbers to generate - * @param {[number]} start starting point for count - * - * @return {number[]} array of numbers */ -export const numbRange = (length: number, start?: number = 1) => +export const numbRange = (length: number, startPoint?: number = 1) => Array(length) - .fill(start) + .fill(startPoint) .map((x: number, y: number) => x + y); diff --git a/templates/helpers/objToQueryString.ts b/templates/helpers/objToQueryString.ts index e086da3..8e5fd0d 100644 --- a/templates/helpers/objToQueryString.ts +++ b/templates/helpers/objToQueryString.ts @@ -1,9 +1,5 @@ /** - * Convert an object to a query string for GQL. - * @function - * - * @param obj any key value pair object - * @returns {string[]} array of query string parameters + * Convert an object to a query string for GraphQL. */ export const objToQueryString = (obj: T) => Object.keys(obj).map((key) => { diff --git a/templates/helpers/objectDiff.ts b/templates/helpers/objectDiff.ts index 821d215..c0e485a 100644 --- a/templates/helpers/objectDiff.ts +++ b/templates/helpers/objectDiff.ts @@ -2,12 +2,6 @@ import { difference, isEqual, isObject, transform } from "lodash"; /** * Deep diff between two object, using lodash. - * @function - * - * @param {any} data object compared - * @param {any} base object to compare with - * - * @return {any} data object representing diff */ export const objectDiff = (data: T, base: T): T => transform(data, (result, value, key) => { diff --git a/templates/helpers/objectsEqual.ts b/templates/helpers/objectsEqual.ts index 285664b..0541b3b 100644 --- a/templates/helpers/objectsEqual.ts +++ b/templates/helpers/objectsEqual.ts @@ -1,22 +1,11 @@ /** - * Determine param is an object. - * @function - * - * @param {object} obj param to check against - * - * @returns {boolean} is param an object + * Determines if the given parameter is an object. */ export const isObject = (obj: T): boolean => obj != null && typeof obj === "object"; /** * Determine if two objects are the same. Shallow check. - * @function - * - * @param {object} obj1 main object to compare - * @param {object} obj2 secondary object to compare - * - * @returns {boolean} are objects equal */ export const shallowCheck = (obj1: Obj1, obj2: Obj2): boolean => { const keys1 = Object.keys(obj1); @@ -37,12 +26,6 @@ export const shallowCheck = (obj1: Obj1, obj2: Obj2): boolean => { /** * Determine if two objects are the same. Deep check. - * @function - * - * @param {object} obj1 main object to compare - * @param {object} obj2 secondary object to compare - * - * @returns {boolean} are objects equal */ export const deepCheck = (obj1: Obj1, obj2: Obj2): boolean => { const keys1 = Object.keys(obj1); diff --git a/templates/helpers/permutations.ts b/templates/helpers/permutations.ts index 64addb1..ab8cfd7 100644 --- a/templates/helpers/permutations.ts +++ b/templates/helpers/permutations.ts @@ -1,9 +1,5 @@ /** * Generates all permutations of an array's elements (contains duplicates). - * @function - * - * @param {any[]} arr array of datasets - * @returns {any[][]} possible permutations */ export const permutations = (arr: T[]): T[][] => { if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; diff --git a/templates/helpers/powerset.ts b/templates/helpers/powerset.ts index 7df361c..0a373bf 100644 --- a/templates/helpers/powerset.ts +++ b/templates/helpers/powerset.ts @@ -1,9 +1,5 @@ /** * Get the powerset of a given array of numbers. - * @function - * - * @param {number[]} arr dataset - * @returns {number[]][] | any[][]} */ export const powerset = (arr: number[]): number[][] | any[][] => // iterate over elements and combine into an array containing all combinations diff --git a/templates/helpers/quickSort.ts b/templates/helpers/quickSort.ts index 635aeb0..0a35bae 100644 --- a/templates/helpers/quickSort.ts +++ b/templates/helpers/quickSort.ts @@ -1,4 +1,4 @@ -// Util +// Utils const compare = (a: string | number, b: string | number): number => { if (a === b) return 0; @@ -9,11 +9,6 @@ const lessThan = (a: : string | number, b: : string | number): boolean => compar /** * Quick sort. - * @function - * - * @param {number[]} originalArray - * - * @return {number[]} */ export const quickSort = (originalArray: number[]): number[] => { // Clone original array to prevent it from modification. diff --git a/templates/helpers/roundTo.ts b/templates/helpers/roundTo.ts index 3c2989e..929832f 100644 --- a/templates/helpers/roundTo.ts +++ b/templates/helpers/roundTo.ts @@ -1,11 +1,8 @@ /** * Safe number rounding. toFixed alternative, which will round up or down for you depending on the values beyond 2 decimals. - * @function * - * @param {number} num number to trim - * @param {number} dig amount of digits trimmed to - * - * @return {number} trimmed value + * @param num number to trim + * @param dig amount of digits trimmed to */ export const roundTo = (num: number, dig: number): number => { let negative: boolean = false; diff --git a/templates/helpers/shuffleArrs.ts b/templates/helpers/shuffleArrs.ts index c35329f..5f5bc60 100644 --- a/templates/helpers/shuffleArrs.ts +++ b/templates/helpers/shuffleArrs.ts @@ -1,10 +1,6 @@ /** * Randomizes the order of the values of an array, returning a new array. - * Uses Fisher-Yates algorithm. - * @function - * - * @param {any[]} array - * @returns {any[]} shuffled array + * Uses Fisher-Yates algorithm: https://w.wiki/8Zj */ export const shuffleArrs = ([...arr]: T[]) => { let match = arr.length; diff --git a/templates/helpers/sortArr.ts b/templates/helpers/sortArr.ts index f746938..3be2b91 100644 --- a/templates/helpers/sortArr.ts +++ b/templates/helpers/sortArr.ts @@ -1,12 +1,5 @@ /** * Sort given array by key in descending/ascending order. - * @function - * - * @param {any[]} list array to sort - * @param {string} key ket to sort by - * @param {boolean} asc should order by asc order - * - * @return {any[]} sorted array */ export const sortArr = ( list: T[], diff --git a/templates/helpers/sortObjectByKey.ts b/templates/helpers/sortObjectByKey.ts index c49a97f..2eee438 100644 --- a/templates/helpers/sortObjectByKey.ts +++ b/templates/helpers/sortObjectByKey.ts @@ -1,11 +1,5 @@ /** - * Sort object by key. - * @function - * - * @param {object} obj object to sort - * @param {string} key key to sort by - * - * @returns {object} sorted object + * Sort an object by key. */ export const sortObjectByKey = (obj: T, key: string): T => { const sorted = obj.sort((a, b) => { diff --git a/templates/helpers/states.ts b/templates/helpers/states.ts index d11681d..7a7b0e1 100644 --- a/templates/helpers/states.ts +++ b/templates/helpers/states.ts @@ -3,6 +3,9 @@ export interface StatesValues { name: string; } +/** + * List of US state names with their official abbreviation. + */ export const states: StatesValues[] = [ { abbreviation: "AL", diff --git a/templates/helpers/streamToBuffer.ts b/templates/helpers/streamToBuffer.ts index 5d52383..2db8217 100644 --- a/templates/helpers/streamToBuffer.ts +++ b/templates/helpers/streamToBuffer.ts @@ -2,11 +2,6 @@ import { Readable } from "stream"; /** * Create buffer from readable stream. - * @function - * - * @param {Readable} stream - * - * @returns {Promise} video buffer */ export const streamToBuffer = async (stream: Readable): Promise => { const chunks = []; diff --git a/templates/helpers/stringToFilename.ts b/templates/helpers/stringToFilename.ts index c734fea..55b49ab 100644 --- a/templates/helpers/stringToFilename.ts +++ b/templates/helpers/stringToFilename.ts @@ -2,11 +2,6 @@ import { range } from "./emojiUnicode"; /** * Convert string into a filename. - * @function - * - * @param {string} str - * - * @returns {string} filename */ export const stringToFilename = (str: string): string => str diff --git a/templates/helpers/stringifySchema.ts b/templates/helpers/stringifySchema.ts index 31a68ad..621d98d 100644 --- a/templates/helpers/stringifySchema.ts +++ b/templates/helpers/stringifySchema.ts @@ -1,10 +1,5 @@ /** * Stringify and format compared data for GQL schema mutation. - * @function - * - * @param {any} data new data object - * - * @return {string} schema string */ export const stringifySchema = (data: D): string => JSON.stringify(data).replace(/'([a-zA-Z_]+)':/g, '$1:'); diff --git a/templates/helpers/sw.ts b/templates/helpers/sw.ts index 595539c..8de2eb5 100644 --- a/templates/helpers/sw.ts +++ b/templates/helpers/sw.ts @@ -3,6 +3,9 @@ interface FetchEvent extends Event { respondWith(response: Promise | Response): Promise; } +/** + * Service Worker for caching static assets and pages. + */ (() => { const version: string = ''; const cacheName: string = ':'; diff --git a/templates/helpers/toCapitalized.ts b/templates/helpers/toCapitalized.ts index 050ed9f..1ff3cd5 100644 --- a/templates/helpers/toCapitalized.ts +++ b/templates/helpers/toCapitalized.ts @@ -1,10 +1,5 @@ /** * Turns first letter of a string to uppercase, capitalizing the string - * @function - * - * @param {string} str word to capitalized - * - * @returns {string} capitalized word */ export const toCapitalized = (str: string): string => `${str.charAt(0).toUpperCase()}${str.slice(1)}`; diff --git a/templates/helpers/toOrdinal.ts b/templates/helpers/toOrdinal.ts index 140ccc9..7d6cc61 100644 --- a/templates/helpers/toOrdinal.ts +++ b/templates/helpers/toOrdinal.ts @@ -1,17 +1,12 @@ /** - * Number to ordinal string. It leverages JS's treatment of indices to an array. If you pass an array an index that’s outside the range, it returns undefined, which is considered false. - * @function - * - * @param {number} num - * - * @return {string} ordinal number + * Number to ordinal string. It leverages JS's treatment of indices to an array. If you pass an array an index that's outside the range, it returns undefined, which is considered false. */ export const toOrdinal = (num: number): string => { - const str = ['th', 'st', 'nd', 'rd']; + const string = ['th', 'st', 'nd', 'rd']; // returns a negative number when its first operand (the dividend) is negative - const val = num % 100; - // returns the value of the first operand if it’s true and the value of the second operand otherwise - const type = str[(val - 20) % 10] || str[val] || str[0]; + const value = num % 100; + // returns the value of the first operand if it's true and the value of the second operand otherwise + const type = string[(value - 20) % 10] || string[value] || string[0]; return `${num}${type}`; }; diff --git a/templates/helpers/uploadContentB2.ts b/templates/helpers/uploadContentB2.ts index 0a90963..225734b 100644 --- a/templates/helpers/uploadContentB2.ts +++ b/templates/helpers/uploadContentB2.ts @@ -71,10 +71,8 @@ const BUCKET_NAME = process.env.B2_BUCKET_NAME; /** * Authorize B2 bucket for upload. * docs: https://www.backblaze.com/b2/docs/b2_authorize_account.html - * @function - * @async * - * @returns {B2AuthTokens} api endpoint, auth token, and download url + * @returns api endpoint, auth token, and download url */ const authTokens = async (): Promise => { const token = Buffer.from(`${APP_KEY_ID}:${APP_KEY}`).toString("base64"); @@ -116,10 +114,8 @@ const authTokens = async (): Promise => { /** * Get B2 endpoint for upload. * docs: https://www.backblaze.com/b2/docs/b2_get_upload_url.html - * @function - * @async * - * @returns {B2UploadTokens} upload endpoint, auth token, and download url + * @returns upload endpoint, auth token, and download url */ const getUploadUrl = async (): Promise => { try { @@ -162,13 +158,11 @@ const getUploadUrl = async (): Promise => { /** * Upload file to B2 bucket. * docs: https://www.backblaze.com/b2/docs/b2_upload_file.html - * @function - * @async * - * @param {Buffer} data file buffer - * @param {string} name file name with extension - * @param {string} [type] file type - * @returns {string} file public url + * @param data file buffer + * @param name file name with extension + * @param [type] file type + * @returns file public url */ export const uploadToB2 = async ( data: Buffer, diff --git a/templates/helpers/uploadContentS3.ts b/templates/helpers/uploadContentS3.ts index 57ac55d..1a67f2f 100644 --- a/templates/helpers/uploadContentS3.ts +++ b/templates/helpers/uploadContentS3.ts @@ -14,14 +14,12 @@ const s3 = new AWS.S3({ /** * Upload asset to S3 bucket. - * @function - * @async * - * @param {Buffer} data raw buffer data - * @param {string} type file type - * @param {string} name file name - * @param {string} base database name - * @returns {string} upload response code and message + * @param data raw buffer data + * @param type file type + * @param name file name + * @param base database name + * @returns upload response code and message */ export const uploadContent = async ( data: Buffer, diff --git a/templates/helpers/uuid.ts b/templates/helpers/uuid.ts index e26afee..9ebbdc5 100644 --- a/templates/helpers/uuid.ts +++ b/templates/helpers/uuid.ts @@ -1,14 +1,13 @@ -// 0-255 numbers array > hex string > prepend a 0 = 256 hex values -// hoisted to avoid recalculating +/** + * 0-255 numbers array > hex string > prepend a 0 = 256 hex values + * hoisted to avoid recalculating + */ const hex: string[] = [...Array(256).keys()].map((index: number) => index.toString(16).padStart(2, '0') ); /** - * Simple UUID generating. - * @function - * - * @return {string} natively randomized uuid string + * Natively randomized UUID string generation. */ export const uuid = (): string => { // randomized 16 byte buffer diff --git a/templates/helpers/withinRange.ts b/templates/helpers/withinRange.ts index 5ebab99..bec480b 100644 --- a/templates/helpers/withinRange.ts +++ b/templates/helpers/withinRange.ts @@ -1,12 +1,5 @@ /** - * Is given value between provided range. - * @function - * - * @param {number} num evaluating value - * @param {number} min starting value - * @param {number} max ending value - * - * @returns {boolean} is given value in the range + * Determines if the given value between provided range. */ export const withinRange = (num: number, min: number, max: number): boolean => num >= min && num <= max;