@weasel-js/quantity 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +94 -12
- package/dist/index.js +161 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -117,7 +117,7 @@ interface Part {
|
|
|
117
117
|
}
|
|
118
118
|
/** What formatting and parsing need beyond the value and its display. */
|
|
119
119
|
interface FormatContext {
|
|
120
|
-
/** BCP 47 locale.
|
|
120
|
+
/** BCP 47 locale. Default `en-US`. */
|
|
121
121
|
locale: string;
|
|
122
122
|
/** The unit the value is measured in, from its tag. */
|
|
123
123
|
unit?: Unit;
|
|
@@ -166,7 +166,7 @@ declare function registerDisplayKind<D extends Display>(kind: DisplayKind<D>): (
|
|
|
166
166
|
declare function displayKindOf(display: Display | undefined): DisplayKind<Display>;
|
|
167
167
|
/** Options for presenting or parsing a quantity. */
|
|
168
168
|
interface PresentOptions {
|
|
169
|
-
/** BCP 47 locale. Default `en-US
|
|
169
|
+
/** BCP 47 locale. Default `en-US`. */
|
|
170
170
|
locale?: string;
|
|
171
171
|
}
|
|
172
172
|
/** A quantity as text, spoken text, HTML and, where its kind has one, MathML. */
|
|
@@ -229,14 +229,18 @@ type DecimalDisplay = {
|
|
|
229
229
|
/** Thousands separators. Default true. */
|
|
230
230
|
grouping?: boolean;
|
|
231
231
|
};
|
|
232
|
+
/** A {@link DecimalDisplay}. */
|
|
232
233
|
declare function decimal(options?: Omit<DecimalDisplay, 'kind'>): DecimalDisplay;
|
|
234
|
+
/** The built-in `decimal` kind, to spread into a `registerDisplayKind` replacement. */
|
|
233
235
|
declare const decimalKind: DisplayKind<DecimalDisplay>;
|
|
234
236
|
/** A whole number, rounded. */
|
|
235
237
|
type IntegerDisplay = {
|
|
236
238
|
kind: 'integer';
|
|
237
239
|
grouping?: boolean;
|
|
238
240
|
};
|
|
241
|
+
/** An {@link IntegerDisplay}. */
|
|
239
242
|
declare function integer(options?: Omit<IntegerDisplay, 'kind'>): IntegerDisplay;
|
|
243
|
+
/** The built-in `integer` kind, to spread into a `registerDisplayKind` replacement. */
|
|
240
244
|
declare const integerKind: DisplayKind<IntegerDisplay>;
|
|
241
245
|
/**
|
|
242
246
|
* Below 1,000 at `places` decimals, from 1,000 up at three significant figures
|
|
@@ -247,7 +251,9 @@ type CompactDisplay = {
|
|
|
247
251
|
kind: 'compact';
|
|
248
252
|
places?: number;
|
|
249
253
|
};
|
|
254
|
+
/** A {@link CompactDisplay}. */
|
|
250
255
|
declare function compact(options?: Omit<CompactDisplay, 'kind'>): CompactDisplay;
|
|
256
|
+
/** The built-in `compact` kind, to spread into a `registerDisplayKind` replacement. */
|
|
251
257
|
declare const compactKind: DisplayKind<CompactDisplay>;
|
|
252
258
|
|
|
253
259
|
/** A share of one as a percentage: 0.25 shows `25%`. Typed text reads as
|
|
@@ -257,7 +263,9 @@ type PercentDisplay = {
|
|
|
257
263
|
/** Most decimals shown. Default 0. */
|
|
258
264
|
places?: number;
|
|
259
265
|
};
|
|
266
|
+
/** A {@link PercentDisplay}. */
|
|
260
267
|
declare function percent(options?: Omit<PercentDisplay, 'kind'>): PercentDisplay;
|
|
268
|
+
/** The built-in `percent` kind, to spread into a `registerDisplayKind` replacement. */
|
|
261
269
|
declare const percentKind: DisplayKind<PercentDisplay>;
|
|
262
270
|
/**
|
|
263
271
|
* The nearest fraction whose denominator is at most `maxDenominator`, as
|
|
@@ -266,6 +274,57 @@ declare const percentKind: DisplayKind<PercentDisplay>;
|
|
|
266
274
|
* semiconvergent, which is the closest any denominator in range can get.
|
|
267
275
|
*/
|
|
268
276
|
declare function nearestFraction(x: number, maxDenominator: number): [number, number];
|
|
277
|
+
/**
|
|
278
|
+
* A constant a fraction can count in: `π`, so 3π/4 shows as `3π/4` rather
|
|
279
|
+
* than `2.356`. `names` are what may be typed for it besides the symbol.
|
|
280
|
+
*/
|
|
281
|
+
interface NamedConstant {
|
|
282
|
+
symbol: string;
|
|
283
|
+
value: number;
|
|
284
|
+
/** How it is read aloud: `pi`. */
|
|
285
|
+
spoken: string;
|
|
286
|
+
names?: readonly string[];
|
|
287
|
+
}
|
|
288
|
+
/** The constants `fraction({ of })` knows by symbol. */
|
|
289
|
+
declare const CONSTANTS: {
|
|
290
|
+
readonly π: {
|
|
291
|
+
readonly symbol: "π";
|
|
292
|
+
readonly value: number;
|
|
293
|
+
readonly spoken: "pi";
|
|
294
|
+
readonly names: readonly ["pi"];
|
|
295
|
+
};
|
|
296
|
+
readonly τ: {
|
|
297
|
+
readonly symbol: "τ";
|
|
298
|
+
readonly value: number;
|
|
299
|
+
readonly spoken: "tau";
|
|
300
|
+
readonly names: readonly ["tau"];
|
|
301
|
+
};
|
|
302
|
+
readonly e: {
|
|
303
|
+
readonly symbol: "e";
|
|
304
|
+
readonly value: number;
|
|
305
|
+
readonly spoken: "e";
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
type FractionOptions = {
|
|
309
|
+
/** Default 64. */
|
|
310
|
+
maxDenominator?: number;
|
|
311
|
+
/**
|
|
312
|
+
* `inline` (default) writes `1/12`. `diagonal` writes `¹⁄₁₂` — superscript
|
|
313
|
+
* digits, the fraction slash, subscript digits — so the text itself is
|
|
314
|
+
* diagonal wherever it is drawn, CSS or not.
|
|
315
|
+
*/
|
|
316
|
+
form?: 'inline' | 'diagonal';
|
|
317
|
+
} & ({
|
|
318
|
+
mixed?: boolean;
|
|
319
|
+
of?: never;
|
|
320
|
+
} | {
|
|
321
|
+
/**
|
|
322
|
+
* Count in a constant: with `π`, 3π/4 shows `3π/4` and is spoken `3 pi
|
|
323
|
+
* over 4`. Excludes `mixed`, since `1 1/2π` reads as 1 + ½π.
|
|
324
|
+
*/
|
|
325
|
+
of: keyof typeof CONSTANTS | NamedConstant;
|
|
326
|
+
mixed?: never;
|
|
327
|
+
});
|
|
269
328
|
/**
|
|
270
329
|
* A value as the nearest fraction: 1/12 shows `1/12` and is spoken `1 over 12`.
|
|
271
330
|
* `mixed` splits a whole part off (`1 1/2`); a whole value shows as an integer.
|
|
@@ -273,11 +332,10 @@ declare function nearestFraction(x: number, maxDenominator: number): [number, nu
|
|
|
273
332
|
*/
|
|
274
333
|
type FractionDisplay = {
|
|
275
334
|
kind: 'fraction';
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
declare function fraction(options?: Omit<FractionDisplay, 'kind'>): FractionDisplay;
|
|
335
|
+
} & FractionOptions;
|
|
336
|
+
/** A {@link FractionDisplay}. */
|
|
337
|
+
declare function fraction(options?: FractionOptions): FractionDisplay;
|
|
338
|
+
/** The built-in `fraction` kind, to spread into a `registerDisplayKind` replacement. */
|
|
281
339
|
declare const fractionKind: DisplayKind<FractionDisplay>;
|
|
282
340
|
/** A value as a ratio `a:b` — 1/12 shows `1:12`, spoken `1 to 12`. */
|
|
283
341
|
type RatioDisplay = {
|
|
@@ -285,7 +343,9 @@ type RatioDisplay = {
|
|
|
285
343
|
/** Largest second term. Default 64. */
|
|
286
344
|
maxDenominator?: number;
|
|
287
345
|
};
|
|
346
|
+
/** A {@link RatioDisplay}. */
|
|
288
347
|
declare function ratio(options?: Omit<RatioDisplay, 'kind'>): RatioDisplay;
|
|
348
|
+
/** The built-in `ratio` kind, to spread into a `registerDisplayKind` replacement. */
|
|
289
349
|
declare const ratioKind: DisplayKind<RatioDisplay>;
|
|
290
350
|
/** A factor with a times sign: `2.5×`, spoken `2.5 times`. Typed `x` reads too. */
|
|
291
351
|
type MultiplierDisplay = {
|
|
@@ -295,7 +355,9 @@ type MultiplierDisplay = {
|
|
|
295
355
|
/** Default `×`. */
|
|
296
356
|
symbol?: string;
|
|
297
357
|
};
|
|
358
|
+
/** A {@link MultiplierDisplay}. */
|
|
298
359
|
declare function multiplier(options?: Omit<MultiplierDisplay, 'kind'>): MultiplierDisplay;
|
|
360
|
+
/** The built-in `multiplier` kind, to spread into a `registerDisplayKind` replacement. */
|
|
299
361
|
declare const multiplierKind: DisplayKind<MultiplierDisplay>;
|
|
300
362
|
/**
|
|
301
363
|
* A zoom factor. At 2x and below a percentage reads naturally; past it a
|
|
@@ -305,7 +367,9 @@ declare const multiplierKind: DisplayKind<MultiplierDisplay>;
|
|
|
305
367
|
type ZoomDisplay = {
|
|
306
368
|
kind: 'zoom';
|
|
307
369
|
};
|
|
370
|
+
/** A {@link ZoomDisplay}. */
|
|
308
371
|
declare function zoom(): ZoomDisplay;
|
|
372
|
+
/** The built-in `zoom` kind, to spread into a `registerDisplayKind` replacement. */
|
|
309
373
|
declare const zoomKind: DisplayKind<ZoomDisplay>;
|
|
310
374
|
|
|
311
375
|
/**
|
|
@@ -338,15 +402,21 @@ declare function parseSignedNumber(text: string): number;
|
|
|
338
402
|
*/
|
|
339
403
|
declare function formatCompact(value: number, decimals?: number): string;
|
|
340
404
|
/**
|
|
341
|
-
* Reads a typed number: anything {@link parseSignedNumber} reads, plus
|
|
342
|
-
*
|
|
343
|
-
*
|
|
405
|
+
* Reads a typed number: anything {@link parseSignedNumber} reads, plus the
|
|
406
|
+
* locale's group and decimal separators (`40,000` and `2.5` in `en-US`,
|
|
407
|
+
* `40.000` and `2,5` in `de-DE`) and a `k`/`m`/`b`/`t` suffix in either case
|
|
408
|
+
* (`2.5m` is 2,500,000). Empty text is NaN rather than zero.
|
|
409
|
+
*
|
|
410
|
+
* Text the locale's form does not read is tried as `en-US`, so `1.5` is still
|
|
411
|
+
* one and a half in `de-DE`; where both read, the locale wins. A locale that
|
|
412
|
+
* groups with a space accepts any space there, since a keyboard types a plain
|
|
413
|
+
* one where `Intl` writes a no-break space.
|
|
344
414
|
*
|
|
345
415
|
* Given `units` — a suffix mapped to the factor it scales by — a trailing unit
|
|
346
416
|
* name is read first: the longest match wins, exact case before any case, and
|
|
347
417
|
* a unit beats a magnitude suffix, so with `m` accepted `2m` is `2 * units.m`.
|
|
348
418
|
*/
|
|
349
|
-
declare function parseNumber(text: string, units?: Readonly<UnitTable
|
|
419
|
+
declare function parseNumber(text: string, units?: Readonly<UnitTable>, locale?: string): number;
|
|
350
420
|
/** Suffixes a person may type, each mapped to its conversion into the shown unit. */
|
|
351
421
|
type UnitTable = Record<string, UnitEntry>;
|
|
352
422
|
|
|
@@ -367,7 +437,9 @@ type UnitDisplay = {
|
|
|
367
437
|
/** Singular and plural names, for a unit `Intl` cannot name. */
|
|
368
438
|
spoken?: readonly [string, string];
|
|
369
439
|
};
|
|
440
|
+
/** A {@link UnitDisplay} in `name`. With no name, the unit comes from the value's tag. */
|
|
370
441
|
declare function unit(name?: string, options?: Omit<UnitDisplay, 'kind' | 'unit'>): UnitDisplay;
|
|
442
|
+
/** The built-in `unit` kind, to spread into a `registerDisplayKind` replacement. */
|
|
371
443
|
declare const unitKind: DisplayKind<UnitDisplay>;
|
|
372
444
|
/** Money in an ISO 4217 currency: `$12.50`, spoken `12.50 US dollars`. */
|
|
373
445
|
type CurrencyDisplay = {
|
|
@@ -376,7 +448,9 @@ type CurrencyDisplay = {
|
|
|
376
448
|
/** Fixed decimals. Defaults to the currency's own (2 for USD, 0 for JPY). */
|
|
377
449
|
places?: number;
|
|
378
450
|
};
|
|
451
|
+
/** A {@link CurrencyDisplay} in the ISO 4217 currency `code`. */
|
|
379
452
|
declare function currency(code: string, options?: Omit<CurrencyDisplay, 'kind' | 'currency'>): CurrencyDisplay;
|
|
453
|
+
/** The built-in `currency` kind, to spread into a `registerDisplayKind` replacement. */
|
|
380
454
|
declare const currencyKind: DisplayKind<CurrencyDisplay>;
|
|
381
455
|
/**
|
|
382
456
|
* A span of time, the value in seconds. `clock` shows `1:02:03` or `4:05.5`;
|
|
@@ -390,7 +464,9 @@ type DurationDisplay = {
|
|
|
390
464
|
/** Decimals on the seconds. Default 0. */
|
|
391
465
|
places?: number;
|
|
392
466
|
};
|
|
467
|
+
/** A {@link DurationDisplay}. */
|
|
393
468
|
declare function duration(options?: Omit<DurationDisplay, 'kind'>): DurationDisplay;
|
|
469
|
+
/** The built-in `duration` kind, to spread into a `registerDisplayKind` replacement. */
|
|
394
470
|
declare const durationKind: DisplayKind<DurationDisplay>;
|
|
395
471
|
/** A byte count in the largest unit that keeps it at or above 1: `1.2 MB`,
|
|
396
472
|
* spoken `1.2 megabytes`. `base: 1024` uses `KiB`, `MiB`, … */
|
|
@@ -401,7 +477,9 @@ type BytesDisplay = {
|
|
|
401
477
|
/** Most decimals. Default 1. */
|
|
402
478
|
places?: number;
|
|
403
479
|
};
|
|
480
|
+
/** A {@link BytesDisplay}. */
|
|
404
481
|
declare function bytes(options?: Omit<BytesDisplay, 'kind'>): BytesDisplay;
|
|
482
|
+
/** The built-in `bytes` kind, to spread into a `registerDisplayKind` replacement. */
|
|
405
483
|
declare const bytesKind: DisplayKind<BytesDisplay>;
|
|
406
484
|
|
|
407
485
|
/**
|
|
@@ -413,18 +491,22 @@ type RomanDisplay = {
|
|
|
413
491
|
kind: 'roman';
|
|
414
492
|
lower?: boolean;
|
|
415
493
|
};
|
|
494
|
+
/** A {@link RomanDisplay}. */
|
|
416
495
|
declare function roman(options?: Omit<RomanDisplay, 'kind'>): RomanDisplay;
|
|
417
496
|
/** `n` in Roman numerals, or undefined outside 1–3999. */
|
|
418
497
|
declare function toRoman(n: number): string | undefined;
|
|
419
498
|
/** The value of well-formed Roman numerals, either case; NaN otherwise. */
|
|
420
499
|
declare function fromRoman(text: string): number;
|
|
500
|
+
/** The built-in `roman` kind, to spread into a `registerDisplayKind` replacement. */
|
|
421
501
|
declare const romanKind: DisplayKind<RomanDisplay>;
|
|
422
502
|
/** A whole number as an ordinal: `1st`, `22nd`, `113th`. English suffixes;
|
|
423
503
|
* in any other locale the number shows alone. */
|
|
424
504
|
type OrdinalDisplay = {
|
|
425
505
|
kind: 'ordinal';
|
|
426
506
|
};
|
|
507
|
+
/** An {@link OrdinalDisplay}. */
|
|
427
508
|
declare function ordinal(): OrdinalDisplay;
|
|
509
|
+
/** The built-in `ordinal` kind, to spread into a `registerDisplayKind` replacement. */
|
|
428
510
|
declare const ordinalKind: DisplayKind<OrdinalDisplay>;
|
|
429
511
|
|
|
430
|
-
export { ANGLE_RADIANS, type BytesDisplay, type CompactDisplay, type CurrencyDisplay, type DecimalDisplay, type Display, type DisplayKind, type DurationDisplay, type FormatContext, type FractionDisplay, IMPERIAL_INCHES, type IntegerDisplay, METRIC_MM, MINUS_SIGN, type MultiplierDisplay, type OrdinalDisplay, PIXELS, type Part, type PercentDisplay, type PresentOptions, type Presentation, type Quantity, QuantityView, type RatioDisplay, type RomanDisplay, type Tagged, type Unit, type UnitDisplay, type UnitEntry, type UnitScale, type UnitSystem, type UnitTable, type UnitValue, type ZoomDisplay, amount, bytes, bytesKind, compact, compactKind, currency, currencyKind, decimal, decimalKind, displayKindOf, displayOf, duration, durationKind, entryScale, formatCompact, formatNumber, formatUnit, fraction, fractionKind, fromRoman, integer, integerKind, intlParts, multiplier, multiplierKind, nearestFraction, numberPart, ordinal, ordinalKind, parseAs, parseNumber, parseSignedNumber, partsOf, partsToHtml, percent, percentKind, plural, present, qty, ratio, ratioKind, registerDisplayKind, resolveUnit, retag, roman, romanKind, signed, spokenSign, tag, textOf, toRoman, unit, unitKind, unitOf, unitScale, zoom, zoomKind };
|
|
512
|
+
export { ANGLE_RADIANS, type BytesDisplay, CONSTANTS, type CompactDisplay, type CurrencyDisplay, type DecimalDisplay, type Display, type DisplayKind, type DurationDisplay, type FormatContext, type FractionDisplay, IMPERIAL_INCHES, type IntegerDisplay, METRIC_MM, MINUS_SIGN, type MultiplierDisplay, type NamedConstant, type OrdinalDisplay, PIXELS, type Part, type PercentDisplay, type PresentOptions, type Presentation, type Quantity, QuantityView, type RatioDisplay, type RomanDisplay, type Tagged, type Unit, type UnitDisplay, type UnitEntry, type UnitScale, type UnitSystem, type UnitTable, type UnitValue, type ZoomDisplay, amount, bytes, bytesKind, compact, compactKind, currency, currencyKind, decimal, decimalKind, displayKindOf, displayOf, duration, durationKind, entryScale, formatCompact, formatNumber, formatUnit, fraction, fractionKind, fromRoman, integer, integerKind, intlParts, multiplier, multiplierKind, nearestFraction, numberPart, ordinal, ordinalKind, parseAs, parseNumber, parseSignedNumber, partsOf, partsToHtml, percent, percentKind, plural, present, qty, ratio, ratioKind, registerDisplayKind, resolveUnit, retag, roman, romanKind, signed, spokenSign, tag, textOf, toRoman, unit, unitKind, unitOf, unitScale, zoom, zoomKind };
|
package/dist/index.js
CHANGED
|
@@ -87,30 +87,92 @@ function formatNumber(value, options) {
|
|
|
87
87
|
function parseSignedNumber(text) {
|
|
88
88
|
return Number(text.replace(MINUS_SIGN, "-"));
|
|
89
89
|
}
|
|
90
|
+
var TERM_NUMBER = String.raw`\d+(?:\.\d+)?|\.\d+`;
|
|
90
91
|
var EXPONENTS = { k: 3, m: 6, b: 9, t: 12 };
|
|
91
92
|
function formatCompact(value, decimals = 0) {
|
|
92
93
|
if (!Number.isFinite(value)) return formatNumber(value);
|
|
93
94
|
const options = Math.abs(value) < 1e3 ? { useGrouping: false, minimumFractionDigits: decimals, maximumFractionDigits: decimals } : { notation: "compact", minimumSignificantDigits: 3, maximumSignificantDigits: 3 };
|
|
94
95
|
return value.toLocaleString("en-US", options).replace(/^-/, MINUS_SIGN);
|
|
95
96
|
}
|
|
96
|
-
function parseNumber(text, units) {
|
|
97
|
+
function parseNumber(text, units, locale = "en-US") {
|
|
98
|
+
const n = readNumber(delocalized(text, locale), units);
|
|
99
|
+
return Number.isNaN(n) && locale !== "en-US" ? readNumber(delocalized(text, "en-US"), units) : n;
|
|
100
|
+
}
|
|
101
|
+
function readNumber(text, units) {
|
|
97
102
|
if (units) {
|
|
103
|
+
units = withSpellings(units);
|
|
98
104
|
const trimmed = text.trim();
|
|
99
105
|
const name = unitSuffixOf(trimmed, units);
|
|
100
106
|
if (name !== void 0) {
|
|
101
107
|
const terms = compoundTermsOf(trimmed, units);
|
|
102
108
|
if (terms !== void 0 && terms.length > 1) return compoundValue(terms, trimmed, units);
|
|
103
109
|
const { factor, offset } = entryScale(units[name]);
|
|
104
|
-
return scaled(
|
|
110
|
+
return scaled(readNumber(trimmed.slice(0, -name.length)), factor) + offset;
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
113
|
let t = text.trim().replace(MINUS_SIGN, "-");
|
|
108
114
|
const exponent = EXPONENTS[t.slice(-1).toLowerCase()];
|
|
109
115
|
if (exponent !== void 0) t = t.slice(0, -1).trimEnd();
|
|
110
|
-
if (/^[-+]?\d{1,3}(,\d{3})+(\.\d*)?$/.test(t)) t = t.replace(/,/g, "");
|
|
111
116
|
if (!/\d/.test(t)) return Number.NaN;
|
|
112
117
|
return Number(exponent === void 0 ? t : `${t}e${exponent}`);
|
|
113
118
|
}
|
|
119
|
+
var shapes = /* @__PURE__ */ new Map();
|
|
120
|
+
function shapeOf(locale) {
|
|
121
|
+
const known = shapes.get(locale);
|
|
122
|
+
if (known) return known;
|
|
123
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(1234567895e-1);
|
|
124
|
+
const sizes = parts.filter((p) => p.type === "integer").map((p) => p.value.length);
|
|
125
|
+
const primary = sizes.at(-1);
|
|
126
|
+
const secondary = sizes.length > 2 ? sizes.at(-2) : primary;
|
|
127
|
+
const groupChar = parts.find((p) => p.type === "group")?.value ?? ",";
|
|
128
|
+
const decimal2 = parts.find((p) => p.type === "decimal")?.value ?? ".";
|
|
129
|
+
const g = /\s/.test(groupChar) ? String.raw`\s` : /['’]/.test(groupChar) ? `'\u2019` : escapeClass(groupChar);
|
|
130
|
+
const own = [...new Intl.NumberFormat(locale, { useGrouping: false }).format(9876543210)].reverse();
|
|
131
|
+
const digits = own.join("") === "0123456789" ? void 0 : { pattern: new RegExp(`[${own.join("")}]`, "gu"), latin: new Map(own.map((c, i) => [c, String(i)])) };
|
|
132
|
+
const d = escapeClass(decimal2);
|
|
133
|
+
const integer2 = String.raw`\d{1,${secondary}}(?:[${g}]\d{${secondary}})*[${g}]\d{${primary}}|\d*`;
|
|
134
|
+
const shape = {
|
|
135
|
+
run: new RegExp(String.raw`(?:\d|[${d}]\d)(?:[\d${g}${d}]*\d)?[${d}]?`, "g"),
|
|
136
|
+
whole: new RegExp(String.raw`^(?:${integer2})(?:[${d}]\d*)?$`),
|
|
137
|
+
group: new RegExp(`[${g}]`, "g"),
|
|
138
|
+
decimal: decimal2,
|
|
139
|
+
digits
|
|
140
|
+
};
|
|
141
|
+
shapes.set(locale, shape);
|
|
142
|
+
return shape;
|
|
143
|
+
}
|
|
144
|
+
var escapeClass = (c) => c.replace(/[\\\]^-]/g, "\\$&");
|
|
145
|
+
function delocalized(text, locale) {
|
|
146
|
+
const shape = shapeOf(locale);
|
|
147
|
+
return latinDigits(text, locale).replace(
|
|
148
|
+
shape.run,
|
|
149
|
+
(run) => shape.whole.test(run) ? run.replace(shape.group, "").replace(shape.decimal, ".") : run
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
function latinDigits(text, locale) {
|
|
153
|
+
const { digits } = shapeOf(locale);
|
|
154
|
+
const t = text.replace(BIDI_MARKS, "");
|
|
155
|
+
return digits ? t.replace(digits.pattern, (c) => digits.latin.get(c)) : t;
|
|
156
|
+
}
|
|
157
|
+
var BIDI_MARKS = /[\u061c\u200e\u200f]/g;
|
|
158
|
+
var decimalOf = (locale) => shapeOf(locale).decimal;
|
|
159
|
+
var SPELLINGS = [
|
|
160
|
+
["in", '"', "\u2033", "\u201D"],
|
|
161
|
+
["ft", "'", "\u2032", "\u2019"]
|
|
162
|
+
];
|
|
163
|
+
function withSpellings(units) {
|
|
164
|
+
let out;
|
|
165
|
+
for (const group of SPELLINGS) {
|
|
166
|
+
const known = group.find((n) => units[n] !== void 0);
|
|
167
|
+
if (known === void 0) continue;
|
|
168
|
+
for (const n of group) {
|
|
169
|
+
if (units[n] !== void 0) continue;
|
|
170
|
+
out ??= { ...units };
|
|
171
|
+
out[n] = units[known];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return out ?? units;
|
|
175
|
+
}
|
|
114
176
|
function scaled(n, factor) {
|
|
115
177
|
return factor < 1 ? n / (1 / factor) : n * factor;
|
|
116
178
|
}
|
|
@@ -122,7 +184,7 @@ function compoundTermsOf(text, units) {
|
|
|
122
184
|
if (name === void 0) return void 0;
|
|
123
185
|
names.push(name);
|
|
124
186
|
const before = rest.slice(0, -name.length);
|
|
125
|
-
const m =
|
|
187
|
+
const m = new RegExp(`(?:${TERM_NUMBER})\\s*$`).exec(before);
|
|
126
188
|
if (!m) return void 0;
|
|
127
189
|
rest = before.slice(0, m.index).trimEnd();
|
|
128
190
|
if (rest === "-" || rest === "+" || rest === MINUS_SIGN) rest = "";
|
|
@@ -130,7 +192,7 @@ function compoundTermsOf(text, units) {
|
|
|
130
192
|
return names.length === 0 ? void 0 : names.reverse();
|
|
131
193
|
}
|
|
132
194
|
function compoundValue(names, text, units) {
|
|
133
|
-
const digits = text.match(
|
|
195
|
+
const digits = text.match(new RegExp(TERM_NUMBER, "g"));
|
|
134
196
|
if (!digits || digits.length !== names.length) return Number.NaN;
|
|
135
197
|
const sign = /^\s*[-\u2212]/.test(text) ? -1 : 1;
|
|
136
198
|
let total = 0;
|
|
@@ -184,7 +246,7 @@ var decimalKind = {
|
|
|
184
246
|
kind: "decimal",
|
|
185
247
|
format: (value, d, ctx) => intlParts(value, ctx.locale, decimalOptions(d)),
|
|
186
248
|
speak: (value, d, ctx) => spokenSign(textOf(intlParts(value, ctx.locale, decimalOptions(d)))),
|
|
187
|
-
parse: (text) => parseNumber(text)
|
|
249
|
+
parse: (text, _d, ctx) => parseNumber(text, void 0, ctx.locale)
|
|
188
250
|
};
|
|
189
251
|
function decimalOptions(d) {
|
|
190
252
|
const grouping = d.grouping ?? true;
|
|
@@ -197,7 +259,7 @@ var integerKind = {
|
|
|
197
259
|
kind: "integer",
|
|
198
260
|
format: (value, d, ctx) => intlParts(value, ctx.locale, { maximumFractionDigits: 0, useGrouping: d.grouping ?? true }),
|
|
199
261
|
speak: (value, d, ctx) => spokenSign(textOf(integerKind.format(value, d, ctx))),
|
|
200
|
-
parse: (text) => Math.round(parseNumber(text))
|
|
262
|
+
parse: (text, _d, ctx) => Math.round(parseNumber(text, void 0, ctx.locale))
|
|
201
263
|
};
|
|
202
264
|
function compact(options = {}) {
|
|
203
265
|
return { kind: "compact", ...options };
|
|
@@ -241,7 +303,7 @@ var percentKind = {
|
|
|
241
303
|
})
|
|
242
304
|
)
|
|
243
305
|
),
|
|
244
|
-
parse: (text) => parseNumber(text.replace(
|
|
306
|
+
parse: (text, _d, ctx) => parseNumber(text.replace(/^\s*%|%\s*$/, ""), void 0, ctx.locale) / 100
|
|
245
307
|
};
|
|
246
308
|
function nearestFraction(x, maxDenominator) {
|
|
247
309
|
if (!Number.isFinite(x)) return [x, 1];
|
|
@@ -265,57 +327,104 @@ function nearestFraction(x, maxDenominator) {
|
|
|
265
327
|
}
|
|
266
328
|
return [sign * h1, k1];
|
|
267
329
|
}
|
|
330
|
+
var CONSTANTS = {
|
|
331
|
+
\u03C0: { symbol: "\u03C0", value: Math.PI, spoken: "pi", names: ["pi"] },
|
|
332
|
+
\u03C4: { symbol: "\u03C4", value: 2 * Math.PI, spoken: "tau", names: ["tau"] },
|
|
333
|
+
e: { symbol: "e", value: Math.E, spoken: "e" }
|
|
334
|
+
};
|
|
335
|
+
var SUPERSCRIPT = "\u2070\xB9\xB2\xB3\u2074\u2075\u2076\u2077\u2078\u2079";
|
|
336
|
+
var SUBSCRIPT = "\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089";
|
|
337
|
+
var inDigits = (n, digits) => String(n).replace(/\d/g, (c) => digits[Number(c)]);
|
|
338
|
+
var fromDigits = (text, digits) => Number([...text].map((c) => digits.indexOf(c)).join(""));
|
|
268
339
|
function fraction(options = {}) {
|
|
269
340
|
return { kind: "fraction", ...options };
|
|
270
341
|
}
|
|
342
|
+
function constantOf(d) {
|
|
343
|
+
return typeof d.of === "string" ? CONSTANTS[d.of] : d.of;
|
|
344
|
+
}
|
|
271
345
|
function fractionPieces(value, d) {
|
|
272
|
-
const
|
|
346
|
+
const constant = constantOf(d);
|
|
347
|
+
const [n, den] = nearestFraction(constant ? value / constant.value : value, d.maxDenominator ?? 64);
|
|
273
348
|
const negative = n < 0;
|
|
274
349
|
const abs = Math.abs(n);
|
|
275
350
|
const whole = d.mixed || den === 1 ? Math.floor(abs / den) : 0;
|
|
276
|
-
return { negative, whole, num: abs - whole * den, den };
|
|
277
|
-
}
|
|
351
|
+
return { negative, whole, num: abs - whole * den, den, constant };
|
|
352
|
+
}
|
|
353
|
+
function parseFraction(text) {
|
|
354
|
+
const inline = /^\s*([-−+]?)\s*(?:(\d+)\s+)?(\d+)\s*[/⁄]\s*(\d+)\s*$/.exec(text);
|
|
355
|
+
const diagonal = /^\s*([-−+]?)\s*(\d+)?\s*([⁰¹²³⁴⁵⁶⁷⁸⁹]+)\s*[/⁄]\s*([₀₁₂₃₄₅₆₇₈₉]+)\s*$/.exec(text);
|
|
356
|
+
let magnitude;
|
|
357
|
+
if (inline) magnitude = Number(inline[2] ?? 0) + Number(inline[3]) / Number(inline[4]);
|
|
358
|
+
else if (diagonal) {
|
|
359
|
+
magnitude = Number(diagonal[2] ?? 0) + fromDigits(diagonal[3], SUPERSCRIPT) / fromDigits(diagonal[4], SUBSCRIPT);
|
|
360
|
+
} else return parseNumber(text);
|
|
361
|
+
const sign = (inline ?? diagonal)[1];
|
|
362
|
+
return sign === "-" || sign === MINUS_SIGN ? -magnitude : magnitude;
|
|
363
|
+
}
|
|
364
|
+
var escape = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
278
365
|
var fractionKind = {
|
|
279
366
|
kind: "fraction",
|
|
280
367
|
format: (value, d) => {
|
|
281
368
|
if (!Number.isFinite(value)) return [{ type: "number", value: String(value) }];
|
|
282
|
-
const { negative, whole, num, den } = fractionPieces(value, d);
|
|
369
|
+
const { negative, whole, num, den, constant } = fractionPieces(value, d);
|
|
370
|
+
const diagonal = d.form === "diagonal";
|
|
371
|
+
const symbol = constant ? [{ type: "constant", value: constant.symbol }] : [];
|
|
283
372
|
const parts = [];
|
|
284
373
|
if (negative) parts.push({ type: "sign", value: MINUS_SIGN });
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
if (whole
|
|
374
|
+
if (num === 0) {
|
|
375
|
+
if (whole === 0) return [...parts, { type: "whole", value: "0" }];
|
|
376
|
+
if (!(constant && whole === 1)) parts.push({ type: "whole", value: String(whole) });
|
|
377
|
+
return [...parts, ...symbol];
|
|
378
|
+
}
|
|
379
|
+
if (whole > 0) {
|
|
380
|
+
parts.push({ type: "whole", value: String(whole) });
|
|
381
|
+
if (!diagonal) parts.push({ type: "literal", value: " " });
|
|
382
|
+
}
|
|
383
|
+
if (diagonal) {
|
|
288
384
|
parts.push(
|
|
289
|
-
{ type: "numerator", value:
|
|
290
|
-
{ type: "literal", value: "
|
|
291
|
-
{ type: "denominator", value:
|
|
385
|
+
{ type: "numerator", value: inDigits(num, SUPERSCRIPT) },
|
|
386
|
+
{ type: "literal", value: "\u2044" },
|
|
387
|
+
{ type: "denominator", value: inDigits(den, SUBSCRIPT) },
|
|
388
|
+
...symbol
|
|
292
389
|
);
|
|
390
|
+
} else {
|
|
391
|
+
if (!(constant && num === 1)) parts.push({ type: "numerator", value: String(num) });
|
|
392
|
+
parts.push(...symbol, { type: "literal", value: "/" }, { type: "denominator", value: String(den) });
|
|
293
393
|
}
|
|
294
394
|
return parts;
|
|
295
395
|
},
|
|
296
396
|
speak: (value, d) => {
|
|
297
397
|
if (!Number.isFinite(value)) return String(value);
|
|
298
|
-
const { negative, whole, num, den } = fractionPieces(value, d);
|
|
398
|
+
const { negative, whole, num, den, constant } = fractionPieces(value, d);
|
|
399
|
+
const counted = (n) => !constant ? String(n) : n === 1 ? constant.spoken : `${n} ${constant.spoken}`;
|
|
299
400
|
const words = [
|
|
300
|
-
whole > 0
|
|
401
|
+
whole > 0 ? counted(whole) : num === 0 ? "0" : "",
|
|
301
402
|
whole > 0 && num > 0 ? "and" : "",
|
|
302
|
-
num > 0 ? `${num} over ${den}` : ""
|
|
403
|
+
num > 0 ? `${counted(num)} over ${den}` : ""
|
|
303
404
|
].filter(Boolean);
|
|
304
405
|
return `${negative ? "minus " : ""}${words.join(" ")}`;
|
|
305
406
|
},
|
|
306
|
-
parse: (text) => {
|
|
307
|
-
const
|
|
308
|
-
if (!
|
|
309
|
-
const
|
|
310
|
-
|
|
407
|
+
parse: (text, d) => {
|
|
408
|
+
const constant = constantOf(d);
|
|
409
|
+
if (!constant) return parseFraction(text);
|
|
410
|
+
const spellings = [constant.symbol, ...constant.names ?? []].sort((a, b) => b.length - a.length);
|
|
411
|
+
const token = new RegExp(spellings.map(escape).join("|"), "i");
|
|
412
|
+
if (!token.test(text)) return parseFraction(text);
|
|
413
|
+
const coefficient = text.replace(token, "").replace(/^(\s*[-−+]?\s*)(?=[/⁄]|\s*$)/, "$11");
|
|
414
|
+
return parseFraction(coefficient) * constant.value;
|
|
311
415
|
},
|
|
312
416
|
mathml: (value, d) => {
|
|
313
417
|
if (!Number.isFinite(value)) return void 0;
|
|
314
|
-
const { negative, whole, num, den } = fractionPieces(value, d);
|
|
418
|
+
const { negative, whole, num, den, constant } = fractionPieces(value, d);
|
|
419
|
+
const counted = (n) => {
|
|
420
|
+
if (!constant) return `<mn>${n}</mn>`;
|
|
421
|
+
const mi = `<mi>${constant.symbol}</mi>`;
|
|
422
|
+
return n === 1 ? mi : `<mn>${n}</mn>${mi}`;
|
|
423
|
+
};
|
|
315
424
|
const body = [
|
|
316
425
|
negative ? `<mo>${MINUS_SIGN}</mo>` : "",
|
|
317
|
-
whole > 0
|
|
318
|
-
num > 0 ? `<mfrac
|
|
426
|
+
whole > 0 ? counted(whole) : num === 0 ? "<mn>0</mn>" : "",
|
|
427
|
+
num > 0 ? `<mfrac>${num === 1 || !constant ? counted(num) : `<mrow>${counted(num)}</mrow>`}<mn>${den}</mn></mfrac>` : ""
|
|
319
428
|
].join("");
|
|
320
429
|
return `<math>${body}</math>`;
|
|
321
430
|
}
|
|
@@ -354,7 +463,7 @@ var multiplierKind = {
|
|
|
354
463
|
{ type: "symbol", value: d.symbol ?? "\xD7" }
|
|
355
464
|
],
|
|
356
465
|
speak: (value, d, ctx) => spokenSign(`${numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2 }).value} times`),
|
|
357
|
-
parse: (text) => parseNumber(text.replace(/\s*[x×X]\s*$/, ""))
|
|
466
|
+
parse: (text, _d, ctx) => parseNumber(text.replace(/\s*[x×X]\s*$/, ""), void 0, ctx.locale)
|
|
358
467
|
};
|
|
359
468
|
function zoom() {
|
|
360
469
|
return { kind: "zoom" };
|
|
@@ -386,7 +495,11 @@ var INTL_UNITS = {
|
|
|
386
495
|
m: "meter",
|
|
387
496
|
km: "kilometer",
|
|
388
497
|
in: "inch",
|
|
498
|
+
'"': "inch",
|
|
499
|
+
"\u2033": "inch",
|
|
389
500
|
ft: "foot",
|
|
501
|
+
"'": "foot",
|
|
502
|
+
"\u2032": "foot",
|
|
390
503
|
yd: "yard",
|
|
391
504
|
mi: "mile",
|
|
392
505
|
deg: "degree",
|
|
@@ -436,7 +549,7 @@ var unitKind = {
|
|
|
436
549
|
},
|
|
437
550
|
parse: (text, d, ctx) => {
|
|
438
551
|
const name = d.unit ?? ctx.unit;
|
|
439
|
-
return parseNumber(text, d.accepts ?? (name ? { [name]: 1 } : void 0));
|
|
552
|
+
return parseNumber(text, d.accepts ?? (name ? { [name]: 1 } : void 0), ctx.locale);
|
|
440
553
|
}
|
|
441
554
|
};
|
|
442
555
|
function currency(code, options = {}) {
|
|
@@ -454,7 +567,7 @@ var currencyKind = {
|
|
|
454
567
|
kind: "currency",
|
|
455
568
|
format: (value, d, ctx) => intlParts(value, ctx.locale, currencyOptions(d)),
|
|
456
569
|
speak: (value, d, ctx) => spokenSign(textOf(intlParts(value, ctx.locale, { ...currencyOptions(d), currencyDisplay: "name" }))),
|
|
457
|
-
parse: (text) => parseNumber(text.replace(/[^\d
|
|
570
|
+
parse: (text, _d, ctx) => parseNumber(text.replace(/[^\d.,'’+\-−]/g, ""), void 0, ctx.locale)
|
|
458
571
|
};
|
|
459
572
|
function duration(options = {}) {
|
|
460
573
|
return { kind: "duration", ...options };
|
|
@@ -506,10 +619,12 @@ var durationKind = {
|
|
|
506
619
|
if (s > 0 || terms.length === 0) terms.push(`${s} ${plural(s, ctx.locale, "second", "seconds")}`);
|
|
507
620
|
return `${negative ? "minus " : ""}${terms.join(", ")}`;
|
|
508
621
|
},
|
|
509
|
-
parse: (text) => {
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
const
|
|
622
|
+
parse: (text, _d, ctx) => {
|
|
623
|
+
const d = escapeClass(decimalOf(ctx.locale));
|
|
624
|
+
const clock = new RegExp(String.raw`^\s*([-−+]?)\s*(?:(\d+):)?(\d+):(\d+)(?:[.${d}](\d+))?\s*$`);
|
|
625
|
+
const m = clock.exec(latinDigits(text, ctx.locale));
|
|
626
|
+
if (!m) return parseNumber(text, DURATION_UNITS, ctx.locale);
|
|
627
|
+
const total = Number(m[2] ?? 0) * 3600 + Number(m[3]) * 60 + Number(`${m[4]}.${m[5] ?? 0}`);
|
|
513
628
|
return m[1] === "-" || m[1] === "\u2212" ? -total : total;
|
|
514
629
|
}
|
|
515
630
|
};
|
|
@@ -551,9 +666,9 @@ var bytesKind = {
|
|
|
551
666
|
const { scaled: scaled2, step } = byteScale(value, base);
|
|
552
667
|
const name = (base === 1024 ? BINARY_NAMES : DECIMAL_NAMES)[step];
|
|
553
668
|
const number = numberPart(scaled2, ctx.locale, { maximumFractionDigits: step === 0 ? 0 : d.places ?? 1 }).value;
|
|
554
|
-
return spokenSign(`${number} ${plural(
|
|
669
|
+
return spokenSign(`${number} ${plural(Math.abs(parseNumber(number, void 0, ctx.locale)), ctx.locale, name, `${name}s`)}`);
|
|
555
670
|
},
|
|
556
|
-
parse: (text) => parseNumber(text, BYTE_UNITS)
|
|
671
|
+
parse: (text, _d, ctx) => parseNumber(text, BYTE_UNITS, ctx.locale)
|
|
557
672
|
};
|
|
558
673
|
|
|
559
674
|
// src/kinds/numeral.ts
|
|
@@ -608,9 +723,9 @@ var romanKind = {
|
|
|
608
723
|
return [{ type: "numeral", value: d.lower ? r.toLowerCase() : r }];
|
|
609
724
|
},
|
|
610
725
|
speak: (value, _d, ctx) => spokenSign(numberPart(Math.round(value), ctx.locale, { maximumFractionDigits: 0, useGrouping: false }).value),
|
|
611
|
-
parse: (text) => {
|
|
726
|
+
parse: (text, _d, ctx) => {
|
|
612
727
|
const r = fromRoman(text);
|
|
613
|
-
return Number.isNaN(r) ? parseNumber(text) : r;
|
|
728
|
+
return Number.isNaN(r) ? parseNumber(text, void 0, ctx.locale) : r;
|
|
614
729
|
}
|
|
615
730
|
};
|
|
616
731
|
function ordinal() {
|
|
@@ -626,7 +741,7 @@ var ordinalKind = {
|
|
|
626
741
|
const rule = new Intl.PluralRules("en-US", { type: "ordinal" }).select(n);
|
|
627
742
|
return [number, { type: "ordinal", value: SUFFIXES[rule] ?? "th" }];
|
|
628
743
|
},
|
|
629
|
-
parse: (text) => Math.round(parseNumber(text.replace(/(st|nd|rd|th)\s*$/i, "")))
|
|
744
|
+
parse: (text, _d, ctx) => Math.round(parseNumber(text.replace(/(st|nd|rd|th)\s*$/i, ""), void 0, ctx.locale))
|
|
630
745
|
};
|
|
631
746
|
|
|
632
747
|
// src/present.ts
|
|
@@ -666,12 +781,12 @@ function contextOf(q, options) {
|
|
|
666
781
|
return unit2 === void 0 ? { locale: options?.locale ?? "en-US" } : { locale: options?.locale ?? "en-US", unit: unit2 };
|
|
667
782
|
}
|
|
668
783
|
var ESCAPES = { "&": "&", "<": "<", ">": ">", '"': """ };
|
|
669
|
-
function
|
|
784
|
+
function escape2(s) {
|
|
670
785
|
return s.replace(/[&<>"]/g, (c) => ESCAPES[c]);
|
|
671
786
|
}
|
|
672
787
|
function partsToHtml(value, parts) {
|
|
673
|
-
const body = parts.map((p) => p.type === "literal" ?
|
|
674
|
-
return `<data value="${
|
|
788
|
+
const body = parts.map((p) => p.type === "literal" ? escape2(p.value) : `<span data-part="${escape2(p.type)}">${escape2(p.value)}</span>`).join("");
|
|
789
|
+
return `<data value="${escape2(String(value))}">${body}</data>`;
|
|
675
790
|
}
|
|
676
791
|
function partsOf(q, fallback, options) {
|
|
677
792
|
const display = displayOf(q, fallback) ?? DEFAULT_DISPLAY;
|
|
@@ -698,7 +813,7 @@ function parseAs(text, display, options) {
|
|
|
698
813
|
const kind = displayKindOf(d);
|
|
699
814
|
const ctx = { locale: options?.locale ?? "en-US" };
|
|
700
815
|
if (options?.unit !== void 0) ctx.unit = options.unit;
|
|
701
|
-
return kind.parse ? kind.parse(text, d, ctx) : parseNumber(text);
|
|
816
|
+
return kind.parse ? kind.parse(text, d, ctx) : parseNumber(text, void 0, ctx.locale);
|
|
702
817
|
}
|
|
703
818
|
var QuantityView = class _QuantityView {
|
|
704
819
|
constructor(raw, fallback, options) {
|
|
@@ -760,6 +875,6 @@ function qty(q, fallback, options) {
|
|
|
760
875
|
return new QuantityView(q, fallback, options);
|
|
761
876
|
}
|
|
762
877
|
|
|
763
|
-
export { ANGLE_RADIANS, IMPERIAL_INCHES, METRIC_MM, MINUS_SIGN, PIXELS, QuantityView, amount, bytes, bytesKind, compact, compactKind, currency, currencyKind, decimal, decimalKind, displayKindOf, displayOf, duration, durationKind, entryScale, formatCompact, formatNumber, formatUnit, fraction, fractionKind, fromRoman, integer, integerKind, intlParts, multiplier, multiplierKind, nearestFraction, numberPart, ordinal, ordinalKind, parseAs, parseNumber, parseSignedNumber, partsOf, partsToHtml, percent, percentKind, plural, present, qty, ratio, ratioKind, registerDisplayKind, resolveUnit, retag, roman, romanKind, signed, spokenSign, tag, textOf, toRoman, unit, unitKind, unitOf, unitScale, zoom, zoomKind };
|
|
878
|
+
export { ANGLE_RADIANS, CONSTANTS, IMPERIAL_INCHES, METRIC_MM, MINUS_SIGN, PIXELS, QuantityView, amount, bytes, bytesKind, compact, compactKind, currency, currencyKind, decimal, decimalKind, displayKindOf, displayOf, duration, durationKind, entryScale, formatCompact, formatNumber, formatUnit, fraction, fractionKind, fromRoman, integer, integerKind, intlParts, multiplier, multiplierKind, nearestFraction, numberPart, ordinal, ordinalKind, parseAs, parseNumber, parseSignedNumber, partsOf, partsToHtml, percent, percentKind, plural, present, qty, ratio, ratioKind, registerDisplayKind, resolveUnit, retag, roman, romanKind, signed, spokenSign, tag, textOf, toRoman, unit, unitKind, unitOf, unitScale, zoom, zoomKind };
|
|
764
879
|
//# sourceMappingURL=index.js.map
|
|
765
880
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/quantity.ts","../src/units.ts","../src/number.ts","../src/kind.ts","../src/kinds/plain.ts","../src/kinds/proportion.ts","../src/kinds/measure.ts","../src/kinds/numeral.ts","../src/present.ts"],"names":["unit","scaled"],"mappings":"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","file":"index.js","sourcesContent":["import type { Unit } from './units';\n\n/**\n * How a number shows, speaks and reads back, as plain data: `{ kind: 'fraction',\n * maxDenominator: 64 }`. Data rather than a function so a tagged value keeps its\n * presentation through JSON, history snapshots and `structuredClone`. The\n * behavior lives on the registered {@link DisplayKind} of the same `kind`.\n */\nexport interface Display {\n readonly kind: string;\n readonly [option: string]: unknown;\n}\n\n/** A number that carries its unit, its display, or both. */\nexport interface Tagged {\n value: number;\n /** The unit `value` is measured in. Absent is the base unit. */\n unit?: Unit;\n display?: Display;\n}\n\n/**\n * A number anywhere the engine takes one: bare, which costs nothing, or\n * {@link Tagged}, which keeps its unit and display as it moves. Every reader\n * goes through {@link amount}, and every writer through {@link retag}, so a\n * value leaves in the shape it arrived in.\n */\nexport type Quantity = number | Tagged;\n\n/** The number a quantity holds. */\nexport function amount(q: Quantity): number {\n return typeof q === 'number' ? q : q.value;\n}\n\n/**\n * `next` in the shape of `q`: a bare number stays bare, and a tagged one keeps\n * its unit and display. What an editor calls when it changes a value it was\n * handed, so the presentation survives the edit.\n */\nexport function retag<Q extends Quantity>(q: Q, next: number): Q {\n return (typeof q === 'number' ? next : { ...(q as Tagged), value: next }) as Q;\n}\n\n/** A tagged quantity. `display` and `unit` are left off when absent, so the\n * JSON carries only what was set. */\nexport function tag(value: number, display?: Display, unit?: Unit): Tagged {\n const t: Tagged = { value };\n if (unit !== undefined) t.unit = unit;\n if (display !== undefined) t.display = display;\n return t;\n}\n\n/** The display `q` carries, else `fallback`. A value's own tag wins over the\n * default of whatever shows it. */\nexport function displayOf(q: Quantity, fallback?: Display): Display | undefined {\n return (typeof q === 'number' ? undefined : q.display) ?? fallback;\n}\n\n/** The unit `q` is measured in, when it says. */\nexport function unitOf(q: Quantity): Unit | undefined {\n return typeof q === 'number' ? undefined : q.unit;\n}\n","import type { Quantity } from './quantity';\n\n/**\n * Units — a tiny customizable unit system.\n *\n * The kit stores all coordinates as bare numbers in a single base unit\n * chosen by the consumer app. To make API call sites self-documenting,\n * the public surface accepts `UnitValue` — either a bare number (interpreted\n * as base units) or a `{ value, unit }` tag that's resolved against a\n * `UnitSystem` at the API boundary. Internals never see units.\n *\n * An entry is affine — `base = value * factor + offset` — so a scale that\n * puts zero somewhere else (degC against K) is expressible. No per-axis\n * units. No mixed-unit arithmetic.\n */\n\n/** A unit name (e.g. `'in'`, `'ft'`, `'mm'`). Looked up in a `UnitSystem`. */\nexport type Unit = string;\n\n/** What one unit is worth in base units: `base = value * factor + offset`. */\nexport interface UnitScale {\n factor: number;\n /** Where this unit puts zero, in base units. Absent is 0 — a pure scale. */\n offset?: number;\n}\n\n/** One unit's conversion. A bare number is the `{ factor }` shorthand. */\nexport type UnitEntry = number | UnitScale;\n\n/** Conversion table mapping unit names to their scale against a base unit. */\nexport interface UnitSystem {\n /** Name of the base unit, e.g. 'in'. All conversions resolve to this. */\n base: Unit;\n /** How to reach base units from each unit. The base unit's entry is 1. */\n units: Record<Unit, UnitEntry>;\n}\n\n/**\n * One unit's scale, with the bare-number shorthand widened and the offset\n * defaulted — what every conversion in the kit reads. Throws if the system\n * does not carry the unit.\n */\nexport function unitScale(unitSystem: UnitSystem, unit: Unit): Required<UnitScale> {\n const entry = unitSystem.units[unit];\n if (entry === undefined) {\n const known = Object.keys(unitSystem.units).join(', ') || '(none)';\n throw new Error(\n `unknown unit '${unit}' (system base: '${unitSystem.base}', known units: ${known})`,\n );\n }\n return entryScale(entry);\n}\n\n/** An entry's scale, with the bare-number shorthand widened and the offset defaulted. */\nexport function entryScale(entry: UnitEntry): Required<UnitScale> {\n return typeof entry === 'number'\n ? { factor: entry, offset: 0 }\n : { factor: entry.factor, offset: entry.offset ?? 0 };\n}\n\n/** Value at a unit-aware API boundary: bare number (in base units) or `{ value, unit }` tag. */\nexport type UnitValue = number | { value: number; unit: Unit };\n\n/**\n * Resolve a UnitValue to a number in base units.\n * - bare number, or a quantity tagged with no unit: its value, as base\n * - tagged: looks up factor; throws if unit not in unit system\n */\nexport function resolveUnit(v: UnitValue | Quantity, unitSystem?: UnitSystem): number {\n if (typeof v === 'number') return v;\n if (v.unit === undefined) return v.value;\n if (!unitSystem) {\n throw new Error(\n `resolveUnit: tagged value { value: ${v.value}, unit: '${v.unit}' } requires a UnitSystem`,\n );\n }\n const { factor, offset } = scaleOrThrow('resolveUnit', unitSystem, v.unit);\n return v.value * factor + offset;\n}\n\n/**\n * Format a base-unit number as a string in the named display unit.\n * e.g. formatUnit(36, 'ft', IMPERIAL_INCHES) => '3ft'\n * Default precision: 2. Trailing zeros trimmed.\n */\nexport function formatUnit(\n baseValue: number,\n displayUnit: Unit,\n unitSystem: UnitSystem,\n opts?: { precision?: number; suffix?: boolean },\n): string {\n const { factor, offset } = scaleOrThrow('formatUnit', unitSystem, displayUnit);\n const precision = opts?.precision ?? 2;\n const suffix = opts?.suffix ?? true;\n const display = (baseValue - offset) / factor;\n // Trim trailing zeros (and a dangling decimal point) without losing precision.\n let s = display.toFixed(precision);\n if (s.includes('.')) {\n s = s.replace(/0+$/, '').replace(/\\.$/, '');\n }\n return suffix ? `${s}${displayUnit}` : s;\n}\n\n/** `unitScale`, with the caller's name in front of the message. */\nfunction scaleOrThrow(caller: string, unitSystem: UnitSystem, unit: Unit): Required<UnitScale> {\n try {\n return unitScale(unitSystem, unit);\n } catch (e) {\n throw new Error(`${caller}: ${e instanceof Error ? e.message : String(e)}`);\n }\n}\n\n/** Imperial unit system with base 'in'. */\nexport const IMPERIAL_INCHES: UnitSystem = {\n base: 'in',\n units: { in: 1, ft: 12, yd: 36, mi: 63360 },\n};\n\n/** Metric unit system with base 'mm'. */\nexport const METRIC_MM: UnitSystem = {\n base: 'mm',\n units: { mm: 1, cm: 10, m: 1000, km: 1_000_000 },\n};\n\n/** Angle unit system with base 'rad'. */\nexport const ANGLE_RADIANS: UnitSystem = {\n base: 'rad',\n units: { rad: 1, deg: Math.PI / 180, turn: Math.PI * 2 },\n};\n\n/** Pixel unit system — sole unit is the base. */\nexport const PIXELS: UnitSystem = {\n base: 'px',\n units: { px: 1 },\n};\n","import { entryScale, type UnitEntry } from './units';\n\n/**\n * Display-formatter for numbers. Use this anywhere a number is shown to\n * a user. The whole point: negative values get prefixed with the real\n * MINUS SIGN (U+2212) instead of the ASCII HYPHEN-MINUS (U+002D) that\n * `toLocaleString` and template literals produce by default.\n *\n * U+2212 is the same visual width as `+` and reads as a sign rather\n * than a hyphen — columns of signed numbers align cleanly and the\n * glyph doesn't get confused with a bullet or list dash.\n */\nexport const MINUS_SIGN = '−';\n\n/**\n * Formats a number for display, substituting {@link MINUS_SIGN} for the ASCII\n * hyphen `toLocaleString` emits. Non-finite values stringify as-is.\n */\nexport function formatNumber(value: number, options?: Intl.NumberFormatOptions): string {\n const formatted = Number.isFinite(value)\n ? value.toLocaleString(undefined, options)\n : String(value);\n return formatted.replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Parses a string that may carry {@link MINUS_SIGN} in place of the ASCII\n * hyphen. The inverse of {@link formatNumber} for any editing surface that\n * renders its value through it and reads the edited text back.\n */\nexport function parseSignedNumber(text: string): number {\n return Number(text.replace(MINUS_SIGN, '-'));\n}\n\n/** Powers of ten a typed magnitude suffix stands for. */\nconst EXPONENTS: Record<string, number> = { k: 3, m: 6, b: 9, t: 12 };\n\n/**\n * Formats a number the way a `compact` readout shows it: below 1,000 at\n * `decimals` places, from 1,000 up at three significant figures with a magnitude\n * suffix (`40.0K`, `294K`, `2.00M`), so the readout holds one width whatever the\n * value. Always `en-US`, so {@link parseNumber} reads it back.\n */\nexport function formatCompact(value: number, decimals = 0): string {\n if (!Number.isFinite(value)) return formatNumber(value);\n const options: Intl.NumberFormatOptions =\n Math.abs(value) < 1000\n ? { useGrouping: false, minimumFractionDigits: decimals, maximumFractionDigits: decimals }\n : { notation: 'compact', minimumSignificantDigits: 3, maximumSignificantDigits: 3 };\n return value.toLocaleString('en-US', options).replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Reads a typed number: anything {@link parseSignedNumber} reads, plus\n * thousands commas in the `40,000` shape and a `k`/`m`/`b`/`t` suffix in either\n * case (`2.5m` is 2,500,000). Empty text is NaN rather than zero.\n *\n * Given `units` — a suffix mapped to the factor it scales by — a trailing unit\n * name is read first: the longest match wins, exact case before any case, and\n * a unit beats a magnitude suffix, so with `m` accepted `2m` is `2 * units.m`.\n */\nexport function parseNumber(text: string, units?: Readonly<UnitTable>): number {\n if (units) {\n const trimmed = text.trim();\n const name = unitSuffixOf(trimmed, units);\n if (name !== undefined) {\n const terms = compoundTermsOf(trimmed, units);\n if (terms !== undefined && terms.length > 1) return compoundValue(terms, trimmed, units);\n const { factor, offset } = entryScale(units[name]!);\n return scaled(parseNumber(trimmed.slice(0, -name.length)), factor) + offset;\n }\n }\n let t = text.trim().replace(MINUS_SIGN, '-');\n const exponent = EXPONENTS[t.slice(-1).toLowerCase()];\n if (exponent !== undefined) t = t.slice(0, -1).trimEnd();\n if (/^[-+]?\\d{1,3}(,\\d{3})+(\\.\\d*)?$/.test(t)) t = t.replace(/,/g, '');\n if (!/\\d/.test(t)) return Number.NaN;\n // Scaled through the exponent rather than by multiplying: 1.1 * 1000 is 1100.0000000000002.\n return Number(exponent === undefined ? t : `${t}e${exponent}`);\n}\n\n/** Suffixes a person may type, each mapped to its conversion into the shown unit. */\nexport type UnitTable = Record<string, UnitEntry>;\n\n/** Divided by the reciprocal below 1: 12 * 0.1 is 1.2000000000000002, 12 / 10 is 1.2. */\nfunction scaled(n: number, factor: number): number {\n return factor < 1 ? n / (1 / factor) : n * factor;\n}\n\n/**\n * The unit names in `text`, in reading order, when every one of them closes a\n * `<number><unit>` term — which is what tells `5ft 3in` from a malformed\n * `5ft 3`. Undefined when the text is not a run of whole terms.\n */\nfunction compoundTermsOf(text: string, units: Readonly<UnitTable>): string[] | undefined {\n const names: string[] = [];\n let rest = text.trimEnd();\n while (rest !== '') {\n const name = unitSuffixOf(rest, units);\n if (name === undefined) return undefined;\n names.push(name);\n const before = rest.slice(0, -name.length);\n const m = /(\\d+(?:\\.\\d+)?|\\.\\d+)\\s*$/.exec(before);\n if (!m) return undefined;\n rest = before.slice(0, m.index).trimEnd();\n // A sign leads the whole value, so it ends the walk rather than a term.\n if (rest === '-' || rest === '+' || rest === MINUS_SIGN) rest = '';\n }\n return names.length === 0 ? undefined : names.reverse();\n}\n\n/**\n * `5ft 3in` as one number in the shown unit. Every term scales and they sum;\n * a leading sign carries across all of them, so `-5ft 3in` is −63in and not\n * −57. Offsets have no meaning in a sum — 1K + 2degC is not a temperature —\n * so a term carrying one makes the whole value unreadable.\n */\nfunction compoundValue(names: string[], text: string, units: Readonly<UnitTable>): number {\n const digits = text.match(/\\d+(?:\\.\\d+)?|\\.\\d+/g);\n if (!digits || digits.length !== names.length) return Number.NaN;\n const sign = /^\\s*[-\\u2212]/.test(text) ? -1 : 1;\n let total = 0;\n for (const [i, name] of names.entries()) {\n const { factor, offset } = entryScale(units[name]!);\n if (offset !== 0) return Number.NaN;\n total += scaled(Number(digits[i]), factor);\n }\n return sign * total;\n}\n\n/** The longest unit name `text` ends with — exact case first, then any case. */\nfunction unitSuffixOf(text: string, units: Readonly<UnitTable>): string | undefined {\n const names = Object.keys(units).filter((n) => n !== '').sort((a, b) => b.length - a.length);\n const lower = text.toLowerCase();\n return names.find((n) => text.endsWith(n)) ?? names.find((n) => lower.endsWith(n.toLowerCase()));\n}\n","import type { Display } from './quantity';\nimport type { Unit } from './units';\nimport { MINUS_SIGN } from './number';\n\n/**\n * One run of a formatted value, named for what it is: `number`, `unit`,\n * `currency`, `numerator`, `literal`. The HTML serialization marks each\n * non-literal run with `data-part`, which is the whole styling surface.\n */\nexport interface Part {\n type: string;\n value: string;\n}\n\n/** What formatting and parsing need beyond the value and its display. */\nexport interface FormatContext {\n /** BCP 47 locale. Every kind parses `en-US` text, so it is the default. */\n locale: string;\n /** The unit the value is measured in, from its tag. */\n unit?: Unit;\n}\n\n/**\n * The behavior behind one `Display.kind`. `format` is required; `speak`\n * defaults to the formatted text, `parse` to `parseNumber`, and `mathml` to\n * nothing, which means the kind has no MathML form.\n */\nexport interface DisplayKind<D extends Display = Display> {\n kind: D['kind'];\n format(value: number, display: D, ctx: FormatContext): Part[];\n speak?(value: number, display: D, ctx: FormatContext): string;\n parse?(text: string, display: D, ctx: FormatContext): number;\n mathml?(value: number, display: D, ctx: FormatContext): string | undefined;\n}\n\n/** Parts joined into plain text. */\nexport function textOf(parts: readonly Part[]): string {\n return parts.map((p) => p.value).join('');\n}\n\n/** A number run from `Intl`, with the real minus sign. */\nexport function numberPart(value: number, locale: string, options?: Intl.NumberFormatOptions): Part {\n return { type: 'number', value: signed(value.toLocaleString(locale, options)) };\n}\n\n/** `-` swapped for {@link MINUS_SIGN} at the front of already-formatted text. */\nexport function signed(text: string): string {\n return text.replace(/^-/, MINUS_SIGN);\n}\n\n/** A leading minus sign read aloud: `−3` is spoken `minus 3`, which a screen\n * reader otherwise renders as a dash or drops. */\nexport function spokenSign(text: string): string {\n return text.replace(/^[-−]/, 'minus ');\n}\n\n/** `singular` or `plural` for `value`, by the locale's plural rules. */\nexport function plural(value: number, locale: string, singular: string, pluralForm: string): string {\n return new Intl.PluralRules(locale).select(value) === 'one' ? singular : pluralForm;\n}\n\n/**\n * `Intl.NumberFormat`'s parts, with the digit runs — sign, integer, group,\n * decimal, fraction — merged into one `number` part, so a styling layer sees\n * the number as one thing and its unit or symbol as another.\n */\nexport function intlParts(value: number, locale: string, options: Intl.NumberFormatOptions): Part[] {\n const out: Part[] = [];\n for (const p of new Intl.NumberFormat(locale, options).formatToParts(value)) {\n const type = DIGIT_RUNS.has(p.type) ? 'number' : p.type;\n const v = p.type === 'minusSign' ? MINUS_SIGN : p.value;\n const last = out[out.length - 1];\n if (type === 'number' && last?.type === 'number') last.value += v;\n else out.push({ type, value: v });\n }\n return out;\n}\n\nconst DIGIT_RUNS = new Set(['minusSign', 'plusSign', 'integer', 'group', 'decimal', 'fraction']);\n","import { intlParts, spokenSign, textOf, type DisplayKind } from '../kind';\nimport { formatCompact, parseNumber } from '../number';\n\n/** A plain number. `places` fixes the decimals, trailing zeros included;\n * otherwise up to `maxPlaces` (default 3) show and trailing zeros drop. */\nexport type DecimalDisplay = {\n kind: 'decimal';\n places?: number;\n maxPlaces?: number;\n /** Thousands separators. Default true. */\n grouping?: boolean;\n};\n\nexport function decimal(options: Omit<DecimalDisplay, 'kind'> = {}): DecimalDisplay {\n return { kind: 'decimal', ...options };\n}\n\nexport const decimalKind: DisplayKind<DecimalDisplay> = {\n kind: 'decimal',\n format: (value, d, ctx) => intlParts(value, ctx.locale, decimalOptions(d)),\n speak: (value, d, ctx) => spokenSign(textOf(intlParts(value, ctx.locale, decimalOptions(d)))),\n parse: (text) => parseNumber(text),\n};\n\nfunction decimalOptions(d: DecimalDisplay): Intl.NumberFormatOptions {\n const grouping = d.grouping ?? true;\n return d.places === undefined\n ? { maximumFractionDigits: d.maxPlaces ?? 3, useGrouping: grouping }\n : { minimumFractionDigits: d.places, maximumFractionDigits: d.places, useGrouping: grouping };\n}\n\n/** A whole number, rounded. */\nexport type IntegerDisplay = {\n kind: 'integer';\n grouping?: boolean;\n};\n\nexport function integer(options: Omit<IntegerDisplay, 'kind'> = {}): IntegerDisplay {\n return { kind: 'integer', ...options };\n}\n\nexport const integerKind: DisplayKind<IntegerDisplay> = {\n kind: 'integer',\n format: (value, d, ctx) =>\n intlParts(value, ctx.locale, { maximumFractionDigits: 0, useGrouping: d.grouping ?? true }),\n speak: (value, d, ctx) =>\n spokenSign(textOf(integerKind.format(value, d, ctx))),\n parse: (text) => Math.round(parseNumber(text)),\n};\n\n/**\n * Below 1,000 at `places` decimals, from 1,000 up at three significant figures\n * with a magnitude suffix (`40.0K`, `2.00M`), so a readout holds one width.\n * Spoken long: `2 million`.\n */\nexport type CompactDisplay = {\n kind: 'compact';\n places?: number;\n};\n\nexport function compact(options: Omit<CompactDisplay, 'kind'> = {}): CompactDisplay {\n return { kind: 'compact', ...options };\n}\n\nexport const compactKind: DisplayKind<CompactDisplay> = {\n kind: 'compact',\n format: (value, d) => {\n const text = formatCompact(value, d.places ?? 0);\n const m = /^(.*?\\d)([A-Za-z]+)$/.exec(text);\n return m\n ? [\n { type: 'number', value: m[1]! },\n { type: 'compact', value: m[2]! },\n ]\n : [{ type: 'number', value: text }];\n },\n speak: (value, d, ctx) =>\n spokenSign(\n textOf(\n Math.abs(value) < 1000\n ? compactKind.format(value, d, ctx)\n : intlParts(value, ctx.locale, {\n notation: 'compact',\n compactDisplay: 'long',\n maximumSignificantDigits: 3,\n }),\n ),\n ),\n parse: (text) => parseNumber(text),\n};\n","import { intlParts, numberPart, spokenSign, textOf, type DisplayKind, type Part } from '../kind';\nimport { MINUS_SIGN, parseNumber } from '../number';\n\n/** A share of one as a percentage: 0.25 shows `25%`. Typed text reads as\n * percent with or without the sign. */\nexport type PercentDisplay = {\n kind: 'percent';\n /** Most decimals shown. Default 0. */\n places?: number;\n};\n\nexport function percent(options: Omit<PercentDisplay, 'kind'> = {}): PercentDisplay {\n return { kind: 'percent', ...options };\n}\n\nexport const percentKind: DisplayKind<PercentDisplay> = {\n kind: 'percent',\n format: (value, d, ctx) =>\n intlParts(value, ctx.locale, { style: 'percent', maximumFractionDigits: d.places ?? 0 }),\n speak: (value, d, ctx) =>\n spokenSign(\n textOf(\n intlParts(value * 100, ctx.locale, {\n style: 'unit',\n unit: 'percent',\n unitDisplay: 'long',\n maximumFractionDigits: d.places ?? 0,\n }),\n ),\n ),\n parse: (text) => parseNumber(text.replace(/%\\s*$/, '')) / 100,\n};\n\n/**\n * The nearest fraction whose denominator is at most `maxDenominator`, as\n * `[numerator, denominator]` in lowest terms with the sign on the numerator.\n * Walks the continued fraction and settles the last step on the best\n * semiconvergent, which is the closest any denominator in range can get.\n */\nexport function nearestFraction(x: number, maxDenominator: number): [number, number] {\n if (!Number.isFinite(x)) return [x, 1];\n const sign = x < 0 ? -1 : 1;\n const target = Math.abs(x);\n let [h0, h1, k0, k1] = [0, 1, 1, 0];\n let y = target;\n for (let i = 0; i < 64; i++) {\n const a = Math.floor(y);\n const k2 = a * k1 + k0;\n if (k2 > maxDenominator) {\n const t = Math.floor((maxDenominator - k0) / k1);\n const [hs, ks] = [t * h1 + h0, t * k1 + k0];\n if (Math.abs(hs / ks - target) < Math.abs(h1 / k1 - target)) [h1, k1] = [hs, ks];\n break;\n }\n [h0, h1, k0, k1] = [h1, a * h1 + h0, k1, k2];\n const rest = y - a;\n if (rest < 1e-12 || Math.abs(h1 / k1 - target) < 1e-15) break;\n y = 1 / rest;\n }\n return [sign * h1, k1];\n}\n\n/**\n * A value as the nearest fraction: 1/12 shows `1/12` and is spoken `1 over 12`.\n * `mixed` splits a whole part off (`1 1/2`); a whole value shows as an integer.\n * Has a MathML form, as `<mfrac>`.\n */\nexport type FractionDisplay = {\n kind: 'fraction';\n /** Default 64. */\n maxDenominator?: number;\n mixed?: boolean;\n};\n\nexport function fraction(options: Omit<FractionDisplay, 'kind'> = {}): FractionDisplay {\n return { kind: 'fraction', ...options };\n}\n\n/** A fraction's pieces: sign, whole part (mixed only), numerator, denominator. */\nfunction fractionPieces(value: number, d: FractionDisplay) {\n const [n, den] = nearestFraction(value, d.maxDenominator ?? 64);\n const negative = n < 0;\n const abs = Math.abs(n);\n const whole = d.mixed || den === 1 ? Math.floor(abs / den) : 0;\n return { negative, whole, num: abs - whole * den, den };\n}\n\nexport const fractionKind: DisplayKind<FractionDisplay> = {\n kind: 'fraction',\n format: (value, d) => {\n if (!Number.isFinite(value)) return [{ type: 'number', value: String(value) }];\n const { negative, whole, num, den } = fractionPieces(value, d);\n const parts: Part[] = [];\n if (negative) parts.push({ type: 'sign', value: MINUS_SIGN });\n if (whole > 0 || num === 0) parts.push({ type: 'whole', value: String(whole) });\n if (num > 0) {\n if (whole > 0) parts.push({ type: 'literal', value: ' ' });\n parts.push(\n { type: 'numerator', value: String(num) },\n { type: 'literal', value: '/' },\n { type: 'denominator', value: String(den) },\n );\n }\n return parts;\n },\n speak: (value, d) => {\n if (!Number.isFinite(value)) return String(value);\n const { negative, whole, num, den } = fractionPieces(value, d);\n const words = [\n whole > 0 || num === 0 ? String(whole) : '',\n whole > 0 && num > 0 ? 'and' : '',\n num > 0 ? `${num} over ${den}` : '',\n ].filter(Boolean);\n return `${negative ? 'minus ' : ''}${words.join(' ')}`;\n },\n parse: (text) => {\n const m = /^\\s*([-−+]?)\\s*(?:(\\d+)\\s+)?(\\d+)\\s*[/⁄]\\s*(\\d+)\\s*$/.exec(text);\n if (!m) return parseNumber(text);\n const magnitude = Number(m[2] ?? 0) + Number(m[3]) / Number(m[4]);\n return m[1] === '-' || m[1] === MINUS_SIGN ? -magnitude : magnitude;\n },\n mathml: (value, d) => {\n if (!Number.isFinite(value)) return undefined;\n const { negative, whole, num, den } = fractionPieces(value, d);\n const body = [\n negative ? `<mo>${MINUS_SIGN}</mo>` : '',\n whole > 0 || num === 0 ? `<mn>${whole}</mn>` : '',\n num > 0 ? `<mfrac><mn>${num}</mn><mn>${den}</mn></mfrac>` : '',\n ].join('');\n return `<math>${body}</math>`;\n },\n};\n\n/** A value as a ratio `a:b` — 1/12 shows `1:12`, spoken `1 to 12`. */\nexport type RatioDisplay = {\n kind: 'ratio';\n /** Largest second term. Default 64. */\n maxDenominator?: number;\n};\n\nexport function ratio(options: Omit<RatioDisplay, 'kind'> = {}): RatioDisplay {\n return { kind: 'ratio', ...options };\n}\n\nexport const ratioKind: DisplayKind<RatioDisplay> = {\n kind: 'ratio',\n format: (value, d) => {\n if (!Number.isFinite(value)) return [{ type: 'number', value: String(value) }];\n const [n, den] = nearestFraction(value, d.maxDenominator ?? 64);\n return [\n { type: 'antecedent', value: String(n).replace(/^-/, MINUS_SIGN) },\n { type: 'literal', value: ':' },\n { type: 'consequent', value: String(den) },\n ];\n },\n speak: (value, d) => {\n if (!Number.isFinite(value)) return String(value);\n const [n, den] = nearestFraction(value, d.maxDenominator ?? 64);\n return spokenSign(`${String(n).replace(/^-/, MINUS_SIGN)} to ${den}`);\n },\n parse: (text) => {\n const m = /^\\s*(.+?)\\s*:\\s*(.+?)\\s*$/.exec(text);\n return m ? parseNumber(m[1]!) / parseNumber(m[2]!) : parseNumber(text);\n },\n};\n\n/** A factor with a times sign: `2.5×`, spoken `2.5 times`. Typed `x` reads too. */\nexport type MultiplierDisplay = {\n kind: 'multiplier';\n /** Most decimals. Default 2. */\n places?: number;\n /** Default `×`. */\n symbol?: string;\n};\n\nexport function multiplier(options: Omit<MultiplierDisplay, 'kind'> = {}): MultiplierDisplay {\n return { kind: 'multiplier', ...options };\n}\n\nexport const multiplierKind: DisplayKind<MultiplierDisplay> = {\n kind: 'multiplier',\n format: (value, d, ctx) => [\n numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2 }),\n { type: 'symbol', value: d.symbol ?? '×' },\n ],\n speak: (value, d, ctx) =>\n spokenSign(`${numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2 }).value} times`),\n parse: (text) => parseNumber(text.replace(/\\s*[x×X]\\s*$/, '')),\n};\n\n/**\n * A zoom factor. At 2x and below a percentage reads naturally; past it a\n * multiplier is what people say, so 2.5 shows `2.5x`. Past 100x a tenth is\n * noise: `1009.74` shows `1,010x`. Typed text without a sign reads as percent.\n */\nexport type ZoomDisplay = {\n kind: 'zoom';\n};\n\nexport function zoom(): ZoomDisplay {\n return { kind: 'zoom' };\n}\n\nfunction zoomParts(z: number): Part[] {\n if (!Number.isFinite(z)) return [{ type: 'number', value: String(z) }];\n const n = (v: number, grouping = false) =>\n ({ type: 'number', value: v.toLocaleString('en-US', { useGrouping: grouping, maximumFractionDigits: 1 }).replace(/^-/, MINUS_SIGN) });\n if (z <= 2) return [n(Math.round(z * 100)), { type: 'percentSign', value: '%' }];\n if (z >= 100) return [n(Math.round(z), true), { type: 'symbol', value: 'x' }];\n return [n(Math.round(z * 10) / 10), { type: 'symbol', value: 'x' }];\n}\n\nexport const zoomKind: DisplayKind<ZoomDisplay> = {\n kind: 'zoom',\n format: (value) => zoomParts(value),\n speak: (value) =>\n spokenSign(\n zoomParts(value)\n .map((p) => (p.type === 'percentSign' ? ' percent' : p.type === 'symbol' ? ' times' : p.value))\n .join(''),\n ),\n parse: (text) => {\n const t = text.trim();\n if (/[x×X]$/.test(t)) return parseNumber(t.slice(0, -1));\n return parseNumber(t.replace(/%$/, '')) / 100;\n },\n};\n","import { intlParts, numberPart, plural, spokenSign, textOf, type DisplayKind, type Part } from '../kind';\nimport { parseNumber, type UnitTable } from '../number';\n\n/**\n * Units `Intl` can name aloud, by the symbol a field shows. A unit outside it\n * speaks through the display's `spoken` names, else as its symbol.\n */\nconst INTL_UNITS: Record<string, string> = {\n mm: 'millimeter',\n cm: 'centimeter',\n m: 'meter',\n km: 'kilometer',\n in: 'inch',\n ft: 'foot',\n yd: 'yard',\n mi: 'mile',\n deg: 'degree',\n '°': 'degree',\n ms: 'millisecond',\n s: 'second',\n min: 'minute',\n h: 'hour',\n g: 'gram',\n kg: 'kilogram',\n L: 'liter',\n '%': 'percent',\n};\n\n/** Names for common units `Intl` has none for. */\nconst OWN_UNITS: Record<string, readonly [string, string]> = {\n px: ['pixel', 'pixels'],\n pt: ['point', 'points'],\n rad: ['radian', 'radians'],\n turn: ['turn', 'turns'],\n};\n\n/**\n * A number with its unit: `12mm`, spoken `12 millimeters`. The unit is the\n * display's, else the one the value is tagged with. `accepts` is what a person\n * may type, each unit mapped to its conversion into the shown one; compound\n * text such as `5ft 3in` reads when every term's unit is accepted.\n */\nexport type UnitDisplay = {\n kind: 'unit';\n unit?: string;\n /** Most decimals, trailing zeros dropped. Default 2. */\n places?: number;\n /** A space between number and unit. Default false. */\n space?: boolean;\n accepts?: UnitTable;\n /** Singular and plural names, for a unit `Intl` cannot name. */\n spoken?: readonly [string, string];\n};\n\nexport function unit(name?: string, options: Omit<UnitDisplay, 'kind' | 'unit'> = {}): UnitDisplay {\n return name === undefined ? { kind: 'unit', ...options } : { kind: 'unit', unit: name, ...options };\n}\n\nexport const unitKind: DisplayKind<UnitDisplay> = {\n kind: 'unit',\n format: (value, d, ctx) => {\n const parts: Part[] = [numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2, useGrouping: false })];\n const name = d.unit ?? ctx.unit;\n if (name) {\n if (d.space) parts.push({ type: 'literal', value: ' ' });\n parts.push({ type: 'unit', value: name });\n }\n return parts;\n },\n speak: (value, d, ctx) => {\n const places = d.places ?? 2;\n const name = d.unit ?? ctx.unit;\n const intl = name === undefined ? undefined : INTL_UNITS[name];\n if (intl !== undefined && d.spoken === undefined) {\n return spokenSign(\n textOf(intlParts(value, ctx.locale, { style: 'unit', unit: intl, unitDisplay: 'long', maximumFractionDigits: places })),\n );\n }\n const number = numberPart(value, ctx.locale, { maximumFractionDigits: places, useGrouping: false }).value;\n const names = d.spoken ?? (name === undefined ? undefined : OWN_UNITS[name]);\n const word = names ? plural(value, ctx.locale, names[0], names[1]) : name;\n return spokenSign(word ? `${number} ${word}` : number);\n },\n parse: (text, d, ctx) => {\n const name = d.unit ?? ctx.unit;\n return parseNumber(text, d.accepts ?? (name ? { [name]: 1 } : undefined));\n },\n};\n\n/** Money in an ISO 4217 currency: `$12.50`, spoken `12.50 US dollars`. */\nexport type CurrencyDisplay = {\n kind: 'currency';\n currency: string;\n /** Fixed decimals. Defaults to the currency's own (2 for USD, 0 for JPY). */\n places?: number;\n};\n\nexport function currency(code: string, options: Omit<CurrencyDisplay, 'kind' | 'currency'> = {}): CurrencyDisplay {\n return { kind: 'currency', currency: code, ...options };\n}\n\nfunction currencyOptions(d: CurrencyDisplay): Intl.NumberFormatOptions {\n const options: Intl.NumberFormatOptions = { style: 'currency', currency: d.currency };\n if (d.places !== undefined) {\n options.minimumFractionDigits = d.places;\n options.maximumFractionDigits = d.places;\n }\n return options;\n}\n\nexport const currencyKind: DisplayKind<CurrencyDisplay> = {\n kind: 'currency',\n format: (value, d, ctx) => intlParts(value, ctx.locale, currencyOptions(d)),\n speak: (value, d, ctx) =>\n spokenSign(textOf(intlParts(value, ctx.locale, { ...currencyOptions(d), currencyDisplay: 'name' }))),\n parse: (text) => parseNumber(text.replace(/[^\\d.,+\\-−]/g, '')),\n};\n\n/**\n * A span of time, the value in seconds. `clock` shows `1:02:03` or `4:05.5`;\n * `units` shows `2h 5m 3s`. Spoken `2 hours, 5 minutes, 3 seconds`. Typed text\n * reads in either form.\n */\nexport type DurationDisplay = {\n kind: 'duration';\n /** Default `'clock'`. */\n style?: 'clock' | 'units';\n /** Decimals on the seconds. Default 0. */\n places?: number;\n};\n\nexport function duration(options: Omit<DurationDisplay, 'kind'> = {}): DurationDisplay {\n return { kind: 'duration', ...options };\n}\n\n/** Hours, minutes and seconds of `value` after rounding to `places`. */\nfunction hms(value: number, places: number) {\n const scale = 10 ** places;\n const total = Math.round(Math.abs(value) * scale) / scale;\n const h = Math.floor(total / 3600);\n const m = Math.floor((total - h * 3600) / 60);\n const s = Math.round((total - h * 3600 - m * 60) * scale) / scale;\n return { negative: value < 0 && total > 0, h, m, s };\n}\n\nconst DURATION_UNITS: UnitTable = { h: 3600, m: 60, min: 60, s: 1, ms: 0.001 };\n\nexport const durationKind: DisplayKind<DurationDisplay> = {\n kind: 'duration',\n format: (value, d) => {\n if (!Number.isFinite(value)) return [{ type: 'number', value: String(value) }];\n const places = d.places ?? 0;\n const { negative, h, m, s } = hms(value, places);\n const sec = s.toFixed(places);\n const parts: Part[] = negative ? [{ type: 'sign', value: '−' }] : [];\n if (d.style === 'units') {\n const terms: Part[][] = [];\n if (h > 0) terms.push([{ type: 'hours', value: String(h) }, { type: 'unit', value: 'h' }]);\n if (m > 0) terms.push([{ type: 'minutes', value: String(m) }, { type: 'unit', value: 'm' }]);\n if (s > 0 || terms.length === 0) terms.push([{ type: 'seconds', value: sec }, { type: 'unit', value: 's' }]);\n terms.forEach((t, i) => parts.push(...(i > 0 ? [{ type: 'literal', value: ' ' }] : []), ...t));\n return parts;\n }\n const pad = (n: string) => (n.split('.')[0]!.length < 2 ? `0${n}` : n);\n if (h > 0) {\n parts.push(\n { type: 'hours', value: String(h) },\n { type: 'literal', value: ':' },\n { type: 'minutes', value: pad(String(m)) },\n );\n } else {\n parts.push({ type: 'minutes', value: String(m) });\n }\n parts.push({ type: 'literal', value: ':' }, { type: 'seconds', value: pad(sec) });\n return parts;\n },\n speak: (value, d, ctx) => {\n if (!Number.isFinite(value)) return String(value);\n const { negative, h, m, s } = hms(value, d.places ?? 0);\n const terms: string[] = [];\n if (h > 0) terms.push(`${h} ${plural(h, ctx.locale, 'hour', 'hours')}`);\n if (m > 0) terms.push(`${m} ${plural(m, ctx.locale, 'minute', 'minutes')}`);\n if (s > 0 || terms.length === 0) terms.push(`${s} ${plural(s, ctx.locale, 'second', 'seconds')}`);\n return `${negative ? 'minus ' : ''}${terms.join(', ')}`;\n },\n parse: (text) => {\n const m = /^\\s*([-−+]?)\\s*(?:(\\d+):)?(\\d+):(\\d+(?:\\.\\d+)?)\\s*$/.exec(text);\n if (!m) return parseNumber(text, DURATION_UNITS);\n const total = Number(m[2] ?? 0) * 3600 + Number(m[3]) * 60 + Number(m[4]);\n return m[1] === '-' || m[1] === '−' ? -total : total;\n },\n};\n\nconst DECIMAL_BYTES = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'] as const;\nconst BINARY_BYTES = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] as const;\nconst DECIMAL_NAMES = ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte', 'petabyte'] as const;\nconst BINARY_NAMES = ['byte', 'kibibyte', 'mebibyte', 'gibibyte', 'tebibyte', 'pebibyte'] as const;\n\n/** A byte count in the largest unit that keeps it at or above 1: `1.2 MB`,\n * spoken `1.2 megabytes`. `base: 1024` uses `KiB`, `MiB`, … */\nexport type BytesDisplay = {\n kind: 'bytes';\n /** Default 1000. */\n base?: 1000 | 1024;\n /** Most decimals. Default 1. */\n places?: number;\n};\n\nexport function bytes(options: Omit<BytesDisplay, 'kind'> = {}): BytesDisplay {\n return { kind: 'bytes', ...options };\n}\n\nfunction byteScale(value: number, base: number): { scaled: number; step: number } {\n let step = 0;\n let scaled = value;\n while (Math.abs(scaled) >= base && step < DECIMAL_BYTES.length - 1) {\n scaled /= base;\n step++;\n }\n return { scaled, step };\n}\n\nconst BYTE_UNITS: UnitTable = Object.fromEntries([\n ...DECIMAL_BYTES.map((u, i) => [u, 1000 ** i] as const),\n ['KB', 1000],\n ...BINARY_BYTES.slice(1).map((u, i) => [u, 1024 ** (i + 1)] as const),\n]);\n\nexport const bytesKind: DisplayKind<BytesDisplay> = {\n kind: 'bytes',\n format: (value, d, ctx) => {\n const base = d.base ?? 1000;\n const { scaled, step } = byteScale(value, base);\n const units = base === 1024 ? BINARY_BYTES : DECIMAL_BYTES;\n return [\n numberPart(scaled, ctx.locale, { maximumFractionDigits: step === 0 ? 0 : (d.places ?? 1) }),\n { type: 'literal', value: ' ' },\n { type: 'unit', value: units[step]! },\n ];\n },\n speak: (value, d, ctx) => {\n const base = d.base ?? 1000;\n const { scaled, step } = byteScale(value, base);\n const name = (base === 1024 ? BINARY_NAMES : DECIMAL_NAMES)[step]!;\n const number = numberPart(scaled, ctx.locale, { maximumFractionDigits: step === 0 ? 0 : (d.places ?? 1) }).value;\n return spokenSign(`${number} ${plural(Number(number.replace(/[^\\d.]/g, '')), ctx.locale, name, `${name}s`)}`);\n },\n parse: (text) => parseNumber(text, BYTE_UNITS),\n};\n","import { numberPart, spokenSign, type DisplayKind } from '../kind';\nimport { parseNumber } from '../number';\n\n/**\n * A whole number in Roman numerals, `XII`. Spoken as the plain number, since a\n * screen reader otherwise spells the letters out. Outside 1–3999, which the\n * numerals cannot write, it shows as a plain number.\n */\nexport type RomanDisplay = {\n kind: 'roman';\n lower?: boolean;\n};\n\nexport function roman(options: Omit<RomanDisplay, 'kind'> = {}): RomanDisplay {\n return { kind: 'roman', ...options };\n}\n\nconst NUMERALS: readonly [number, string][] = [\n [1000, 'M'], [900, 'CM'], [500, 'D'], [400, 'CD'], [100, 'C'], [90, 'XC'],\n [50, 'L'], [40, 'XL'], [10, 'X'], [9, 'IX'], [5, 'V'], [4, 'IV'], [1, 'I'],\n];\n\n/** `n` in Roman numerals, or undefined outside 1–3999. */\nexport function toRoman(n: number): string | undefined {\n let rest = Math.round(n);\n if (!(rest >= 1 && rest <= 3999)) return undefined;\n let out = '';\n for (const [v, s] of NUMERALS) {\n while (rest >= v) {\n out += s;\n rest -= v;\n }\n }\n return out;\n}\n\n/** The value of well-formed Roman numerals, either case; NaN otherwise. */\nexport function fromRoman(text: string): number {\n const t = text.trim().toUpperCase();\n if (!/^[MDCLXVI]+$/.test(t)) return Number.NaN;\n let total = 0;\n let i = 0;\n for (const [v, s] of NUMERALS) {\n while (t.startsWith(s, i)) {\n total += v;\n i += s.length;\n }\n }\n // Anything left unread, or a non-canonical spelling such as `IIII`, is not a numeral.\n return i === t.length && toRoman(total) === t ? total : Number.NaN;\n}\n\nexport const romanKind: DisplayKind<RomanDisplay> = {\n kind: 'roman',\n format: (value, d, ctx) => {\n const r = toRoman(value);\n if (r === undefined) return [numberPart(value, ctx.locale, { maximumFractionDigits: 0 })];\n return [{ type: 'numeral', value: d.lower ? r.toLowerCase() : r }];\n },\n speak: (value, _d, ctx) => spokenSign(numberPart(Math.round(value), ctx.locale, { maximumFractionDigits: 0, useGrouping: false }).value),\n parse: (text) => {\n const r = fromRoman(text);\n return Number.isNaN(r) ? parseNumber(text) : r;\n },\n};\n\n/** A whole number as an ordinal: `1st`, `22nd`, `113th`. English suffixes;\n * in any other locale the number shows alone. */\nexport type OrdinalDisplay = {\n kind: 'ordinal';\n};\n\nexport function ordinal(): OrdinalDisplay {\n return { kind: 'ordinal' };\n}\n\nconst SUFFIXES: Record<string, string> = { one: 'st', two: 'nd', few: 'rd', other: 'th' };\n\nexport const ordinalKind: DisplayKind<OrdinalDisplay> = {\n kind: 'ordinal',\n format: (value, _d, ctx) => {\n const n = Math.round(value);\n const number = numberPart(n, ctx.locale, { maximumFractionDigits: 0 });\n if (!Number.isFinite(n) || !ctx.locale.startsWith('en')) return [number];\n const rule = new Intl.PluralRules('en-US', { type: 'ordinal' }).select(n);\n return [number, { type: 'ordinal', value: SUFFIXES[rule] ?? 'th' }];\n },\n parse: (text) => Math.round(parseNumber(text.replace(/(st|nd|rd|th)\\s*$/i, ''))),\n};\n","import { textOf, type DisplayKind, type FormatContext, type Part } from './kind';\nimport { compactKind, decimalKind, integerKind } from './kinds/plain';\nimport { fractionKind, multiplierKind, percentKind, ratioKind, zoomKind } from './kinds/proportion';\nimport { bytesKind, currencyKind, durationKind, unitKind } from './kinds/measure';\nimport { ordinalKind, romanKind } from './kinds/numeral';\nimport { parseNumber } from './number';\nimport { amount, displayOf, retag, tag, unitOf, type Display, type Quantity, type Tagged } from './quantity';\nimport { unitScale, type Unit, type UnitSystem } from './units';\n\n// A static table rather than registration at import, so the package stays\n// free of side effects and a bundler can drop what nobody imports.\nconst BUILTIN: Record<string, DisplayKind<never>> = Object.fromEntries(\n [\n decimalKind, integerKind, compactKind,\n percentKind, fractionKind, ratioKind, multiplierKind, zoomKind,\n unitKind, currencyKind, durationKind, bytesKind,\n romanKind, ordinalKind,\n ].map((k) => [k.kind, k as DisplayKind<never>]),\n);\n\nconst registered = new Map<string, DisplayKind<never>>();\n\n/**\n * Adds a display kind, or replaces a built-in one — the way to swap in a words\n * library for `fraction`'s spoken form (`{ ...fractionKind, speak }`). Returns\n * a function that removes it again.\n */\nexport function registerDisplayKind<D extends Display>(kind: DisplayKind<D>): () => void {\n const entry = kind as unknown as DisplayKind<never>;\n registered.set(kind.kind, entry);\n return () => {\n if (registered.get(kind.kind) === entry) registered.delete(kind.kind);\n };\n}\n\n/**\n * The kind behind `display`. An unknown kind resolves to `decimal` rather than\n * throwing: a document saved by an app with a custom kind still opens in one\n * without it, and its tag survives untouched.\n */\nexport function displayKindOf(display: Display | undefined): DisplayKind<Display> {\n const kind = display === undefined ? undefined : (registered.get(display.kind) ?? BUILTIN[display.kind]);\n return (kind ?? decimalKind) as unknown as DisplayKind<Display>;\n}\n\n/** Options for presenting or parsing a quantity. */\nexport interface PresentOptions {\n /** BCP 47 locale. Default `en-US`, which every kind parses. */\n locale?: string;\n}\n\n/** A quantity as text, spoken text, HTML and, where its kind has one, MathML. */\nexport interface Presentation {\n text: string;\n spoken: string;\n /** Unstyled: a `<data value>` wrapping one `<span data-part>` per named part. */\n html: string;\n mathml?: string;\n}\n\nconst DEFAULT_DISPLAY: Display = { kind: 'decimal' };\n\nfunction contextOf(q: Quantity, options: PresentOptions | undefined): FormatContext {\n const unit = unitOf(q);\n return unit === undefined ? { locale: options?.locale ?? 'en-US' } : { locale: options?.locale ?? 'en-US', unit };\n}\n\nconst ESCAPES: Record<string, string> = { '&': '&', '<': '<', '>': '>', '\"': '"' };\nfunction escape(s: string): string {\n return s.replace(/[&<>\"]/g, (c) => ESCAPES[c]!);\n}\n\n/** Parts as the unstyled HTML fragment {@link Presentation.html} describes. */\nexport function partsToHtml(value: number, parts: readonly Part[]): string {\n const body = parts\n .map((p) => (p.type === 'literal' ? escape(p.value) : `<span data-part=\"${escape(p.type)}\">${escape(p.value)}</span>`))\n .join('');\n return `<data value=\"${escape(String(value))}\">${body}</data>`;\n}\n\n/** Parts of `q` under its own display, else `fallback`, else `decimal`. */\nexport function partsOf(q: Quantity, fallback?: Display, options?: PresentOptions): Part[] {\n const display = displayOf(q, fallback) ?? DEFAULT_DISPLAY;\n return displayKindOf(display).format(amount(q), display, contextOf(q, options));\n}\n\n/** `q` as text, spoken text, HTML and MathML. See {@link qty} for one at a time. */\nexport function present(q: Quantity, fallback?: Display, options?: PresentOptions): Presentation {\n const display = displayOf(q, fallback) ?? DEFAULT_DISPLAY;\n const kind = displayKindOf(display);\n const value = amount(q);\n const ctx = contextOf(q, options);\n const parts = kind.format(value, display, ctx);\n const text = textOf(parts);\n const out: Presentation = {\n text,\n spoken: kind.speak ? kind.speak(value, display, ctx) : text,\n html: partsToHtml(value, parts),\n };\n const mathml = kind.mathml?.(value, display, ctx);\n if (mathml !== undefined) out.mathml = mathml;\n return out;\n}\n\n/** Typed text read through `display`: NaN when it does not read. */\nexport function parseAs(text: string, display?: Display, options?: PresentOptions & { unit?: Unit }): number {\n const d = display ?? DEFAULT_DISPLAY;\n const kind = displayKindOf(d);\n const ctx: FormatContext = { locale: options?.locale ?? 'en-US' };\n if (options?.unit !== undefined) ctx.unit = options.unit;\n return kind.parse ? kind.parse(text, d, ctx) : parseNumber(text);\n}\n\n/**\n * A short-lived view of a quantity with its presentation as methods. Nothing\n * about it is stored — keep the quantity, and wrap it where it is shown.\n */\nexport class QuantityView<Q extends Quantity = Quantity> {\n constructor(\n /** The quantity as given. */\n readonly raw: Q,\n private readonly fallback?: Display,\n private readonly options?: PresentOptions,\n ) {}\n\n get value(): number {\n return amount(this.raw);\n }\n get unit(): Unit | undefined {\n return unitOf(this.raw);\n }\n /** The display in effect: the value's own, else the fallback. */\n get display(): Display | undefined {\n return displayOf(this.raw, this.fallback);\n }\n get parts(): Part[] {\n return partsOf(this.raw, this.fallback, this.options);\n }\n get text(): string {\n return textOf(this.parts);\n }\n get spoken(): string {\n return present(this.raw, this.fallback, this.options).spoken;\n }\n get html(): string {\n return partsToHtml(this.value, this.parts);\n }\n get mathml(): string | undefined {\n return present(this.raw, this.fallback, this.options).mathml;\n }\n /** `next` in this quantity's shape — see {@link retag}. */\n with(next: number): QuantityView<Q> {\n return new QuantityView(retag(this.raw, next), this.fallback, this.options);\n }\n /** Typed text read through this quantity's display; NaN when it does not read. */\n parse(text: string): number {\n const unit = this.unit;\n return parseAs(text, this.display, unit === undefined ? this.options : { ...this.options, unit });\n }\n /** The same amount in `target`, converted through `system`, tagged with it. */\n to(target: Unit, system: UnitSystem): QuantityView {\n const from = unitScale(system, this.unit ?? system.base);\n const to = unitScale(system, target);\n const base = this.value * from.factor + from.offset;\n const value = (base - to.offset) / to.factor;\n const raw = typeof this.raw === 'number' ? tag(value, undefined, target) : { ...(this.raw as Tagged), value, unit: target };\n return new QuantityView(raw, this.fallback, this.options);\n }\n toJSON(): Q {\n return this.raw;\n }\n}\n\n/** Wraps `q` for display: `qty(band.from, fraction()).text`. `fallback` is the\n * display for a value that carries none of its own. */\nexport function qty<Q extends Quantity>(q: Q, fallback?: Display, options?: PresentOptions): QuantityView<Q> {\n return new QuantityView(q, fallback, options);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/quantity.ts","../src/units.ts","../src/number.ts","../src/kind.ts","../src/kinds/plain.ts","../src/kinds/proportion.ts","../src/kinds/measure.ts","../src/kinds/numeral.ts","../src/present.ts"],"names":["unit","decimal","integer","scaled","escape"],"mappings":"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","file":"index.js","sourcesContent":["import type { Unit } from './units';\n\n/**\n * How a number shows, speaks and reads back, as plain data: `{ kind: 'fraction',\n * maxDenominator: 64 }`. Data rather than a function so a tagged value keeps its\n * presentation through JSON, history snapshots and `structuredClone`. The\n * behavior lives on the registered {@link DisplayKind} of the same `kind`.\n */\nexport interface Display {\n readonly kind: string;\n readonly [option: string]: unknown;\n}\n\n/** A number that carries its unit, its display, or both. */\nexport interface Tagged {\n value: number;\n /** The unit `value` is measured in. Absent is the base unit. */\n unit?: Unit;\n display?: Display;\n}\n\n/**\n * A number anywhere the engine takes one: bare, which costs nothing, or\n * {@link Tagged}, which keeps its unit and display as it moves. Every reader\n * goes through {@link amount}, and every writer through {@link retag}, so a\n * value leaves in the shape it arrived in.\n */\nexport type Quantity = number | Tagged;\n\n/** The number a quantity holds. */\nexport function amount(q: Quantity): number {\n return typeof q === 'number' ? q : q.value;\n}\n\n/**\n * `next` in the shape of `q`: a bare number stays bare, and a tagged one keeps\n * its unit and display. What an editor calls when it changes a value it was\n * handed, so the presentation survives the edit.\n */\nexport function retag<Q extends Quantity>(q: Q, next: number): Q {\n return (typeof q === 'number' ? next : { ...(q as Tagged), value: next }) as Q;\n}\n\n/** A tagged quantity. `display` and `unit` are left off when absent, so the\n * JSON carries only what was set. */\nexport function tag(value: number, display?: Display, unit?: Unit): Tagged {\n const t: Tagged = { value };\n if (unit !== undefined) t.unit = unit;\n if (display !== undefined) t.display = display;\n return t;\n}\n\n/** The display `q` carries, else `fallback`. A value's own tag wins over the\n * default of whatever shows it. */\nexport function displayOf(q: Quantity, fallback?: Display): Display | undefined {\n return (typeof q === 'number' ? undefined : q.display) ?? fallback;\n}\n\n/** The unit `q` is measured in, when it says. */\nexport function unitOf(q: Quantity): Unit | undefined {\n return typeof q === 'number' ? undefined : q.unit;\n}\n","import type { Quantity } from './quantity';\n\n/**\n * Units — a tiny customizable unit system.\n *\n * The kit stores all coordinates as bare numbers in a single base unit\n * chosen by the consumer app. To make API call sites self-documenting,\n * the public surface accepts `UnitValue` — either a bare number (interpreted\n * as base units) or a `{ value, unit }` tag that's resolved against a\n * `UnitSystem` at the API boundary. Internals never see units.\n *\n * An entry is affine — `base = value * factor + offset` — so a scale that\n * puts zero somewhere else (degC against K) is expressible. No per-axis\n * units. No mixed-unit arithmetic.\n */\n\n/** A unit name (e.g. `'in'`, `'ft'`, `'mm'`). Looked up in a `UnitSystem`. */\nexport type Unit = string;\n\n/** What one unit is worth in base units: `base = value * factor + offset`. */\nexport interface UnitScale {\n factor: number;\n /** Where this unit puts zero, in base units. Absent is 0 — a pure scale. */\n offset?: number;\n}\n\n/** One unit's conversion. A bare number is the `{ factor }` shorthand. */\nexport type UnitEntry = number | UnitScale;\n\n/** Conversion table mapping unit names to their scale against a base unit. */\nexport interface UnitSystem {\n /** Name of the base unit, e.g. 'in'. All conversions resolve to this. */\n base: Unit;\n /** How to reach base units from each unit. The base unit's entry is 1. */\n units: Record<Unit, UnitEntry>;\n}\n\n/**\n * One unit's scale, with the bare-number shorthand widened and the offset\n * defaulted — what every conversion in the kit reads. Throws if the system\n * does not carry the unit.\n */\nexport function unitScale(unitSystem: UnitSystem, unit: Unit): Required<UnitScale> {\n const entry = unitSystem.units[unit];\n if (entry === undefined) {\n const known = Object.keys(unitSystem.units).join(', ') || '(none)';\n throw new Error(\n `unknown unit '${unit}' (system base: '${unitSystem.base}', known units: ${known})`,\n );\n }\n return entryScale(entry);\n}\n\n/** An entry's scale, with the bare-number shorthand widened and the offset defaulted. */\nexport function entryScale(entry: UnitEntry): Required<UnitScale> {\n return typeof entry === 'number'\n ? { factor: entry, offset: 0 }\n : { factor: entry.factor, offset: entry.offset ?? 0 };\n}\n\n/** Value at a unit-aware API boundary: bare number (in base units) or `{ value, unit }` tag. */\nexport type UnitValue = number | { value: number; unit: Unit };\n\n/**\n * Resolve a UnitValue to a number in base units.\n * - bare number, or a quantity tagged with no unit: its value, as base\n * - tagged: looks up factor; throws if unit not in unit system\n */\nexport function resolveUnit(v: UnitValue | Quantity, unitSystem?: UnitSystem): number {\n if (typeof v === 'number') return v;\n if (v.unit === undefined) return v.value;\n if (!unitSystem) {\n throw new Error(\n `resolveUnit: tagged value { value: ${v.value}, unit: '${v.unit}' } requires a UnitSystem`,\n );\n }\n const { factor, offset } = scaleOrThrow('resolveUnit', unitSystem, v.unit);\n return v.value * factor + offset;\n}\n\n/**\n * Format a base-unit number as a string in the named display unit.\n * e.g. formatUnit(36, 'ft', IMPERIAL_INCHES) => '3ft'\n * Default precision: 2. Trailing zeros trimmed.\n */\nexport function formatUnit(\n baseValue: number,\n displayUnit: Unit,\n unitSystem: UnitSystem,\n opts?: { precision?: number; suffix?: boolean },\n): string {\n const { factor, offset } = scaleOrThrow('formatUnit', unitSystem, displayUnit);\n const precision = opts?.precision ?? 2;\n const suffix = opts?.suffix ?? true;\n const display = (baseValue - offset) / factor;\n // Trim trailing zeros (and a dangling decimal point) without losing precision.\n let s = display.toFixed(precision);\n if (s.includes('.')) {\n s = s.replace(/0+$/, '').replace(/\\.$/, '');\n }\n return suffix ? `${s}${displayUnit}` : s;\n}\n\n/** `unitScale`, with the caller's name in front of the message. */\nfunction scaleOrThrow(caller: string, unitSystem: UnitSystem, unit: Unit): Required<UnitScale> {\n try {\n return unitScale(unitSystem, unit);\n } catch (e) {\n throw new Error(`${caller}: ${e instanceof Error ? e.message : String(e)}`);\n }\n}\n\n/** Imperial unit system with base 'in'. */\nexport const IMPERIAL_INCHES: UnitSystem = {\n base: 'in',\n units: { in: 1, ft: 12, yd: 36, mi: 63360 },\n};\n\n/** Metric unit system with base 'mm'. */\nexport const METRIC_MM: UnitSystem = {\n base: 'mm',\n units: { mm: 1, cm: 10, m: 1000, km: 1_000_000 },\n};\n\n/** Angle unit system with base 'rad'. */\nexport const ANGLE_RADIANS: UnitSystem = {\n base: 'rad',\n units: { rad: 1, deg: Math.PI / 180, turn: Math.PI * 2 },\n};\n\n/** Pixel unit system — sole unit is the base. */\nexport const PIXELS: UnitSystem = {\n base: 'px',\n units: { px: 1 },\n};\n","import { entryScale, type UnitEntry } from './units';\n\n/**\n * Display-formatter for numbers. Use this anywhere a number is shown to\n * a user. The whole point: negative values get prefixed with the real\n * MINUS SIGN (U+2212) instead of the ASCII HYPHEN-MINUS (U+002D) that\n * `toLocaleString` and template literals produce by default.\n *\n * U+2212 is the same visual width as `+` and reads as a sign rather\n * than a hyphen — columns of signed numbers align cleanly and the\n * glyph doesn't get confused with a bullet or list dash.\n */\nexport const MINUS_SIGN = '−';\n\n/**\n * Formats a number for display, substituting {@link MINUS_SIGN} for the ASCII\n * hyphen `toLocaleString` emits. Non-finite values stringify as-is.\n */\nexport function formatNumber(value: number, options?: Intl.NumberFormatOptions): string {\n const formatted = Number.isFinite(value)\n ? value.toLocaleString(undefined, options)\n : String(value);\n return formatted.replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Parses a string that may carry {@link MINUS_SIGN} in place of the ASCII\n * hyphen. The inverse of {@link formatNumber} for any editing surface that\n * renders its value through it and reads the edited text back.\n */\nexport function parseSignedNumber(text: string): number {\n return Number(text.replace(MINUS_SIGN, '-'));\n}\n\n/** One unsigned number in the text `readNumber` sees: digits, with an optional `.` fraction. */\nconst TERM_NUMBER = String.raw`\\d+(?:\\.\\d+)?|\\.\\d+`;\n\n/** Powers of ten a typed magnitude suffix stands for. */\nconst EXPONENTS: Record<string, number> = { k: 3, m: 6, b: 9, t: 12 };\n\n/**\n * Formats a number the way a `compact` readout shows it: below 1,000 at\n * `decimals` places, from 1,000 up at three significant figures with a magnitude\n * suffix (`40.0K`, `294K`, `2.00M`), so the readout holds one width whatever the\n * value. Always `en-US`, so {@link parseNumber} reads it back.\n */\nexport function formatCompact(value: number, decimals = 0): string {\n if (!Number.isFinite(value)) return formatNumber(value);\n const options: Intl.NumberFormatOptions =\n Math.abs(value) < 1000\n ? { useGrouping: false, minimumFractionDigits: decimals, maximumFractionDigits: decimals }\n : { notation: 'compact', minimumSignificantDigits: 3, maximumSignificantDigits: 3 };\n return value.toLocaleString('en-US', options).replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Reads a typed number: anything {@link parseSignedNumber} reads, plus the\n * locale's group and decimal separators (`40,000` and `2.5` in `en-US`,\n * `40.000` and `2,5` in `de-DE`) and a `k`/`m`/`b`/`t` suffix in either case\n * (`2.5m` is 2,500,000). Empty text is NaN rather than zero.\n *\n * Text the locale's form does not read is tried as `en-US`, so `1.5` is still\n * one and a half in `de-DE`; where both read, the locale wins. A locale that\n * groups with a space accepts any space there, since a keyboard types a plain\n * one where `Intl` writes a no-break space.\n *\n * Given `units` — a suffix mapped to the factor it scales by — a trailing unit\n * name is read first: the longest match wins, exact case before any case, and\n * a unit beats a magnitude suffix, so with `m` accepted `2m` is `2 * units.m`.\n */\nexport function parseNumber(text: string, units?: Readonly<UnitTable>, locale = 'en-US'): number {\n const n = readNumber(delocalized(text, locale), units);\n return Number.isNaN(n) && locale !== 'en-US' ? readNumber(delocalized(text, 'en-US'), units) : n;\n}\n\n/** `parseNumber` once every number in the text is in `en-US` form with no grouping. */\nfunction readNumber(text: string, units?: Readonly<UnitTable>): number {\n if (units) {\n units = withSpellings(units);\n const trimmed = text.trim();\n const name = unitSuffixOf(trimmed, units);\n if (name !== undefined) {\n const terms = compoundTermsOf(trimmed, units);\n if (terms !== undefined && terms.length > 1) return compoundValue(terms, trimmed, units);\n const { factor, offset } = entryScale(units[name]!);\n return scaled(readNumber(trimmed.slice(0, -name.length)), factor) + offset;\n }\n }\n let t = text.trim().replace(MINUS_SIGN, '-');\n const exponent = EXPONENTS[t.slice(-1).toLowerCase()];\n if (exponent !== undefined) t = t.slice(0, -1).trimEnd();\n if (!/\\d/.test(t)) return Number.NaN;\n // Scaled through the exponent rather than by multiplying: 1.1 * 1000 is 1100.0000000000002.\n return Number(exponent === undefined ? t : `${t}e${exponent}`);\n}\n\ninterface NumberShape {\n /** A run of digits and separators in a text, a candidate number. */\n run: RegExp;\n /** Whether a run is a whole number in the locale's form. */\n whole: RegExp;\n group: RegExp;\n decimal: string;\n /** The locale's own digits, where they are not `0`–`9`, each mapped to its Latin one. */\n digits?: { pattern: RegExp; latin: ReadonlyMap<string, string> };\n}\n\nconst shapes = new Map<string, NumberShape>();\n\n/** How `locale` writes a number, read off `Intl`: its separators and group sizes (`12,34,567` in `en-IN`). */\nfunction shapeOf(locale: string): NumberShape {\n const known = shapes.get(locale);\n if (known) return known;\n const parts = new Intl.NumberFormat(locale).formatToParts(123_456_789.5);\n const sizes = parts.filter((p) => p.type === 'integer').map((p) => p.value.length);\n const primary = sizes.at(-1)!;\n const secondary = sizes.length > 2 ? sizes.at(-2)! : primary;\n const groupChar = parts.find((p) => p.type === 'group')?.value ?? ',';\n const decimal = parts.find((p) => p.type === 'decimal')?.value ?? '.';\n // CLDR versions disagree between a straight and a curly apostrophe, as keyboards do.\n const g = /\\s/.test(groupChar) ? String.raw`\\s` : /['’]/.test(groupChar) ? `'’` : escapeClass(groupChar);\n const own = [...new Intl.NumberFormat(locale, { useGrouping: false }).format(9_876_543_210)].reverse();\n const digits = own.join('') === '0123456789'\n ? undefined\n : { pattern: new RegExp(`[${own.join('')}]`, 'gu'), latin: new Map(own.map((c, i) => [c, String(i)])) };\n const d = escapeClass(decimal);\n const integer = String.raw`\\d{1,${secondary}}(?:[${g}]\\d{${secondary}})*[${g}]\\d{${primary}}|\\d*`;\n const shape: NumberShape = {\n run: new RegExp(String.raw`(?:\\d|[${d}]\\d)(?:[\\d${g}${d}]*\\d)?[${d}]?`, 'g'),\n whole: new RegExp(String.raw`^(?:${integer})(?:[${d}]\\d*)?$`),\n group: new RegExp(`[${g}]`, 'g'),\n decimal,\n digits,\n };\n shapes.set(locale, shape);\n return shape;\n}\n\nexport const escapeClass = (c: string) => c.replace(/[\\\\\\]^-]/g, '\\\\$&');\n\n/** `text` with each number in `locale`'s form rewritten ungrouped with a `.` decimal, and the rest untouched. */\nfunction delocalized(text: string, locale: string): string {\n const shape = shapeOf(locale);\n return latinDigits(text, locale).replace(shape.run, (run) =>\n shape.whole.test(run) ? run.replace(shape.group, '').replace(shape.decimal, '.') : run,\n );\n}\n\n/**\n * `text` with `locale`'s own digits written `0`–`9` and the bidi marks `Intl`\n * puts around a sign (`-` in `ar-EG`) dropped.\n */\nexport function latinDigits(text: string, locale: string): string {\n const { digits } = shapeOf(locale);\n const t = text.replace(BIDI_MARKS, '');\n return digits ? t.replace(digits.pattern, (c) => digits.latin.get(c)!) : t;\n}\n\nconst BIDI_MARKS = /[\\u061c\\u200e\\u200f]/g;\n\n/** The mark `locale` writes before a fraction: `.` in `en-US`, `,` in `de-DE`. */\nexport const decimalOf = (locale: string): string => shapeOf(locale).decimal;\n\n/** Suffixes a person may type, each mapped to its conversion into the shown unit. */\nexport type UnitTable = Record<string, UnitEntry>;\n\n/**\n * Units that are written more than one way. A table accepting any spelling\n * accepts them all: `\"` wherever `in` is, `ft` wherever `'` is. The primes and\n * curly quotes are there because a keyboard substitutes them for the marks.\n */\nconst SPELLINGS: readonly (readonly string[])[] = [\n ['in', '\"', '″', '”'],\n ['ft', \"'\", '′', '’'],\n];\n\nfunction withSpellings(units: Readonly<UnitTable>): Readonly<UnitTable> {\n let out: UnitTable | undefined;\n for (const group of SPELLINGS) {\n const known = group.find((n) => units[n] !== undefined);\n if (known === undefined) continue;\n for (const n of group) {\n if (units[n] !== undefined) continue;\n out ??= { ...units };\n out[n] = units[known]!;\n }\n }\n return out ?? units;\n}\n\n/** Divided by the reciprocal below 1: 12 * 0.1 is 1.2000000000000002, 12 / 10 is 1.2. */\nfunction scaled(n: number, factor: number): number {\n return factor < 1 ? n / (1 / factor) : n * factor;\n}\n\n/**\n * The unit names in `text`, in reading order, when every one of them closes a\n * `<number><unit>` term — which is what tells `5ft 3in` from a malformed\n * `5ft 3`. Undefined when the text is not a run of whole terms.\n */\nfunction compoundTermsOf(text: string, units: Readonly<UnitTable>): string[] | undefined {\n const names: string[] = [];\n let rest = text.trimEnd();\n while (rest !== '') {\n const name = unitSuffixOf(rest, units);\n if (name === undefined) return undefined;\n names.push(name);\n const before = rest.slice(0, -name.length);\n const m = new RegExp(`(?:${TERM_NUMBER})\\\\s*$`).exec(before);\n if (!m) return undefined;\n rest = before.slice(0, m.index).trimEnd();\n // A sign leads the whole value, so it ends the walk rather than a term.\n if (rest === '-' || rest === '+' || rest === MINUS_SIGN) rest = '';\n }\n return names.length === 0 ? undefined : names.reverse();\n}\n\n/**\n * `5ft 3in` as one number in the shown unit. Every term scales and they sum;\n * a leading sign carries across all of them, so `-5ft 3in` is −63in and not\n * −57. Offsets have no meaning in a sum — 1K + 2degC is not a temperature —\n * so a term carrying one makes the whole value unreadable.\n */\nfunction compoundValue(names: string[], text: string, units: Readonly<UnitTable>): number {\n const digits = text.match(new RegExp(TERM_NUMBER, 'g'));\n if (!digits || digits.length !== names.length) return Number.NaN;\n const sign = /^\\s*[-\\u2212]/.test(text) ? -1 : 1;\n let total = 0;\n for (const [i, name] of names.entries()) {\n const { factor, offset } = entryScale(units[name]!);\n if (offset !== 0) return Number.NaN;\n total += scaled(Number(digits[i]), factor);\n }\n return sign * total;\n}\n\n/** The longest unit name `text` ends with — exact case first, then any case. */\nfunction unitSuffixOf(text: string, units: Readonly<UnitTable>): string | undefined {\n const names = Object.keys(units).filter((n) => n !== '').sort((a, b) => b.length - a.length);\n const lower = text.toLowerCase();\n return names.find((n) => text.endsWith(n)) ?? names.find((n) => lower.endsWith(n.toLowerCase()));\n}\n","import type { Display } from './quantity';\nimport type { Unit } from './units';\nimport { MINUS_SIGN } from './number';\n\n/**\n * One run of a formatted value, named for what it is: `number`, `unit`,\n * `currency`, `numerator`, `literal`. The HTML serialization marks each\n * non-literal run with `data-part`, which is the whole styling surface.\n */\nexport interface Part {\n type: string;\n value: string;\n}\n\n/** What formatting and parsing need beyond the value and its display. */\nexport interface FormatContext {\n /** BCP 47 locale. Default `en-US`. */\n locale: string;\n /** The unit the value is measured in, from its tag. */\n unit?: Unit;\n}\n\n/**\n * The behavior behind one `Display.kind`. `format` is required; `speak`\n * defaults to the formatted text, `parse` to `parseNumber`, and `mathml` to\n * nothing, which means the kind has no MathML form.\n */\nexport interface DisplayKind<D extends Display = Display> {\n kind: D['kind'];\n format(value: number, display: D, ctx: FormatContext): Part[];\n speak?(value: number, display: D, ctx: FormatContext): string;\n parse?(text: string, display: D, ctx: FormatContext): number;\n mathml?(value: number, display: D, ctx: FormatContext): string | undefined;\n}\n\n/** Parts joined into plain text. */\nexport function textOf(parts: readonly Part[]): string {\n return parts.map((p) => p.value).join('');\n}\n\n/** A number run from `Intl`, with the real minus sign. */\nexport function numberPart(value: number, locale: string, options?: Intl.NumberFormatOptions): Part {\n return { type: 'number', value: signed(value.toLocaleString(locale, options)) };\n}\n\n/** `-` swapped for {@link MINUS_SIGN} at the front of already-formatted text. */\nexport function signed(text: string): string {\n return text.replace(/^-/, MINUS_SIGN);\n}\n\n/** A leading minus sign read aloud: `−3` is spoken `minus 3`, which a screen\n * reader otherwise renders as a dash or drops. */\nexport function spokenSign(text: string): string {\n return text.replace(/^[-−]/, 'minus ');\n}\n\n/** `singular` or `plural` for `value`, by the locale's plural rules. */\nexport function plural(value: number, locale: string, singular: string, pluralForm: string): string {\n return new Intl.PluralRules(locale).select(value) === 'one' ? singular : pluralForm;\n}\n\n/**\n * `Intl.NumberFormat`'s parts, with the digit runs — sign, integer, group,\n * decimal, fraction — merged into one `number` part, so a styling layer sees\n * the number as one thing and its unit or symbol as another.\n */\nexport function intlParts(value: number, locale: string, options: Intl.NumberFormatOptions): Part[] {\n const out: Part[] = [];\n for (const p of new Intl.NumberFormat(locale, options).formatToParts(value)) {\n const type = DIGIT_RUNS.has(p.type) ? 'number' : p.type;\n const v = p.type === 'minusSign' ? MINUS_SIGN : p.value;\n const last = out[out.length - 1];\n if (type === 'number' && last?.type === 'number') last.value += v;\n else out.push({ type, value: v });\n }\n return out;\n}\n\nconst DIGIT_RUNS = new Set(['minusSign', 'plusSign', 'integer', 'group', 'decimal', 'fraction']);\n","import { intlParts, spokenSign, textOf, type DisplayKind } from '../kind';\nimport { formatCompact, parseNumber } from '../number';\n\n/** A plain number. `places` fixes the decimals, trailing zeros included;\n * otherwise up to `maxPlaces` (default 3) show and trailing zeros drop. */\nexport type DecimalDisplay = {\n kind: 'decimal';\n places?: number;\n maxPlaces?: number;\n /** Thousands separators. Default true. */\n grouping?: boolean;\n};\n\n/** A {@link DecimalDisplay}. */\nexport function decimal(options: Omit<DecimalDisplay, 'kind'> = {}): DecimalDisplay {\n return { kind: 'decimal', ...options };\n}\n\n/** The built-in `decimal` kind, to spread into a `registerDisplayKind` replacement. */\nexport const decimalKind: DisplayKind<DecimalDisplay> = {\n kind: 'decimal',\n format: (value, d, ctx) => intlParts(value, ctx.locale, decimalOptions(d)),\n speak: (value, d, ctx) => spokenSign(textOf(intlParts(value, ctx.locale, decimalOptions(d)))),\n parse: (text, _d, ctx) => parseNumber(text, undefined, ctx.locale),\n};\n\nfunction decimalOptions(d: DecimalDisplay): Intl.NumberFormatOptions {\n const grouping = d.grouping ?? true;\n return d.places === undefined\n ? { maximumFractionDigits: d.maxPlaces ?? 3, useGrouping: grouping }\n : { minimumFractionDigits: d.places, maximumFractionDigits: d.places, useGrouping: grouping };\n}\n\n/** A whole number, rounded. */\nexport type IntegerDisplay = {\n kind: 'integer';\n grouping?: boolean;\n};\n\n/** An {@link IntegerDisplay}. */\nexport function integer(options: Omit<IntegerDisplay, 'kind'> = {}): IntegerDisplay {\n return { kind: 'integer', ...options };\n}\n\n/** The built-in `integer` kind, to spread into a `registerDisplayKind` replacement. */\nexport const integerKind: DisplayKind<IntegerDisplay> = {\n kind: 'integer',\n format: (value, d, ctx) =>\n intlParts(value, ctx.locale, { maximumFractionDigits: 0, useGrouping: d.grouping ?? true }),\n speak: (value, d, ctx) =>\n spokenSign(textOf(integerKind.format(value, d, ctx))),\n parse: (text, _d, ctx) => Math.round(parseNumber(text, undefined, ctx.locale)),\n};\n\n/**\n * Below 1,000 at `places` decimals, from 1,000 up at three significant figures\n * with a magnitude suffix (`40.0K`, `2.00M`), so a readout holds one width.\n * Spoken long: `2 million`.\n */\nexport type CompactDisplay = {\n kind: 'compact';\n places?: number;\n};\n\n/** A {@link CompactDisplay}. */\nexport function compact(options: Omit<CompactDisplay, 'kind'> = {}): CompactDisplay {\n return { kind: 'compact', ...options };\n}\n\n/** The built-in `compact` kind, to spread into a `registerDisplayKind` replacement. */\nexport const compactKind: DisplayKind<CompactDisplay> = {\n kind: 'compact',\n format: (value, d) => {\n const text = formatCompact(value, d.places ?? 0);\n const m = /^(.*?\\d)([A-Za-z]+)$/.exec(text);\n return m\n ? [\n { type: 'number', value: m[1]! },\n { type: 'compact', value: m[2]! },\n ]\n : [{ type: 'number', value: text }];\n },\n speak: (value, d, ctx) =>\n spokenSign(\n textOf(\n Math.abs(value) < 1000\n ? compactKind.format(value, d, ctx)\n : intlParts(value, ctx.locale, {\n notation: 'compact',\n compactDisplay: 'long',\n maximumSignificantDigits: 3,\n }),\n ),\n ),\n parse: (text) => parseNumber(text),\n};\n","import { intlParts, numberPart, spokenSign, textOf, type DisplayKind, type Part } from '../kind';\nimport { MINUS_SIGN, parseNumber } from '../number';\n\n/** A share of one as a percentage: 0.25 shows `25%`. Typed text reads as\n * percent with or without the sign. */\nexport type PercentDisplay = {\n kind: 'percent';\n /** Most decimals shown. Default 0. */\n places?: number;\n};\n\n/** A {@link PercentDisplay}. */\nexport function percent(options: Omit<PercentDisplay, 'kind'> = {}): PercentDisplay {\n return { kind: 'percent', ...options };\n}\n\n/** The built-in `percent` kind, to spread into a `registerDisplayKind` replacement. */\nexport const percentKind: DisplayKind<PercentDisplay> = {\n kind: 'percent',\n format: (value, d, ctx) =>\n intlParts(value, ctx.locale, { style: 'percent', maximumFractionDigits: d.places ?? 0 }),\n speak: (value, d, ctx) =>\n spokenSign(\n textOf(\n intlParts(value * 100, ctx.locale, {\n style: 'unit',\n unit: 'percent',\n unitDisplay: 'long',\n maximumFractionDigits: d.places ?? 0,\n }),\n ),\n ),\n parse: (text, _d, ctx) => parseNumber(text.replace(/^\\s*%|%\\s*$/, ''), undefined, ctx.locale) / 100,\n};\n\n/**\n * The nearest fraction whose denominator is at most `maxDenominator`, as\n * `[numerator, denominator]` in lowest terms with the sign on the numerator.\n * Walks the continued fraction and settles the last step on the best\n * semiconvergent, which is the closest any denominator in range can get.\n */\nexport function nearestFraction(x: number, maxDenominator: number): [number, number] {\n if (!Number.isFinite(x)) return [x, 1];\n const sign = x < 0 ? -1 : 1;\n const target = Math.abs(x);\n let [h0, h1, k0, k1] = [0, 1, 1, 0];\n let y = target;\n for (let i = 0; i < 64; i++) {\n const a = Math.floor(y);\n const k2 = a * k1 + k0;\n if (k2 > maxDenominator) {\n const t = Math.floor((maxDenominator - k0) / k1);\n const [hs, ks] = [t * h1 + h0, t * k1 + k0];\n if (Math.abs(hs / ks - target) < Math.abs(h1 / k1 - target)) [h1, k1] = [hs, ks];\n break;\n }\n [h0, h1, k0, k1] = [h1, a * h1 + h0, k1, k2];\n const rest = y - a;\n if (rest < 1e-12 || Math.abs(h1 / k1 - target) < 1e-15) break;\n y = 1 / rest;\n }\n return [sign * h1, k1];\n}\n\n/**\n * A constant a fraction can count in: `π`, so 3π/4 shows as `3π/4` rather\n * than `2.356`. `names` are what may be typed for it besides the symbol.\n */\nexport interface NamedConstant {\n symbol: string;\n value: number;\n /** How it is read aloud: `pi`. */\n spoken: string;\n names?: readonly string[];\n}\n\n/** The constants `fraction({ of })` knows by symbol. */\nexport const CONSTANTS = {\n π: { symbol: 'π', value: Math.PI, spoken: 'pi', names: ['pi'] },\n τ: { symbol: 'τ', value: 2 * Math.PI, spoken: 'tau', names: ['tau'] },\n e: { symbol: 'e', value: Math.E, spoken: 'e' },\n} as const satisfies Record<string, NamedConstant>;\n\ntype FractionOptions = {\n /** Default 64. */\n maxDenominator?: number;\n /**\n * `inline` (default) writes `1/12`. `diagonal` writes `¹⁄₁₂` — superscript\n * digits, the fraction slash, subscript digits — so the text itself is\n * diagonal wherever it is drawn, CSS or not.\n */\n form?: 'inline' | 'diagonal';\n} & (\n | { mixed?: boolean; of?: never }\n | {\n /**\n * Count in a constant: with `π`, 3π/4 shows `3π/4` and is spoken `3 pi\n * over 4`. Excludes `mixed`, since `1 1/2π` reads as 1 + ½π.\n */\n of: keyof typeof CONSTANTS | NamedConstant;\n mixed?: never;\n }\n);\n\n/**\n * A value as the nearest fraction: 1/12 shows `1/12` and is spoken `1 over 12`.\n * `mixed` splits a whole part off (`1 1/2`); a whole value shows as an integer.\n * Has a MathML form, as `<mfrac>`.\n */\nexport type FractionDisplay = { kind: 'fraction' } & FractionOptions;\n\nconst SUPERSCRIPT = '⁰¹²³⁴⁵⁶⁷⁸⁹';\nconst SUBSCRIPT = '₀₁₂₃₄₅₆₇₈₉';\n\nconst inDigits = (n: number, digits: string) => String(n).replace(/\\d/g, (c) => digits[Number(c)]!);\nconst fromDigits = (text: string, digits: string) =>\n Number([...text].map((c) => digits.indexOf(c)).join(''));\n\n/** A {@link FractionDisplay}. */\nexport function fraction(options: FractionOptions = {}): FractionDisplay {\n return { kind: 'fraction', ...options };\n}\n\nfunction constantOf(d: FractionDisplay): NamedConstant | undefined {\n return typeof d.of === 'string' ? CONSTANTS[d.of] : d.of;\n}\n\n/** A fraction's pieces: sign, whole part (mixed only), numerator, denominator,\n * and the constant they count in. */\nfunction fractionPieces(value: number, d: FractionDisplay) {\n const constant = constantOf(d);\n const [n, den] = nearestFraction(constant ? value / constant.value : value, d.maxDenominator ?? 64);\n const negative = n < 0;\n const abs = Math.abs(n);\n const whole = d.mixed || den === 1 ? Math.floor(abs / den) : 0;\n return { negative, whole, num: abs - whole * den, den, constant };\n}\n\n/** A fraction typed inline (`1 1/2`) or diagonally (`1¹⁄₂`), else a plain number. */\nfunction parseFraction(text: string): number {\n const inline = /^\\s*([-−+]?)\\s*(?:(\\d+)\\s+)?(\\d+)\\s*[/⁄]\\s*(\\d+)\\s*$/.exec(text);\n const diagonal = /^\\s*([-−+]?)\\s*(\\d+)?\\s*([⁰¹²³⁴⁵⁶⁷⁸⁹]+)\\s*[/⁄]\\s*([₀₁₂₃₄₅₆₇₈₉]+)\\s*$/.exec(text);\n let magnitude: number;\n if (inline) magnitude = Number(inline[2] ?? 0) + Number(inline[3]) / Number(inline[4]);\n else if (diagonal) {\n magnitude = Number(diagonal[2] ?? 0) + fromDigits(diagonal[3]!, SUPERSCRIPT) / fromDigits(diagonal[4]!, SUBSCRIPT);\n } else return parseNumber(text);\n const sign = (inline ?? diagonal)![1];\n return sign === '-' || sign === MINUS_SIGN ? -magnitude : magnitude;\n}\n\nconst escape = (t: string) => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** The built-in `fraction` kind, to spread into a `registerDisplayKind` replacement. */\nexport const fractionKind: DisplayKind<FractionDisplay> = {\n kind: 'fraction',\n format: (value, d) => {\n if (!Number.isFinite(value)) return [{ type: 'number', value: String(value) }];\n const { negative, whole, num, den, constant } = fractionPieces(value, d);\n const diagonal = d.form === 'diagonal';\n const symbol: Part[] = constant ? [{ type: 'constant', value: constant.symbol }] : [];\n const parts: Part[] = [];\n if (negative) parts.push({ type: 'sign', value: MINUS_SIGN });\n if (num === 0) {\n if (whole === 0) return [...parts, { type: 'whole', value: '0' }];\n if (!(constant && whole === 1)) parts.push({ type: 'whole', value: String(whole) });\n return [...parts, ...symbol];\n }\n if (whole > 0) {\n parts.push({ type: 'whole', value: String(whole) });\n if (!diagonal) parts.push({ type: 'literal', value: ' ' });\n }\n if (diagonal) {\n parts.push(\n { type: 'numerator', value: inDigits(num, SUPERSCRIPT) },\n { type: 'literal', value: '⁄' },\n { type: 'denominator', value: inDigits(den, SUBSCRIPT) },\n ...symbol,\n );\n } else {\n if (!(constant && num === 1)) parts.push({ type: 'numerator', value: String(num) });\n parts.push(...symbol, { type: 'literal', value: '/' }, { type: 'denominator', value: String(den) });\n }\n return parts;\n },\n speak: (value, d) => {\n if (!Number.isFinite(value)) return String(value);\n const { negative, whole, num, den, constant } = fractionPieces(value, d);\n const counted = (n: number) => (!constant ? String(n) : n === 1 ? constant.spoken : `${n} ${constant.spoken}`);\n const words = [\n whole > 0 ? counted(whole) : num === 0 ? '0' : '',\n whole > 0 && num > 0 ? 'and' : '',\n num > 0 ? `${counted(num)} over ${den}` : '',\n ].filter(Boolean);\n return `${negative ? 'minus ' : ''}${words.join(' ')}`;\n },\n parse: (text, d) => {\n const constant = constantOf(d);\n if (!constant) return parseFraction(text);\n const spellings = [constant.symbol, ...(constant.names ?? [])].sort((a, b) => b.length - a.length);\n const token = new RegExp(spellings.map(escape).join('|'), 'i');\n if (!token.test(text)) return parseFraction(text);\n // With the constant taken out, a bare `/2` or nothing at all counts one of it.\n const coefficient = text.replace(token, '').replace(/^(\\s*[-−+]?\\s*)(?=[/⁄]|\\s*$)/, '$11');\n return parseFraction(coefficient) * constant.value;\n },\n mathml: (value, d) => {\n if (!Number.isFinite(value)) return undefined;\n const { negative, whole, num, den, constant } = fractionPieces(value, d);\n const counted = (n: number) => {\n if (!constant) return `<mn>${n}</mn>`;\n const mi = `<mi>${constant.symbol}</mi>`;\n return n === 1 ? mi : `<mn>${n}</mn>${mi}`;\n };\n const body = [\n negative ? `<mo>${MINUS_SIGN}</mo>` : '',\n whole > 0 ? counted(whole) : num === 0 ? '<mn>0</mn>' : '',\n num > 0 ? `<mfrac>${num === 1 || !constant ? counted(num) : `<mrow>${counted(num)}</mrow>`}<mn>${den}</mn></mfrac>` : '',\n ].join('');\n return `<math>${body}</math>`;\n },\n};\n\n/** A value as a ratio `a:b` — 1/12 shows `1:12`, spoken `1 to 12`. */\nexport type RatioDisplay = {\n kind: 'ratio';\n /** Largest second term. Default 64. */\n maxDenominator?: number;\n};\n\n/** A {@link RatioDisplay}. */\nexport function ratio(options: Omit<RatioDisplay, 'kind'> = {}): RatioDisplay {\n return { kind: 'ratio', ...options };\n}\n\n/** The built-in `ratio` kind, to spread into a `registerDisplayKind` replacement. */\nexport const ratioKind: DisplayKind<RatioDisplay> = {\n kind: 'ratio',\n format: (value, d) => {\n if (!Number.isFinite(value)) return [{ type: 'number', value: String(value) }];\n const [n, den] = nearestFraction(value, d.maxDenominator ?? 64);\n return [\n { type: 'antecedent', value: String(n).replace(/^-/, MINUS_SIGN) },\n { type: 'literal', value: ':' },\n { type: 'consequent', value: String(den) },\n ];\n },\n speak: (value, d) => {\n if (!Number.isFinite(value)) return String(value);\n const [n, den] = nearestFraction(value, d.maxDenominator ?? 64);\n return spokenSign(`${String(n).replace(/^-/, MINUS_SIGN)} to ${den}`);\n },\n parse: (text) => {\n const m = /^\\s*(.+?)\\s*:\\s*(.+?)\\s*$/.exec(text);\n return m ? parseNumber(m[1]!) / parseNumber(m[2]!) : parseNumber(text);\n },\n};\n\n/** A factor with a times sign: `2.5×`, spoken `2.5 times`. Typed `x` reads too. */\nexport type MultiplierDisplay = {\n kind: 'multiplier';\n /** Most decimals. Default 2. */\n places?: number;\n /** Default `×`. */\n symbol?: string;\n};\n\n/** A {@link MultiplierDisplay}. */\nexport function multiplier(options: Omit<MultiplierDisplay, 'kind'> = {}): MultiplierDisplay {\n return { kind: 'multiplier', ...options };\n}\n\n/** The built-in `multiplier` kind, to spread into a `registerDisplayKind` replacement. */\nexport const multiplierKind: DisplayKind<MultiplierDisplay> = {\n kind: 'multiplier',\n format: (value, d, ctx) => [\n numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2 }),\n { type: 'symbol', value: d.symbol ?? '×' },\n ],\n speak: (value, d, ctx) =>\n spokenSign(`${numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2 }).value} times`),\n parse: (text, _d, ctx) => parseNumber(text.replace(/\\s*[x×X]\\s*$/, ''), undefined, ctx.locale),\n};\n\n/**\n * A zoom factor. At 2x and below a percentage reads naturally; past it a\n * multiplier is what people say, so 2.5 shows `2.5x`. Past 100x a tenth is\n * noise: `1009.74` shows `1,010x`. Typed text without a sign reads as percent.\n */\nexport type ZoomDisplay = {\n kind: 'zoom';\n};\n\n/** A {@link ZoomDisplay}. */\nexport function zoom(): ZoomDisplay {\n return { kind: 'zoom' };\n}\n\nfunction zoomParts(z: number): Part[] {\n if (!Number.isFinite(z)) return [{ type: 'number', value: String(z) }];\n const n = (v: number, grouping = false) =>\n ({ type: 'number', value: v.toLocaleString('en-US', { useGrouping: grouping, maximumFractionDigits: 1 }).replace(/^-/, MINUS_SIGN) });\n if (z <= 2) return [n(Math.round(z * 100)), { type: 'percentSign', value: '%' }];\n if (z >= 100) return [n(Math.round(z), true), { type: 'symbol', value: 'x' }];\n return [n(Math.round(z * 10) / 10), { type: 'symbol', value: 'x' }];\n}\n\n/** The built-in `zoom` kind, to spread into a `registerDisplayKind` replacement. */\nexport const zoomKind: DisplayKind<ZoomDisplay> = {\n kind: 'zoom',\n format: (value) => zoomParts(value),\n speak: (value) =>\n spokenSign(\n zoomParts(value)\n .map((p) => (p.type === 'percentSign' ? ' percent' : p.type === 'symbol' ? ' times' : p.value))\n .join(''),\n ),\n parse: (text) => {\n const t = text.trim();\n if (/[x×X]$/.test(t)) return parseNumber(t.slice(0, -1));\n return parseNumber(t.replace(/%$/, '')) / 100;\n },\n};\n","import { intlParts, numberPart, plural, spokenSign, textOf, type DisplayKind, type Part } from '../kind';\nimport { decimalOf, escapeClass, latinDigits, parseNumber, type UnitTable } from '../number';\n\n/**\n * Units `Intl` can name aloud, by the symbol a field shows. A unit outside it\n * speaks through the display's `spoken` names, else as its symbol.\n */\nconst INTL_UNITS: Record<string, string> = {\n mm: 'millimeter',\n cm: 'centimeter',\n m: 'meter',\n km: 'kilometer',\n in: 'inch',\n '\"': 'inch',\n '″': 'inch',\n ft: 'foot',\n \"'\": 'foot',\n '′': 'foot',\n yd: 'yard',\n mi: 'mile',\n deg: 'degree',\n '°': 'degree',\n ms: 'millisecond',\n s: 'second',\n min: 'minute',\n h: 'hour',\n g: 'gram',\n kg: 'kilogram',\n L: 'liter',\n '%': 'percent',\n};\n\n/** Names for common units `Intl` has none for. */\nconst OWN_UNITS: Record<string, readonly [string, string]> = {\n px: ['pixel', 'pixels'],\n pt: ['point', 'points'],\n rad: ['radian', 'radians'],\n turn: ['turn', 'turns'],\n};\n\n/**\n * A number with its unit: `12mm`, spoken `12 millimeters`. The unit is the\n * display's, else the one the value is tagged with. `accepts` is what a person\n * may type, each unit mapped to its conversion into the shown one; compound\n * text such as `5ft 3in` reads when every term's unit is accepted.\n */\nexport type UnitDisplay = {\n kind: 'unit';\n unit?: string;\n /** Most decimals, trailing zeros dropped. Default 2. */\n places?: number;\n /** A space between number and unit. Default false. */\n space?: boolean;\n accepts?: UnitTable;\n /** Singular and plural names, for a unit `Intl` cannot name. */\n spoken?: readonly [string, string];\n};\n\n/** A {@link UnitDisplay} in `name`. With no name, the unit comes from the value's tag. */\nexport function unit(name?: string, options: Omit<UnitDisplay, 'kind' | 'unit'> = {}): UnitDisplay {\n return name === undefined ? { kind: 'unit', ...options } : { kind: 'unit', unit: name, ...options };\n}\n\n/** The built-in `unit` kind, to spread into a `registerDisplayKind` replacement. */\nexport const unitKind: DisplayKind<UnitDisplay> = {\n kind: 'unit',\n format: (value, d, ctx) => {\n const parts: Part[] = [numberPart(value, ctx.locale, { maximumFractionDigits: d.places ?? 2, useGrouping: false })];\n const name = d.unit ?? ctx.unit;\n if (name) {\n if (d.space) parts.push({ type: 'literal', value: ' ' });\n parts.push({ type: 'unit', value: name });\n }\n return parts;\n },\n speak: (value, d, ctx) => {\n const places = d.places ?? 2;\n const name = d.unit ?? ctx.unit;\n const intl = name === undefined ? undefined : INTL_UNITS[name];\n if (intl !== undefined && d.spoken === undefined) {\n return spokenSign(\n textOf(intlParts(value, ctx.locale, { style: 'unit', unit: intl, unitDisplay: 'long', maximumFractionDigits: places })),\n );\n }\n const number = numberPart(value, ctx.locale, { maximumFractionDigits: places, useGrouping: false }).value;\n const names = d.spoken ?? (name === undefined ? undefined : OWN_UNITS[name]);\n const word = names ? plural(value, ctx.locale, names[0], names[1]) : name;\n return spokenSign(word ? `${number} ${word}` : number);\n },\n parse: (text, d, ctx) => {\n const name = d.unit ?? ctx.unit;\n return parseNumber(text, d.accepts ?? (name ? { [name]: 1 } : undefined), ctx.locale);\n },\n};\n\n/** Money in an ISO 4217 currency: `$12.50`, spoken `12.50 US dollars`. */\nexport type CurrencyDisplay = {\n kind: 'currency';\n currency: string;\n /** Fixed decimals. Defaults to the currency's own (2 for USD, 0 for JPY). */\n places?: number;\n};\n\n/** A {@link CurrencyDisplay} in the ISO 4217 currency `code`. */\nexport function currency(code: string, options: Omit<CurrencyDisplay, 'kind' | 'currency'> = {}): CurrencyDisplay {\n return { kind: 'currency', currency: code, ...options };\n}\n\nfunction currencyOptions(d: CurrencyDisplay): Intl.NumberFormatOptions {\n const options: Intl.NumberFormatOptions = { style: 'currency', currency: d.currency };\n if (d.places !== undefined) {\n options.minimumFractionDigits = d.places;\n options.maximumFractionDigits = d.places;\n }\n return options;\n}\n\n/** The built-in `currency` kind, to spread into a `registerDisplayKind` replacement. */\nexport const currencyKind: DisplayKind<CurrencyDisplay> = {\n kind: 'currency',\n format: (value, d, ctx) => intlParts(value, ctx.locale, currencyOptions(d)),\n speak: (value, d, ctx) =>\n spokenSign(textOf(intlParts(value, ctx.locale, { ...currencyOptions(d), currencyDisplay: 'name' }))),\n parse: (text, _d, ctx) => parseNumber(text.replace(/[^\\d.,'’+\\-−]/g, ''), undefined, ctx.locale),\n};\n\n/**\n * A span of time, the value in seconds. `clock` shows `1:02:03` or `4:05.5`;\n * `units` shows `2h 5m 3s`. Spoken `2 hours, 5 minutes, 3 seconds`. Typed text\n * reads in either form.\n */\nexport type DurationDisplay = {\n kind: 'duration';\n /** Default `'clock'`. */\n style?: 'clock' | 'units';\n /** Decimals on the seconds. Default 0. */\n places?: number;\n};\n\n/** A {@link DurationDisplay}. */\nexport function duration(options: Omit<DurationDisplay, 'kind'> = {}): DurationDisplay {\n return { kind: 'duration', ...options };\n}\n\n/** Hours, minutes and seconds of `value` after rounding to `places`. */\nfunction hms(value: number, places: number) {\n const scale = 10 ** places;\n const total = Math.round(Math.abs(value) * scale) / scale;\n const h = Math.floor(total / 3600);\n const m = Math.floor((total - h * 3600) / 60);\n const s = Math.round((total - h * 3600 - m * 60) * scale) / scale;\n return { negative: value < 0 && total > 0, h, m, s };\n}\n\nconst DURATION_UNITS: UnitTable = { h: 3600, m: 60, min: 60, s: 1, ms: 0.001 };\n\n/** The built-in `duration` kind, to spread into a `registerDisplayKind` replacement. */\nexport const durationKind: DisplayKind<DurationDisplay> = {\n kind: 'duration',\n format: (value, d) => {\n if (!Number.isFinite(value)) return [{ type: 'number', value: String(value) }];\n const places = d.places ?? 0;\n const { negative, h, m, s } = hms(value, places);\n const sec = s.toFixed(places);\n const parts: Part[] = negative ? [{ type: 'sign', value: '−' }] : [];\n if (d.style === 'units') {\n const terms: Part[][] = [];\n if (h > 0) terms.push([{ type: 'hours', value: String(h) }, { type: 'unit', value: 'h' }]);\n if (m > 0) terms.push([{ type: 'minutes', value: String(m) }, { type: 'unit', value: 'm' }]);\n if (s > 0 || terms.length === 0) terms.push([{ type: 'seconds', value: sec }, { type: 'unit', value: 's' }]);\n terms.forEach((t, i) => parts.push(...(i > 0 ? [{ type: 'literal', value: ' ' }] : []), ...t));\n return parts;\n }\n const pad = (n: string) => (n.split('.')[0]!.length < 2 ? `0${n}` : n);\n if (h > 0) {\n parts.push(\n { type: 'hours', value: String(h) },\n { type: 'literal', value: ':' },\n { type: 'minutes', value: pad(String(m)) },\n );\n } else {\n parts.push({ type: 'minutes', value: String(m) });\n }\n parts.push({ type: 'literal', value: ':' }, { type: 'seconds', value: pad(sec) });\n return parts;\n },\n speak: (value, d, ctx) => {\n if (!Number.isFinite(value)) return String(value);\n const { negative, h, m, s } = hms(value, d.places ?? 0);\n const terms: string[] = [];\n if (h > 0) terms.push(`${h} ${plural(h, ctx.locale, 'hour', 'hours')}`);\n if (m > 0) terms.push(`${m} ${plural(m, ctx.locale, 'minute', 'minutes')}`);\n if (s > 0 || terms.length === 0) terms.push(`${s} ${plural(s, ctx.locale, 'second', 'seconds')}`);\n return `${negative ? 'minus ' : ''}${terms.join(', ')}`;\n },\n parse: (text, _d, ctx) => {\n const d = escapeClass(decimalOf(ctx.locale));\n const clock = new RegExp(String.raw`^\\s*([-−+]?)\\s*(?:(\\d+):)?(\\d+):(\\d+)(?:[.${d}](\\d+))?\\s*$`);\n const m = clock.exec(latinDigits(text, ctx.locale));\n if (!m) return parseNumber(text, DURATION_UNITS, ctx.locale);\n const total = Number(m[2] ?? 0) * 3600 + Number(m[3]) * 60 + Number(`${m[4]}.${m[5] ?? 0}`);\n return m[1] === '-' || m[1] === '−' ? -total : total;\n },\n};\n\nconst DECIMAL_BYTES = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'] as const;\nconst BINARY_BYTES = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] as const;\nconst DECIMAL_NAMES = ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte', 'petabyte'] as const;\nconst BINARY_NAMES = ['byte', 'kibibyte', 'mebibyte', 'gibibyte', 'tebibyte', 'pebibyte'] as const;\n\n/** A byte count in the largest unit that keeps it at or above 1: `1.2 MB`,\n * spoken `1.2 megabytes`. `base: 1024` uses `KiB`, `MiB`, … */\nexport type BytesDisplay = {\n kind: 'bytes';\n /** Default 1000. */\n base?: 1000 | 1024;\n /** Most decimals. Default 1. */\n places?: number;\n};\n\n/** A {@link BytesDisplay}. */\nexport function bytes(options: Omit<BytesDisplay, 'kind'> = {}): BytesDisplay {\n return { kind: 'bytes', ...options };\n}\n\nfunction byteScale(value: number, base: number): { scaled: number; step: number } {\n let step = 0;\n let scaled = value;\n while (Math.abs(scaled) >= base && step < DECIMAL_BYTES.length - 1) {\n scaled /= base;\n step++;\n }\n return { scaled, step };\n}\n\nconst BYTE_UNITS: UnitTable = Object.fromEntries([\n ...DECIMAL_BYTES.map((u, i) => [u, 1000 ** i] as const),\n ['KB', 1000],\n ...BINARY_BYTES.slice(1).map((u, i) => [u, 1024 ** (i + 1)] as const),\n]);\n\n/** The built-in `bytes` kind, to spread into a `registerDisplayKind` replacement. */\nexport const bytesKind: DisplayKind<BytesDisplay> = {\n kind: 'bytes',\n format: (value, d, ctx) => {\n const base = d.base ?? 1000;\n const { scaled, step } = byteScale(value, base);\n const units = base === 1024 ? BINARY_BYTES : DECIMAL_BYTES;\n return [\n numberPart(scaled, ctx.locale, { maximumFractionDigits: step === 0 ? 0 : (d.places ?? 1) }),\n { type: 'literal', value: ' ' },\n { type: 'unit', value: units[step]! },\n ];\n },\n speak: (value, d, ctx) => {\n const base = d.base ?? 1000;\n const { scaled, step } = byteScale(value, base);\n const name = (base === 1024 ? BINARY_NAMES : DECIMAL_NAMES)[step]!;\n const number = numberPart(scaled, ctx.locale, { maximumFractionDigits: step === 0 ? 0 : (d.places ?? 1) }).value;\n return spokenSign(`${number} ${plural(Math.abs(parseNumber(number, undefined, ctx.locale)), ctx.locale, name, `${name}s`)}`);\n },\n parse: (text, _d, ctx) => parseNumber(text, BYTE_UNITS, ctx.locale),\n};\n","import { numberPart, spokenSign, type DisplayKind } from '../kind';\nimport { parseNumber } from '../number';\n\n/**\n * A whole number in Roman numerals, `XII`. Spoken as the plain number, since a\n * screen reader otherwise spells the letters out. Outside 1–3999, which the\n * numerals cannot write, it shows as a plain number.\n */\nexport type RomanDisplay = {\n kind: 'roman';\n lower?: boolean;\n};\n\n/** A {@link RomanDisplay}. */\nexport function roman(options: Omit<RomanDisplay, 'kind'> = {}): RomanDisplay {\n return { kind: 'roman', ...options };\n}\n\nconst NUMERALS: readonly [number, string][] = [\n [1000, 'M'], [900, 'CM'], [500, 'D'], [400, 'CD'], [100, 'C'], [90, 'XC'],\n [50, 'L'], [40, 'XL'], [10, 'X'], [9, 'IX'], [5, 'V'], [4, 'IV'], [1, 'I'],\n];\n\n/** `n` in Roman numerals, or undefined outside 1–3999. */\nexport function toRoman(n: number): string | undefined {\n let rest = Math.round(n);\n if (!(rest >= 1 && rest <= 3999)) return undefined;\n let out = '';\n for (const [v, s] of NUMERALS) {\n while (rest >= v) {\n out += s;\n rest -= v;\n }\n }\n return out;\n}\n\n/** The value of well-formed Roman numerals, either case; NaN otherwise. */\nexport function fromRoman(text: string): number {\n const t = text.trim().toUpperCase();\n if (!/^[MDCLXVI]+$/.test(t)) return Number.NaN;\n let total = 0;\n let i = 0;\n for (const [v, s] of NUMERALS) {\n while (t.startsWith(s, i)) {\n total += v;\n i += s.length;\n }\n }\n // Anything left unread, or a non-canonical spelling such as `IIII`, is not a numeral.\n return i === t.length && toRoman(total) === t ? total : Number.NaN;\n}\n\n/** The built-in `roman` kind, to spread into a `registerDisplayKind` replacement. */\nexport const romanKind: DisplayKind<RomanDisplay> = {\n kind: 'roman',\n format: (value, d, ctx) => {\n const r = toRoman(value);\n if (r === undefined) return [numberPart(value, ctx.locale, { maximumFractionDigits: 0 })];\n return [{ type: 'numeral', value: d.lower ? r.toLowerCase() : r }];\n },\n speak: (value, _d, ctx) => spokenSign(numberPart(Math.round(value), ctx.locale, { maximumFractionDigits: 0, useGrouping: false }).value),\n parse: (text, _d, ctx) => {\n const r = fromRoman(text);\n return Number.isNaN(r) ? parseNumber(text, undefined, ctx.locale) : r;\n },\n};\n\n/** A whole number as an ordinal: `1st`, `22nd`, `113th`. English suffixes;\n * in any other locale the number shows alone. */\nexport type OrdinalDisplay = {\n kind: 'ordinal';\n};\n\n/** An {@link OrdinalDisplay}. */\nexport function ordinal(): OrdinalDisplay {\n return { kind: 'ordinal' };\n}\n\nconst SUFFIXES: Record<string, string> = { one: 'st', two: 'nd', few: 'rd', other: 'th' };\n\n/** The built-in `ordinal` kind, to spread into a `registerDisplayKind` replacement. */\nexport const ordinalKind: DisplayKind<OrdinalDisplay> = {\n kind: 'ordinal',\n format: (value, _d, ctx) => {\n const n = Math.round(value);\n const number = numberPart(n, ctx.locale, { maximumFractionDigits: 0 });\n if (!Number.isFinite(n) || !ctx.locale.startsWith('en')) return [number];\n const rule = new Intl.PluralRules('en-US', { type: 'ordinal' }).select(n);\n return [number, { type: 'ordinal', value: SUFFIXES[rule] ?? 'th' }];\n },\n parse: (text, _d, ctx) => Math.round(parseNumber(text.replace(/(st|nd|rd|th)\\s*$/i, ''), undefined, ctx.locale)),\n};\n","import { textOf, type DisplayKind, type FormatContext, type Part } from './kind';\nimport { compactKind, decimalKind, integerKind } from './kinds/plain';\nimport { fractionKind, multiplierKind, percentKind, ratioKind, zoomKind } from './kinds/proportion';\nimport { bytesKind, currencyKind, durationKind, unitKind } from './kinds/measure';\nimport { ordinalKind, romanKind } from './kinds/numeral';\nimport { parseNumber } from './number';\nimport { amount, displayOf, retag, tag, unitOf, type Display, type Quantity, type Tagged } from './quantity';\nimport { unitScale, type Unit, type UnitSystem } from './units';\n\n// A static table rather than registration at import, so the package stays\n// free of side effects and a bundler can drop what nobody imports.\nconst BUILTIN: Record<string, DisplayKind<never>> = Object.fromEntries(\n [\n decimalKind, integerKind, compactKind,\n percentKind, fractionKind, ratioKind, multiplierKind, zoomKind,\n unitKind, currencyKind, durationKind, bytesKind,\n romanKind, ordinalKind,\n ].map((k) => [k.kind, k as DisplayKind<never>]),\n);\n\nconst registered = new Map<string, DisplayKind<never>>();\n\n/**\n * Adds a display kind, or replaces a built-in one — the way to swap in a words\n * library for `fraction`'s spoken form (`{ ...fractionKind, speak }`). Returns\n * a function that removes it again.\n */\nexport function registerDisplayKind<D extends Display>(kind: DisplayKind<D>): () => void {\n const entry = kind as unknown as DisplayKind<never>;\n registered.set(kind.kind, entry);\n return () => {\n if (registered.get(kind.kind) === entry) registered.delete(kind.kind);\n };\n}\n\n/**\n * The kind behind `display`. An unknown kind resolves to `decimal` rather than\n * throwing: a document saved by an app with a custom kind still opens in one\n * without it, and its tag survives untouched.\n */\nexport function displayKindOf(display: Display | undefined): DisplayKind<Display> {\n const kind = display === undefined ? undefined : (registered.get(display.kind) ?? BUILTIN[display.kind]);\n return (kind ?? decimalKind) as unknown as DisplayKind<Display>;\n}\n\n/** Options for presenting or parsing a quantity. */\nexport interface PresentOptions {\n /** BCP 47 locale. Default `en-US`. */\n locale?: string;\n}\n\n/** A quantity as text, spoken text, HTML and, where its kind has one, MathML. */\nexport interface Presentation {\n text: string;\n spoken: string;\n /** Unstyled: a `<data value>` wrapping one `<span data-part>` per named part. */\n html: string;\n mathml?: string;\n}\n\nconst DEFAULT_DISPLAY: Display = { kind: 'decimal' };\n\nfunction contextOf(q: Quantity, options: PresentOptions | undefined): FormatContext {\n const unit = unitOf(q);\n return unit === undefined ? { locale: options?.locale ?? 'en-US' } : { locale: options?.locale ?? 'en-US', unit };\n}\n\nconst ESCAPES: Record<string, string> = { '&': '&', '<': '<', '>': '>', '\"': '"' };\nfunction escape(s: string): string {\n return s.replace(/[&<>\"]/g, (c) => ESCAPES[c]!);\n}\n\n/** Parts as the unstyled HTML fragment {@link Presentation.html} describes. */\nexport function partsToHtml(value: number, parts: readonly Part[]): string {\n const body = parts\n .map((p) => (p.type === 'literal' ? escape(p.value) : `<span data-part=\"${escape(p.type)}\">${escape(p.value)}</span>`))\n .join('');\n return `<data value=\"${escape(String(value))}\">${body}</data>`;\n}\n\n/** Parts of `q` under its own display, else `fallback`, else `decimal`. */\nexport function partsOf(q: Quantity, fallback?: Display, options?: PresentOptions): Part[] {\n const display = displayOf(q, fallback) ?? DEFAULT_DISPLAY;\n return displayKindOf(display).format(amount(q), display, contextOf(q, options));\n}\n\n/** `q` as text, spoken text, HTML and MathML. See {@link qty} for one at a time. */\nexport function present(q: Quantity, fallback?: Display, options?: PresentOptions): Presentation {\n const display = displayOf(q, fallback) ?? DEFAULT_DISPLAY;\n const kind = displayKindOf(display);\n const value = amount(q);\n const ctx = contextOf(q, options);\n const parts = kind.format(value, display, ctx);\n const text = textOf(parts);\n const out: Presentation = {\n text,\n spoken: kind.speak ? kind.speak(value, display, ctx) : text,\n html: partsToHtml(value, parts),\n };\n const mathml = kind.mathml?.(value, display, ctx);\n if (mathml !== undefined) out.mathml = mathml;\n return out;\n}\n\n/** Typed text read through `display`: NaN when it does not read. */\nexport function parseAs(text: string, display?: Display, options?: PresentOptions & { unit?: Unit }): number {\n const d = display ?? DEFAULT_DISPLAY;\n const kind = displayKindOf(d);\n const ctx: FormatContext = { locale: options?.locale ?? 'en-US' };\n if (options?.unit !== undefined) ctx.unit = options.unit;\n return kind.parse ? kind.parse(text, d, ctx) : parseNumber(text, undefined, ctx.locale);\n}\n\n/**\n * A short-lived view of a quantity with its presentation as methods. Nothing\n * about it is stored — keep the quantity, and wrap it where it is shown.\n */\nexport class QuantityView<Q extends Quantity = Quantity> {\n constructor(\n /** The quantity as given. */\n readonly raw: Q,\n private readonly fallback?: Display,\n private readonly options?: PresentOptions,\n ) {}\n\n get value(): number {\n return amount(this.raw);\n }\n get unit(): Unit | undefined {\n return unitOf(this.raw);\n }\n /** The display in effect: the value's own, else the fallback. */\n get display(): Display | undefined {\n return displayOf(this.raw, this.fallback);\n }\n get parts(): Part[] {\n return partsOf(this.raw, this.fallback, this.options);\n }\n get text(): string {\n return textOf(this.parts);\n }\n get spoken(): string {\n return present(this.raw, this.fallback, this.options).spoken;\n }\n get html(): string {\n return partsToHtml(this.value, this.parts);\n }\n get mathml(): string | undefined {\n return present(this.raw, this.fallback, this.options).mathml;\n }\n /** `next` in this quantity's shape — see {@link retag}. */\n with(next: number): QuantityView<Q> {\n return new QuantityView(retag(this.raw, next), this.fallback, this.options);\n }\n /** Typed text read through this quantity's display; NaN when it does not read. */\n parse(text: string): number {\n const unit = this.unit;\n return parseAs(text, this.display, unit === undefined ? this.options : { ...this.options, unit });\n }\n /** The same amount in `target`, converted through `system`, tagged with it. */\n to(target: Unit, system: UnitSystem): QuantityView {\n const from = unitScale(system, this.unit ?? system.base);\n const to = unitScale(system, target);\n const base = this.value * from.factor + from.offset;\n const value = (base - to.offset) / to.factor;\n const raw = typeof this.raw === 'number' ? tag(value, undefined, target) : { ...(this.raw as Tagged), value, unit: target };\n return new QuantityView(raw, this.fallback, this.options);\n }\n toJSON(): Q {\n return this.raw;\n }\n}\n\n/** Wraps `q` for display: `qty(band.from, fraction()).text`. `fallback` is the\n * display for a value that carries none of its own. */\nexport function qty<Q extends Quantity>(q: Q, fallback?: Display, options?: PresentOptions): QuantityView<Q> {\n return new QuantityView(q, fallback, options);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/quantity",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Numbers with units and a display: fractions, ratios, currency, durations and more, as text, spoken text, HTML and MathML. No React, no DOM.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|