diff --git a/.changeset/bright-adults-battle.md b/.changeset/bright-adults-battle.md new file mode 100644 index 0000000..adeadd7 --- /dev/null +++ b/.changeset/bright-adults-battle.md @@ -0,0 +1,5 @@ +--- +"@obosbbl/format": minor +--- + +initial release diff --git a/packages/format/README.md b/packages/format/README.md new file mode 100644 index 0000000..05d87b2 --- /dev/null +++ b/packages/format/README.md @@ -0,0 +1,39 @@ +# @obosbbl/format + +[![NPM Version](https://img.shields.io/npm/v/%40obosbbl%2Fformat)](https://www.npmjs.com/package/@obosbbl/format) + + +A collection of formatting functions for both πŸ‡³πŸ‡΄ and πŸ‡ΈπŸ‡ͺ with zero dependencies. + +## Install + +```sh +# npm +npm install @obosbbl/format + +# pnpm +pnpm add @obosbbl/format +``` + +## Usage + +The package has two entrypoints, one for `no` and one for `se`. That allows you to import for only the locale you need. + +Note that the methods are very lenient when attempting to format the input. It will strip all characters that aren't digits or letters before it applies the formatting. +That way any existing format of the input won't affect the formatted output + +If unable to format the input, the method will return the (cleaned) input as is. + +```js +// πŸ‡³πŸ‡΄ example +import { formatOrganizationNumber } from '@obosbbl/format/no'; +formatOrganizationNumber('000000000') // => '000 000 000' + +// πŸ‡ΈπŸ‡ͺ example +import { formatOrganizationNumber } from '@obosbbl/format/se'; +formatOrganizationNumber('0000000000') // => '000000-0000' +``` + +## Methods + +* formatOrganizationNumber diff --git a/packages/format/package.json b/packages/format/package.json new file mode 100644 index 0000000..2b8057a --- /dev/null +++ b/packages/format/package.json @@ -0,0 +1,28 @@ +{ + "name": "@obosbbl/format", + "version": "0.0.0", + "description": "A collection of formatting methods for OBOS", + "repository": { + "url": "https://github.com/code-obos/public-frontend-modules" + }, + "license": "MIT", + "sideEffects": false, + "type": "module", + "exports": { + "./no": { + "types": "./dist/no.d.mts", + "default": "./dist/no.mjs" + }, + "./se": { + "types": "./dist/se.d.mts", + "default": "./dist/se.mjs" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "bunchee" + }, + "dependencies": {} +} diff --git a/packages/format/src/format.test.ts b/packages/format/src/format.test.ts new file mode 100644 index 0000000..919cbd9 --- /dev/null +++ b/packages/format/src/format.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, test } from 'vitest'; +import { formatOrganizationNumber as formatOrganizationNumberNo } from './no'; +import { formatOrganizationNumber as formatOrganizationNumberSe } from './se'; + +describe('no', () => { + test.each([ + ['000000000', '000 000 000'], + ['000 000 000', '000 000 000'], + ['000-000-000', '000 000 000'], + ['abc', 'abc'], + ])('formatOrganizationNumber(%s) -> %s', (input, expected) => { + expect(formatOrganizationNumberNo(input)).toBe(expected); + }); +}); + +describe('se', () => { + test.each([ + ['0000000000', '000000-0000'], + ['000000-0000', '000000-0000'], + ['000000 0000', '000000-0000'], + [' 000000 0000 ', '000000-0000'], + ['000', '000'], + ['abc', 'abc'], + ])('formatOrganizationNumber(%s) -> %s', (input, expected) => { + expect(formatOrganizationNumberSe(input)).toBe(expected); + }); +}); diff --git a/packages/format/src/no.ts b/packages/format/src/no.ts new file mode 100644 index 0000000..c2e823f --- /dev/null +++ b/packages/format/src/no.ts @@ -0,0 +1,14 @@ +import { replaceIfMatch } from './utils'; + +const ORG_NUMBER_FORMAT = /^(\d{3})(\d{3})(\d{3})$/; + +/** + * Format an organization number + * @example + * ``` + * formatOrganizationNumber('000000000') // => '000 000 000' + * ``` + */ +export function formatOrganizationNumber(input: string): string { + return replaceIfMatch(input, ORG_NUMBER_FORMAT, '$1 $2 $3'); +} diff --git a/packages/format/src/se.ts b/packages/format/src/se.ts new file mode 100644 index 0000000..363ce12 --- /dev/null +++ b/packages/format/src/se.ts @@ -0,0 +1,14 @@ +import { replaceIfMatch } from './utils'; + +const ORG_NUMBER_FORMAT = /^(\d{6})(\d{4})$/; + +/** + * Format an organization number + * @example + * ``` + * formatOrganizationNumber('0000000000') // => '000000-0000' + * ``` + */ +export function formatOrganizationNumber(input: string): string { + return replaceIfMatch(input, ORG_NUMBER_FORMAT, '$1-$2'); +} diff --git a/packages/format/src/utils.ts b/packages/format/src/utils.ts new file mode 100644 index 0000000..80e96ee --- /dev/null +++ b/packages/format/src/utils.ts @@ -0,0 +1,12 @@ +export function replaceIfMatch( + input: string, + regex: RegExp, + replacerPattern: string, +): string { + // We're extremely lenient when attemtping to format the input. + // We remove everything that isn't a letter or a number, that way we can get rid of any + // formatting that might already be present in the input, eg spaces, hyphens or dots + const cleaned = input.replace(/[^a-zA-Z0-9]/g, ''); + + return cleaned.replace(regex, replacerPattern); +} diff --git a/packages/format/tsconfig.json b/packages/format/tsconfig.json new file mode 100644 index 0000000..dcbf63f --- /dev/null +++ b/packages/format/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./src/*"], + "compilerOptions": { + "outDir": "dist" + } +}