UNPKG

n2words

Version:

Convert numbers to words in 70+ languages with zero dependencies. Supports BigInt, decimals, and browser/Node.js environments.

82 lines (71 loc) 2.72 kB
/** * Cardinal value parsing utility. * Transforms user input (number, string, or bigint) into normalized components. * Handles negatives, decimals, and scientific notation. * @module parse-cardinal */ import { expandScientificNotation, hasScientificNotation, numberToString } from './expand-scientific.js' /** * Parses a value for cardinal conversion. * Cardinals accept any numeric value: integers, decimals, negatives. * @param {number|string|bigint} value - The value to parse * @returns {{isNegative: boolean, integerPart: bigint, decimalPart?: string}} The parsed cardinal components * @throws {TypeError} If value is not number, string, or bigint * @throws {RangeError} If value is not finite */ export function parseCardinalValue(value) { const type = typeof value // BigInt: simplest case if (typeof value === 'bigint') { return value < 0n ? { isNegative: true, integerPart: -value } : { isNegative: false, integerPart: value } } // Number: fast path for safe integers if (typeof value === 'number') { if (!Number.isFinite(value)) { throw new RangeError('Number must be finite (NaN and Infinity are not supported)') } if (Number.isSafeInteger(value)) { return value < 0 ? { isNegative: true, integerPart: BigInt(-value) } : { isNegative: false, integerPart: BigInt(value) } } return parseNumericString(numberToString(value)) } // String input if (typeof value === 'string') { return parseNumericString(normalizeString(value)) } throw new TypeError( `Invalid value type: expected number, string, or bigint, received ${type}`, ) } /** * Validates and normalizes a string numeric input. * @param {string} value - The string to normalize * @returns {string} The normalized numeric string */ function normalizeString(value) { const trimmed = value.trim() if (trimmed.length === 0 || Number.isNaN(Number(trimmed))) { throw new RangeError(`Invalid number format: "${value}"`) } return hasScientificNotation(trimmed) ? expandScientificNotation(trimmed) : trimmed } /** * Parses a normalized numeric string into components. * @param {string} str - The normalized numeric string * @returns {{isNegative: boolean, integerPart: bigint, decimalPart?: string}} The parsed numeric components */ function parseNumericString(str) { const isNegative = str[0] === '-' if (isNegative) str = str.slice(1) const dotIndex = str.indexOf('.') if (dotIndex === -1) { return { isNegative, integerPart: BigInt(str) } } const integerStr = str.slice(0, dotIndex) || '0' const decimalPart = str.slice(dotIndex + 1) return { isNegative, integerPart: BigInt(integerStr), decimalPart } }