Skip to content

Commit

Permalink
Rewrite in TypeScript with enahcements
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Rewrote the core into Typescript.

feat: added options ignoreDecimal, ignoreZeroCurrency

feat: added provision for i18n, currently supports en-IN (default) and en-US

fix: wrong conversion of fractional unit beginning with zero

docs: updated README

test: added unit tests with jest
  • Loading branch information
mastermunj committed Apr 23, 2020
1 parent b93a7a3 commit 9617f26
Show file tree
Hide file tree
Showing 28 changed files with 1,130 additions and 214 deletions.
6 changes: 0 additions & 6 deletions .babelrc

This file was deleted.

13 changes: 0 additions & 13 deletions .editorconfig

This file was deleted.

4 changes: 3 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
lib
node_modules
dist
coverage
13 changes: 0 additions & 13 deletions .eslintrc

This file was deleted.

17 changes: 17 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
env: {
es6: true,
commonjs: true,
browser: true,
},
};
65 changes: 55 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,76 @@ Converts Numbers (including decimal points) into words for Indian style. It also
npm install to-words --save
```

## Usage

Importing
```js
const { ToWords } = require('to-words');
```
OR
```js
Import { ToWords } from 'to-words';
```

Config Options
```js
yarn add to-words
const toWords = new ToWords({
localeCode: 'en-IN',
converterOptions: {
currency: true,
ignoreDecimal: false,
ignoreZeroCurrency: false,
}
});
```
Options can be set at instance level, or along with individual call to `convert` method.

```js
const toWords = new ToWords();
let words = toWords.convert(123); // words = One Hundred Twenty Three

words = toWords.convert(123.45); // words = One Hundred Twenty Three Point Fourty Five

words = toWords.convert(123.045); // words = One Hundred Twenty Three Point Zero Four Five
```
*Note: When fractional part starts with zero, the digits after decimal points are converted into respective numbers individually*

## Usage

To convert to currency

```js
let toWords = require('to-words');
let words = toWords(123); // words = One Hundred Twenty Three
const toWords = new ToWords();
let words = toWords.convert(452, { currency: true }); // words = Four Hundred Fifty Two Rupees Only

words = toWords.convert(452.36, { currency: true }); // words = Four Hundred Fifty Two Rupees And Thirty Six Paise Only

words = toWords(123.45); // words = One Hundred Twenty Three Point Fourty Five
```

To convert to currency
To discard fractional unit

```js
let toWords = require('to-words');
let words = toWords(452, {currency: true}); // words = Four Hundred Fifty Two Rupee Only
const toWords = new ToWords();

words = toWords(452.36, {currency: true}); // words = Four Hundred Fifty Two Rupee And Thirty Six Paise Only
let words = toWords.convert(452.36, { currency: true, ignoreDecimal: true }); // words = Four Hundred Fifty Two Rupees Only
```

To ignore major currency number when it's zero

```js
const toWords = new ToWords();

