Skip to content

Commit a4938b2

Browse files
authored
Add format package (#1)
1 parent a0897c8 commit a4938b2

File tree

8 files changed

+146
-0
lines changed

8 files changed

+146
-0
lines changed

.changeset/bright-adults-battle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@obosbbl/format": minor
3+
---
4+
5+
initial release

packages/format/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# @obosbbl/format
2+
3+
[![NPM Version](https://img.shields.io/npm/v/%40obosbbl%2Fformat)](https://www.npmjs.com/package/@obosbbl/format)
4+
5+
6+
A collection of formatting functions for both 🇳🇴 and 🇸🇪 with zero dependencies.
7+
8+
## Install
9+
10+
```sh
11+
# npm
12+
npm install @obosbbl/format
13+
14+
# pnpm
15+
pnpm add @obosbbl/format
16+
```
17+
18+
## Usage
19+
20+
The package has two entrypoints, one for `no` and one for `se`. That allows you to import for only the locale you need.
21+
22+
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.
23+
That way any existing format of the input won't affect the formatted output
24+
25+
If unable to format the input, the method will return the (cleaned) input as is.
26+
27+
```js
28+
// 🇳🇴 example
29+
import { formatOrganizationNumber } from '@obosbbl/format/no';
30+
formatOrganizationNumber('000000000') // => '000 000 000'
31+
32+
// 🇸🇪 example
33+
import { formatOrganizationNumber } from '@obosbbl/format/se';
34+
formatOrganizationNumber('0000000000') // => '000000-0000'
35+
```
36+
37+
## Methods
38+
39+
* formatOrganizationNumber

packages/format/package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "@obosbbl/format",
3+
"version": "0.0.0",
4+
"description": "A collection of formatting methods for OBOS",
5+
"repository": {
6+
"url": "https://github.com/code-obos/public-frontend-modules"
7+
},
8+
"license": "MIT",
9+
"sideEffects": false,
10+
"type": "module",
11+
"exports": {
12+
"./no": {
13+
"types": "./dist/no.d.mts",
14+
"default": "./dist/no.mjs"
15+
},
16+
"./se": {
17+
"types": "./dist/se.d.mts",
18+
"default": "./dist/se.mjs"
19+
}
20+
},
21+
"files": [
22+
"dist"
23+
],
24+
"scripts": {
25+
"build": "bunchee"
26+
},
27+
"dependencies": {}
28+
}

packages/format/src/format.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, expect, test } from 'vitest';
2+
import { formatOrganizationNumber as formatOrganizationNumberNo } from './no';
3+
import { formatOrganizationNumber as formatOrganizationNumberSe } from './se';
4+
5+
describe('no', () => {
6+
test.each([
7+
['000000000', '000 000 000'],
8+
['000 000 000', '000 000 000'],
9+
['000-000-000', '000 000 000'],
10+
['abc', 'abc'],
11+
])('formatOrganizationNumber(%s) -> %s', (input, expected) => {
12+
expect(formatOrganizationNumberNo(input)).toBe(expected);
13+
});
14+
});
15+
16+
describe('se', () => {
17+
test.each([
18+
['0000000000', '000000-0000'],
19+
['000000-0000', '000000-0000'],
20+
['000000 0000', '000000-0000'],
21+
[' 000000 0000 ', '000000-0000'],
22+
['000', '000'],
23+
['abc', 'abc'],
24+
])('formatOrganizationNumber(%s) -> %s', (input, expected) => {
25+
expect(formatOrganizationNumberSe(input)).toBe(expected);
26+
});
27+
});

packages/format/src/no.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { replaceIfMatch } from './utils';
2+
3+
const ORG_NUMBER_FORMAT = /^(\d{3})(\d{3})(\d{3})$/;
4+
5+
/**
6+
* Format an organization number
7+
* @example
8+
* ```
9+
* formatOrganizationNumber('000000000') // => '000 000 000'
10+
* ```
11+
*/
12+
export function formatOrganizationNumber(input: string): string {
13+
return replaceIfMatch(input, ORG_NUMBER_FORMAT, '$1 $2 $3');
14+
}

packages/format/src/se.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { replaceIfMatch } from './utils';
2+
3+
const ORG_NUMBER_FORMAT = /^(\d{6})(\d{4})$/;
4+
5+
/**
6+
* Format an organization number
7+
* @example
8+
* ```
9+
* formatOrganizationNumber('0000000000') // => '000000-0000'
10+
* ```
11+
*/
12+
export function formatOrganizationNumber(input: string): string {
13+
return replaceIfMatch(input, ORG_NUMBER_FORMAT, '$1-$2');
14+
}

packages/format/src/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export function replaceIfMatch(
2+
input: string,
3+
regex: RegExp,
4+
replacerPattern: string,
5+
): string {
6+
// We're extremely lenient when attemtping to format the input.
7+
// We remove everything that isn't a letter or a number, that way we can get rid of any
8+
// formatting that might already be present in the input, eg spaces, hyphens or dots
9+
const cleaned = input.replace(/[^a-zA-Z0-9]/g, '');
10+
11+
return cleaned.replace(regex, replacerPattern);
12+
}

packages/format/tsconfig.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"include": ["./src/*"],
4+
"compilerOptions": {
5+
"outDir": "dist"
6+
}
7+
}

0 commit comments

Comments
 (0)