spell-vn-number
Version:
Vietnamese number speller
176 lines • 7.34 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.cleanInputNumber = cleanInputNumber;
exports.normalizeNumberString = normalizeNumberString;
exports.trimLeft = trimLeft;
exports.trimRight = trimRight;
exports.trimRedundantZeros = trimRedundantZeros;
var types_1 = require("./types");
/**
* Validates an input number, ensures it's a valid string representation.
* @param input The input number to validate
* @param config NormalizeOptions
* @returns A valid string representation of the number
*/
function cleanInputNumber(input, config) {
if (input === null || input === undefined || input === '') {
throw new types_1.InvalidFormatError('Input cannot be null or undefined');
}
// Handle bigint - simplest case, just convert to string and return
if (typeof input === 'bigint') {
return input.toString();
}
// Handle number
if (typeof input === 'number') {
if (!Number.isFinite(input) || Number.isNaN(input)) {
throw new types_1.InvalidFormatError('Input must be a finite number');
}
// Convert number to string and handle scientific notation
var numberStr = input.toString();
return /e/i.test(numberStr) ? convertScientificToDecimal(input) : numberStr;
}
// Handle string - requires validation
var strWithoutSeparators = normalizeNumberString(input, config);
// Create a dynamic pattern based on config - IE11 compatible
var validPattern = new RegExp('^-?\\d+(' + escapeRegExp(config.decimalPoint || '.') + '\\d+)?$');
// Check if the string follows a valid number pattern
if (!validPattern.test(strWithoutSeparators)) {
throw new types_1.InvalidNumberError('Invalid number format');
}
return strWithoutSeparators;
}
/**
* Converts a number in scientific notation to decimal notation
* Compatible with older browsers including IE11
* @param num The number to convert
* @returns String representation in decimal notation
*/
function convertScientificToDecimal(num) {
// Get string representation in exponential format
var str = num.toString();
// If it doesn't contain 'e', return as is
if (!str.includes('e') && !str.includes('E')) {
return str;
}
// Normalize the exponential notation
var normalizedStr = str.replace(/E/i, 'e');
// Split into base and exponent
var parts = normalizedStr.split('e');
var base = parts[0];
var exponent = parseInt(parts[1], 10);
// If exponent is 0, return the base
if (exponent === 0) {
return base;
}
// Handle the case without decimal point in base
var hasDecimal = base.includes('.');
var coefficient = hasDecimal ? base.replace('.', '') : base;
var decimalPosition = hasDecimal ? base.indexOf('.') : base.length;
// Adjust decimal position based on exponent
decimalPosition += exponent;
// Create result with appropriate decimal position
var result = '';
if (decimalPosition <= 0) {
// Need leading zeros (e.g., 0.000123)
result = '0.' + '0'.repeat(-decimalPosition) + coefficient;
}
else if (decimalPosition >= coefficient.length) {
// Need trailing zeros (e.g., 123000)
result = coefficient + '0'.repeat(decimalPosition - coefficient.length);
}
else {
// Insert decimal point at the right position
result = coefficient.substring(0, decimalPosition) + '.' + coefficient.substring(decimalPosition);
}
// If the original number was negative, keep the sign
if (base.startsWith('-')) {
result = '-' + result.replace('-', '');
}
return result;
}
/**
* Normalizes a number string by cleaning whitespace and special characters.
* Compatible with IE11 and older browsers.
* @param input The string to normalize
* @param options Options for normalization
* @returns Normalized number string
*/
function normalizeNumberString(input, options) {
if (options === void 0) { options = { decimalPoint: '.', thousandSign: ',' }; }
return input
.replace(/[\s\u00A0]/g, '') // Remove all spaces and non-breaking spaces
.replace(/[\u2013\u2014]/g, '-') // Replace en/em dash with hyphen-minus
.replace(new RegExp(escapeRegExp(options.thousandSign || ','), 'g'), ''); // Remove thousands separators
}
/**
* Escapes special characters for use in RegExp
* @param string String to escape
* @returns Escaped string
*/
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
/**
* Removes leading characters from a string.
* If the result was empty after removing all leading characters that match the input character,
* returns the input character (char parameter) instead of an empty string.
*
* @example
* trimLeft('000123', '0') // returns '123'
* trimLeft('000', '0') // returns '0'
* trimLeft('000', '1') // returns '000' (no trimming since no '1's at start)
* trimLeft('111', '1') // returns '1'
*
* @param str The input string
* @param char The character to trim (default '0')
* @returns The string with leading chars removed, or the input char if all matching characters were removed
*/
function trimLeft(str, char) {
if (char === void 0) { char = '0'; }
var startIndex = 0;
while (startIndex < str.length && str.charAt(startIndex) === char) {
startIndex++;
}
return startIndex === str.length ? char : str.substring(startIndex);
}
/**
* Removes trailing zeros from a string
* @param str The input string
* @param char The character to trim (default '0')
* @param keepOneZeroWhenAllZeros
* @returns The string with trailing chars removed
*/
function trimRight(str, char, keepOneZeroWhenAllZeros) {
if (char === void 0) { char = '0'; }
if (keepOneZeroWhenAllZeros === void 0) { keepOneZeroWhenAllZeros = false; }
var endIndex = str.length - 1;
while (endIndex >= 0 && str.charAt(endIndex) === char) {
endIndex--;
}
return endIndex < 0 ? (keepOneZeroWhenAllZeros ? char : '') : str.substring(0, endIndex + 1);
}
/**
* Trims redundant zeros at the beginning and end of a number string with configurable behavior
* For integral part: trims leading zeros but always keeps at least one if at start
* For fractional part: trims trailing zeros with configurable behavior
* keepOneZeroWhenAllZeros:
* - When true, fractional part that consists of all zeros will result in a single trailing zero
* - When false, fractional part that consists of all zeros will be completely removed, leaving only the decimal point
* @param config Configuration object with trim settings
* @param numberStr The number string to process
* @returns The trimmed number string
*/
function trimRedundantZeros(config, numberStr) {
if (numberStr.includes(config.decimalPoint)) {
// Handle decimal numbers
var parts = numberStr.split(config.decimalPoint);
var intPart = trimLeft(parts[0], config.redundantZeroChar);
var fractionalPart = trimRight(parts[1], config.redundantZeroChar, config.keepOneZeroWhenAllZeros);
return "".concat(intPart).concat(config.decimalPoint).concat(fractionalPart);
}
else {
// Handle integer numbers
return trimLeft(numberStr, config.redundantZeroChar);
}
}
//# sourceMappingURL=utils.js.map