let words = toWords.convert(0.572, { currency: true, ignoreZeroCurrency: true }); // words = Five Hundred Seventy Two Paise Only
```


## Options
| Option | Type | Default | Description |
| ------------- | ------------- | ------------- | ------------- |
| localeCode | string | 'en-IN' | Locale code for selecting i18n. Currently only `en-IN` & `en-US` are supported. Please open issue / PR if more needed. |
| currency | boolean | false | Whether the number to be converted into words written as currency. *Note: When currency:true, number will be rounded off to two decimals before converting to words* |
| ignoreDecimal | boolean | false | Whether to ignore fractional unit of number while converting into words. |
| ignoreZeroCurrency | boolean | false | Whether to ignore zero currency value while converting into words. |


## Inspiration
## Inspiration for core logic
[https://stackoverflow.com/a/46221860](https://stackoverflow.com/a/46221860)
155 changes: 155 additions & 0 deletions __tests__/en-IN.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { ToWords } from '../src/to-words';
import cloneDeep from 'lodash/cloneDeep';

const toWords = new ToWords({
localeCode: 'en-IN'
});

const testIntegers = [
[0, 'Zero'],
[137, 'One Hundred Thirty Seven'],
[700, 'Seven Hundred'],
[4680, 'Four Thousand Six Hundred Eighty'],
[63892, 'Sixty Three Thousand Eight Hundred Ninety Two'],
[792581, 'Seven Lakh Ninety Two Thousand Five Hundred Eighty One'],
[2741034, 'Twenty Seven Lakh Forty One Thousand Thirty Four'],
[86429753, 'Eight Crore Sixty Four Lakh Twenty Nine Thousand Seven Hundred Fifty Three'],
[975310864, 'Ninety Seven Crore Fifty Three Lakh Ten Thousand Eight Hundred Sixty Four'],
[9876543210, 'Nine Hundred Eighty Seven Crore Sixty Five Lakh Forty Three Thousand Two Hundred Ten'],
[98765432101, 'Nine Thousand Eight Hundred Seventy Six Crore Fifty Four Lakh Thirty Two Thousand One Hundred One'],
[987654321012, 'Ninety Eight Thousand Seven Hundred Sixty Five Crore Forty Three Lakh Twenty One Thousand Twelve'],
[9876543210123, 'Nine Lakh Eighty Seven Thousand Six Hundred Fifty Four Crore Thirty Two Lakh Ten Thousand One Hundred Twenty Three'],
[98765432101234, 'Ninety Eight Lakh Seventy Six Thousand Five Hundred Forty Three Crore Twenty One Lakh One Thousand Two Hundred Thirty Four'],
];

describe('Test Integers with options = {}', () => {
test.each(testIntegers)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
});
});

const testNegativeIntegers = cloneDeep(testIntegers);
testNegativeIntegers.map((row, i) => {
if (i === 0) {
return;
}
row[0] = -row[0];
row[1] = 'Minus ' + row[1];
});

describe('Test Negative Integers with options = {}', () => {
test.each(testNegativeIntegers)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
});
});

const testIntegersWithCurrency = cloneDeep(testIntegers);
testIntegersWithCurrency.map((row) => {
row[1] = row[1] + ` Rupees Only`
});

describe('Test Integers with options = { currency: true }', () => {
test.each(testIntegersWithCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true })).toBe(expected);
});
});

const testIntegersWithCurrencyAndIgnoreZeroCurrency = cloneDeep(testIntegersWithCurrency);
testIntegersWithCurrencyAndIgnoreZeroCurrency[0][1] = '';

describe('Test Integers with options = { currency: true, ignoreZeroCurrency: true }', () => {
test.each(testIntegersWithCurrencyAndIgnoreZeroCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true, ignoreZeroCurrency: true })).toBe(expected);
});
});


const testFloats = [
[0.0, 'Zero'],
[0.04, 'Zero Point Zero Four'],
[0.0468, 'Zero Point Zero Four Six Eight'],
[0.4, 'Zero Point Four'],
[0.63, 'Zero Point Sixty Three'],
[0.973, 'Zero Point Nine Hundred Seventy Three'],
[0.999, 'Zero Point Nine Hundred Ninety Nine'],
[37.06, 'Thirty Seven Point Zero Six'],
[37.068, 'Thirty Seven Point Zero Six Eight'],
[37.68, 'Thirty Seven Point Sixty Eight'],
[37.683, 'Thirty Seven Point Six Hundred Eighty Three'],
];

describe('Test Floats with options = {}', () => {
test.each(testFloats)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
});
});


const testFloatsWithCurrency = [
[0.0, `Zero Rupees Only`],
[0.04, `Zero Rupees And Four Paise Only`],
[0.0468, `Zero Rupees And Five Paise Only`],
[0.4, `Zero Rupees And Forty Paise Only`],
[0.63, `Zero Rupees And Sixty Three Paise Only`],
[0.973, `Zero Rupees And Ninety Seven Paise Only`],
[0.999, `One Rupees Only`],
[37.06, `Thirty Seven Rupees And Six Paise Only`],
[37.068, `Thirty Seven Rupees And Seven Paise Only`],
[37.68, `Thirty Seven Rupees And Sixty Eight Paise Only`],
[37.683, `Thirty Seven Rupees And Sixty Eight Paise Only`],
];

describe('Test Floats with options = { currency: true }', () => {
test.each(testFloatsWithCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true })).toBe(expected);
});
});

const testFloatsWithCurrencyAndIgnoreZeroCurrency = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreZeroCurrency[0][1] = '';
testFloatsWithCurrencyAndIgnoreZeroCurrency.map((row, i) => {
if (i === 0) {
row[1] = '';
return;
}
if (row[0] > 0 && row[0] < 1) {
row[1] = (row[1] as string).replace(`Zero Rupees And `, '');
}
});

describe('Test Floats with options = { currency: true, ignoreZeroCurrency: true }', () => {
test.each(testFloatsWithCurrencyAndIgnoreZeroCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true, ignoreZeroCurrency: true })).toBe(expected);
});
});

const testFloatsWithCurrencyAndIgnoreDecimal = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreDecimal.map((row) => {
if (row[0] === 0.999) {
row[1] = `Zero Rupees Only`;
} else {
row[1] = (row[1] as string).replace(new RegExp(` And [\\w ]+ Paise`), '');
}
});

describe('Test Floats with options = { currency: true, ignoreDecimal: true }', () => {
test.each(testFloatsWithCurrencyAndIgnoreDecimal)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true, ignoreDecimal: true })).toBe(expected);
});
});

const testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals[0][1] = '';
testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals.map((row) => {
if (row[0] > 0 && row[0] < 1) {
row[1] = '';
}
row[1] = (row[1] as string).replace(new RegExp(` And [\\w ]+ Paise`), '');
});

describe('Test Floats with options = { currency: true, ignoreZeroCurrency: true, ignoreDecimal: true }', () => {
test.each(testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true, ignoreZeroCurrency: true, ignoreDecimal: true })).toBe(expected);
});
});

Loading

0 comments on commit 9617f26

Please sign in to comment.