Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typescript improvements #153

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/typescript-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: TypeScript Check

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
typescript-check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: TypeScript check
run: npx tsc --noEmit
44 changes: 38 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,55 @@ npm install n2words
### ESM

```js
import n2words from 'n2words'
// Default import
import n2words from 'n2words';
n2words(100); // "one hundred"

// Named import
import { n2words } from 'n2words';
n2words(100); // "one hundred"
```

### CommonJS ([dynamic import](https://nodejs.org/api/esm.html#import-expressions))
### TypeScript

```typescript
import n2words, { N2WordsOptions } from 'n2words';

// With TypeScript type checking
const options: N2WordsOptions = {
lang: 'fr',
negativeWord: 'négatif'
};

n2words(42, options); // "quarante-deux"
```

### CommonJS

```js
// Using require (CommonJS)
const { n2words } = require('n2words');
n2words(100); // "one hundred"

// Or using dynamic import
import('n2words').then(({default: n2words}) => {
n2words(100)
})
n2words(100); // "one hundred"
});
```

### Browser

```html
<script src="./n2words.js"></script>
<!-- UMD version for direct browser usage -->
<script src="https://cdn.jsdelivr.net/npm/n2words/dist/umd/n2words.js"></script>
<script>
n2words(100)
n2words(100); // "one hundred"
</script>

<!-- Modern browsers can use the ESM version -->
<script type="module">
import n2words from 'https://cdn.jsdelivr.net/npm/n2words/dist/esm/n2words.js';
console.log(n2words(100)); // "one hundred"
</script>
```

Expand Down
12 changes: 12 additions & 0 deletions examples/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": []
},
"include": ["*.ts"]
}
32 changes: 32 additions & 0 deletions examples/typescript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import n2words, { N2WordsOptions } from '../lib/n2words';

// Basic usage with default settings
console.log(n2words(123)); // "one hundred and twenty-three"

// Using language option
console.log(n2words(42, { lang: 'fr' })); // "quarante-deux"

// Using multiple options with types
const options: N2WordsOptions = {
lang: 'de',
negativeWord: 'minus',
separatorWord: 'Komma',
spaceSeparator: ' '
};

console.log(n2words(-42.5, options)); // "minus zweiundvierzig Komma fünf"

// Using named export
import { n2words as convertToWords } from '../lib/n2words';
console.log(convertToWords(7)); // "seven"

// All supported languages example
const languages = [
'en', 'fr', 'es', 'de', 'pt', 'it', 'tr', 'ru', 'cz',
'no', 'dk', 'pl', 'uk', 'lt', 'lv', 'ar', 'he', 'ko',
'nl', 'sr', 'fa', 'id', 'hu', 'vi', 'az', 'zh', 'hr'
];

