UNPKG

khmer-money-formatter

Version:

Lightweight, dependency-free TypeScript library for formatting, parsing, and converting Khmer Riel and Khmer numbers.

2,660 lines β€’ 34.9 kB
# Khmer Money Formatter

<p align="center">
  <a href="https://www.npmjs.com/package/khmer-money-formatter">
    <img src="https://img.shields.io/npm/v/khmer-money-formatter.svg?logo=npm&logoColor=white" alt="npm version">
  </a>

  <a href="https://www.npmjs.com/package/khmer-money-formatter">
    <img src="https://img.shields.io/npm/dt/khmer-money-formatter.svg?logo=npm&logoColor=white" alt="npm total downloads">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter">
    <img src="https://img.shields.io/github/stars/SmarterCoding/khmer-money-formatter.svg?logo=github" alt="GitHub stars">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter/pulls">
    <img src="https://img.shields.io/github/issues-pr/SmarterCoding/khmer-money-formatter.svg?logo=github" alt="Pull Requests">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter/graphs/contributors">
    <img src="https://img.shields.io/github/contributors/SmarterCoding/khmer-money-formatter.svg?logo=github" alt="Contributors">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter/security">
    <img src="https://img.shields.io/badge/security-policy-green.svg?logo=github" alt="Security Policy">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter/actions">
    <img src="https://img.shields.io/github/actions/workflow/status/SmarterCoding/khmer-money-formatter/ci.yml?logo=github&label=CI" alt="CI">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter/blob/main/LICENSE">
    <img src="https://img.shields.io/npm/l/khmer-money-formatter.svg" alt="License">
  </a>
</p>

<p align="center">
  <a href="https://cdn.jsdelivr.net/npm/khmer-money-formatter/">
    <img src="https://img.shields.io/badge/CDN-jsDelivr-ff5627.svg?logo=jsdelivr&logoColor=white" alt="jsDelivr CDN">
  </a>
  <a href="https://unpkg.com/khmer-money-formatter/">
    <img src="https://img.shields.io/badge/CDN-unpkg-orange.svg?logo=npm&logoColor=white" alt="unpkg CDN">
  </a>
  <a href="https://securityscorecards.dev/">
    <img src="https://img.shields.io/badge/Security-Scorecard-blue.svg?logo=securityscorecard&logoColor=white" alt="Security Scorecard">
  </a>
  <a href="https://github.com/SmarterCoding/khmer-money-formatter/network/dependents">
    <img src="https://img.shields.io/github/forks/SmarterCoding/khmer-money-formatter.svg?logo=github" alt="GitHub forks">
  </a>
</p>


<p align="center">
  <strong>πŸ‡°πŸ‡­ Khmer-friendly money and number utilities for JavaScript and TypeScript.</strong>
</p>

<p align="center">
  Format Khmer Riel, parse money values, convert Khmer numerals, and convert numbers into Khmer text β€” with zero runtime dependencies.
</p>

---

## Table of Contents

* [Introduction](#introduction)
* [Features](#features)
* [Installation](#installation)
* [CDN Usage](#cdn-usage)
* [Quick Start](#quick-start)
* [Money Formatting](#money-formatting)
* [Formatting Options](#formatting-options)
* [Without Currency Symbol](#without-currency-symbol)
* [Custom Currency Symbol](#custom-currency-symbol)
* [Currency Position](#currency-position)
* [Decimal Places](#decimal-places)
* [Rounding](#rounding)
* [Custom Separators](#custom-separators)
* [Negative Values](#negative-values)
* [Null and Empty Values](#null-and-empty-values)
* [Input Formatting](#input-formatting)
* [Parsing Money](#parsing-money)
* [Generic Number Formatting](#generic-number-formatting)
* [Generic Number Parsing](#generic-number-parsing)
* [Khmer Digit Support](#khmer-digit-support)
* [Number to Khmer Text](#number-to-khmer-text)
* [Decimal Number to Khmer Text](#decimal-number-to-khmer-text)
* [Long Khmer Currency](#long-khmer-currency)
* [Money to Khmer Text](#money-to-khmer-text)
* [Validation](#validation)
* [TypeScript](#typescript)
* [Browser Usage](#browser-usage)
* [Vanilla JavaScript](#vanilla-javascript)
* [jQuery](#jquery)
* [React](#react)
* [Next.js](#nextjs)
* [Vue](#vue)
* [Nuxt](#nuxt)
* [Node.js](#nodejs)
* [Express](#express)
* [NestJS](#nestjs)
* [Laravel Blade](#laravel-blade)
* [API Reference](#api-reference)
* [Tree Shaking](#tree-shaking)
* [Module Formats](#module-formats)
* [Framework Independence](#framework-independence)
* [Dependency Free](#dependency-free)
* [POS and Invoice Examples](#pos-and-invoice-examples)
* [Testing](#testing)
* [Building](#building)
* [Project Structure](#project-structure)
* [Security](#security)
* [Changelog](#changelog)
* [Contributing](#contributing)
* [FAQ](#faq)
* [License](#license)

---

# Introduction

**Khmer Money Formatter** is a lightweight, TypeScript-first, dependency-free library for working with Khmer currency and numbers.

The primary currency supported is:

* **KHR**
* **Khmer Riel**
* **αŸ›**
* **αžšαŸ€αž›**

The package provides simple APIs for:

```ts
formatKHR(10000);
// "10,000 αŸ›"

parseKHR("10,000 αŸ›");
// 10000
```

It also supports Khmer numerals:

```ts
toKhmerNumber(123456);
// "៑្៣ៀαŸ₯៦"
```

And number-to-Khmer-text conversion:

```ts
numberToKhmerText(123);
// "αž˜αž½αž™αžšαž™αž˜αŸ’αž—αŸƒαž”αžΈ"
```

The library is designed for:

* POS systems
* Invoices
* Receipts
* Accounting systems
* E-commerce applications
* Payment applications
* Banking interfaces
* Khmer websites
* Khmer forms
* Business applications
* JavaScript applications
* TypeScript applications

---

# Features

## Money Formatting

```ts
formatKHR(1000);
// "1,000 αŸ›"
```

## Number Formatting

```ts
formatNumber(1234567);
// "1,234,567"
```

## Khmer Digits

```ts
toKhmerNumber(123456);
// "៑្៣ៀαŸ₯៦"
```

## Number to Khmer Text

```ts
numberToKhmerText(123);
// "αž˜αž½αž™αžšαž™αž˜αŸ’αž—αŸƒαž”αžΈ"
```

## Money Parsing

```ts
parseKHR("10,000 αŸ›");
// 10000
```

## Input Formatting

```ts
formatKHRInput("10000");
// "10,000"
```

## Validation

```ts
isValidMoney("10,000");
// true
```

## Long Currency Format

```ts
formatKHRLong(1000);
// "1,000 αžšαŸ€αž›"
```

## Multiple Module Formats

Supports:

* ESM
* CommonJS
* Browser IIFE

## Tree-Shaking

Import only the functions you need.

## Zero Runtime Dependencies

The package has no production dependencies.

---

# Installation

Install using npm:

```bash
npm install khmer-money-formatter
```

Using pnpm:

```bash
pnpm add khmer-money-formatter
```

Using yarn:

```bash
yarn add khmer-money-formatter
```

Using Bun:

```bash
bun add khmer-money-formatter
```

---

## CDN Usage

You can use `khmer-money-formatter` directly in the browser without installing it with npm.

### jsDelivr

#### ES Module

```html
<script type="module">
  import {
    formatKHR,
    parseKHR,
    formatNumber,
    parseNumber,
    toKhmerNumber,
    fromKhmerNumber,
    numberToKhmerText,
    decimalToKhmerText,
    formatKHRLong,
    formatKHRInput,
    isValidMoney
  } from "https://cdn.jsdelivr.net/npm/khmer-money-formatter/dist/index.js";

  console.log(formatKHR(1000));
  console.log(formatNumber(1234567));
  console.log(toKhmerNumber(1234567));
  console.log(numberToKhmerText(1234567));
</script>
```

#### Minified ES Module

```html
<script type="module">
  import {
    formatKHR,
    numberToKhmerText
  } from "https://cdn.jsdelivr.net/npm/khmer-money-formatter/dist/index.iife.js";

  console.log(formatKHR(1000));
  console.log(numberToKhmerText(1000));
</script>
```

### unpkg

#### ES Module

```html
<script type="module">
  import {
    formatKHR,
    parseKHR,
    formatNumber,
    parseNumber,
    toKhmerNumber,
    fromKhmerNumber,
    numberToKhmerText,
    decimalToKhmerText,
    formatKHRLong,
    formatKHRInput,
    isValidMoney
  } from "https://unpkg.com/khmer-money-formatter/dist/index.js";

  console.log(formatKHR(1000));
  console.log(formatNumber(1234567));
  console.log(toKhmerNumber(1234567));
  console.log(numberToKhmerText(1234567));
</script>
```

#### Minified ES Module

```html
<script type="module">
  import {
    formatKHR,
    numberToKhmerText
  } from "https://unpkg.com/khmer-money-formatter/dist/index.iife.js";

  console.log(formatKHR(1000));
  console.log(numberToKhmerText(1000));
</script>
```

### Complete HTML Example

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1.0"
  />

  <title>Khmer Money Formatter</title>
</head>

<body>
  <h1>Khmer Money Formatter</h1>

  <p id="money"></p>
  <p id="khmer-number"></p>
  <p id="khmer-text"></p>

  <script type="module">
    import {
      formatKHR,
      toKhmerNumber,
      numberToKhmerText
    } from "https://cdn.jsdelivr.net/npm/khmer-money-formatter/dist/index.js";

    const amount = 1234567;

    document.getElementById("money").textContent =
      formatKHR(amount);

    document.getElementById("khmer-number").textContent =
      toKhmerNumber(amount);

    document.getElementById("khmer-text").textContent =
      numberToKhmerText(amount);
  </script>
</body>
</html>
```

### CDN Links

| CDN      | Development                                                        | Minified                                                               |
| -------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| jsDelivr | `https://cdn.jsdelivr.net/npm/khmer-money-formatter/dist/index.js` | `https://cdn.jsdelivr.net/npm/khmer-money-formatter/dist/index.iife.js` |
| unpkg    | `https://unpkg.com/khmer-money-formatter/dist/index.js`            | `https://unpkg.com/khmer-money-formatter/dist/index.iife.js`            |

> **Note:** CDN URLs are generated from the files published in the npm package. Make sure `dist/index.js` and `dist/index.min.js` are included in the published package.

### Recommended CDN

For most browser projects, **jsDelivr** is recommended:

```html
<script type="module">
  import {
    formatKHR,
    numberToKhmerText
  } from "https://cdn.jsdelivr.net/npm/khmer-money-formatter/dist/index.js";

  console.log(formatKHR(1000));
  console.log(numberToKhmerText(1000));
</script>
```

You can also pin a specific package version for production:

```html
<script type="module">
  import {
    formatKHR
  } from "https://cdn.jsdelivr.net/npm/khmer-money-formatter@1.0.0/dist/index.js";

  console.log(formatKHR(1000));
</script>
```

Pinning a version prevents your application from unexpectedly receiving a newer package version.

# Quick Start

Import the formatter:

```ts
import { formatKHR } from "khmer-money-formatter";
```

Format a number:

```ts
const price = formatKHR(10000);

console.log(price);
```

Output:

```text
10,000 αŸ›
```

Parsing:

```ts
import { parseKHR } from "khmer-money-formatter";

const value = parseKHR("10,000 αŸ›");

console.log(value);
```

Output:

```text
10000
```

---

# Money Formatting

The main function is:

```ts
formatKHR(value, options?)
```

Basic example:

```ts
formatKHR(1000);
```

Result:

```text
1,000 αŸ›
```

Large number:

```ts
formatKHR(1234567);
```

Result:

```text
1,234,567 αŸ›
```

Decimal:

```ts
formatKHR(1234567.5, {
  decimals: 2
});
```

Result:

```text
1,234,567.50 αŸ›
```

---

# Formatting Options

The formatter supports:

```ts
interface MoneyFormatOptions {
  symbol?: boolean;
  currency?: string;
  decimals?: number;
  separator?: string;
  decimalSeparator?: string;
  currencyPosition?: "prefix" | "suffix";
  khmerDigits?: boolean;
  empty?: string;
}
```

Default configuration:

```ts
{
  symbol: true,
  currency: "αŸ›",
  decimals: 0,
  separator: ",",
  decimalSeparator: ".",
  currencyPosition: "suffix",
  khmerDigits: false,
  empty: "0"
}
```

---

# Without Currency Symbol

```ts
formatKHR(50000, {
  symbol: false
});
```

Result:

```text
50,000
```

This is useful when the currency is displayed separately.

Example:

```ts
const amount = formatKHR(50000, {
  symbol: false
});

console.log(amount);
```

---

# Custom Currency Symbol

You can replace the default `αŸ›` symbol.

```ts
formatKHR(50000, {
  currency: "KHR"
});
```

Result:

```text
50,000 KHR
```

Another example:

```ts
formatKHR(50000, {
  currency: "Riel"
});
```

Result:

```text
50,000 Riel
```

---

# Currency Position

## Suffix

Default:

```ts
formatKHR(1000, {
  currencyPosition: "suffix"
});
```

Result:

```text
1,000 αŸ›
```

## Prefix

```ts
formatKHR(1000, {
  currencyPosition: "prefix"
});
```

Result:

```text
αŸ›1,000
```

---

# Decimal Places

## No decimals

```ts
formatKHR(1000, {
  decimals: 0
});
```

Result:

```text
1,000 αŸ›
```

## Two decimals

```ts
formatKHR(1000.5, {
  decimals: 2
});
```

Result:

```text
1,000.50 αŸ›
```

## Three decimals

```ts
formatKHR(1000.567, {
  decimals: 3
});
```

Result:

```text
1,000.567 αŸ›
```

---

# Rounding

The formatter uses JavaScript number rounding through `toFixed()`.

```ts
formatKHR(1000.567, {
  decimals: 2
});
```

Result:

```text
1,000.57 αŸ›
```

Another example:

```ts
formatKHR(1234.564, {
  decimals: 2
});
```

Result:

```text
1,234.56 αŸ›
```

---

# Custom Separators

Default:

```ts
formatKHR(1234567.89, {
  decimals: 2
});
```

Result:

```text
1,234,567.89 αŸ›
```

You can change the separators:

```ts
formatKHR(1234567.89, {
  decimals: 2,
  separator: ".",
  decimalSeparator: ","
});
```

Result:

```text
1.234.567,89 αŸ›
```

---

# Negative Values

Negative values are supported.

```ts
formatKHR(-5000);
```

Result:

```text
-5,000 αŸ›
```

With decimals:

```ts
formatKHR(-5000.5, {
  decimals: 2
});
```

Result:

```text
-5,000.50 αŸ›
```

---

# Null and Empty Values

The formatter safely handles common application values.

```ts
formatKHR(0);
// "0 αŸ›"

formatKHR(null);
// "0 αŸ›"

formatKHR(undefined);
// "0 αŸ›"

formatKHR("");
// "0 αŸ›"
```

You can customize empty output:

```ts
formatKHR(null, {
  empty: ""
});
```

Result:

```text
""
```

---

# Input Formatting

Use `formatKHRInput()` when you need to format values inside an HTML input.

```ts
import { formatKHRInput } from "khmer-money-formatter";

formatKHRInput("10000");
```

Result:

```text
10,000
```

Unlike `formatKHR()`, this function does not add the currency symbol.

This makes it useful for:

* POS
* Invoice forms
* Payment forms
* Accounting forms
* Quantity fields
* Price inputs

Example:

```html
<input
  type="text"
  class="money"
  value="10000"
/>
```

---

# Parsing Money

Use `parseKHR()` to convert formatted money back into a JavaScript number.

```ts
parseKHR("1,000 αŸ›");
```

Result:

```text
1000
```

Large values:

```ts
parseKHR("1,234,567 αŸ›");
```

Result:

```text
1234567
```

Decimal:

```ts
parseKHR("1,234,567.50 αŸ›");
```

Result:

```text
1234567.5
```

---

# Supported Money Input

`parseKHR()` supports multiple formats.

```ts
parseKHR("αŸ› 10,000");
// 10000
```

```ts
parseKHR("10,000αŸ›");
// 10000
```

```ts
parseKHR("10,000 αŸ›");
// 10000
```

```ts
parseKHR("10,000");
// 10000
```

Khmer currency name:

```ts
parseKHR("10,000 αžšαŸ€αž›");
// 10000
```

---

# Generic Number Formatting

Use `formatNumber()` when you do not want currency formatting.

```ts
import { formatNumber } from "khmer-money-formatter";

formatNumber(1234567);
```

Result:

```text
1,234,567
```

With decimals:

```ts
formatNumber(1234567.89, {
  decimals: 2
});
```

Result:

```text
1,234,567.89
```

---

# Generic Number Parsing

```ts
import { parseNumber } from "khmer-money-formatter";

parseNumber("1,234,567");
```

Result:

```text
1234567
```

Decimal:

```ts
parseNumber("1,234.50");
```

Result:

```text
1234.5
```

---

# Khmer Digit Support

The package supports conversion between Arabic and Khmer numerals.

## Arabic to Khmer

```ts
import { toKhmerNumber } from "khmer-money-formatter";

toKhmerNumber(123456);
```

Result:

```text
៑្៣ៀαŸ₯៦
```

With separators:

```ts
toKhmerNumber("123,456.78");
```

Result:

```text
៑្៣,ៀαŸ₯៦.៧៨
```

---

# Khmer to Arabic

```ts
import { fromKhmerNumber } from "khmer-money-formatter";

fromKhmerNumber("៑្៣,ៀαŸ₯៦");
```

Result:

```text
123456
```

Decimal:

```ts
fromKhmerNumber("៑្៣.αŸ₯");
```

Result:

```text
123.5
```

---

# Khmer Digits in Money

Enable Khmer digits using:

```ts
formatKHR(123456, {
  khmerDigits: true
});
```

Result:

```text
៑្៣,ៀαŸ₯៦ αŸ›
```

With decimals:

```ts
formatKHR(123456.5, {
  decimals: 2,
  khmerDigits: true
});
```

Result:

```text
៑្៣,ៀαŸ₯៦.αŸ₯០ αŸ›
```

---

# Number to Khmer Text

The package can convert numeric values into Khmer words.

```ts
import {
  numberToKhmerText
} from "khmer-money-formatter";

numberToKhmerText(1);
```

Result:

```text
αž˜αž½αž™
```

Other examples:

```ts
numberToKhmerText(5);
// "αž”αŸ’αžšαžΆαŸ†"
```

```ts
numberToKhmerText(10);
// "αžŠαž”αŸ‹"
```

```ts
numberToKhmerText(11);
// "αžŠαž”αŸ‹αž˜αž½αž™"
```

```ts
numberToKhmerText(20);
// "αž˜αŸ’αž—αŸƒ"
```

```ts
numberToKhmerText(21);
// "αž˜αŸ’αž—αŸƒαž˜αž½αž™"
```

```ts
numberToKhmerText(100);
// "αž˜αž½αž™αžšαž™"
```

```ts
numberToKhmerText(101);
// "αž˜αž½αž™αžšαž™αž˜αž½αž™"
```

```ts
numberToKhmerText(1000);
// "αž˜αž½αž™αž–αžΆαž“αŸ‹"
```

```ts
numberToKhmerText(1000000);
// "αž˜αž½αž™αž›αžΆαž“"
```

This is useful for:

* Khmer invoices
* Receipts
* Payment documents
* Accounting systems
* Contracts
* Financial documents

---

# Decimal Number to Khmer Text

Use `decimalToKhmerText()` for decimal values.

```ts
import {
  decimalToKhmerText
} from "khmer-money-formatter";

decimalToKhmerText(123.55);
```

Result:

```text
αž˜αž½αž™αžšαž™αž˜αŸ’αž—αŸƒαž”αžΈαž…αž»αž…αž αžΆαžŸαž·αž”αž”αŸ’αžšαžΆαŸ†
```

---

# Long Khmer Currency

Use `formatKHRLong()` to display the Khmer currency name.

```ts
import {
  formatKHRLong
} from "khmer-money-formatter";

formatKHRLong(1000);
```

Result:

```text
1,000 αžšαŸ€αž›
```

With Khmer digits:

```ts
formatKHRLong(1000, {
  khmer: true
});
```

Result:

```text
៑,០០០ αžšαŸ€αž›
```

---

# Money to Khmer Text

For invoice and receipt applications, you can combine money formatting and Khmer text.

Example:

```ts
const amount = 10000;

const formatted = formatKHR(amount);

const text = numberToKhmerText(amount);

console.log(formatted);
console.log(text);
```

Output:

```text
10,000 αŸ›
αž˜αž½αž™αž˜αŸ‰αžΊαž“
```

A receipt could display:

```text
αž…αŸ†αž“αž½αž“αž‘αžΉαž€αž”αŸ’αžšαžΆαž€αŸ‹: 10,000 αŸ›

αž‡αžΆαž’αž€αŸ’αžŸαžš: αž˜αž½αž™αž˜αŸ‰αžΊαž“αžšαŸ€αž›
```

---

# Validation

Use `isValidMoney()` to check whether a value is a valid money value.

```ts
import {
  isValidMoney
} from "khmer-money-formatter";

isValidMoney("10,000");
```

Result:

```text
true
```

Currency:

```ts
isValidMoney("10,000 αŸ›");
// true
```

Khmer digits:

```ts
isValidMoney("៑្៣,ៀαŸ₯៦");
// true
```

Invalid:

```ts
isValidMoney("hello");
// false
```

Empty:

```ts
isValidMoney("");
// false
```

---

# TypeScript

The package is written in TypeScript and includes declaration files.

```ts
import {
  formatKHR,
  parseKHR,
  formatNumber,
  parseNumber,
  toKhmerNumber,
  fromKhmerNumber,
  numberToKhmerText,
  decimalToKhmerText,
  formatKHRLong,
  formatKHRInput,
  isValidMoney
} from "khmer-money-formatter";
```

---

# Type Definitions

## MoneyFormatOptions

```ts
export interface MoneyFormatOptions {
  symbol?: boolean;
  currency?: string;
  decimals?: number;
  separator?: string;
  decimalSeparator?: string;
  currencyPosition?: "prefix" | "suffix";
  khmerDigits?: boolean;
  empty?: string;
}
```

## NumberFormatOptions

```ts
export interface NumberFormatOptions {
  decimals?: number;
  separator?: string;
  decimalSeparator?: string;
  khmerDigits?: boolean;
  empty?: string;
}
```

---

# Browser Usage

The package provides an IIFE browser build.

```html
<script src="./dist/index.iife.js"></script>
```

The global object is:

```js
KhmerMoneyFormatter
```

Example:

```html
<script>
  const price =
    KhmerMoneyFormatter.formatKHR(50000);

  console.log(price);
</script>
```

Result:

```text
50,000 αŸ›
```

---

# Vanilla JavaScript

```js
import {
  formatKHR,
  parseKHR
} from "khmer-money-formatter";

const price = formatKHR(50000);

console.log(price);

const value = parseKHR(price);

console.log(value);
```

---

# jQuery

The package does not depend on jQuery, but it can easily be used with jQuery.

```ts
import {
  formatKHRInput
} from "khmer-money-formatter";

$(".money").on("input", function () {
  const value = $(this).val();

  $(this).val(formatKHRInput(value));
});
```

Example HTML:

```html
<input
  type="text"
  class="money"
  placeholder="Enter amount"
/>
```

If the user enters:

```text
10000
```

the input becomes:

```text
10,000
```

---

# React

```tsx
import {
  formatKHR
} from "khmer-money-formatter";

export default function Price() {
  const price = 50000;

  return (
    <span>
      {formatKHR(price)}
    </span>
  );
}
```

Result:

```text
50,000 αŸ›
```

---

# Next.js

The package can be used in Next.js applications.

```tsx
import {
  formatKHR
} from "khmer-money-formatter";

export default function ProductPrice() {
  const price = 125000;

  return (
    <div>
      {formatKHR(price)}
    </div>
  );
}
```

For a server component, normal imports can be used because the formatter does not require browser APIs.

---

# Vue

```vue
<script setup lang="ts">
import { formatKHR } from "khmer-money-formatter";

const price = 50000;
</script>

<template>
  <span>
    {{ formatKHR(price) }}
  </span>
</template>
```

---

# Nuxt

```ts
import {
  formatKHR
} from "khmer-money-formatter";

const price = formatKHR(50000);
```

---

# Node.js

## ESM

```ts
import {
  formatKHR
} from "khmer-money-formatter";

console.log(
  formatKHR(50000)
);
```

## CommonJS

```js
const {
  formatKHR
} = require("khmer-money-formatter");

console.log(
  formatKHR(50000)
);
```

---

# Express

```ts
import express from "express";
import {
  formatKHR
} from "khmer-money-formatter";

const app = express();

app.get("/price", (req, res) => {
  const price = 50000;

  res.json({
    amount: price,
    formatted: formatKHR(price)
  });
});

app.listen(3000);
```

Response:

```json
{
  "amount": 50000,
  "formatted": "50,000 αŸ›"
}
```

---

# NestJS

The package can be used directly inside services.

```ts
import {
  Injectable
} from "@nestjs/common";

import {
  formatKHR
} from "khmer-money-formatter";

@Injectable()
export class PaymentService {
  formatAmount(amount: number): string {
    return formatKHR(amount);
  }
}
```

---

# Laravel Blade

The package itself is JavaScript/TypeScript and does not require Laravel.

For frontend formatting with Vite:

```ts
import {
  formatKHR
} from "khmer-money-formatter";

window.formatKHR = formatKHR;
```

Then in Blade:

```blade
<span id="price"></span>

<script>
  document.getElementById("price").textContent =
    window.formatKHR(50000);
</script>
```

Result:

```text
50,000 αŸ›
```

For server-side PHP formatting, use PHP's own formatting logic. This package is intended for JavaScript/TypeScript applications and browser-side formatting.

---

# POS Example

A simple POS price input:

```html
<input
  id="price"
  type="text"
  value="0"
/>

<div>
  Total:
  <strong id="total"></strong>
</div>
```

TypeScript:

```ts
import {
  formatKHRInput,
  formatKHR,
  parseKHR
} from "khmer-money-formatter";

const priceInput =
  document.querySelector<HTMLInputElement>("#price");

const total =
  document.querySelector<HTMLElement>("#total");

priceInput?.addEventListener("input", () => {
  const value = priceInput.value;

  priceInput.value =
    formatKHRInput(value);

  const amount =
    parseKHR(priceInput.value);

  if (total) {
    total.textContent =
      formatKHR(amount);
  }
});
```

---

# Invoice Example

```ts
import {
  formatKHR,
  numberToKhmerText
} from "khmer-money-formatter";

const subtotal = 150000;
const tax = 15000;
const total = subtotal + tax;

console.log(
  `Subtotal: ${formatKHR(subtotal)}`
);

console.log(
  `Tax: ${formatKHR(tax)}`
);

console.log(
  `Total: ${formatKHR(total)}`
);

console.log(
  `In words: ${numberToKhmerText(total)}`
);
```

Example output:

```text
Subtotal: 150,000 αŸ›
Tax: 15,000 αŸ›
Total: 165,000 αŸ›
In words: ...
```

---

# API Reference

## `formatKHR()`

Format a value as Khmer Riel.

```ts
formatKHR(
  value: unknown,
  options?: MoneyFormatOptions
): string;
```

Example:

```ts
formatKHR(10000);
// "10,000 αŸ›"
```

---

## `formatKHRInput()`

Format a number for an input field without a currency symbol.

```ts
formatKHRInput(
  value: unknown,
  options?: NumberFormatOptions
): string;
```

Example:

```ts
formatKHRInput("10000");
// "10,000"
```

---

## `formatKHRLong()`

Format a value using the Khmer currency name.

```ts
formatKHRLong(
  value: unknown,
  options?: MoneyFormatOptions & {
    khmer?: boolean;
  }
): string;
```

Example:

```ts
formatKHRLong(1000);
// "1,000 αžšαŸ€αž›"
```

---

## `parseKHR()`

Parse a formatted Khmer money value.

```ts
parseKHR(
  value: unknown
): number;
```

Example:

```ts
parseKHR("10,000 αŸ›");
// 10000
```

---

## `formatNumber()`

Generic number formatter.

```ts
formatNumber(
  value: unknown,
  options?: NumberFormatOptions
): string;
```

---

## `parseNumber()`

Generic number parser.

```ts
parseNumber(
  value: unknown
): number;
```

---

## `toKhmerNumber()`

Convert Arabic numerals to Khmer numerals.

```ts
toKhmerNumber(
  value: number | string
): string;
```

Example:

```ts
toKhmerNumber(123456);
// "៑្៣ៀαŸ₯៦"
```

---

## `fromKhmerNumber()`

Convert Khmer numerals to JavaScript numbers.

```ts
fromKhmerNumber(
  value: string
): number;
```

Example:

```ts
fromKhmerNumber("៑្៣,ៀαŸ₯៦");
// 123456
```

---

## `numberToKhmerText()`

Convert an integer number into Khmer words.

```ts
numberToKhmerText(
  value: number | string
): string;
```

Example:

```ts
numberToKhmerText(123);
// "αž˜αž½αž™αžšαž™αž˜αŸ’αž—αŸƒαž”αžΈ"
```

---

## `decimalToKhmerText()`

Convert a decimal number into Khmer text.

```ts
decimalToKhmerText(
  value: number | string
): string;
```

Example:

```ts
decimalToKhmerText(123.45);
```

---

## `isValidMoney()`

Validate a money value.

```ts
isValidMoney(
  value: unknown
): boolean;
```

Example:

```ts
isValidMoney("10,000");
// true
```

---

# Tree Shaking

The package uses named exports.

You can import only what you need:

```ts
import {
  formatKHR
} from "khmer-money-formatter";
```

Or:

```ts
import {
  parseKHR
} from "khmer-money-formatter";
```

This allows modern bundlers to remove unused exports.

Supported bundlers include:

* Vite
* Rollup
* Webpack
* esbuild
* tsup
* Next.js
* Nuxt

---

# Module Formats

The package provides:

```text
dist/
β”œβ”€β”€ index.js
β”œβ”€β”€ index.cjs
β”œβ”€β”€ index.iife.js
└── index.d.ts
```

## ESM

```ts
import {
  formatKHR
} from "khmer-money-formatter";
```

## CommonJS

```js
const {
  formatKHR
} = require("khmer-money-formatter");
```

## Browser

```html
<script src="dist/index.iife.js"></script>
```

Then:

```js
KhmerMoneyFormatter.formatKHR(50000);
```

---

# Framework Independence

The package does not depend on:

* React
* Vue
* Angular
* Next.js
* Nuxt
* jQuery
* Laravel
* Express
* NestJS
* Node.js APIs

It uses standard JavaScript/TypeScript functionality.

Therefore it can be used in:

```text
Browser
    ↓
JavaScript
    ↓
TypeScript
    ↓
React
    ↓
Next.js
    ↓
Vue
    ↓
Nuxt
    ↓
Node.js
    ↓
Express
    ↓
NestJS
    ↓
Laravel Blade
```

---

# Dependency Free

Runtime dependencies:

```json
{
  "dependencies": {}
}
```

The package does not require external libraries to perform formatting.

Development dependencies are used only for:

* TypeScript
* Vitest
* tsup

---

# Security

The package is designed to have a minimal attack surface.

It:

* Does not use `eval()`.
* Does not use `new Function()`.
* Does not execute downloaded code.
* Does not make network requests.
* Does not collect analytics.
* Does not collect personal information.
* Does not store passwords.
* Does not communicate with payment gateways.
* Has no runtime dependencies.

See:

```text
SECURITY.md
```

for the complete security policy.

---

# Testing

The project uses Vitest.

Run all tests:

```bash
npm test
```

Run tests in watch mode:

```bash
npm run test:watch
```

Run TypeScript validation:

```bash
npm run typecheck
```

Run the complete check:

```bash
npm run check
```

The test suite covers:

* Integer values
* Decimal values
* Zero
* Negative values
* Null
* Undefined
* Empty values
* Large numbers
* Rounding
* Custom separators
* Currency symbols
* Prefix/suffix
* Khmer digits
* Khmer text conversion
* Parsing
* Validation
* Invalid values

---

# Building

Build the package:

```bash
npm run build
```

The output will be generated in:

```text
dist/
```

Expected files:

```text
dist/
β”œβ”€β”€ index.js
β”œβ”€β”€ index.cjs
β”œβ”€β”€ index.iife.js
β”œβ”€β”€ index.d.ts
└── source maps
```

---

# Development

Clone the repository:

```bash
git clone https://github.com/SmarterCoding/khmer-money-formatter.git
```

Enter the directory:

```bash
cd khmer-money-formatter
```

Install dependencies:

```bash
npm install
```

Run tests:

```bash
npm test
```

Type check:

```bash
npm run typecheck
```

Build:

```bash
npm run build
```

Run all checks:

```bash
npm run check
```

---

# Project Structure

```text
khmer-money-formatter/
β”‚
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts
β”‚   β”œβ”€β”€ formatter.ts
β”‚   β”œβ”€β”€ parser.ts
β”‚   β”œβ”€β”€ number.ts
β”‚   β”œβ”€β”€ khmer.ts
β”‚   β”œβ”€β”€ khmer-text.ts
β”‚   └── types.ts
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ formatter.test.ts
β”‚   β”œβ”€β”€ parser.test.ts
β”‚   β”œβ”€β”€ number.test.ts
β”‚   β”œβ”€β”€ khmer.test.ts
β”‚   └── khmer-text.test.ts
β”‚
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       β”œβ”€β”€ ci.yml
β”‚       └── publish.yml
β”‚
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tsup.config.ts
β”œβ”€β”€ vitest.config.ts
β”‚
β”œβ”€β”€ README.md
β”œβ”€β”€ SECURITY.md
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ LICENSE
└── .gitignore
```

---

# Release and Publishing

The project uses GitHub Actions for automated npm publishing.

Create a new version:

```bash
npm version patch
```

Or:

```bash
npm version minor
```

Or:

```bash
npm version major
```

Push commits and tags:

```bash
git push origin main --follow-tags
```

The publishing workflow is triggered by version tags:

```text
v1.0.0
v1.0.1
v1.1.0
v2.0.0
```

The workflow:

```text
Git Tag
   ↓
GitHub Actions
   ↓
npm ci
   ↓
TypeScript Check
   ↓
Vitest
   ↓
Build
   ↓
npm publish
```

---

# npm Trusted Publishing

For npm publishing, GitHub Actions should use **npm Trusted Publishing / OIDC** where supported.

This avoids storing a long-lived npm access token in GitHub Actions.

The repository workflow should have:

```yaml
permissions:
  contents: read
  id-token: write
```

Publishing:

```bash
npm publish --access public
```

---

# Changelog

Release history is maintained in:

```text
CHANGELOG.md
```

Example:

```md
# Changelog

## [1.0.0] - 2026-08-21

### Added

- Khmer Riel formatter
- Khmer money parser
- Generic number formatter
- Generic number parser
- Khmer numeral conversion
- Number-to-Khmer-text conversion
- Khmer currency long format
- Money validation
- Input formatting
- ESM build
- CommonJS build
- Browser build
- TypeScript definitions
- GitHub Actions CI
- npm publishing
```

---

# FAQ

## Does this package support TypeScript?

Yes.

The package is written in TypeScript and includes `.d.ts` declaration files.

---

## Does it require jQuery?

No.

jQuery is not a dependency.

It can optionally be used together with jQuery.

---

## Does it work with React?

Yes.

It is framework independent and works with React.

---

## Does it work with Next.js?

Yes.

It can be used in both frontend and server-side code where appropriate.

---

## Does it work with Vue?

Yes.

---

## Does it work with Node.js?

Yes.

ESM and CommonJS builds are provided.

---

## Does it support Khmer digits?

Yes.

```ts
formatKHR(123456, {
  khmerDigits: true
});
```

Result:

```text
៑្៣,ៀαŸ₯៦ αŸ›
```

---

## Can it convert numbers into Khmer words?

Yes.

```ts
numberToKhmerText(123);
```

Result:

```text
αž˜αž½αž™αžšαž™αž˜αŸ’αž—αŸƒαž”αžΈ
```

---

## Does it support Khmer Riel?

Yes.

The default currency is:

```text
αŸ›
```

and the long currency name is:

```text
αžšαŸ€αž›
```

---

## Does it make API requests?

No.

The formatter is completely local.

---

## Does it collect user data?

No.

There is no analytics, tracking, or data collection.

---

## Does it have runtime dependencies?

No.

The package is dependency-free at runtime.

---

## Is it suitable for financial calculations?

The package is intended primarily for **formatting and parsing display values**.

For financial systems that require exact decimal arithmetic, use an appropriate decimal or integer-based monetary representation in your application's calculation layer rather than relying on JavaScript floating-point arithmetic.

For example, storing amounts as integer Riel:

```ts
const amountInRiel = 10000;
```

and formatting only for display:

```ts
formatKHR(amountInRiel);
```

---

# Contributing

Contributions are welcome.

Before submitting a pull request:

```bash
npm install
npm run check
npm run build
```

Please make sure:

* Tests pass.
* TypeScript passes.
* New functionality has tests.
* Public APIs are documented.
* Existing APIs remain backward compatible where possible.

---

# License

MIT License.

Copyright (c) 2026 Chamnan dev.

See [LICENSE](LICENSE) for the complete license text.

---

# Author

**Chamnan dev**

GitHub:

```text
https://github.com/SmarterCoding
```

---

# Final Example

The simplest usage:

```ts
import {
  formatKHR,
  parseKHR
} from "khmer-money-formatter";

const formatted = formatKHR(10000);

console.log(formatted);
// "10,000 αŸ›"

const amount = parseKHR(formatted);

console.log(amount);
// 10000
```

Khmer digits:

```ts
import {
  formatKHR,
  toKhmerNumber
} from "khmer-money-formatter";

console.log(
  toKhmerNumber(123456)
);

// "៑្៣ៀαŸ₯៦"

console.log(
  formatKHR(123456, {
    khmerDigits: true
  })
);

// "៑្៣,ៀαŸ₯៦ αŸ›"
```

Khmer text:

```ts
import {
  numberToKhmerText
} from "khmer-money-formatter";

console.log(
  numberToKhmerText(123)
);

// "αž˜αž½αž™αžšαž™αž˜αŸ’αž—αŸƒαž”αžΈ"
```

For a Khmer invoice:

```ts
import {
  formatKHR,
  numberToKhmerText
} from "khmer-money-formatter";

const total = 150000;

console.log(
  `Total: ${formatKHR(total)}`
);

console.log(
  `In words: ${numberToKhmerText(total)}`
);
```

The goal of **Khmer Money Formatter** is simple:

> **Small + Fast + Dependency-Free + TypeScript-first + Khmer-friendly + Framework-independent.**

πŸ‡°πŸ‡­ Built for Khmer developers and applications.