@neutrium/formatter - v1.0.2
    Preparing search index...

    @neutrium/formatter - v1.0.2

    @neutrium/formatter

    Humanise numbers: display prices, measurements, file sizes, and durations in your users' locale. Parse formatted input back into exact values, and keep table or chart labels on a consistent scale.

    The library builds on JavaScript's Intl APIs. For simple one-way number, currency, or unit display, Intl.NumberFormat may be enough.

    Interactive demo · API reference

    pnpm add @neutrium/formatter
    

    The package is ESM-only. Use Node.js 24+ with full ICU data, or a browser with ES2020 modules, BigInt, and modern Intl support, including exact decimal-string formatting. TypeScript 5.4+ is supported. See compatibility requirements before deploying to browsers or using Intl polyfills.

    Call format(value, spec) to get display text. A specification is an options object: kind selects the format, and the remaining fields control its presentation.

    import { formatter } from "@neutrium/formatter";

    formatter.format("1234.5", { kind: "currency", currency: "USD" }); // "$1,234.50"

    The shared instance defaults to the en-US locale. Create an independent instance for another default locale:

    import { createFormatter } from "@neutrium/formatter";

    const german = createFormatter({ locale: "de-DE" });
    german.format("1234.5", { kind: "number" }); // "1.234,5"
    german.format("1234.5", { kind: "number", locale: "en-US" }); // "1,234.5"

    Choose a format below, then use the formatting guide for additional options. Examples use en-US unless specified; localized spacing and wording can vary with the runtime's locale data.

    Numeric specifications use kind: "number" for general localized numbers. Inputs may be numbers, decimal strings, bigint values, or compatible decimal objects; use strings or @neutrium/decimal when the digits must remain exact:

    import { formatter } from "@neutrium/formatter";

    const str = formatter.format("9007199254740993.25", {
    kind: "number",
    maximumFractionDigits: 2,
    });

    console.log(str); // "9,007,199,254,740,993.25"

    Set both minimumFractionDigits and maximumFractionDigits for a fixed number of decimal places. A JavaScript number may already have lost precision before it reaches the formatter. Formatting also rounds for display, so retain the original value for calculations. See exact inputs and magnitude limits.

    Ordinal formatting applies locale-specific rules to numbers that describe an order, such as a position in a list:

    import { formatter } from "@neutrium/formatter";

    const str = formatter.format(23, { kind: "ordinal" });

    console.log(str); // "23rd"

    You can provide a custom pattern for a locale, using {number} where the formatted number belongs:

    import { formatter } from "@neutrium/formatter";

    formatter.format(42, {
    kind: "ordinal",
    ordinalPatterns: { other: "No. {number}" },
    });
    // "No. 42"

    Supply an ISO currency code. Values are amounts in that currency, not minor units such as cents. The currency determines the default number of decimal places.

    import { formatter } from "@neutrium/formatter";

    const str = formatter.format("1234.5", { kind: "currency", currency: "USD" });

    console.log(str); // "$1,234.50"

    Use a unit identifier such as meter or kilometer-per-hour. This adds a localized unit label; it does not convert the value between units.

    import { formatter } from "@neutrium/formatter";

    formatter.format(12.5, {
    kind: "unit", unit: "kilometer-per-hour", unitDisplay: "long",
    }); // "12.5 kilometers per hour"

    Use compact notation for abbreviated magnitudes. The locale selects the label and plural form, while compactExponent can fix a shared scale:

    import { formatter } from "@neutrium/formatter";

    let str = formatter.format(1536, {
    kind: "number",
    notation: "compact",
    maximumFractionDigits: 1,
    });

    console.log(str); // "1.5K"

    str = formatter.format(1_250_000, {
    kind: "number",
    notation: "compact",
    compactExponent: 6,
    maximumFractionDigits: 1,
    });

    console.log(str); // "1.3M"

    Pass a ratio: 0.125 means 12.5%, while 12.5 means 1,250%. Set the precision explicitly when you need fractional percentages:

    import { formatter } from "@neutrium/formatter";

    const str = formatter.format(0.125, {
    kind: "percentage",
    maximumFractionDigits: 1,
    });

    console.log(str); // "12.5%"

    Choose presentation: "elapsed" for H:MM:SS text that can also be parsed. Scalar inputs default to seconds; set inputUnit: "milliseconds" for millisecond values. Choose presentation: "localized" for words or localized digital time; it accepts scalar values or records, requires Intl.DurationFormat, and is format-only.

    import { formatter } from "@neutrium/formatter";

    let str = formatter.format(3661, { kind: "duration", presentation: "elapsed" });

    console.log(str); // "1:01:01"

    str = formatter.format(
    { hours: 1, minutes: 1, seconds: 1 },
    { kind: "duration", presentation: "localized", style: "long" },
    );

    console.log(str); // "1 hour, 1 minute, 1 second"

    Pass a byte count. The default uses IEC units (base 1024); choose base 1000 for SI units:

    import { formatter } from "@neutrium/formatter";

    formatter.format(1536, { kind: "bytes" }); // "1.5 KiB"
    formatter.format(1500000, { kind: "bytes", byteBase: 1000 }); // "1.5 MB"

    Use formatSeries() to give chart or table labels one shared compact or byte scale. Use formatColumn() for padded, monospaced text reports, and formatRange() for localized endpoints:

    import { formatter } from "@neutrium/formatter";

    formatter.formatSeries([1200, 1500, 900], {
    kind: "number",
    notation: "compact",
    maximumFractionDigits: 1,
    });
    // ["1.2K", "1.5K", "0.9K"] — one shared scale

    formatter.formatColumn([1.2, 12, 123.45], {
    kind: "number",
    maximumFractionDigits: 2,
    });
    // [" 1.2 ", " 12 ", "123.45"]

    formatter.formatRange(1, 2, { kind: "number" }); // "1–2"

    Series use shared compact/byte scales by default. Pass { scale: "individual" } as the third argument for independent scales. Use formatRange(start, end, spec) for localized ranges.

    Use formatter.compileSeries(values, spec) to select a scale once and reuse it for later batches or scalar formatting; pass its .spec to parser.compile() for strict parsing. The returned compiled formatter exposes the selected scale in its frozen .spec.

    See series and columns for scale and parsing caveats, and ranges for supported domains.

    Compile once when repeatedly formatting the same kind of value, such as prices in a product list. The resulting methods can be passed directly to map():

    import { formatter, type CurrencyFormatSpec } from "@neutrium/formatter";

    const moneySpec = {
    kind: "currency",
    currency: "USD",
    maximumFractionDigits: 2,
    } satisfies CurrencyFormatSpec;

    const money = formatter.compile(moneySpec);
    ["12.25", "20"].map(money.format); // ["$12.25", "$20.00"]

    Compilation validates the options and freezes a copy, so later edits to moneySpec do not change money. Its methods work as callbacks. See compiled formatters for pairing one with a parser.

    Import parsing separately when your application accepts formatted text. Built-in parsers return exact numeric strings, not JavaScript numbers:

    import { parser, createParser } from "@neutrium/formatter/parse";

    const money = parser.compile({ kind: "currency", currency: "USD" });
    money.parse("$12.25"); // "12.25"

    const german = createParser({ locale: "de-DE" });
    german.parse("1.234,5", { kind: "number" }); // "1234.5"

    You can pass a compiled formatter's .spec to parser.compile() to preserve its locale and selected scale.

    Parsing validates the complete presentation, including grouping, signs, and labels. Use matching formatting and parsing options, and catch invalid user input. Parsing cannot restore digits removed by display rounding; retain original values separately when you need them for calculations or editing.

    See the parsing guide for input validation, matching locales, and parsing scaled values.

    • Change separators, symbols, signs, or zero placeholders with presentation overrides.
    • Style a currency symbol or unit separately with formatToParts(). Render every part in order to preserve localized punctuation and spacing.
    • Explain a rounded chart label with formatDetailed(). It provides display text and the value represented after rounding; keep the original value for calculations.
    • Add a new value type or rendering rule with a custom codec. Ordinary applications can use the built-in formats without writing codecs.

    The default formatter includes all built-in formats; parsing is a separate import. For a smaller bundle, register only the codecs you need. The bundle-size guide compares minified and gzipped costs by functionality, including the additional cost when your application already bundles @neutrium/decimal.

    • Interactive demo: a demonstration of how to use this library and exploration of formatting specifications.
    • API reference: full detail of the library api including accepted parameters and return types.
    • Formatting guide: precision, locales, currencies, units, compact scales, bytes, ordinals, durations, and overrides.
    • Parsing guide: accept localized input, handle errors, reuse parsers, and recover exact scaled values.
    • Diagnostics and compatibility: supports() vs resolve(), runtime capabilities, and deployment requirements.
    • Custom codecs: extending the library, isolated registries, custom parse types, and advanced contracts.
    • Bundle size guide: compares minified and gzipped sizes for the default formatter/parser and individual codecs.

    Contributing to the library? See the development guide for tests, documentation builds, and releases.

    This project is licensed under the MIT License, see the LICENSE file for details.

    You are free to:

    • Use this plugin for personal or commercial purposes
    • Modify and distribute the code
    • Include it in other projects

    Under the following conditions:

    • You must include the original license and copyright notice

    This plugin is provided "as is", without warranty of any kind. Use at your own risk.