numeric-quantity 2.0.0-beta.3 → 2.0.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/README.md CHANGED
@@ -1,12 +1,12 @@
1
- # numeric-quantity
2
-
3
1
  [![npm][badge-npm]](https://www.npmjs.com/package/numeric-quantity)
4
2
  ![workflow status](https://github.com/jakeboone02/numeric-quantity/actions/workflows/main.yml/badge.svg)
5
3
  [![codecov.io](https://codecov.io/github/jakeboone02/numeric-quantity/coverage.svg?branch=main)](https://codecov.io/github/jakeboone02/numeric-quantity?branch=main)
6
4
  [![downloads](https://img.shields.io/npm/dm/numeric-quantity.svg)](http://npm-stat.com/charts.html?package=numeric-quantity&from=2015-08-01)
7
5
  [![MIT License](https://img.shields.io/npm/l/numeric-quantity.svg)](http://opensource.org/licenses/MIT)
8
6
 
9
- Converts a string to a number, like an enhanced version of `parseFloat`. The return value will be `NaN` if the provided string does not resemble a number.
7
+ Converts a string to a number, like an enhanced version of `parseFloat`.
8
+
9
+ **[Full documentation](https://jakeboone02.github.io/numeric-quantity/)**
10
10
 
11
11
  Features:
12
12
 
@@ -14,6 +14,7 @@ Features:
14
14
  - To allow and ignore trailing invalid characters _à la_ `parseFloat`, pass `{ allowTrailingInvalid: true }` as the second argument.
15
15
  - To parse Roman numerals like `'MCCXIV'` or `'Ⅻ'`, pass `{ romanNumerals: true }` as the second argument or call `parseRomanNumerals` directly.
16
16
  - Results will be rounded to three decimal places by default. To avoid rounding, pass `{ round: false }` as the second argument. To round to a different number of decimal places, assign that number to the `round` option (`{ round: 5 }` will round to five decimal places).
17
+ - Returns `NaN` if the provided string does not resemble a number.
17
18
 
18
19
  > _For the inverse operation—converting a number to an imperial measurement—check out [format-quantity](https://www.npmjs.com/package/format-quantity)._
19
20
  >
@@ -47,28 +48,8 @@ As UMD (all exports are properties of the global object `NumericQuantity`):
47
48
  ```html
48
49
  <script src="https://unpkg.com/numeric-quantity"></script>
49
50
  <script>
50
- console.log(NumericQuantity.numericQuantity('xii')); // 12
51
+ console.log(NumericQuantity.numericQuantity('xii', { romanNumerals: true })); // 12
51
52
  </script>
52
53
  ```
53
54
 
54
- ## Other exports
55
-
56
- | Name | Type | Description |
57
- | --------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------- |
58
- | `numericRegex` | `RegExp` | Regular expression matching a string that resembles a number (using Arabic numerals) in its entirety |
59
- | `numericRegexWithTrailingInvalid` | `RegExp` | Same as `numericRegex`, but allows/ignores trailing invalid characters. |
60
- | `VulgarFraction` | `type` | Union type of all unicode vulgar fraction code points |
61
- | `vulgarFractionsRegex` | `RegExp` | Regular expression matching the first unicode vulgar fraction code point |
62
- | `vulgarFractionToAsciiMap` | `object` | Mapping of each vulgar fraction to its traditional ASCII representation (e.g., `'½'` to `'1/2'`) |
63
- | `parseRomanNumerals` | `function` | Same function signature as `numericQuantity`, but only for Roman numerals (used internally) |
64
- | `romanNumeralRegex` | `RegExp` | Regular expression matching valid Roman numeral sequences (uses modern, strict rules) |
65
- | `romanNumeralUnicodeRegex` | `RegExp` | Regular expression matching any unicode Roman numeral code point |
66
- | `romanNumeralUnicodeToAsciiMap` | `object` | Mapping of each Roman numeral to its traditional ASCII representation (e.g., `'Ⅻ'` to `'XII'`) |
67
- | `romanNumeralValues` | `object` | Mapping of each valid Roman numeral sequence fragment to its numeric value |
68
- | `NumericQuantityOptions` | `interface` | Shape of the (optional) second argument to `numericQuantity` |
69
- | `RomanNumeralAscii` | `type` | Union type of allowable Roman numeral characters (uppercase only) |
70
- | `RomanNumeralUnicode` | `type` | Union type of all Unicode Roman numeral characters (representing 1-12, 50, 100, 500, and 1000) |
71
- | `RomanNumeral` | `type` | Union type of `RomanNumeralAscii` and `RomanNumeralUnicode` |
72
- | `defaultOptions` | `object` | Object representing the default options |
73
-
74
55
  [badge-npm]: https://img.shields.io/npm/v/numeric-quantity.svg?cacheSeconds=3600&logo=npm
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Map of Unicode fraction code points to their ASCII equivalents.
3
+ */
4
+ declare const vulgarFractionToAsciiMap: {
5
+ readonly '\u00BC': "1/4";
6
+ readonly '\u00BD': "1/2";
7
+ readonly '\u00BE': "3/4";
8
+ readonly '\u2150': "1/7";
9
+ readonly '\u2151': "1/9";
10
+ readonly '\u2152': "1/10";
11
+ readonly '\u2153': "1/3";
12
+ readonly '\u2154': "2/3";
13
+ readonly '\u2155': "1/5";
14
+ readonly '\u2156': "2/5";
15
+ readonly '\u2157': "3/5";
16
+ readonly '\u2158': "4/5";
17
+ readonly '\u2159': "1/6";
18
+ readonly '\u215A': "5/6";
19
+ readonly '\u215B': "1/8";
20
+ readonly '\u215C': "3/8";
21
+ readonly '\u215D': "5/8";
22
+ readonly '\u215E': "7/8";
23
+ readonly '\u215F': "1/";
24
+ };
25
+ /**
26
+ * Captures the individual elements of a numeric string.
27
+ *
28
+ * Capture groups:
29
+ *
30
+ * | # | Description | Example(s) |
31
+ * | --- | ------------------------------------------------ | ------------------------------------------------------------------- |
32
+ * | `0` | entire string | `"2 1/3"` from `"2 1/3"` |
33
+ * | `1` | "negative" dash | `"-"` from `"-2 1/3"` |
34
+ * | `2` | whole number or numerator | `"2"` from `"2 1/3"`; `"1"` from `"1/3"` |
35
+ * | `3` | entire fraction, decimal portion, or denominator | `" 1/3"` from `"2 1/3"`; `".33"` from `"2.33"`; `"/3"` from `"1/3"` |
36
+ *
37
+ * _Capture group 2 may include comma/underscore separators._
38
+ *
39
+ * @example
40
+ *
41
+ * ```ts
42
+ * numericRegex.exec("1") // [ "1", "1", null, null ]
43
+ * numericRegex.exec("1.23") // [ "1.23", "1", ".23", null ]
44
+ * numericRegex.exec("1 2/3") // [ "1 2/3", "1", " 2/3", " 2" ]
45
+ * numericRegex.exec("2/3") // [ "2/3", "2", "/3", null ]
46
+ * numericRegex.exec("2 / 3") // [ "2 / 3", "2", "/ 3", null ]
47
+ * ```
48
+ */
49
+ declare const numericRegex: RegExp;
50
+ /**
51
+ * Same as {@link numericRegex}, but allows (and ignores) trailing invalid characters.
52
+ */
53
+ declare const numericRegexWithTrailingInvalid: RegExp;
54
+ /**
55
+ * Captures any Unicode vulgar fractions.
56
+ */
57
+ declare const vulgarFractionsRegex: RegExp;
58
+ /**
59
+ * Map of Roman numeral sequences to their decimal equivalents.
60
+ */
61
+ declare const romanNumeralValues: {
62
+ readonly MMM: 3000;
63
+ readonly MM: 2000;
64
+ readonly M: 1000;
65
+ readonly CM: 900;
66
+ readonly DCCC: 800;
67
+ readonly DCC: 700;
68
+ readonly DC: 600;
69
+ readonly D: 500;
70
+ readonly CD: 400;
71
+ readonly CCC: 300;
72
+ readonly CC: 200;
73
+ readonly C: 100;
74
+ readonly XC: 90;
75
+ readonly LXXX: 80;
76
+ readonly LXX: 70;
77
+ readonly LX: 60;
78
+ readonly L: 50;
79
+ readonly XL: 40;
80
+ readonly XXX: 30;
81
+ readonly XX: 20;
82
+ readonly XII: 12;
83
+ readonly XI: 11;
84
+ readonly X: 10;
85
+ readonly IX: 9;
86
+ readonly VIII: 8;
87
+ readonly VII: 7;
88
+ readonly VI: 6;
89
+ readonly V: 5;
90
+ readonly IV: 4;
91
+ readonly III: 3;
92
+ readonly II: 2;
93
+ readonly I: 1;
94
+ };
95
+ /**
96
+ * Map of Unicode Roman numeral code points to their ASCII equivalents.
97
+ */
98
+ declare const romanNumeralUnicodeToAsciiMap: {
99
+ readonly Ⅰ: "I";
100
+ readonly Ⅱ: "II";
101
+ readonly Ⅲ: "III";
102
+ readonly Ⅳ: "IV";
103
+ readonly Ⅴ: "V";
104
+ readonly Ⅵ: "VI";
105
+ readonly Ⅶ: "VII";
106
+ readonly Ⅷ: "VIII";
107
+ readonly Ⅸ: "IX";
108
+ readonly Ⅹ: "X";
109
+ readonly Ⅺ: "XI";
110
+ readonly Ⅻ: "XII";
111
+ readonly Ⅼ: "L";
112
+ readonly Ⅽ: "C";
113
+ readonly Ⅾ: "D";
114
+ readonly Ⅿ: "M";
115
+ readonly ⅰ: "I";
116
+ readonly ⅱ: "II";
117
+ readonly ⅲ: "III";
118
+ readonly ⅳ: "IV";
119
+ readonly ⅴ: "V";
120
+ readonly ⅵ: "VI";
121
+ readonly ⅶ: "VII";
122
+ readonly ⅷ: "VIII";
123
+ readonly ⅸ: "IX";
124
+ readonly ⅹ: "X";
125
+ readonly ⅺ: "XI";
126
+ readonly ⅻ: "XII";
127
+ readonly ⅼ: "L";
128
+ readonly ⅽ: "C";
129
+ readonly ⅾ: "D";
130
+ readonly ⅿ: "M";
131
+ };
132
+ /**
133
+ * Captures all Unicode Roman numeral code points.
134
+ */
135
+ declare const romanNumeralUnicodeRegex: RegExp;
136
+ /**
137
+ * Captures a valid Roman numeral sequence.
138
+ *
139
+ * Capture groups:
140
+ *
141
+ * | # | Description | Example |
142
+ * | --- | --------------- | ------------------------ |
143
+ * | `0` | Entire string | "MCCXIV" from "MCCXIV" |
144
+ * | `1` | Thousands | "M" from "MCCXIV" |
145
+ * | `2` | Hundreds | "CC" from "MCCXIV" |
146
+ * | `3` | Tens | "X" from "MCCXIV" |
147
+ * | `4` | Ones | "IV" from "MCCXIV" |
148
+ *
149
+ * @example
150
+ *
151
+ * ```ts
152
+ * romanNumeralRegex.exec("M") // [ "M", "M", "", "", "" ]
153
+ * romanNumeralRegex.exec("XII") // [ "XII", "", "", "X", "II" ]
154
+ * romanNumeralRegex.exec("MCCXIV") // [ "MCCXIV", "M", "CC", "X", "IV" ]
155
+ * ```
156
+ */
157
+ declare const romanNumeralRegex: RegExp;
158
+ /**
159
+ * Default options for {@link numericQuantity}.
160
+ */
161
+ declare const defaultOptions: {
162
+ round: number;
163
+ allowTrailingInvalid: false;
164
+ romanNumerals: false;
165
+ };
166
+
167
+ interface NumericQuantityOptions {
168
+ /**
169
+ * Round the result to this many decimal places. Defaults to 3; must
170
+ * be greater than or equal to zero.
171
+ *
172
+ * @default 3
173
+ */
174
+ round?: number | false;
175
+ /**
176
+ * Allow and ignore trailing invalid characters _à la_ `parseFloat`.
177
+ *
178
+ * @default false
179
+ */
180
+ allowTrailingInvalid?: boolean;
181
+ /**
182
+ * Attempt to parse Roman numerals if Arabic numeral parsing fails.
183
+ *
184
+ * @default false
185
+ */
186
+ romanNumerals?: boolean;
187
+ }
188
+ /**
189
+ * Unicode vulgar fraction code points.
190
+ */
191
+ type VulgarFraction = '¼' | '½' | '¾' | '⅐' | '⅑' | '⅒' | '⅓' | '⅔' | '⅕' | '⅖' | '⅗' | '⅘' | '⅙' | '⅚' | '⅛' | '⅜' | '⅝' | '⅞' | '⅟';
192
+ /**
193
+ * Allowable Roman numeral characters (ASCII, uppercase only).
194
+ */
195
+ type RomanNumeralAscii = 'I' | 'V' | 'X' | 'L' | 'C' | 'D' | 'M';
196
+ /**
197
+ * Unicode Roman numeral code points (uppercase and lowercase,
198
+ * representing 1-12, 50, 100, 500, and 1000).
199
+ */
200
+ type RomanNumeralUnicode = 'Ⅰ' | 'Ⅱ' | 'Ⅲ' | 'Ⅳ' | 'Ⅴ' | 'Ⅵ' | 'Ⅶ' | 'Ⅷ' | 'Ⅸ' | 'Ⅹ' | 'Ⅺ' | 'Ⅻ' | 'Ⅼ' | 'Ⅽ' | 'Ⅾ' | 'Ⅿ' | 'ⅰ' | 'ⅱ' | 'ⅲ' | 'ⅳ' | 'ⅴ' | 'ⅵ' | 'ⅶ' | 'ⅷ' | 'ⅸ' | 'ⅹ' | 'ⅺ' | 'ⅻ' | 'ⅼ' | 'ⅽ' | 'ⅾ' | 'ⅿ';
201
+ /**
202
+ * Union of ASCII and Unicode Roman numeral characters/code points.
203
+ */
204
+ type RomanNumeral = RomanNumeralAscii | RomanNumeralUnicode;
205
+
206
+ /**
207
+ * Converts a string to a number, like an enhanced version of `parseFloat`.
208
+ *
209
+ * The string can include mixed numbers, vulgar fractions, or Roman numerals.
210
+ */
211
+ declare const numericQuantity: (quantity: string | number, options?: NumericQuantityOptions) => number;
212
+
213
+ /**
214
+ * Converts a string of Roman numerals to a number, like `parseInt`
215
+ * for Roman numerals. Uses modern, strict rules (only 1 to 3999).
216
+ *
217
+ * The string can include ASCII representations of Roman numerals
218
+ * or Unicode Roman numeral code points (`U+2160` through `U+217F`).
219
+ */
220
+ declare const parseRomanNumerals: (romanNumerals: string) => number;
221
+
222
+ export { type NumericQuantityOptions, type RomanNumeral, type RomanNumeralAscii, type RomanNumeralUnicode, type VulgarFraction, defaultOptions, numericQuantity, numericRegex, numericRegexWithTrailingInvalid, parseRomanNumerals, romanNumeralRegex, romanNumeralUnicodeRegex, romanNumeralUnicodeToAsciiMap, romanNumeralValues, vulgarFractionToAsciiMap, vulgarFractionsRegex };
@@ -2,21 +2,7 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __spreadValues = (a, b) => {
10
- for (var prop in b || (b = {}))
11
- if (__hasOwnProp.call(b, prop))
12
- __defNormalProp(a, prop, b[prop]);
13
- if (__getOwnPropSymbols)
14
- for (var prop of __getOwnPropSymbols(b)) {
15
- if (__propIsEnum.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- }
18
- return a;
19
- };
20
6
  var __export = (target, all) => {
21
7
  for (var name in all)
22
8
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -71,7 +57,9 @@ var vulgarFractionToAsciiMap = {
71
57
  "\u215F": "1/"
72
58
  };
73
59
  var numericRegex = /^(?=-?\s*\.\d|-?\s*\d)(-)?\s*((?:\d(?:[\d,_]*\d)?)*)(([eE][+-]?\d(?:[\d,_]*\d)?)?|\.\d(?:[\d,_]*\d)?([eE][+-]?\d(?:[\d,_]*\d)?)?|(\s+\d(?:[\d,_]*\d)?\s*)?\s*\/\s*\d(?:[\d,_]*\d)?)?$/;
74
- var numericRegexWithTrailingInvalid = /^(?=-?\s*\.\d|-?\s*\d)(-)?\s*((?:\d(?:[\d,_]*\d)?)*)(([eE][+-]?\d(?:[\d,_]*\d)?)?|\.\d(?:[\d,_]*\d)?([eE][+-]?\d(?:[\d,_]*\d)?)?|(\s+\d(?:[\d,_]*\d)?\s*)?\s*\/\s*\d(?:[\d,_]*\d)?)?(?:\s*[^\.\d\/].*)?/;
60
+ var numericRegexWithTrailingInvalid = new RegExp(
61
+ numericRegex.source.replace(/\$$/, "(?:\\s*[^\\.\\d\\/].*)?")
62
+ );
75
63
  var vulgarFractionsRegex = new RegExp(
76
64
  `(${Object.keys(vulgarFractionToAsciiMap).join("|")})`
77
65
  );
@@ -96,10 +84,10 @@ var romanNumeralValues = {
96
84
  XL: 40,
97
85
  XXX: 30,
98
86
  XX: 20,
99
- // Twelve is only here for tests; not used in practice
100
87
  XII: 12,
101
- // Eleven is only here for tests; not used in practice
88
+ // only here for tests; not used in practice
102
89
  XI: 11,
90
+ // only here for tests; not used in practice
103
91
  X: 10,
104
92
  IX: 9,
105
93
  VIII: 8,
@@ -190,7 +178,6 @@ var defaultOptions = {
190
178
 
191
179
  // src/parseRomanNumerals.ts
192
180
  var parseRomanNumerals = (romanNumerals) => {
193
- var _a, _b, _c, _d;
194
181
  const normalized = `${romanNumerals}`.replace(
195
182
  romanNumeralUnicodeRegex,
196
183
  (_m, rn) => romanNumeralUnicodeToAsciiMap[rn]
@@ -200,7 +187,7 @@ var parseRomanNumerals = (romanNumerals) => {
200
187
  return NaN;
201
188
  }
202
189
  const [, thousands, hundreds, tens, ones] = regexResult;
203
- return ((_a = romanNumeralValues[thousands]) != null ? _a : 0) + ((_b = romanNumeralValues[hundreds]) != null ? _b : 0) + ((_c = romanNumeralValues[tens]) != null ? _c : 0) + ((_d = romanNumeralValues[ones]) != null ? _d : 0);
190
+ return (romanNumeralValues[thousands] ?? 0) + (romanNumeralValues[hundreds] ?? 0) + (romanNumeralValues[tens] ?? 0) + (romanNumeralValues[ones] ?? 0);
204
191
  };
205
192
 
206
193
  // src/numericQuantity.ts
@@ -217,7 +204,10 @@ var numericQuantity = (quantity, options = defaultOptions) => {
217
204
  if (quantityAsString.length === 0) {
218
205
  return NaN;
219
206
  }
220
- const opts = __spreadValues(__spreadValues({}, defaultOptions), options);
207
+ const opts = {
208
+ ...defaultOptions,
209
+ ...options
210
+ };
221
211
  const regexResult = (opts.allowTrailingInvalid ? numericRegexWithTrailingInvalid : numericRegex).exec(quantityAsString);
222
212
  if (!regexResult) {
223
213
  return opts.romanNumerals ? parseRomanNumerals(quantityAsString) : NaN;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/constants.ts","../../src/parseRomanNumerals.ts","../../src/numericQuantity.ts"],"sourcesContent":["export * from './constants';\nexport * from './numericQuantity';\nexport * from './parseRomanNumerals';\nexport * from './types';\n","import type {\n NumericQuantityOptions,\n RomanNumeralAscii,\n RomanNumeralUnicode,\n VulgarFraction,\n} from './types';\n\n// #region Arabic numerals\n/**\n * Map of Unicode fraction code points to their ASCII equivalents\n */\nexport const vulgarFractionToAsciiMap: Record<VulgarFraction, string> = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n '⅟': '1/',\n};\n\n/**\n * Captures the individual elements of a numeric string.\n *\n * Capture groups:\n *\n * +=====+====================+========================+\n * | # | Description | Example |\n * +=====+====================+========================+\n * | 0 | entire string | \"2 1/3\" from \"2 1/3\" |\n * +-----+--------------------+------------------------+\n * | 1 | \"negative\" dash | \"-\" from \"-2 1/3\" |\n * +-----+--------------------+------------------------+\n * | 2 | the whole number | \"2\" from \"2 1/3\" |\n * | | - OR - | |\n * | | the numerator | \"1\" from \"1/3\" |\n * | + + |\n * | (This may include comma/underscore separators) |\n * +-----+--------------------+------------------------+\n * | 3 | entire fraction | \" 1/3\" from \"2 1/3\" |\n * | | - OR - | |\n * | | decimal portion | \".33\" from \"2.33\" |\n * | | - OR - | |\n * | | denominator | \"/3\" from \"1/3\" |\n * +=====+====================+========================+\n *\n * @example\n * numericRegex.exec(\"1\") // [ \"1\", \"1\", null, null ]\n * numericRegex.exec(\"1.23\") // [ \"1.23\", \"1\", \".23\", null ]\n * numericRegex.exec(\"1 2/3\") // [ \"1 2/3\", \"1\", \" 2/3\", \" 2\" ]\n * numericRegex.exec(\"2/3\") // [ \"2/3\", \"2\", \"/3\", null ]\n * numericRegex.exec(\"2 / 3\") // [ \"2 / 3\", \"2\", \"/ 3\", null ]\n */\nexport const numericRegex =\n /^(?=-?\\s*\\.\\d|-?\\s*\\d)(-)?\\s*((?:\\d(?:[\\d,_]*\\d)?)*)(([eE][+-]?\\d(?:[\\d,_]*\\d)?)?|\\.\\d(?:[\\d,_]*\\d)?([eE][+-]?\\d(?:[\\d,_]*\\d)?)?|(\\s+\\d(?:[\\d,_]*\\d)?\\s*)?\\s*\\/\\s*\\d(?:[\\d,_]*\\d)?)?$/;\n/**\n * Same as `numericRegex`, but allows/ignores trailing invalid characters.\n */\nexport const numericRegexWithTrailingInvalid =\n /^(?=-?\\s*\\.\\d|-?\\s*\\d)(-)?\\s*((?:\\d(?:[\\d,_]*\\d)?)*)(([eE][+-]?\\d(?:[\\d,_]*\\d)?)?|\\.\\d(?:[\\d,_]*\\d)?([eE][+-]?\\d(?:[\\d,_]*\\d)?)?|(\\s+\\d(?:[\\d,_]*\\d)?\\s*)?\\s*\\/\\s*\\d(?:[\\d,_]*\\d)?)?(?:\\s*[^\\.\\d\\/].*)?/;\n\n/**\n * Captures any Unicode vulgar fractions\n */\nexport const vulgarFractionsRegex = new RegExp(\n `(${Object.keys(vulgarFractionToAsciiMap).join('|')})`\n);\n// #endregion\n\n// #region Roman numerals\ntype RomanNumeralSequenceFragment =\n | `${RomanNumeralAscii}`\n | `${RomanNumeralAscii}${RomanNumeralAscii}`\n | `${RomanNumeralAscii}${RomanNumeralAscii}${RomanNumeralAscii}`\n | `${RomanNumeralAscii}${RomanNumeralAscii}${RomanNumeralAscii}${RomanNumeralAscii}`;\n\nexport const romanNumeralValues = {\n MMM: 3000,\n MM: 2000,\n M: 1000,\n CM: 900,\n DCCC: 800,\n DCC: 700,\n DC: 600,\n D: 500,\n CD: 400,\n CCC: 300,\n CC: 200,\n C: 100,\n XC: 90,\n LXXX: 80,\n LXX: 70,\n LX: 60,\n L: 50,\n XL: 40,\n XXX: 30,\n XX: 20,\n // Twelve is only here for tests; not used in practice\n XII: 12,\n // Eleven is only here for tests; not used in practice\n XI: 11,\n X: 10,\n IX: 9,\n VIII: 8,\n VII: 7,\n VI: 6,\n V: 5,\n IV: 4,\n III: 3,\n II: 2,\n I: 1,\n} satisfies { [k in RomanNumeralSequenceFragment]?: number };\n\n/**\n * Map of Unicode Roman numeral code points to their ASCII equivalents\n */\nexport const romanNumeralUnicodeToAsciiMap: Record<\n RomanNumeralUnicode,\n keyof typeof romanNumeralValues\n> = {\n // Roman Numeral One (U+2160)\n Ⅰ: 'I',\n // Roman Numeral Two (U+2161)\n Ⅱ: 'II',\n // Roman Numeral Three (U+2162)\n Ⅲ: 'III',\n // Roman Numeral Four (U+2163)\n Ⅳ: 'IV',\n // Roman Numeral Five (U+2164)\n Ⅴ: 'V',\n // Roman Numeral Six (U+2165)\n Ⅵ: 'VI',\n // Roman Numeral Seven (U+2166)\n Ⅶ: 'VII',\n // Roman Numeral Eight (U+2167)\n Ⅷ: 'VIII',\n // Roman Numeral Nine (U+2168)\n Ⅸ: 'IX',\n // Roman Numeral Ten (U+2169)\n Ⅹ: 'X',\n // Roman Numeral Eleven (U+216A)\n Ⅺ: 'XI',\n // Roman Numeral Twelve (U+216B)\n Ⅻ: 'XII',\n // Roman Numeral Fifty (U+216C)\n Ⅼ: 'L',\n // Roman Numeral One Hundred (U+216D)\n Ⅽ: 'C',\n // Roman Numeral Five Hundred (U+216E)\n Ⅾ: 'D',\n // Roman Numeral One Thousand (U+216F)\n Ⅿ: 'M',\n // Small Roman Numeral One (U+2170)\n ⅰ: 'I',\n // Small Roman Numeral Two (U+2171)\n ⅱ: 'II',\n // Small Roman Numeral Three (U+2172)\n ⅲ: 'III',\n // Small Roman Numeral Four (U+2173)\n ⅳ: 'IV',\n // Small Roman Numeral Five (U+2174)\n ⅴ: 'V',\n // Small Roman Numeral Six (U+2175)\n ⅵ: 'VI',\n // Small Roman Numeral Seven (U+2176)\n ⅶ: 'VII',\n // Small Roman Numeral Eight (U+2177)\n ⅷ: 'VIII',\n // Small Roman Numeral Nine (U+2178)\n ⅸ: 'IX',\n // Small Roman Numeral Ten (U+2179)\n ⅹ: 'X',\n // Small Roman Numeral Eleven (U+217A)\n ⅺ: 'XI',\n // Small Roman Numeral Twelve (U+217B)\n ⅻ: 'XII',\n // Small Roman Numeral Fifty (U+217C)\n ⅼ: 'L',\n // Small Roman Numeral One Hundred (U+217D)\n ⅽ: 'C',\n // Small Roman Numeral Five Hundred (U+217E)\n ⅾ: 'D',\n // Small Roman Numeral One Thousand (U+217F)\n ⅿ: 'M',\n};\n\n/**\n * Captures all Unicode Roman numeral code points\n */\nexport const romanNumeralUnicodeRegex = new RegExp(\n `(${Object.keys(romanNumeralUnicodeToAsciiMap).join('|')})`,\n 'gi'\n);\n\n/**\n * Captures a valid Roman numeral sequence\n *\n * Capture groups:\n *\n * +=====+=================+==========================+\n * | # | Description | Example |\n * +=====+=================+==========================+\n * | 0 | Entire string | \"MCCXIV\" from \"MCCXIV\" |\n * +-----+-----------------+--------------------------+\n * | 1 | Thousands | \"M\" from \"MCCXIV\" |\n * +-----+-----------------+--------------------------+\n * | 2 | Hundreds | \"CC\" from \"MCCXIV\" |\n * +-----+-----------------+--------------------------+\n * | 3 | Tens | \"X\" from \"MCCXIV\" |\n * +-----+-----------------+--------------------------+\n * | 4 | Ones | \"IV\" from \"MCCXIV\" |\n * +=====+=================+==========================+\n *\n * @example\n * romanNumeralRegex.exec(\"M\") // [ \"M\", \"M\", \"\", \"\", \"\" ]\n * romanNumeralRegex.exec(\"XII\") // [ \"XII\", \"\", \"\", \"X\", \"II\" ]\n * romanNumeralRegex.exec(\"MCCXIV\") // [ \"MCCXIV\", \"M\", \"CC\", \"X\", \"IV\" ]\n */\nexport const romanNumeralRegex =\n /^(?=[MDCLXVI])(M{0,3})(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/i;\n// #endregion\n\nexport const defaultOptions = {\n round: 3,\n allowTrailingInvalid: false,\n romanNumerals: false,\n} satisfies Required<NumericQuantityOptions>;\n","import {\n romanNumeralRegex,\n romanNumeralUnicodeRegex,\n romanNumeralUnicodeToAsciiMap,\n romanNumeralValues,\n} from './constants';\n\n// Just a shorthand type alias\ntype RNV = keyof typeof romanNumeralValues;\n\n/**\n * Converts a string of Roman numerals to a number, like `parseInt`\n * for Roman numerals. Uses modern, strict rules (only 1 to 3999).\n *\n * The string can include ASCII representations of Roman numerals\n * or Unicode Roman numeral code points (`U+2160` through `U+217F`).\n */\nexport const parseRomanNumerals = (romanNumerals: string) => {\n const normalized = `${romanNumerals}`\n // Convert Unicode Roman numerals to ASCII\n .replace(\n romanNumeralUnicodeRegex,\n (_m, rn: keyof typeof romanNumeralUnicodeToAsciiMap) =>\n romanNumeralUnicodeToAsciiMap[rn]\n )\n // Normalize to uppercase (more common for Roman numerals)\n .toUpperCase();\n\n const regexResult = romanNumeralRegex.exec(normalized);\n\n if (!regexResult) {\n return NaN;\n }\n\n const [, thousands, hundreds, tens, ones] = regexResult;\n\n return (\n (romanNumeralValues[thousands as RNV] ?? 0) +\n (romanNumeralValues[hundreds as RNV] ?? 0) +\n (romanNumeralValues[tens as RNV] ?? 0) +\n (romanNumeralValues[ones as RNV] ?? 0)\n );\n};\n","import {\n defaultOptions,\n numericRegex,\n numericRegexWithTrailingInvalid,\n vulgarFractionToAsciiMap,\n vulgarFractionsRegex,\n} from './constants';\nimport { parseRomanNumerals } from './parseRomanNumerals';\nimport type { NumericQuantityOptions } from './types';\n\nconst spaceThenSlashRegex = /^\\s*\\//;\n\n/**\n * Converts a string to a number, like an enhanced version of `parseFloat`.\n *\n * The string can include mixed numbers, vulgar fractions, or Roman numerals.\n */\nexport const numericQuantity = (\n quantity: string | number,\n options: NumericQuantityOptions = defaultOptions\n) => {\n if (typeof quantity === 'number' || typeof quantity === 'bigint') {\n return quantity;\n }\n\n let finalResult = NaN;\n\n // Coerce to string in case qty is a number\n const quantityAsString = `${quantity}`\n // Convert vulgar fractions to ASCII, with a leading space\n // to keep the whole number and the fraction separate\n .replace(\n vulgarFractionsRegex,\n (_m, vf: keyof typeof vulgarFractionToAsciiMap) =>\n ` ${vulgarFractionToAsciiMap[vf]}`\n )\n // Convert fraction slash to standard slash\n .replace('⁄', '/')\n .trim();\n\n // Bail out if the string was only white space\n if (quantityAsString.length === 0) {\n return NaN;\n }\n\n const opts: Required<NumericQuantityOptions> = {\n ...defaultOptions,\n ...options,\n };\n\n const regexResult = (\n opts.allowTrailingInvalid ? numericRegexWithTrailingInvalid : numericRegex\n ).exec(quantityAsString);\n\n // If the Arabic numeral regex fails, try Roman numerals\n if (!regexResult) {\n return opts.romanNumerals ? parseRomanNumerals(quantityAsString) : NaN;\n }\n\n const [, dash, ng1temp, ng2temp] = regexResult;\n const numberGroup1 = ng1temp.replace(/[,_]/g, '');\n const numberGroup2 = ng2temp?.replace(/[,_]/g, '');\n\n // Numerify capture group 1\n if (!numberGroup1 && numberGroup2 && numberGroup2.startsWith('.')) {\n finalResult = 0;\n } else {\n finalResult = parseInt(numberGroup1);\n }\n\n // If capture group 2 is null, then we're dealing with an integer\n // and there is nothing left to process\n if (!numberGroup2) {\n return dash ? finalResult * -1 : finalResult;\n }\n\n const roundingFactor =\n opts.round === false\n ? NaN\n : parseFloat(`1e${Math.floor(Math.max(0, opts.round))}`);\n\n if (\n numberGroup2.startsWith('.') ||\n numberGroup2.startsWith('e') ||\n numberGroup2.startsWith('E')\n ) {\n // If first char of `numberGroup2` is \".\" or \"e\"/\"E\", it's a decimal\n const decimalValue = parseFloat(`${finalResult}${numberGroup2}`);\n finalResult = isNaN(roundingFactor)\n ? decimalValue\n : Math.round(decimalValue * roundingFactor) / roundingFactor;\n } else if (spaceThenSlashRegex.test(numberGroup2)) {\n // If the first non-space char is \"/\" it's a pure fraction (e.g. \"1/2\")\n const numerator = parseInt(numberGroup1);\n const denominator = parseInt(numberGroup2.replace('/', ''));\n finalResult = isNaN(roundingFactor)\n ? numerator / denominator\n : Math.round((numerator * roundingFactor) / denominator) / roundingFactor;\n } else {\n // Otherwise it's a mixed fraction (e.g. \"1 2/3\")\n const fractionArray = numberGroup2.split('/');\n const [numerator, denominator] = fractionArray.map(v => parseInt(v));\n finalResult += isNaN(roundingFactor)\n ? numerator / denominator\n : Math.round((numerator * roundingFactor) / denominator) / roundingFactor;\n }\n\n return dash ? finalResult * -1 : finalResult;\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/constants.ts","../../src/parseRomanNumerals.ts","../../src/numericQuantity.ts"],"sourcesContent":["export * from './constants';\nexport * from './numericQuantity';\nexport * from './parseRomanNumerals';\nexport * from './types';\n","import type {\n NumericQuantityOptions,\n RomanNumeralAscii,\n RomanNumeralUnicode,\n VulgarFraction,\n} from './types';\n\n// #region Arabic numerals\n/**\n * Map of Unicode fraction code points to their ASCII equivalents.\n */\nexport const vulgarFractionToAsciiMap = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n '⅟': '1/',\n} as const satisfies Record<VulgarFraction, string>;\n\n/**\n * Captures the individual elements of a numeric string.\n *\n * Capture groups:\n *\n * | # | Description | Example(s) |\n * | --- | ------------------------------------------------ | ------------------------------------------------------------------- |\n * | `0` | entire string | `\"2 1/3\"` from `\"2 1/3\"` |\n * | `1` | \"negative\" dash | `\"-\"` from `\"-2 1/3\"` |\n * | `2` | whole number or numerator | `\"2\"` from `\"2 1/3\"`; `\"1\"` from `\"1/3\"` |\n * | `3` | entire fraction, decimal portion, or denominator | `\" 1/3\"` from `\"2 1/3\"`; `\".33\"` from `\"2.33\"`; `\"/3\"` from `\"1/3\"` |\n *\n * _Capture group 2 may include comma/underscore separators._\n *\n * @example\n *\n * ```ts\n * numericRegex.exec(\"1\") // [ \"1\", \"1\", null, null ]\n * numericRegex.exec(\"1.23\") // [ \"1.23\", \"1\", \".23\", null ]\n * numericRegex.exec(\"1 2/3\") // [ \"1 2/3\", \"1\", \" 2/3\", \" 2\" ]\n * numericRegex.exec(\"2/3\") // [ \"2/3\", \"2\", \"/3\", null ]\n * numericRegex.exec(\"2 / 3\") // [ \"2 / 3\", \"2\", \"/ 3\", null ]\n * ```\n */\nexport const numericRegex =\n /^(?=-?\\s*\\.\\d|-?\\s*\\d)(-)?\\s*((?:\\d(?:[\\d,_]*\\d)?)*)(([eE][+-]?\\d(?:[\\d,_]*\\d)?)?|\\.\\d(?:[\\d,_]*\\d)?([eE][+-]?\\d(?:[\\d,_]*\\d)?)?|(\\s+\\d(?:[\\d,_]*\\d)?\\s*)?\\s*\\/\\s*\\d(?:[\\d,_]*\\d)?)?$/;\n/**\n * Same as {@link numericRegex}, but allows (and ignores) trailing invalid characters.\n */\nexport const numericRegexWithTrailingInvalid = new RegExp(\n numericRegex.source.replace(/\\$$/, '(?:\\\\s*[^\\\\.\\\\d\\\\/].*)?')\n);\n\n/**\n * Captures any Unicode vulgar fractions.\n */\nexport const vulgarFractionsRegex = new RegExp(\n `(${Object.keys(vulgarFractionToAsciiMap).join('|')})`\n);\n// #endregion\n\n// #region Roman numerals\ntype RomanNumeralSequenceFragment =\n | `${RomanNumeralAscii}`\n | `${RomanNumeralAscii}${RomanNumeralAscii}`\n | `${RomanNumeralAscii}${RomanNumeralAscii}${RomanNumeralAscii}`\n | `${RomanNumeralAscii}${RomanNumeralAscii}${RomanNumeralAscii}${RomanNumeralAscii}`;\n\n/**\n * Map of Roman numeral sequences to their decimal equivalents.\n */\nexport const romanNumeralValues = {\n MMM: 3000,\n MM: 2000,\n M: 1000,\n CM: 900,\n DCCC: 800,\n DCC: 700,\n DC: 600,\n D: 500,\n CD: 400,\n CCC: 300,\n CC: 200,\n C: 100,\n XC: 90,\n LXXX: 80,\n LXX: 70,\n LX: 60,\n L: 50,\n XL: 40,\n XXX: 30,\n XX: 20,\n XII: 12, // only here for tests; not used in practice\n XI: 11, // only here for tests; not used in practice\n X: 10,\n IX: 9,\n VIII: 8,\n VII: 7,\n VI: 6,\n V: 5,\n IV: 4,\n III: 3,\n II: 2,\n I: 1,\n} as const satisfies { [k in RomanNumeralSequenceFragment]?: number };\n\n/**\n * Map of Unicode Roman numeral code points to their ASCII equivalents.\n */\nexport const romanNumeralUnicodeToAsciiMap = {\n // Roman Numeral One (U+2160)\n Ⅰ: 'I',\n // Roman Numeral Two (U+2161)\n Ⅱ: 'II',\n // Roman Numeral Three (U+2162)\n Ⅲ: 'III',\n // Roman Numeral Four (U+2163)\n Ⅳ: 'IV',\n // Roman Numeral Five (U+2164)\n Ⅴ: 'V',\n // Roman Numeral Six (U+2165)\n Ⅵ: 'VI',\n // Roman Numeral Seven (U+2166)\n Ⅶ: 'VII',\n // Roman Numeral Eight (U+2167)\n Ⅷ: 'VIII',\n // Roman Numeral Nine (U+2168)\n Ⅸ: 'IX',\n // Roman Numeral Ten (U+2169)\n Ⅹ: 'X',\n // Roman Numeral Eleven (U+216A)\n Ⅺ: 'XI',\n // Roman Numeral Twelve (U+216B)\n Ⅻ: 'XII',\n // Roman Numeral Fifty (U+216C)\n Ⅼ: 'L',\n // Roman Numeral One Hundred (U+216D)\n Ⅽ: 'C',\n // Roman Numeral Five Hundred (U+216E)\n Ⅾ: 'D',\n // Roman Numeral One Thousand (U+216F)\n Ⅿ: 'M',\n // Small Roman Numeral One (U+2170)\n ⅰ: 'I',\n // Small Roman Numeral Two (U+2171)\n ⅱ: 'II',\n // Small Roman Numeral Three (U+2172)\n ⅲ: 'III',\n // Small Roman Numeral Four (U+2173)\n ⅳ: 'IV',\n // Small Roman Numeral Five (U+2174)\n ⅴ: 'V',\n // Small Roman Numeral Six (U+2175)\n ⅵ: 'VI',\n // Small Roman Numeral Seven (U+2176)\n ⅶ: 'VII',\n // Small Roman Numeral Eight (U+2177)\n ⅷ: 'VIII',\n // Small Roman Numeral Nine (U+2178)\n ⅸ: 'IX',\n // Small Roman Numeral Ten (U+2179)\n ⅹ: 'X',\n // Small Roman Numeral Eleven (U+217A)\n ⅺ: 'XI',\n // Small Roman Numeral Twelve (U+217B)\n ⅻ: 'XII',\n // Small Roman Numeral Fifty (U+217C)\n ⅼ: 'L',\n // Small Roman Numeral One Hundred (U+217D)\n ⅽ: 'C',\n // Small Roman Numeral Five Hundred (U+217E)\n ⅾ: 'D',\n // Small Roman Numeral One Thousand (U+217F)\n ⅿ: 'M',\n} as const satisfies Record<\n RomanNumeralUnicode,\n keyof typeof romanNumeralValues\n>;\n\n/**\n * Captures all Unicode Roman numeral code points.\n */\nexport const romanNumeralUnicodeRegex = new RegExp(\n `(${Object.keys(romanNumeralUnicodeToAsciiMap).join('|')})`,\n 'gi'\n);\n\n/**\n * Captures a valid Roman numeral sequence.\n *\n * Capture groups:\n *\n * | # | Description | Example |\n * | --- | --------------- | ------------------------ |\n * | `0` | Entire string | \"MCCXIV\" from \"MCCXIV\" |\n * | `1` | Thousands | \"M\" from \"MCCXIV\" |\n * | `2` | Hundreds | \"CC\" from \"MCCXIV\" |\n * | `3` | Tens | \"X\" from \"MCCXIV\" |\n * | `4` | Ones | \"IV\" from \"MCCXIV\" |\n *\n * @example\n *\n * ```ts\n * romanNumeralRegex.exec(\"M\") // [ \"M\", \"M\", \"\", \"\", \"\" ]\n * romanNumeralRegex.exec(\"XII\") // [ \"XII\", \"\", \"\", \"X\", \"II\" ]\n * romanNumeralRegex.exec(\"MCCXIV\") // [ \"MCCXIV\", \"M\", \"CC\", \"X\", \"IV\" ]\n * ```\n */\nexport const romanNumeralRegex =\n /^(?=[MDCLXVI])(M{0,3})(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/i;\n// #endregion\n\n/**\n * Default options for {@link numericQuantity}.\n */\nexport const defaultOptions = {\n round: 3,\n allowTrailingInvalid: false,\n romanNumerals: false,\n} satisfies Required<NumericQuantityOptions>;\n","import {\n romanNumeralRegex,\n romanNumeralUnicodeRegex,\n romanNumeralUnicodeToAsciiMap,\n romanNumeralValues,\n} from './constants';\n\n// Just a shorthand type alias\ntype RNV = keyof typeof romanNumeralValues;\n\n/**\n * Converts a string of Roman numerals to a number, like `parseInt`\n * for Roman numerals. Uses modern, strict rules (only 1 to 3999).\n *\n * The string can include ASCII representations of Roman numerals\n * or Unicode Roman numeral code points (`U+2160` through `U+217F`).\n */\nexport const parseRomanNumerals = (romanNumerals: string) => {\n const normalized = `${romanNumerals}`\n // Convert Unicode Roman numerals to ASCII\n .replace(\n romanNumeralUnicodeRegex,\n (_m, rn: keyof typeof romanNumeralUnicodeToAsciiMap) =>\n romanNumeralUnicodeToAsciiMap[rn]\n )\n // Normalize to uppercase (more common for Roman numerals)\n .toUpperCase();\n\n const regexResult = romanNumeralRegex.exec(normalized);\n\n if (!regexResult) {\n return NaN;\n }\n\n const [, thousands, hundreds, tens, ones] = regexResult;\n\n return (\n (romanNumeralValues[thousands as RNV] ?? 0) +\n (romanNumeralValues[hundreds as RNV] ?? 0) +\n (romanNumeralValues[tens as RNV] ?? 0) +\n (romanNumeralValues[ones as RNV] ?? 0)\n );\n};\n","import {\n defaultOptions,\n numericRegex,\n numericRegexWithTrailingInvalid,\n vulgarFractionToAsciiMap,\n vulgarFractionsRegex,\n} from './constants';\nimport { parseRomanNumerals } from './parseRomanNumerals';\nimport type { NumericQuantityOptions } from './types';\n\nconst spaceThenSlashRegex = /^\\s*\\//;\n\n/**\n * Converts a string to a number, like an enhanced version of `parseFloat`.\n *\n * The string can include mixed numbers, vulgar fractions, or Roman numerals.\n */\nexport const numericQuantity = (\n quantity: string | number,\n options: NumericQuantityOptions = defaultOptions\n) => {\n if (typeof quantity === 'number' || typeof quantity === 'bigint') {\n return quantity;\n }\n\n let finalResult = NaN;\n\n // Coerce to string in case qty is a number\n const quantityAsString = `${quantity}`\n // Convert vulgar fractions to ASCII, with a leading space\n // to keep the whole number and the fraction separate\n .replace(\n vulgarFractionsRegex,\n (_m, vf: keyof typeof vulgarFractionToAsciiMap) =>\n ` ${vulgarFractionToAsciiMap[vf]}`\n )\n // Convert fraction slash to standard slash\n .replace('⁄', '/')\n .trim();\n\n // Bail out if the string was only white space\n if (quantityAsString.length === 0) {\n return NaN;\n }\n\n const opts: Required<NumericQuantityOptions> = {\n ...defaultOptions,\n ...options,\n };\n\n const regexResult = (\n opts.allowTrailingInvalid ? numericRegexWithTrailingInvalid : numericRegex\n ).exec(quantityAsString);\n\n // If the Arabic numeral regex fails, try Roman numerals\n if (!regexResult) {\n return opts.romanNumerals ? parseRomanNumerals(quantityAsString) : NaN;\n }\n\n const [, dash, ng1temp, ng2temp] = regexResult;\n const numberGroup1 = ng1temp.replace(/[,_]/g, '');\n const numberGroup2 = ng2temp?.replace(/[,_]/g, '');\n\n // Numerify capture group 1\n if (!numberGroup1 && numberGroup2 && numberGroup2.startsWith('.')) {\n finalResult = 0;\n } else {\n finalResult = parseInt(numberGroup1);\n }\n\n // If capture group 2 is null, then we're dealing with an integer\n // and there is nothing left to process\n if (!numberGroup2) {\n return dash ? finalResult * -1 : finalResult;\n }\n\n const roundingFactor =\n opts.round === false\n ? NaN\n : parseFloat(`1e${Math.floor(Math.max(0, opts.round))}`);\n\n if (\n numberGroup2.startsWith('.') ||\n numberGroup2.startsWith('e') ||\n numberGroup2.startsWith('E')\n ) {\n // If first char of `numberGroup2` is \".\" or \"e\"/\"E\", it's a decimal\n const decimalValue = parseFloat(`${finalResult}${numberGroup2}`);\n finalResult = isNaN(roundingFactor)\n ? decimalValue\n : Math.round(decimalValue * roundingFactor) / roundingFactor;\n } else if (spaceThenSlashRegex.test(numberGroup2)) {\n // If the first non-space char is \"/\" it's a pure fraction (e.g. \"1/2\")\n const numerator = parseInt(numberGroup1);\n const denominator = parseInt(numberGroup2.replace('/', ''));\n finalResult = isNaN(roundingFactor)\n ? numerator / denominator\n : Math.round((numerator * roundingFactor) / denominator) / roundingFactor;\n } else {\n // Otherwise it's a mixed fraction (e.g. \"1 2/3\")\n const fractionArray = numberGroup2.split('/');\n const [numerator, denominator] = fractionArray.map(v => parseInt(v));\n finalResult += isNaN(roundingFactor)\n ? numerator / denominator\n : Math.round((numerator * roundingFactor) / denominator) / roundingFactor;\n }\n\n return dash ? finalResult * -1 : finalResult;\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Map of Unicode fraction code points to their ASCII equivalents.
3
+ */
4
+ declare const vulgarFractionToAsciiMap: {
5
+ readonly '\u00BC': "1/4";
6
+ readonly '\u00BD': "1/2";
7
+ readonly '\u00BE': "3/4";
8
+ readonly '\u2150': "1/7";
9
+ readonly '\u2151': "1/9";
10
+ readonly '\u2152': "1/10";
11
+ readonly '\u2153': "1/3";
12
+ readonly '\u2154': "2/3";
13
+ readonly '\u2155': "1/5";
14
+ readonly '\u2156': "2/5";
15
+ readonly '\u2157': "3/5";
16
+ readonly '\u2158': "4/5";
17
+ readonly '\u2159': "1/6";
18
+ readonly '\u215A': "5/6";
19
+ readonly '\u215B': "1/8";
20
+ readonly '\u215C': "3/8";
21
+ readonly '\u215D': "5/8";
22
+ readonly '\u215E': "7/8";
23
+ readonly '\u215F': "1/";
24
+ };
25
+ /**
26
+ * Captures the individual elements of a numeric string.
27
+ *
28
+ * Capture groups:
29
+ *
30
+ * | # | Description | Example(s) |
31
+ * | --- | ------------------------------------------------ | ------------------------------------------------------------------- |
32
+ * | `0` | entire string | `"2 1/3"` from `"2 1/3"` |
33
+ * | `1` | "negative" dash | `"-"` from `"-2 1/3"` |
34
+ * | `2` | whole number or numerator | `"2"` from `"2 1/3"`; `"1"` from `"1/3"` |
35
+ * | `3` | entire fraction, decimal portion, or denominator | `" 1/3"` from `"2 1/3"`; `".33"` from `"2.33"`; `"/3"` from `"1/3"` |
36
+ *
37
+ * _Capture group 2 may include comma/underscore separators._
38
+ *
39
+ * @example
40
+ *
41
+ * ```ts
42
+ * numericRegex.exec("1") // [ "1", "1", null, null ]
43
+ * numericRegex.exec("1.23") // [ "1.23", "1", ".23", null ]
44
+ * numericRegex.exec("1 2/3") // [ "1 2/3", "1", " 2/3", " 2" ]
45
+ * numericRegex.exec("2/3") // [ "2/3", "2", "/3", null ]
46
+ * numericRegex.exec("2 / 3") // [ "2 / 3", "2", "/ 3", null ]
47
+ * ```
48
+ */
49
+ declare const numericRegex: RegExp;
50
+ /**
51
+ * Same as {@link numericRegex}, but allows (and ignores) trailing invalid characters.
52
+ */
53
+ declare const numericRegexWithTrailingInvalid: RegExp;
54
+ /**
55
+ * Captures any Unicode vulgar fractions.
56
+ */
57
+ declare const vulgarFractionsRegex: RegExp;
58
+ /**
59
+ * Map of Roman numeral sequences to their decimal equivalents.
60
+ */
61
+ declare const romanNumeralValues: {
62
+ readonly MMM: 3000;
63
+ readonly MM: 2000;
64
+ readonly M: 1000;
65
+ readonly CM: 900;
66
+ readonly DCCC: 800;
67
+ readonly DCC: 700;
68
+ readonly DC: 600;
69
+ readonly D: 500;
70
+ readonly CD: 400;
71
+ readonly CCC: 300;
72
+ readonly CC: 200;
73
+ readonly C: 100;
74
+ readonly XC: 90;
75
+ readonly LXXX: 80;
76
+ readonly LXX: 70;
77
+ readonly LX: 60;
78
+ readonly L: 50;
79
+ readonly XL: 40;
80
+ readonly XXX: 30;
81
+ readonly XX: 20;
82
+ readonly XII: 12;
83
+ readonly XI: 11;
84
+ readonly X: 10;
85
+ readonly IX: 9;
86
+ readonly VIII: 8;
87
+ readonly VII: 7;
88
+ readonly VI: 6;
89
+ readonly V: 5;
90
+ readonly IV: 4;
91
+ readonly III: 3;
92
+ readonly II: 2;
93
+ readonly I: 1;
94
+ };
95
+ /**
96
+ * Map of Unicode Roman numeral code points to their ASCII equivalents.
97
+ */
98
+ declare const romanNumeralUnicodeToAsciiMap: {
99
+ readonly Ⅰ: "I";
100
+ readonly Ⅱ: "II";
101
+ readonly Ⅲ: "III";
102
+ readonly Ⅳ: "IV";
103
+ readonly Ⅴ: "V";
104
+ readonly Ⅵ: "VI";
105
+ readonly Ⅶ: "VII";
106
+ readonly Ⅷ: "VIII";
107
+ readonly Ⅸ: "IX";
108
+ readonly Ⅹ: "X";
109
+ readonly Ⅺ: "XI";
110
+ readonly Ⅻ: "XII";
111
+ readonly Ⅼ: "L";
112
+ readonly Ⅽ: "C";
113
+ readonly Ⅾ: "D";
114
+ readonly Ⅿ: "M";
115
+ readonly ⅰ: "I";
116
+ readonly ⅱ: "II";
117
+ readonly ⅲ: "III";
118
+ readonly ⅳ: "IV";
119
+ readonly ⅴ: "V";
120
+ readonly ⅵ: "VI";
121
+ readonly ⅶ: "VII";
122
+ readonly ⅷ: "VIII";
123
+ readonly ⅸ: "IX";
124
+ readonly ⅹ: "X";
125
+ readonly ⅺ: "XI";
126
+ readonly ⅻ: "XII";
127
+ readonly ⅼ: "L";
128
+ readonly ⅽ: "C";
129
+ readonly ⅾ: "D";
130
+ readonly ⅿ: "M";
131
+ };
132
+ /**
133
+ * Captures all Unicode Roman numeral code points.
134
+ */
135
+ declare const romanNumeralUnicodeRegex: RegExp;
136
+ /**
137
+ * Captures a valid Roman numeral sequence.
138
+ *
139
+ * Capture groups:
140
+ *
141
+ * | # | Description | Example |
142
+ * | --- | --------------- | ------------------------ |
143
+ * | `0` | Entire string | "MCCXIV" from "MCCXIV" |
144
+ * | `1` | Thousands | "M" from "MCCXIV" |
145
+ * | `2` | Hundreds | "CC" from "MCCXIV" |
146
+ * | `3` | Tens | "X" from "MCCXIV" |
147
+ * | `4` | Ones | "IV" from "MCCXIV" |
148
+ *
149
+ * @example
150
+ *
151
+ * ```ts
152
+ * romanNumeralRegex.exec("M") // [ "M", "M", "", "", "" ]
153
+ * romanNumeralRegex.exec("XII") // [ "XII", "", "", "X", "II" ]
154
+ * romanNumeralRegex.exec("MCCXIV") // [ "MCCXIV", "M", "CC", "X", "IV" ]
155
+ * ```
156
+ */
157
+ declare const romanNumeralRegex: RegExp;
158
+ /**
159
+ * Default options for {@link numericQuantity}.
160
+ */
161
+ declare const defaultOptions: {
162
+ round: number;
163
+ allowTrailingInvalid: false;
164
+ romanNumerals: false;
165
+ };
166
+
167
+ interface NumericQuantityOptions {
168
+ /**
169
+ * Round the result to this many decimal places. Defaults to 3; must
170
+ * be greater than or equal to zero.
171
+ *
172
+ * @default 3
173
+ */
174
+ round?: number | false;
175
+ /**
176
+ * Allow and ignore trailing invalid characters _à la_ `parseFloat`.
177
+ *
178
+ * @default false
179
+ */
180
+ allowTrailingInvalid?: boolean;
181
+ /**
182
+ * Attempt to parse Roman numerals if Arabic numeral parsing fails.
183
+ *
184
+ * @default false
185
+ */
186
+ romanNumerals?: boolean;
187
+ }
188
+ /**
189
+ * Unicode vulgar fraction code points.
190
+ */
191
+ type VulgarFraction = '¼' | '½' | '¾' | '⅐' | '⅑' | '⅒' | '⅓' | '⅔' | '⅕' | '⅖' | '⅗' | '⅘' | '⅙' | '⅚' | '⅛' | '⅜' | '⅝' | '⅞' | '⅟';
192
+ /**
193
+ * Allowable Roman numeral characters (ASCII, uppercase only).
194
+ */
195
+ type RomanNumeralAscii = 'I' | 'V' | 'X' | 'L' | 'C' | 'D' | 'M';
196
+ /**
197
+ * Unicode Roman numeral code points (uppercase and lowercase,
198
+ * representing 1-12, 50, 100, 500, and 1000).
199
+ */
200
+ type RomanNumeralUnicode = 'Ⅰ' | 'Ⅱ' | 'Ⅲ' | 'Ⅳ' | 'Ⅴ' | 'Ⅵ' | 'Ⅶ' | 'Ⅷ' | 'Ⅸ' | 'Ⅹ' | 'Ⅺ' | 'Ⅻ' | 'Ⅼ' | 'Ⅽ' | 'Ⅾ' | 'Ⅿ' | 'ⅰ' | 'ⅱ' | 'ⅲ' | 'ⅳ' | 'ⅴ' | 'ⅵ' | 'ⅶ' | 'ⅷ' | 'ⅸ' | 'ⅹ' | 'ⅺ' | 'ⅻ' | 'ⅼ' | 'ⅽ' | 'ⅾ' | 'ⅿ';
201
+ /**
202
+ * Union of ASCII and Unicode Roman numeral characters/code points.
203
+ */
204
+ type RomanNumeral = RomanNumeralAscii | RomanNumeralUnicode;
205
+
206
+ /**
207
+ * Converts a string to a number, like an enhanced version of `parseFloat`.
208
+ *
209
+ * The string can include mixed numbers, vulgar fractions, or Roman numerals.
210
+ */
211
+ declare const numericQuantity: (quantity: string | number, options?: NumericQuantityOptions) => number;
212
+
213
+ /**
214
+ * Converts a string of Roman numerals to a number, like `parseInt`
215
+ * for Roman numerals. Uses modern, strict rules (only 1 to 3999).
216
+ *
217
+ * The string can include ASCII representations of Roman numerals
218
+ * or Unicode Roman numeral code points (`U+2160` through `U+217F`).
219
+ */
220
+ declare const parseRomanNumerals: (romanNumerals: string) => number;
221
+
222
+ export { type NumericQuantityOptions, type RomanNumeral, type RomanNumeralAscii, type RomanNumeralUnicode, type VulgarFraction, defaultOptions, numericQuantity, numericRegex, numericRegexWithTrailingInvalid, parseRomanNumerals, romanNumeralRegex, romanNumeralUnicodeRegex, romanNumeralUnicodeToAsciiMap, romanNumeralValues, vulgarFractionToAsciiMap, vulgarFractionsRegex };