Skip to content

About

Format Khmer Riel, parse money values, convert Khmer numerals, and convert numbers into Khmer text — with zero runtime dependencies.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Khmer Money Formatter

npm version npm downloads npm total downloads GitHub stars Pull Requests Contributors Security Policy CI License

jsDelivr CDN unpkg CDN Security Scorecard GitHub forks

🇰🇭 Khmer-friendly money and number utilities for JavaScript and TypeScript.

Format Khmer Riel, parse money values, convert Khmer numerals, and convert numbers into Khmer text — with zero runtime dependencies.


Table of Contents


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:

formatKHR(10000);
// "10,000 ៛"

parseKHR("10,000 ៛");
// 10000

It also supports Khmer numerals:

toKhmerNumber(123456);
// "១២៣៤៥៦"

And number-to-Khmer-text conversion:

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

formatKHR(1000);
// "1,000 ៛"

Number Formatting

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

Khmer Digits

toKhmerNumber(123456);
// "១២៣៤៥៦"

Number to Khmer Text

numberToKhmerText(123);
// "មួយរយម្ភៃបី"

Money Parsing

parseKHR("10,000 ៛");
// 10000

Input Formatting

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

Validation

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

Long Currency Format

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:

npm install khmer-money-formatter

Using pnpm:

pnpm add khmer-money-formatter

Using yarn:

yarn add khmer-money-formatter

Using Bun:

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

<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

<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

<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

<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

<!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:

<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:

<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:

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

Format a number:

const price = formatKHR(10000);

console.log(price);

Output:

10,000 ៛

Parsing:

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

const value = parseKHR("10,000 ៛");

console.log(value);

Output:

10000

Money Formatting

The main function is:

formatKHR(value, options?)

Basic example:

formatKHR(1000);

Result:

1,000 ៛

Large number:

formatKHR(1234567);

Result:

1,234,567 ៛

Decimal:

formatKHR(1234567.5, {
  decimals: 2
});

Result:

1,234,567.50 ៛

Formatting Options

The formatter supports:

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

Default configuration:

{
  symbol: true,
  currency: "៛",
  decimals: 0,
  separator: ",",
  decimalSeparator: ".",
  currencyPosition: "suffix",
  khmerDigits: false,
  empty: "0"
}

Without Currency Symbol

formatKHR(50000, {
  symbol: false
});

Result:

50,000

This is useful when the currency is displayed separately.

Example:

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

console.log(amount);

Custom Currency Symbol

You can replace the default ៛ symbol.

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

Result:

50,000 KHR

Another example:

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

Result:

50,000 Riel

Currency Position

Suffix

Default:

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

Result:

1,000 ៛

Prefix

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

Result:

៛1,000

Decimal Places

No decimals

formatKHR(1000, {
  decimals: 0
});

Result:

1,000 ៛

Two decimals

formatKHR(1000.5, {
  decimals: 2
});

Result:

1,000.50 ៛

Three decimals

formatKHR(1000.567, {
  decimals: 3
});

Result:

1,000.567 ៛

Rounding

The formatter uses JavaScript number rounding through toFixed().

formatKHR(1000.567, {
  decimals: 2
});

Result:

1,000.57 ៛

Another example:

formatKHR(1234.564, {
  decimals: 2
});

Result:

1,234.56 ៛

Custom Separators

Default:

formatKHR(1234567.89, {
  decimals: 2
});

Result:

1,234,567.89 ៛

You can change the separators:

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

Result:

1.234.567,89 ៛

Negative Values

Negative values are supported.

formatKHR(-5000);

Result:

-5,000 ៛

With decimals:

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

Result:

-5,000.50 ៛

Null and Empty Values

The formatter safely handles common application values.

formatKHR(0);
// "0 ៛"

formatKHR(null);
// "0 ៛"

formatKHR(undefined);
// "0 ៛"

formatKHR("");
// "0 ៛"

You can customize empty output:

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

Result:

""

Input Formatting

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

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

formatKHRInput("10000");

Result:

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:

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

Parsing Money

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

parseKHR("1,000 ៛");

Result:

1000

Large values:

parseKHR("1,234,567 ៛");

Result:

