spell-vn-number
Version:
Vietnamese number speller
274 lines • 11.1 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { cleanInputNumber, trimLeft, trimRight } from './utils';
var InvalidFormatError = /** @class */ (function (_super) {
__extends(InvalidFormatError, _super);
function InvalidFormatError(message) {
var _this = _super.call(this, message) || this;
// For IE 11 and older browsers without proper Error inheritance
_this.name = 'InvalidFormatError';
Object.setPrototypeOf(_this, InvalidFormatError.prototype);
return _this;
}
return InvalidFormatError;
}(Error));
export { InvalidFormatError };
var InvalidNumberError = /** @class */ (function (_super) {
__extends(InvalidNumberError, _super);
function InvalidNumberError(message) {
var _this = _super.call(this, message) || this;
// For IE 11 and older browsers without proper Error inheritance
_this.name = 'InvalidNumberError';
Object.setPrototypeOf(_this, InvalidNumberError.prototype);
return _this;
}
return InvalidNumberError;
}(Error));
export { InvalidNumberError };
/**
* Group and position indices
* Chỉ số nhóm và vị trí
*/
export var Idx;
(function (Idx) {
// Group indices (chỉ số nhóm)
Idx[Idx["BIL"] = 0] = "BIL";
Idx[Idx["MIL"] = 1] = "MIL";
Idx[Idx["THO"] = 2] = "THO";
// Position indices (chỉ số vị trí)
Idx[Idx["HUN"] = 3] = "HUN";
Idx[Idx["TEN"] = 4] = "TEN";
Idx[Idx["UNI"] = 5] = "UNI"; // UNITS:(empty)
})(Idx || (Idx = {}));
var SpellerConfig = /** @class */ (function () {
function SpellerConfig(config) {
if (config === void 0) { config = {}; }
this.separator = ' ';
this.negativeSign = '-';
this.decimalPoint = '.';
this.thousandSign = ',';
this.negativeText = 'âm';
this.pointText = 'chấm';
this.capitalizeInitial = true;
this.currencyUnit = ''; // option for currency unit
/**
* Character used to represent redundant zeros in number strings.
* This character will be trimmed from both the beginning and end of numbers.
* Default is '0'.
*/
this.redundantZeroChar = '0';
// Controls how to handle redundant zeros in fractional part
this.keepOneZeroWhenAllZeros = false; // When true, keeps a single '0' after decimal point when all decimal digits are zeros (e.g., '123.000' -> '123.0')
// When false, removes all trailing zeros and keeps only the decimal point (e.g., '123.000' -> '123.')
/**
* Custom names for digits (chữ số)
* @example { '4': 'tư' }
*/
this.digitNames = {
'0': 'không',
'1': 'một',
'2': 'hai',
'3': 'ba',
'4': 'bốn',
'5': 'năm',
'6': 'sáu',
'7': 'bảy',
'8': 'tám',
'9': 'chín'
};
/**
* Custom names for all units (đơn vị)
* @example {
* 0: 'tỉ', // magnitude unit: billion
* 1: 'triệu', // magnitude unit: million
* 2: 'nghìn', // magnitude unit: thousand
* 3: 'trăm', // position unit: hundred
* 4: 'mươi', // position unit: ten
* 5: '' // position unit: unit
* }
*/
this.unitNames = {
0: 'tỷ',
1: 'triệu',
2: 'nghìn',
3: 'trăm',
4: 'mươi',
5: ''
};
this.specificText = {
oddText: 'lẻ',
tenText: 'mười',
oneToneText: 'mốt',
fourToneText: 'tư',
fiveToneText: 'lăm'
};
// Apply configuration with type safety
if (config) {
var configKeys = Object.keys(config);
for (var i = 0; i < configKeys.length; i++) {
var key = configKeys[i];
if (key !== 'specificText' && key !== 'digitNames' && key !== 'unitNames') {
this[key] = config[key];
}
}
}
// Apply specific text configuration with type safety
if (config === null || config === void 0 ? void 0 : config.specificText) {
this.specificText = {
oddText: config.specificText.oddText || this.specificText.oddText,
tenText: config.specificText.tenText || this.specificText.tenText,
oneToneText: config.specificText.oneToneText || this.specificText.oneToneText,
fourToneText: config.specificText.fourToneText || this.specificText.fourToneText,
fiveToneText: config.specificText.fiveToneText || this.specificText.fiveToneText
};
}
// Apply custom digit names if provided
if (config === null || config === void 0 ? void 0 : config.digitNames) {
this.digitNames = {
'0': config.digitNames['0'] || this.digitNames['0'],
'1': config.digitNames['1'] || this.digitNames['1'],
'2': config.digitNames['2'] || this.digitNames['2'],
'3': config.digitNames['3'] || this.digitNames['3'],
'4': config.digitNames['4'] || this.digitNames['4'],
'5': config.digitNames['5'] || this.digitNames['5'],
'6': config.digitNames['6'] || this.digitNames['6'],
'7': config.digitNames['7'] || this.digitNames['7'],
'8': config.digitNames['8'] || this.digitNames['8'],
'9': config.digitNames['9'] || this.digitNames['9']
};
}
// Apply custom unit names if provided
if (config === null || config === void 0 ? void 0 : config.unitNames) {
this.unitNames = {
0: config.unitNames[0] || this.unitNames[0],
1: config.unitNames[1] || this.unitNames[1],
2: config.unitNames[2] || this.unitNames[2],
3: config.unitNames[3] || this.unitNames[3],
4: config.unitNames[4] || this.unitNames[4],
5: config.unitNames[5] || this.unitNames[5]
};
}
}
SpellerConfig.prototype.getDigit = function (digit) {
return this.digitNames[digit];
};
SpellerConfig.prototype.findUnit = function (index) {
return this.unitNames[index];
};
SpellerConfig.prototype.findMagUnit = function (magnitudeIndex) {
if (magnitudeIndex === Idx.BIL) {
return this.unitNames[Idx.MIL];
}
else if (magnitudeIndex === Idx.MIL) {
return this.unitNames[Idx.THO];
}
// magnitudeIndex === Index.THO //THOUSAND
return this.unitNames[Idx.UNI];
};
Object.defineProperty(SpellerConfig.prototype, "oddText", {
// Getters for specific text
get: function () {
return this.specificText.oddText;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SpellerConfig.prototype, "tenText", {
get: function () {
return this.specificText.tenText;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SpellerConfig.prototype, "oneToneText", {
get: function () {
return this.specificText.oneToneText;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SpellerConfig.prototype, "fourToneText", {
get: function () {
return this.specificText.fourToneText;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SpellerConfig.prototype, "fiveToneText", {
get: function () {
return this.specificText.fiveToneText;
},
enumerable: false,
configurable: true
});
/**
* Parses and processes the input number into a structured format.
* This method is responsible for:
* - Cleaning and validating the input number
* - Handling negative signs
* - Splitting the number into integral and fractional parts
* - Trimming redundant zeros according to configuration
*
* The method can be overridden in a subclass to implement custom parsing logic
* while maintaining the default behavior through super.parseNumberData().
*
* @param input - The number to parse, can be a string, number, or bigint
* @returns A NumberData object containing:
* - isNegative: boolean indicating if the number is negative
* - integralPart: string containing the integral part
* - fractionalPart: string containing the fractional part
*
* @example
* ```typescript
* class CustomSpellerConfig extends SpellerConfig {
* parseNumberData(input: InputNumber): NumberData {
* // Custom parsing logic here
* // For example, handle special number formats
*
* // Use default implementation for standard cases
* return super.parseNumberData(input);
* }
* }
* ```
*/
SpellerConfig.prototype.parseNumberData = function (input) {
// Clean and validate input
var numberStr = cleanInputNumber(input, this);
// Handle negative sign
var isNegative = numberStr.startsWith(this.negativeSign);
numberStr = isNegative ? numberStr.substring(this.negativeSign.length) : numberStr;
// Trim redundant zeros && Split into integral and fractional parts
var pointPos = numberStr.indexOf(this.decimalPoint);
if (pointPos === -1) {
numberStr = trimLeft(numberStr, this.redundantZeroChar);
return {
isNegative: isNegative,
integralPart: numberStr,
fractionalPart: '',
};
}
else {
return {
isNegative: isNegative,
integralPart: trimLeft(numberStr.substring(0, pointPos), this.redundantZeroChar),
fractionalPart: trimRight(numberStr.substring(pointPos + 1), this.redundantZeroChar, this.keepOneZeroWhenAllZeros),
};
}
};
return SpellerConfig;
}());
export { SpellerConfig };
//# sourceMappingURL=types.js.map