@sumup/intl
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -32,8 +32,51 @@ # Contributing | ||
- Continuously transpile and typecheck the code: `yarn start` | ||
- Continuously run the tests: `yarn test` | ||
- Run the linter: `yarn lint` | ||
- Continuously transpile and typecheck the code: `npm run dev` | ||
- Continuously run the tests: `npm run test` | ||
- Run the linter: `npm run lint` | ||
## Troubleshooting | ||
Make sure that you use Node v16.13 _exactly_, otherwise, the unit tests will probably fail. Node's localisation data for the `Intl.NumberFormat` API tends to change between minor versions. | ||
Make sure that you use Node v18.14 _exactly_, otherwise, the unit tests will probably fail. Node's localisation data for the `Intl.NumberFormat` API tends to change between minor versions. | ||
## Release process | ||
`@sumup/intl` follows semantic versioning. In short, this means we use patch versions for bugfixes, minor versions for new features, and major versions for breaking changes. | ||
### Changesets | ||
`@sumup/intl` uses [changesets](https://github.com/atlassian/changesets) to do versioning. A changeset is a piece of information about changes made in a branch or commit. It holds three bits of information: | ||
- What needs to be released | ||
- What version the packages should be released at (using a [semver bump type](https://semver.org/)) | ||
- A changelog entry for the released packages | ||
Refer to the [official documentation](https://github.com/atlassian/changesets/blob/main/docs/adding-a-changeset.md#i-am-in-a-multi-package-repository-a-mono-repo) for more information. | ||
### Release branches | ||
We have a couple of special branches that are used for stable releases and [pre-releases](#pre-releases). | ||
- **`main`** - The code in the `main` branch is stable and production-tested. When a PR is merged to `main` that contains a new changeset, `changesets` opens a PR and keeps it up to date with the latest changes. When the PR is merged, a new version is automatically published to NPM and the changesets since the last release are added to `CHANGELOG.md` files in GitHub. | ||
- **`canary`** - This is a branch you can use to publish a prerelease version if you need to deploy the changes somewhere to test them. `canary` is a throw-away branch that can be recreated from `main` at any time. **Hint**: If you only need to test your changes locally, you can use `npm install ./path-to-foundry` to link the development version. | ||
- **`next`** — This branch is used to develop the next major version in parallel. It is the only branch that can contain breaking changes. | ||
To install the most recent version from a release channel in your project, run: | ||
```sh | ||
npm install --dev @sumup/intl@<release-channel> | ||
``` | ||
#### Pre-releases | ||
Pre-releases can be done for either the `next` or the `canary` release channels. | ||
To publish a pre-release version, check out on the branch for your release channel and run the `changesets pre enter` command: | ||
```sh | ||
git checkout next # or `canary` | ||
npx changeset pre enter next # or `canary` | ||
``` | ||
This will generate a `pre.json` file in the `.changeset` directory. | ||
Push it to the branch, then verify and merge the `changesets` "Version Package" PR for your release channel. `changesets` will publish the pre-release version in CI. |
@@ -23,1 +23,6 @@ /** | ||
}; | ||
/** | ||
* An array of currencies that support decimals according to the ISO standard | ||
* but don't use decimals in everyday life. | ||
*/ | ||
export declare const CURRENCIES_WITHOUT_DECIMALS: string[]; |
@@ -17,3 +17,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CURRENCIES = void 0; | ||
exports.CURRENCIES_WITHOUT_DECIMALS = exports.CURRENCIES = void 0; | ||
/** | ||
@@ -517,1 +517,6 @@ * An object that maps a 2 char country code to its official 3 char currency code. | ||
}; | ||
/** | ||
* An array of currencies that support decimals according to the ISO standard | ||
* but don't use decimals in everyday life. | ||
*/ | ||
exports.CURRENCIES_WITHOUT_DECIMALS = ['COP', 'HUF']; |
@@ -189,3 +189,3 @@ /** | ||
* @remarks | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -192,0 +192,0 @@ * |
@@ -270,3 +270,3 @@ "use strict"; | ||
* @remarks | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -273,0 +273,0 @@ * |
@@ -40,3 +40,3 @@ "use strict"; | ||
var actual = (0, __1.formatDateTime)(shared_1.date, locale, { timeStyle: 'short' }); | ||
expect(actual).toMatchInlineSnapshot('"12:00:00 AM"'); | ||
expect(actual).toMatchInlineSnapshot('"12:00:00 AM"'); | ||
}); | ||
@@ -48,3 +48,3 @@ it('should format a date time', function () { | ||
}); | ||
expect(actual).toMatchInlineSnapshot('"12/31/1899, 12:00:00 AM"'); | ||
expect(actual).toMatchInlineSnapshot('"12/31/1899, 12:00:00 AM"'); | ||
}); | ||
@@ -55,3 +55,3 @@ it('should format a date time to a single literal part', function () { | ||
expect(parts[0]).toHaveProperty('type', 'literal'); | ||
expect(parts[0]).toHaveProperty('value', '12/31/1899, 12:00:00 AM'); | ||
expect(parts[0]).toHaveProperty('value', '12/31/1899, 12:00:00 AM'); | ||
}); | ||
@@ -58,0 +58,0 @@ it('should return `null` for the date time format', function () { |
@@ -71,4 +71,7 @@ "use strict"; | ||
} | ||
if (currencies_1.CURRENCIES_WITHOUT_DECIMALS.includes(finalCurrency)) { | ||
return __assign(__assign({}, options), { style: 'currency', currency: finalCurrency, minimumFractionDigits: 0 }); | ||
} | ||
return __assign(__assign({}, options), { style: 'currency', currency: finalCurrency }); | ||
} | ||
exports.getCurrencyOptions = getCurrencyOptions; |
@@ -61,2 +61,4 @@ /** | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -151,2 +153,4 @@ */ | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -212,3 +216,3 @@ */ | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -287,7 +291,9 @@ * | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
*/ | ||
export declare const resolveCurrencyFormat: (locales?: Locale | Locale[], currency?: Currency, options?: Intl.NumberFormatOptions) => NumberFormat | null; |
@@ -88,2 +88,4 @@ "use strict"; | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -200,2 +202,4 @@ */ | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -285,3 +289,3 @@ */ | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -360,5 +364,7 @@ * | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -365,0 +371,0 @@ */ |
@@ -18,2 +18,3 @@ "use strict"; | ||
var __1 = require(".."); | ||
var currencies_1 = require("../../../data/currencies"); | ||
var shared_1 = require("./shared"); | ||
@@ -47,7 +48,16 @@ describe('Numbers', function () { | ||
expect(actual).toBeArray(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, { | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, expect.objectContaining({ | ||
style: 'currency', | ||
currency: expect.any(String), | ||
}); | ||
})); | ||
}); | ||
it.each(currencies_1.CURRENCIES_WITHOUT_DECIMALS)('should format the %o currency without decimals', function (currency) { | ||
var actual = (0, __1.formatCurrencyToParts)(shared_1.number, undefined, currency); | ||
expect(actual).toBeArray(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(undefined, expect.objectContaining({ | ||
style: 'currency', | ||
currency: currency, | ||
minimumFractionDigits: 0, | ||
})); | ||
}); | ||
it('should accept a custom currency', function () { | ||
@@ -54,0 +64,0 @@ var locale = 'xx-XX'; |
@@ -18,2 +18,3 @@ "use strict"; | ||
var __1 = require(".."); | ||
var currencies_1 = require("../../../data/currencies"); | ||
var shared_1 = require("./shared"); | ||
@@ -47,7 +48,16 @@ describe('Numbers', function () { | ||
expect(actual).toBeString(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, { | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, expect.objectContaining({ | ||
style: 'currency', | ||
currency: expect.any(String), | ||
}); | ||
})); | ||
}); | ||
it.each(currencies_1.CURRENCIES_WITHOUT_DECIMALS)('should format the %o currency without decimals', function (currency) { | ||
var actual = (0, __1.formatCurrency)(shared_1.number, undefined, currency); | ||
expect(actual).toBeString(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(undefined, expect.objectContaining({ | ||
style: 'currency', | ||
currency: currency, | ||
minimumFractionDigits: 0, | ||
})); | ||
}); | ||
it('should accept a custom currency', function () { | ||
@@ -54,0 +64,0 @@ var locale = 'xx-XX'; |
@@ -18,2 +18,3 @@ "use strict"; | ||
var __1 = require(".."); | ||
var currencies_1 = require("../../../data/currencies"); | ||
var shared_1 = require("./shared"); | ||
@@ -42,7 +43,16 @@ describe('Numbers', function () { | ||
expect(actual).toBeObject(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, { | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, expect.objectContaining({ | ||
style: 'currency', | ||
currency: expect.any(String), | ||
}); | ||
})); | ||
}); | ||
it.each(currencies_1.CURRENCIES_WITHOUT_DECIMALS)('should get the %o currency format without decimals', function (currency) { | ||
var actual = (0, __1.resolveCurrencyFormat)(undefined, currency); | ||
expect(actual).toBeObject(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(undefined, expect.objectContaining({ | ||
style: 'currency', | ||
currency: currency, | ||
minimumFractionDigits: 0, | ||
})); | ||
}); | ||
it('should include additional options', function () { | ||
@@ -49,0 +59,0 @@ var locale = 'en-US'; |
@@ -23,1 +23,6 @@ /** | ||
}; | ||
/** | ||
* An array of currencies that support decimals according to the ISO standard | ||
* but don't use decimals in everyday life. | ||
*/ | ||
export declare const CURRENCIES_WITHOUT_DECIMALS: string[]; |
@@ -513,1 +513,6 @@ /** | ||
}; | ||
/** | ||
* An array of currencies that support decimals according to the ISO standard | ||
* but don't use decimals in everyday life. | ||
*/ | ||
export const CURRENCIES_WITHOUT_DECIMALS = ['COP', 'HUF']; |
@@ -189,3 +189,3 @@ /** | ||
* @remarks | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -192,0 +192,0 @@ * |
@@ -251,3 +251,3 @@ /** | ||
* @remarks | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.DateTimeFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -254,0 +254,0 @@ * |
@@ -27,3 +27,3 @@ /** | ||
const actual = formatDateTime(date, locale, { timeStyle: 'short' }); | ||
expect(actual).toMatchInlineSnapshot('"12:00:00 AM"'); | ||
expect(actual).toMatchInlineSnapshot('"12:00:00 AM"'); | ||
}); | ||
@@ -35,3 +35,3 @@ it('should format a date time', () => { | ||
}); | ||
expect(actual).toMatchInlineSnapshot('"12/31/1899, 12:00:00 AM"'); | ||
expect(actual).toMatchInlineSnapshot('"12/31/1899, 12:00:00 AM"'); | ||
}); | ||
@@ -42,3 +42,3 @@ it('should format a date time to a single literal part', () => { | ||
expect(parts[0]).toHaveProperty('type', 'literal'); | ||
expect(parts[0]).toHaveProperty('value', '12/31/1899, 12:00:00 AM'); | ||
expect(parts[0]).toHaveProperty('value', '12/31/1899, 12:00:00 AM'); | ||
}); | ||
@@ -45,0 +45,0 @@ it('should return `null` for the date time format', () => { |
@@ -15,3 +15,3 @@ /** | ||
*/ | ||
import { CURRENCIES } from '../../data/currencies'; | ||
import { CURRENCIES, CURRENCIES_WITHOUT_DECIMALS } from '../../data/currencies'; | ||
import { resolveLocale } from './intl'; | ||
@@ -55,3 +55,6 @@ export function extractCountry(locale) { | ||
} | ||
if (CURRENCIES_WITHOUT_DECIMALS.includes(finalCurrency)) { | ||
return Object.assign(Object.assign({}, options), { style: 'currency', currency: finalCurrency, minimumFractionDigits: 0 }); | ||
} | ||
return Object.assign(Object.assign({}, options), { style: 'currency', currency: finalCurrency }); | ||
} |
@@ -61,2 +61,4 @@ /** | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -151,2 +153,4 @@ */ | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -212,3 +216,3 @@ */ | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -287,7 +291,9 @@ * | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
*/ | ||
export declare const resolveCurrencyFormat: (locales?: Locale | Locale[], currency?: Currency, options?: Intl.NumberFormatOptions) => NumberFormat | null; |
@@ -63,2 +63,4 @@ /** | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -165,2 +167,4 @@ */ | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -240,3 +244,3 @@ */ | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
@@ -315,5 +319,7 @@ * | ||
* | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions' API, | ||
* In runtimes that don't support the `Intl.NumberFormat.resolvedOptions` API, | ||
* `null` is returned. | ||
* | ||
* The COP and HUF currencies are formatted without decimals. | ||
* | ||
* @category Currency | ||
@@ -320,0 +326,0 @@ */ |
@@ -16,2 +16,3 @@ /** | ||
import { formatNumberToParts, formatCurrencyToParts } from '..'; | ||
import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies'; | ||
import { locales, number } from './shared'; | ||
@@ -45,7 +46,16 @@ describe('Numbers', () => { | ||
expect(actual).toBeArray(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, { | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, expect.objectContaining({ | ||
style: 'currency', | ||
currency: expect.any(String), | ||
}); | ||
})); | ||
}); | ||
it.each(CURRENCIES_WITHOUT_DECIMALS)('should format the %o currency without decimals', (currency) => { | ||
const actual = formatCurrencyToParts(number, undefined, currency); | ||
expect(actual).toBeArray(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(undefined, expect.objectContaining({ | ||
style: 'currency', | ||
currency, | ||
minimumFractionDigits: 0, | ||
})); | ||
}); | ||
it('should accept a custom currency', () => { | ||
@@ -52,0 +62,0 @@ const locale = 'xx-XX'; |
@@ -16,2 +16,3 @@ /** | ||
import { formatNumber, formatCurrency } from '..'; | ||
import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies'; | ||
import { locales, number } from './shared'; | ||
@@ -45,7 +46,16 @@ describe('Numbers', () => { | ||
expect(actual).toBeString(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, { | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, expect.objectContaining({ | ||
style: 'currency', | ||
currency: expect.any(String), | ||
}); | ||
})); | ||
}); | ||
it.each(CURRENCIES_WITHOUT_DECIMALS)('should format the %o currency without decimals', (currency) => { | ||
const actual = formatCurrency(number, undefined, currency); | ||
expect(actual).toBeString(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(undefined, expect.objectContaining({ | ||
style: 'currency', | ||
currency, | ||
minimumFractionDigits: 0, | ||
})); | ||
}); | ||
it('should accept a custom currency', () => { | ||
@@ -52,0 +62,0 @@ const locale = 'xx-XX'; |
@@ -16,2 +16,3 @@ /** | ||
import { resolveNumberFormat, resolveCurrencyFormat } from '..'; | ||
import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies'; | ||
import { locales } from './shared'; | ||
@@ -40,7 +41,16 @@ describe('Numbers', () => { | ||
expect(actual).toBeObject(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, { | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(locale, expect.objectContaining({ | ||
style: 'currency', | ||
currency: expect.any(String), | ||
}); | ||
})); | ||
}); | ||
it.each(CURRENCIES_WITHOUT_DECIMALS)('should get the %o currency format without decimals', (currency) => { | ||
const actual = resolveCurrencyFormat(undefined, currency); | ||
expect(actual).toBeObject(); | ||
expect(Intl.NumberFormat).toHaveBeenCalledWith(undefined, expect.objectContaining({ | ||
style: 'currency', | ||
currency, | ||
minimumFractionDigits: 0, | ||
})); | ||
}); | ||
it('should include additional options', () => { | ||
@@ -47,0 +57,0 @@ const locale = 'en-US'; |
{ | ||
"name": "@sumup/intl", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "Format numbers, currency values, dates, and times for any locale with the ECMAScript Internationalization API", | ||
@@ -23,9 +23,6 @@ "repository": "git@github.com:sumup-oss/intl-js.git", | ||
}, | ||
"foundry": { | ||
"publish": true | ||
}, | ||
"scripts": { | ||
"start": "tsc --watch", | ||
"dev": "yarn start", | ||
"build": "yarn build:es && yarn build:cjs", | ||
"dev": "npm run start", | ||
"build": "npm run build:es && npm run build:cjs", | ||
"build:es": "tsc", | ||
@@ -35,10 +32,9 @@ "build:cjs": "tsc --project tsconfig.cjs.json", | ||
"lint": "foundry run eslint . --ext .js,.jsx,.ts,.tsx", | ||
"lint:fix": "yarn lint --fix", | ||
"lint:ci": "yarn lint --format github", | ||
"prerelease": "yarn build", | ||
"release": "foundry run semantic-release", | ||
"lint:fix": "npm run lint -- --fix", | ||
"test": "jest --watch", | ||
"test:ci": "jest --ci --runInBand --coverage --reporters default --reporters \"jest-github-reporter\"", | ||
"test:ci": "jest --ci --runInBand --coverage --reporters default --reporters \"github-actions\"", | ||
"check:security": "audit-ci --critical", | ||
"check:licenses": "license-checker --production --summary --failOn=GPLv3" | ||
"check:licenses": "license-checker --production --summary --failOn=GPLv3", | ||
"prerelease": "npm run build", | ||
"release": "changeset publish" | ||
}, | ||
@@ -52,15 +48,16 @@ "engines": { | ||
"devDependencies": { | ||
"@sumup/foundry": "^5.0.0", | ||
"@types/jest": "^29.1.2", | ||
"audit-ci": "^6.1.0", | ||
"jest": "^29.1.2", | ||
"jest-extended": "^3.0.0", | ||
"jest-github-reporter": "^1.0.2", | ||
"@changesets/changelog-github": "^0.4.8", | ||
"@changesets/cli": "^2.26.2", | ||
"@sumup/foundry": "^6.1.0", | ||
"@types/jest": "^29.5.4", | ||
"audit-ci": "^6.6.1", | ||
"jest": "^29.6.4", | ||
"jest-extended": "^4.0.1", | ||
"license-checker": "^25.0.1", | ||
"ts-jest": "^29.0.3", | ||
"typedoc": "^0.23.16", | ||
"typedoc-github-wiki-theme": "^1.0.1", | ||
"typedoc-plugin-markdown": "^3.13.6", | ||
"typescript": "^4.3.2" | ||
"ts-jest": "^29.1.1", | ||
"typedoc": "^0.25.0", | ||
"typedoc-github-wiki-theme": "^1.1.0", | ||
"typedoc-plugin-markdown": "^3.16.0", | ||
"typescript": "^5.2.2" | ||
} | ||
} |
@@ -98,3 +98,2 @@ <div align="center"> | ||
- [Connor Bär](mailto:connor.baer@sumup.com) | ||
- [Robin Métral](mailto:robin.metral@sumup.com) | ||
@@ -101,0 +100,0 @@ ## About SumUp |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
238284
5911
13
106