1234567

Decimal:

parseKHR("1,234,567.50 ៛");

Result:

1234567.5

Supported Money Input

parseKHR() supports multiple formats.

parseKHR("៛ 10,000");
// 10000
parseKHR("10,000៛");
// 10000
parseKHR("10,000 ៛");
// 10000
parseKHR("10,000");
// 10000

Khmer currency name:

parseKHR("10,000 រៀល");
// 10000

Generic Number Formatting

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

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

formatNumber(1234567);

Result:

1,234,567

With decimals:

formatNumber(1234567.89, {
  decimals: 2
});

Result:

1,234,567.89

Generic Number Parsing

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

parseNumber("1,234,567");

Result:

1234567

Decimal:

parseNumber("1,234.50");

Result:

1234.5

Khmer Digit Support

The package supports conversion between Arabic and Khmer numerals.

Arabic to Khmer

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

toKhmerNumber(123456);

Result:

១២៣៤៥៦

With separators:

toKhmerNumber("123,456.78");

Result:

១២៣,៤៥៦.៧៨

Khmer to Arabic

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

fromKhmerNumber("១២៣,៤៥៦");

Result:

123456

Decimal:

fromKhmerNumber("១២៣.៥");

Result:

123.5

Khmer Digits in Money

Enable Khmer digits using:

formatKHR(123456, {
  khmerDigits: true
});

Result:

១២៣,៤៥៦ ៛

With decimals:

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

Result:

១២៣,៤៥៦.៥០ ៛

Number to Khmer Text

The package can convert numeric values into Khmer words.

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

numberToKhmerText(1);

Result:

មួយ

Other examples:

numberToKhmerText(5);
// "ប្រាំ"
numberToKhmerText(10);
// "ដប់"
numberToKhmerText(11);
// "ដប់មួយ"
numberToKhmerText(20);
// "ម្ភៃ"
numberToKhmerText(21);
// "ម្ភៃមួយ"
numberToKhmerText(100);
// "មួយរយ"
numberToKhmerText(101);
// "មួយរយមួយ"
numberToKhmerText(1000);
// "មួយពាន់"
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.

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

decimalToKhmerText(123.55);

Result:

មួយរយម្ភៃបីចុចហាសិបប្រាំ

Long Khmer Currency

Use formatKHRLong() to display the Khmer currency name.

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

formatKHRLong(1000);

Result:

1,000 រៀល

With Khmer digits:

formatKHRLong(1000, {
  khmer: true
});

Result:

១,០០០ រៀល

Money to Khmer Text

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

Example:

const amount = 10000;

const formatted = formatKHR(amount);

const text = numberToKhmerText(amount);

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

Output:

10,000 ៛
មួយម៉ឺន

A receipt could display:

ចំនួនទឹកប្រាក់: 10,000 ៛

ជាអក្សរ: មួយម៉ឺនរៀល

Validation

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

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

isValidMoney("10,000");

Result:

true

Currency:

isValidMoney("10,000 ៛");
// true

Khmer digits:

isValidMoney("១២៣,៤៥៦");
// true

Invalid:

isValidMoney("hello");
// false

Empty:

isValidMoney("");
// false

TypeScript

The package is written in TypeScript and includes declaration files.

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

Type Definitions

MoneyFormatOptions

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

NumberFormatOptions

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

Browser Usage

The package provides an IIFE browser build.

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

The global object is:

KhmerMoneyFormatter

Example:

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

  console.log(price);
</script>

Result:

50,000 ៛

Vanilla JavaScript

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.

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

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

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

Example HTML:

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

If the user enters:

10000

the input becomes:

10,000

React

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

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

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

Result:

50,000 ៛

Next.js

The package can be used in Next.js applications.

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

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

const price = 50000;
</script>

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

Nuxt

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

const price = formatKHR(50000);

Node.js

ESM

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

console.log(
  formatKHR(50000)
);

CommonJS

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

console.log(
  formatKHR(50000)
);

Express

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:

{
  "amount": 50000,
  "formatted": "50,000 ៛"
}

NestJS

The package can be used directly inside services.

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:

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

window.formatKHR = formatKHR;

Then in Blade:

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

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