for (const lang of languages) {
console.log(`${lang}: ${n2words(42, { lang })}`);
}
7 changes: 5 additions & 2 deletions lib/n2words.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ const dict = {
* @param {number|string|bigint} value The number to convert.
* @param {object} [options] User options.
* @returns {string} Value in written format.
* TODO [2024-06] Migrate to object destructing for parameters
*/
// eslint-disable-next-line unicorn/no-object-as-default-parameter
function floatToCardinal(value, options = { lang: 'en' }) {
Expand All @@ -79,7 +78,11 @@ function floatToCardinal(value, options = { lang: 'en' }) {
.find(l => dict[l] != undefined);
if (fallbackLang != undefined) return dict[fallbackLang](value, options);

throw new Error('Unsupported language: ' + value + '.');
throw new Error('Unsupported language: ' + options.lang + '.');
}

// Named export for better ESM compatibility
export const n2words = floatToCardinal;

// Default export for backward compatibility
export default floatToCardinal;
9 changes: 4 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 22 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,36 @@
],
"sideEffects": false,
"type": "module",
"main": "./dist/cjs/n2words.js",
"module": "./dist/esm/n2words.js",
"types": "./dist/types/n2words.d.ts",
"exports": {
".": "./lib/n2words.js",
"./i18n/*.js": "./lib/i18n/*.js"
".": {
"types": "./dist/types/n2words.d.ts",
"import": "./dist/esm/n2words.js",
"require": "./dist/cjs/n2words.js",
"default": "./dist/esm/n2words.js"
},
"./i18n/*": {
"types": "./dist/types/i18n/*.d.ts",
"import": "./dist/esm/i18n/*.js",
"require": "./dist/cjs/i18n/*.js",
"default": "./dist/esm/i18n/*.js"
}
},
"jsdelivr": "dist/n2words.js",
"unpkg": "dist/n2words.js",
"jsdelivr": "dist/umd/n2words.js",
"unpkg": "dist/umd/n2words.js",
"files": [
"lib/*",
"dist/*"
],
"scripts": {
"bench": "node bench.js",
"build": "webpack --progress",
"build:types": "npx -p typescript tsc lib/n2words.js dist/n2words.js --target es6 --module nodenext --allowJs --declaration --emitDeclarationOnly",
"build": "npm run build:esm && npm run build:cjs && npm run build:umd && npm run build:types",
"build:esm": "mkdir -p dist/esm && cp -r lib/* dist/esm/",
"build:cjs": "webpack --env target=cjs",
"build:umd": "webpack --env target=umd",
"build:types": "tsc --skipLibCheck",
"coverage": "c8 ava",
"docs": "jsdoc -c ./conf.json",
"lint": "npm run lint:js && npm run lint:md",
Expand Down
18 changes: 18 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "esnext",
"moduleResolution": "node",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist/types",
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true,
"allowJs": true,
"types": []
},
"include": ["lib/**/*"],
"exclude": ["node_modules", "dist"]
}
98 changes: 63 additions & 35 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,71 @@
import { readdirSync } from 'node:fs';
import path from 'node:path';

export default {
mode: 'production',
entry: {
n2words: './lib/n2words.js',
...getLanguages()
},
node: false,
devtool: 'source-map',
output: {
filename: '[name].js',
globalObject: 'this',
library: {
name: 'n2words',
type: 'umd2',
export: 'default'
export default (env) => {

Check failure on line 4 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (18)

The arrow function should be named

Check failure on line 4 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (18)

The variable `env` should be named `environment`. A more descriptive name will do too

Check failure on line 4 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (18)

Unexpected parentheses around single function argument

Check failure on line 4 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (22)

The arrow function should be named

Check failure on line 4 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (22)

The variable `env` should be named `environment`. A more descriptive name will do too

Check failure on line 4 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (22)

Unexpected parentheses around single function argument
const target = env.target || 'umd';

Check failure on line 6 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (18)

Trailing spaces not allowed

Check failure on line 6 in webpack.config.js

View workflow job for this annotation

GitHub Actions / build (22)

Trailing spaces not allowed
// Configure output based on target
const outputConfig = {
cjs: {
path: path.resolve('dist', 'cjs'),
filename: '[name].js',
library: {
type: 'commonjs2'
}
},
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: '3.37.1',
targets: 'defaults'
},
esm: {
path: path.resolve('dist', 'esm'),
filename: '[name].js',
library: {
type: 'module'
}
},
umd: {
path: path.resolve('dist', 'umd'),
filename: '[name].js',
globalObject: 'this',
library: {
name: 'n2words',
type: 'umd2',
export: ['default', 'n2words']
}
}
}[target];

return {
mode: 'production',
entry: {
n2words: './lib/n2words.js',
...getLanguages()
},
experiments: target === 'esm' ? { outputModule: true } : {},
node: false,
devtool: 'source-map',
output: outputConfig,
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: '3.37.1',
targets: target === 'esm' ? {
esmodules: true
} : 'defaults'
},
],
],
],
},
},
},
}],
}
}],
}
};
};

/**
Expand Down
Loading