Result:

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:

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

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

TypeScript:

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

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:

Subtotal: 150,000 ៛
Tax: 15,000 ៛
Total: 165,000 ៛
In words: ...

API Reference

formatKHR()

Format a value as Khmer Riel.

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

Example:

formatKHR(10000);
// "10,000 ៛"

formatKHRInput()

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

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

Example:

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

formatKHRLong()

Format a value using the Khmer currency name.

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

Example:

formatKHRLong(1000);
// "1,000 រៀល"

parseKHR()

Parse a formatted Khmer money value.

parseKHR(
  value: unknown
): number;

Example:

parseKHR("10,000 ៛");
// 10000

formatNumber()

Generic number formatter.

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

parseNumber()

Generic number parser.

parseNumber(
  value: unknown
): number;

toKhmerNumber()

Convert Arabic numerals to Khmer numerals.

toKhmerNumber(
  value: number | string
): string;

Example:

toKhmerNumber(123456);
// "១២៣៤៥៦"

fromKhmerNumber()

Convert Khmer numerals to JavaScript numbers.

fromKhmerNumber(
  value: string
): number;

Example:

fromKhmerNumber("១២៣,៤៥៦");
// 123456

numberToKhmerText()

Convert an integer number into Khmer words.

numberToKhmerText(
  value: number | string
): string;

Example:

numberToKhmerText(123);
// "មួយរយម្ភៃបី"

decimalToKhmerText()

Convert a decimal number into Khmer text.

decimalToKhmerText(
  value: number | string
): string;

Example:

decimalToKhmerText(123.45);

isValidMoney()

Validate a money value.

isValidMoney(
  value: unknown
): boolean;

Example:

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

Tree Shaking

The package uses named exports.

You can import only what you need:

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

Or:

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:

dist/
├── index.js
├── index.cjs
├── index.iife.js
└── index.d.ts

ESM

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

CommonJS

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

Browser

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

Then:

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:

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

Dependency Free

Runtime dependencies:

{
  "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:

SECURITY.md

for the complete security policy.


Testing

The project uses Vitest.

Run all tests:

npm test

Run tests in watch mode:

npm run test:watch

Run TypeScript validation:

npm run typecheck

Run the complete check:

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:

npm run build

The output will be generated in:

dist/

Expected files:

dist/
├── index.js
├── index.cjs
├── index.iife.js
├── index.d.ts
└── source maps

Development

Clone the repository:

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

Enter the directory:

cd khmer-money-formatter

Install dependencies:

npm install

Run tests:

npm test

Type check:

npm run typecheck

Build:

npm run build

Run all checks:

npm run check

Project Structure

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:

npm version patch

Or:

npm version minor

Or:

npm version major

Push commits and tags:

git push origin main --follow-tags

The publishing workflow is triggered by version tags:

v1.0.0
v1.0.1
v1.1.0
v2.0.0

The workflow:

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:

permissions:
  contents: read
  id-token: write

Publishing:

npm publish --access public

Changelog

Release history is maintained in:

CHANGELOG.md

Example:

# 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.

formatKHR(123456, {
  khmerDigits: true
});

Result:

១២៣,៤៥៦ ៛

Can it convert numbers into Khmer words?

Yes.

numberToKhmerText(123);

Result:

មួយរយម្ភៃបី

Does it support Khmer Riel?

Yes.

The default currency is:

៛

and the long currency name is:

រៀល

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:

const amountInRiel = 10000;

and formatting only for display:

formatKHR(amountInRiel);

Contributing

Contributions are welcome.

Before submitting a pull request:

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 for the complete license text.


Author

Chamnan dev

GitHub:

https://github.com/SmarterCoding

Final Example

The simplest usage:

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:

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

console.log(
  toKhmerNumber(123456)
);

// "១២៣៤៥៦"

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

// "១២៣,៤៥៦ ៛"

Khmer text:

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

console.log(
  numberToKhmerText(123)
);

// "មួយរយម្ភៃបី"

For a Khmer invoice:

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.

About

Format Khmer Riel, parse money values, convert Khmer numerals, and convert numbers into Khmer text — with zero runtime dependencies.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages