numeric-quantity 2.0.1 → 3.0.0

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.
Files changed (33) hide show
  1. package/README.md +15 -3
  2. package/dist/cjs/numeric-quantity.cjs.development.js +247 -246
  3. package/dist/cjs/numeric-quantity.cjs.development.js.map +1 -1
  4. package/dist/cjs/numeric-quantity.cjs.production.js +1 -1
  5. package/dist/cjs/numeric-quantity.cjs.production.js.map +1 -1
  6. package/dist/numeric-quantity.iife.umd.min.js +2 -0
  7. package/dist/numeric-quantity.iife.umd.min.js.map +1 -0
  8. package/dist/numeric-quantity.legacy-esm.js +301 -225
  9. package/dist/numeric-quantity.legacy-esm.js.map +1 -1
  10. package/dist/numeric-quantity.mjs +237 -210
  11. package/dist/numeric-quantity.mjs.map +1 -1
  12. package/dist/numeric-quantity.production.mjs +1 -1
  13. package/dist/numeric-quantity.production.mjs.map +1 -1
  14. package/dist/types/constants.d.ts +79 -0
  15. package/dist/types/dev.d.ts +1 -0
  16. package/dist/types/index.d.ts +4 -0
  17. package/dist/types/numericQuantity.d.ts +12 -0
  18. package/dist/types/parseRomanNumerals.d.ts +8 -0
  19. package/dist/types/types.d.ts +49 -0
  20. package/dist/types-esm/constants.d.mts +79 -0
  21. package/dist/types-esm/dev.d.mts +1 -0
  22. package/dist/types-esm/index.d.mts +4 -0
  23. package/dist/types-esm/numericQuantity.d.mts +12 -0
  24. package/dist/types-esm/parseRomanNumerals.d.mts +8 -0
  25. package/dist/types-esm/types.d.mts +49 -0
  26. package/package.json +23 -18
  27. package/dist/cjs/numeric-quantity.cjs.development.d.ts +0 -222
  28. package/dist/cjs/numeric-quantity.cjs.production.d.ts +0 -222
  29. package/dist/numeric-quantity.d.mts +0 -222
  30. package/dist/numeric-quantity.legacy-esm.d.mts +0 -222
  31. package/dist/numeric-quantity.production.d.mts +0 -222
  32. package/dist/numeric-quantity.umd.min.js +0 -2
  33. package/dist/numeric-quantity.umd.min.js.map +0 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  [![npm][badge-npm]](https://www.npmjs.com/package/numeric-quantity)
2
2
  ![workflow status](https://github.com/jakeboone02/numeric-quantity/actions/workflows/main.yml/badge.svg)
3
3
  [![codecov.io](https://codecov.io/github/jakeboone02/numeric-quantity/coverage.svg?branch=main)](https://codecov.io/github/jakeboone02/numeric-quantity?branch=main)
4
- [![downloads](https://img.shields.io/npm/dm/numeric-quantity.svg)](http://npm-stat.com/charts.html?package=numeric-quantity&from=2015-08-01)
5
- [![MIT License](https://img.shields.io/npm/l/numeric-quantity.svg)](http://opensource.org/licenses/MIT)
4
+ [![downloads](https://img.shields.io/npm/dm/numeric-quantity.svg)](https://npm-stat.com/charts.html?package=numeric-quantity&from=2015-08-01)
5
+ [![MIT License](https://img.shields.io/npm/l/numeric-quantity.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
7
  Converts a string to a number, like an enhanced version of `parseFloat`.
8
8
 
@@ -13,11 +13,13 @@ Features:
13
13
  - In addition to plain integers and decimals, `numeric-quantity` can parse numbers with comma or underscore separators (`'1,000'` or `'1_000'`), mixed numbers (`'1 2/3'`), vulgar fractions (`'1⅖'`), and the fraction slash character (`'1 2⁄3'`).
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
+ - To parse numbers with European-style decimal comma (where `'1,0'` means `1`, not `10`), pass `{ decimalSeparator: ',' }` as the second argument.
17
+ - To produce `bigint` values when the input represents an integer that would exceeds the boundaries of `number`, pass `{ bigIntOnOverflow: true }` as the second argument.
16
18
  - 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
19
  - Returns `NaN` if the provided string does not resemble a number.
18
20
 
19
21
  > _For the inverse operation—converting a number to an imperial measurement—check out [format-quantity](https://www.npmjs.com/package/format-quantity)._
20
- >
22
+
21
23
  > _For a more complete solution to parsing recipe ingredients, try [parse-ingredient](https://www.npmjs.com/package/parse-ingredient)._
22
24
 
23
25
  ## Usage
@@ -52,4 +54,14 @@ As UMD (all exports are properties of the global object `NumericQuantity`):
52
54
  </script>
53
55
  ```
54
56
 
57
+ ## Options
58
+
59
+ | Option | Type | Default | Description |
60
+ | ---------------------- | ----------------- | ------- | ---------------------------------------------------------------------------------------------------- |
61
+ | `round` | `number \| false` | `3` | Round the result to a certain number of decimal places. Must be greater than or equal to zero. |
62
+ | `allowTrailingInvalid` | `boolean` | `false` | Allow and ignore trailing invalid characters _à la_ `parseFloat`. |
63
+ | `romanNumerals` | `boolean` | `false` | Attempt to parse Roman numerals if Arabic numeral parsing fails. |
64
+ | `bigIntOnOverflow` | `boolean` | `false` | Generates a `bigint` value if the string represents a valid integer too large for the `number` type. |
65
+ | `decimalSeparator` | `',' \| '.'` | `"."` | Specifies which character to treat as the decimal separator. |
66
+
55
67
  [badge-npm]: https://img.shields.io/npm/v/numeric-quantity.svg?cacheSeconds=3600&logo=npm
@@ -1,255 +1,256 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- defaultOptions: () => defaultOptions,
24
- numericQuantity: () => numericQuantity,
25
- numericRegex: () => numericRegex,
26
- numericRegexWithTrailingInvalid: () => numericRegexWithTrailingInvalid,
27
- parseRomanNumerals: () => parseRomanNumerals,
28
- romanNumeralRegex: () => romanNumeralRegex,
29
- romanNumeralUnicodeRegex: () => romanNumeralUnicodeRegex,
30
- romanNumeralUnicodeToAsciiMap: () => romanNumeralUnicodeToAsciiMap,
31
- romanNumeralValues: () => romanNumeralValues,
32
- vulgarFractionToAsciiMap: () => vulgarFractionToAsciiMap,
33
- vulgarFractionsRegex: () => vulgarFractionsRegex
34
- });
35
- module.exports = __toCommonJS(src_exports);
36
1
 
37
- // src/constants.ts
38
- var vulgarFractionToAsciiMap = {
39
- "\xBC": "1/4",
40
- "\xBD": "1/2",
41
- "\xBE": "3/4",
42
- "\u2150": "1/7",
43
- "\u2151": "1/9",
44
- "\u2152": "1/10",
45
- "\u2153": "1/3",
46
- "\u2154": "2/3",
47
- "\u2155": "1/5",
48
- "\u2156": "2/5",
49
- "\u2157": "3/5",
50
- "\u2158": "4/5",
51
- "\u2159": "1/6",
52
- "\u215A": "5/6",
53
- "\u215B": "1/8",
54
- "\u215C": "3/8",
55
- "\u215D": "5/8",
56
- "\u215E": "7/8",
57
- "\u215F": "1/"
2
+ //#region src/constants.ts
3
+ /**
4
+ * Map of Unicode fraction code points to their ASCII equivalents.
5
+ */
6
+ const vulgarFractionToAsciiMap = {
7
+ "¼": "1/4",
8
+ "½": "1/2",
9
+ "¾": "3/4",
10
+ "": "1/7",
11
+ "": "1/9",
12
+ "": "1/10",
13
+ "": "1/3",
14
+ "": "2/3",
15
+ "": "1/5",
16
+ "": "2/5",
17
+ "": "3/5",
18
+ "": "4/5",
19
+ "": "1/6",
20
+ "": "5/6",
21
+ "": "1/8",
22
+ "": "3/8",
23
+ "⅝": "5/8",
24
+ "⅞": "7/8",
25
+ "⅟": "1/"
58
26
  };
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)?)?$/;
60
- var numericRegexWithTrailingInvalid = new RegExp(
61
- numericRegex.source.replace(/\$$/, "(?:\\s*[^\\.\\d\\/].*)?")
62
- );
63
- var vulgarFractionsRegex = new RegExp(
64
- `(${Object.keys(vulgarFractionToAsciiMap).join("|")})`
65
- );
66
- var romanNumeralValues = {
67
- MMM: 3e3,
68
- MM: 2e3,
69
- M: 1e3,
70
- CM: 900,
71
- DCCC: 800,
72
- DCC: 700,
73
- DC: 600,
74
- D: 500,
75
- CD: 400,
76
- CCC: 300,
77
- CC: 200,
78
- C: 100,
79
- XC: 90,
80
- LXXX: 80,
81
- LXX: 70,
82
- LX: 60,
83
- L: 50,
84
- XL: 40,
85
- XXX: 30,
86
- XX: 20,
87
- XII: 12,
88
- // only here for tests; not used in practice
89
- XI: 11,
90
- // only here for tests; not used in practice
91
- X: 10,
92
- IX: 9,
93
- VIII: 8,
94
- VII: 7,
95
- VI: 6,
96
- V: 5,
97
- IV: 4,
98
- III: 3,
99
- II: 2,
100
- I: 1
27
+ /**
28
+ * Captures the individual elements of a numeric string. Commas and underscores are allowed
29
+ * as separators, as long as they appear between digits and are not consecutive.
30
+ *
31
+ * Capture groups:
32
+ *
33
+ * | # | Description | Example(s) |
34
+ * | --- | ------------------------------------------------ | ------------------------------------------------------------------- |
35
+ * | `0` | entire string | `"2 1/3"` from `"2 1/3"` |
36
+ * | `1` | "negative" dash | `"-"` from `"-2 1/3"` |
37
+ * | `2` | whole number or numerator | `"2"` from `"2 1/3"`; `"1"` from `"1/3"` |
38
+ * | `3` | entire fraction, decimal portion, or denominator | `" 1/3"` from `"2 1/3"`; `".33"` from `"2.33"`; `"/3"` from `"1/3"` |
39
+ *
40
+ * _Capture group 2 may include comma/underscore separators._
41
+ *
42
+ * @example
43
+ *
44
+ * ```ts
45
+ * numericRegex.exec("1") // [ "1", "1", null, null ]
46
+ * numericRegex.exec("1.23") // [ "1.23", "1", ".23", null ]
47
+ * numericRegex.exec("1 2/3") // [ "1 2/3", "1", " 2/3", " 2" ]
48
+ * numericRegex.exec("2/3") // [ "2/3", "2", "/3", null ]
49
+ * numericRegex.exec("2 / 3") // [ "2 / 3", "2", "/ 3", null ]
50
+ * ```
51
+ */
52
+ const 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)*)?$/;
53
+ /**
54
+ * Same as {@link numericRegex}, but allows (and ignores) trailing invalid characters.
55
+ */
56
+ const 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/].*)?/;
57
+ /**
58
+ * Captures any Unicode vulgar fractions.
59
+ */
60
+ const vulgarFractionsRegex = /([¼½¾⅐⅑⅒⅓⅔⅕⅖⅗⅘⅙⅚⅛⅜⅝⅞⅟}])/g;
61
+ /**
62
+ * Map of Roman numeral sequences to their decimal equivalents.
63
+ */
64
+ const romanNumeralValues = {
65
+ MMM: 3e3,
66
+ MM: 2e3,
67
+ M: 1e3,
68
+ CM: 900,
69
+ DCCC: 800,
70
+ DCC: 700,
71
+ DC: 600,
72
+ D: 500,
73
+ CD: 400,
74
+ CCC: 300,
75
+ CC: 200,
76
+ C: 100,
77
+ XC: 90,
78
+ LXXX: 80,
79
+ LXX: 70,
80
+ LX: 60,
81
+ L: 50,
82
+ XL: 40,
83
+ XXX: 30,
84
+ XX: 20,
85
+ XII: 12,
86
+ XI: 11,
87
+ X: 10,
88
+ IX: 9,
89
+ VIII: 8,
90
+ VII: 7,
91
+ VI: 6,
92
+ V: 5,
93
+ IV: 4,
94
+ III: 3,
95
+ II: 2,
96
+ I: 1
101
97
  };
102
- var romanNumeralUnicodeToAsciiMap = {
103
- // Roman Numeral One (U+2160)
104
- "\u2160": "I",
105
- // Roman Numeral Two (U+2161)
106
- "\u2161": "II",
107
- // Roman Numeral Three (U+2162)
108
- "\u2162": "III",
109
- // Roman Numeral Four (U+2163)
110
- "\u2163": "IV",
111
- // Roman Numeral Five (U+2164)
112
- "\u2164": "V",
113
- // Roman Numeral Six (U+2165)
114
- "\u2165": "VI",
115
- // Roman Numeral Seven (U+2166)
116
- "\u2166": "VII",
117
- // Roman Numeral Eight (U+2167)
118
- "\u2167": "VIII",
119
- // Roman Numeral Nine (U+2168)
120
- "\u2168": "IX",
121
- // Roman Numeral Ten (U+2169)
122
- "\u2169": "X",
123
- // Roman Numeral Eleven (U+216A)
124
- "\u216A": "XI",
125
- // Roman Numeral Twelve (U+216B)
126
- "\u216B": "XII",
127
- // Roman Numeral Fifty (U+216C)
128
- "\u216C": "L",
129
- // Roman Numeral One Hundred (U+216D)
130
- "\u216D": "C",
131
- // Roman Numeral Five Hundred (U+216E)
132
- "\u216E": "D",
133
- // Roman Numeral One Thousand (U+216F)
134
- "\u216F": "M",
135
- // Small Roman Numeral One (U+2170)
136
- "\u2170": "I",
137
- // Small Roman Numeral Two (U+2171)
138
- "\u2171": "II",
139
- // Small Roman Numeral Three (U+2172)
140
- "\u2172": "III",
141
- // Small Roman Numeral Four (U+2173)
142
- "\u2173": "IV",
143
- // Small Roman Numeral Five (U+2174)
144
- "\u2174": "V",
145
- // Small Roman Numeral Six (U+2175)
146
- "\u2175": "VI",
147
- // Small Roman Numeral Seven (U+2176)
148
- "\u2176": "VII",
149
- // Small Roman Numeral Eight (U+2177)
150
- "\u2177": "VIII",
151
- // Small Roman Numeral Nine (U+2178)
152
- "\u2178": "IX",
153
- // Small Roman Numeral Ten (U+2179)
154
- "\u2179": "X",
155
- // Small Roman Numeral Eleven (U+217A)
156
- "\u217A": "XI",
157
- // Small Roman Numeral Twelve (U+217B)
158
- "\u217B": "XII",
159
- // Small Roman Numeral Fifty (U+217C)
160
- "\u217C": "L",
161
- // Small Roman Numeral One Hundred (U+217D)
162
- "\u217D": "C",
163
- // Small Roman Numeral Five Hundred (U+217E)
164
- "\u217E": "D",
165
- // Small Roman Numeral One Thousand (U+217F)
166
- "\u217F": "M"
98
+ /**
99
+ * Map of Unicode Roman numeral code points to their ASCII equivalents.
100
+ */
101
+ const romanNumeralUnicodeToAsciiMap = {
102
+ Ⅰ: "I",
103
+ Ⅱ: "II",
104
+ Ⅲ: "III",
105
+ Ⅳ: "IV",
106
+ Ⅴ: "V",
107
+ Ⅵ: "VI",
108
+ Ⅶ: "VII",
109
+ Ⅷ: "VIII",
110
+ Ⅸ: "IX",
111
+ Ⅹ: "X",
112
+ Ⅺ: "XI",
113
+ Ⅻ: "XII",
114
+ Ⅼ: "L",
115
+ Ⅽ: "C",
116
+ Ⅾ: "D",
117
+ Ⅿ: "M",
118
+ ⅰ: "I",
119
+ ⅱ: "II",
120
+ ⅲ: "III",
121
+ ⅳ: "IV",
122
+ ⅴ: "V",
123
+ ⅵ: "VI",
124
+ ⅶ: "VII",
125
+ ⅷ: "VIII",
126
+ ⅸ: "IX",
127
+ ⅹ: "X",
128
+ ⅺ: "XI",
129
+ ⅻ: "XII",
130
+ ⅼ: "L",
131
+ ⅽ: "C",
132
+ ⅾ: "D",
133
+ ⅿ: "M"
167
134
  };
168
- var romanNumeralUnicodeRegex = new RegExp(
169
- `(${Object.keys(romanNumeralUnicodeToAsciiMap).join("|")})`,
170
- "gi"
171
- );
172
- var romanNumeralRegex = /^(?=[MDCLXVI])(M{0,3})(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/i;
173
- var defaultOptions = {
174
- round: 3,
175
- allowTrailingInvalid: false,
176
- romanNumerals: false
135
+ /**
136
+ * Captures all Unicode Roman numeral code points.
137
+ */
138
+ const romanNumeralUnicodeRegex = /([ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫⅬⅭⅮⅯⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻⅼⅽⅾⅿ])/gi;
139
+ /**
140
+ * Captures a valid Roman numeral sequence.
141
+ *
142
+ * Capture groups:
143
+ *
144
+ * | # | Description | Example |
145
+ * | --- | --------------- | ------------------------ |
146
+ * | `0` | Entire string | "MCCXIV" from "MCCXIV" |
147
+ * | `1` | Thousands | "M" from "MCCXIV" |
148
+ * | `2` | Hundreds | "CC" from "MCCXIV" |
149
+ * | `3` | Tens | "X" from "MCCXIV" |
150
+ * | `4` | Ones | "IV" from "MCCXIV" |
151
+ *
152
+ * @example
153
+ *
154
+ * ```ts
155
+ * romanNumeralRegex.exec("M") // [ "M", "M", "", "", "" ]
156
+ * romanNumeralRegex.exec("XII") // [ "XII", "", "", "X", "II" ]
157
+ * romanNumeralRegex.exec("MCCXIV") // [ "MCCXIV", "M", "CC", "X", "IV" ]
158
+ * ```
159
+ */
160
+ const romanNumeralRegex = /^(?=[MDCLXVI])(M{0,3})(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/i;
161
+ /**
162
+ * Default options for {@link numericQuantity}.
163
+ */
164
+ const defaultOptions = {
165
+ round: 3,
166
+ allowTrailingInvalid: false,
167
+ romanNumerals: false,
168
+ bigIntOnOverflow: false,
169
+ decimalSeparator: "."
177
170
  };
178
171
 
179
- // src/parseRomanNumerals.ts
180
- var parseRomanNumerals = (romanNumerals) => {
181
- const normalized = `${romanNumerals}`.replace(
182
- romanNumeralUnicodeRegex,
183
- (_m, rn) => romanNumeralUnicodeToAsciiMap[rn]
184
- ).toUpperCase();
185
- const regexResult = romanNumeralRegex.exec(normalized);
186
- if (!regexResult) {
187
- return NaN;
188
- }
189
- const [, thousands, hundreds, tens, ones] = regexResult;
190
- return (romanNumeralValues[thousands] ?? 0) + (romanNumeralValues[hundreds] ?? 0) + (romanNumeralValues[tens] ?? 0) + (romanNumeralValues[ones] ?? 0);
172
+ //#endregion
173
+ //#region src/parseRomanNumerals.ts
174
+ /**
175
+ * Converts a string of Roman numerals to a number, like `parseInt`
176
+ * for Roman numerals. Uses modern, strict rules (only 1 to 3999).
177
+ *
178
+ * The string can include ASCII representations of Roman numerals
179
+ * or Unicode Roman numeral code points (`U+2160` through `U+217F`).
180
+ */
181
+ const parseRomanNumerals = (romanNumerals) => {
182
+ const normalized = `${romanNumerals}`.replace(romanNumeralUnicodeRegex, (_m, rn) => romanNumeralUnicodeToAsciiMap[rn]).toUpperCase();
183
+ const regexResult = romanNumeralRegex.exec(normalized);
184
+ if (!regexResult) return NaN;
185
+ const [, thousands, hundreds, tens, ones] = regexResult;
186
+ return (romanNumeralValues[thousands] ?? 0) + (romanNumeralValues[hundreds] ?? 0) + (romanNumeralValues[tens] ?? 0) + (romanNumeralValues[ones] ?? 0);
191
187
  };
192
188
 
193
- // src/numericQuantity.ts
194
- var spaceThenSlashRegex = /^\s*\//;
195
- var numericQuantity = (quantity, options = defaultOptions) => {
196
- if (typeof quantity === "number" || typeof quantity === "bigint") {
197
- return quantity;
198
- }
199
- let finalResult = NaN;
200
- const quantityAsString = `${quantity}`.replace(
201
- vulgarFractionsRegex,
202
- (_m, vf) => ` ${vulgarFractionToAsciiMap[vf]}`
203
- ).replace("\u2044", "/").trim();
204
- if (quantityAsString.length === 0) {
205
- return NaN;
206
- }
207
- const opts = {
208
- ...defaultOptions,
209
- ...options
210
- };
211
- const regexResult = (opts.allowTrailingInvalid ? numericRegexWithTrailingInvalid : numericRegex).exec(quantityAsString);
212
- if (!regexResult) {
213
- return opts.romanNumerals ? parseRomanNumerals(quantityAsString) : NaN;
214
- }
215
- const [, dash, ng1temp, ng2temp] = regexResult;
216
- const numberGroup1 = ng1temp.replace(/[,_]/g, "");
217
- const numberGroup2 = ng2temp == null ? void 0 : ng2temp.replace(/[,_]/g, "");
218
- if (!numberGroup1 && numberGroup2 && numberGroup2.startsWith(".")) {
219
- finalResult = 0;
220
- } else {
221
- finalResult = parseInt(numberGroup1);
222
- }
223
- if (!numberGroup2) {
224
- return dash ? finalResult * -1 : finalResult;
225
- }
226
- const roundingFactor = opts.round === false ? NaN : parseFloat(`1e${Math.floor(Math.max(0, opts.round))}`);
227
- if (numberGroup2.startsWith(".") || numberGroup2.startsWith("e") || numberGroup2.startsWith("E")) {
228
- const decimalValue = parseFloat(`${finalResult}${numberGroup2}`);
229
- finalResult = isNaN(roundingFactor) ? decimalValue : Math.round(decimalValue * roundingFactor) / roundingFactor;
230
- } else if (spaceThenSlashRegex.test(numberGroup2)) {
231
- const numerator = parseInt(numberGroup1);
232
- const denominator = parseInt(numberGroup2.replace("/", ""));
233
- finalResult = isNaN(roundingFactor) ? numerator / denominator : Math.round(numerator * roundingFactor / denominator) / roundingFactor;
234
- } else {
235
- const fractionArray = numberGroup2.split("/");
236
- const [numerator, denominator] = fractionArray.map((v) => parseInt(v));
237
- finalResult += isNaN(roundingFactor) ? numerator / denominator : Math.round(numerator * roundingFactor / denominator) / roundingFactor;
238
- }
239
- return dash ? finalResult * -1 : finalResult;
240
- };
241
- // Annotate the CommonJS export names for ESM import in node:
242
- 0 && (module.exports = {
243
- defaultOptions,
244
- numericQuantity,
245
- numericRegex,
246
- numericRegexWithTrailingInvalid,
247
- parseRomanNumerals,
248
- romanNumeralRegex,
249
- romanNumeralUnicodeRegex,
250
- romanNumeralUnicodeToAsciiMap,
251
- romanNumeralValues,
252
- vulgarFractionToAsciiMap,
253
- vulgarFractionsRegex
254
- });
189
+ //#endregion
190
+ //#region src/numericQuantity.ts
191
+ const spaceThenSlashRegex = /^\s*\//;
192
+ function numericQuantity(quantity, options = defaultOptions) {
193
+ if (typeof quantity === "number" || typeof quantity === "bigint") return quantity;
194
+ let finalResult = NaN;
195
+ const quantityAsString = `${quantity}`.replace(vulgarFractionsRegex, (_m, vf) => ` ${vulgarFractionToAsciiMap[vf]}`).replace("⁄", "/").trim();
196
+ if (quantityAsString.length === 0) return NaN;
197
+ const opts = {
198
+ ...defaultOptions,
199
+ ...options
200
+ };
201
+ let normalizedString = quantityAsString;
202
+ if (opts.decimalSeparator === ",") {
203
+ const commaCount = (quantityAsString.match(/,/g) || []).length;
204
+ if (commaCount === 1) normalizedString = quantityAsString.replaceAll(".", "_").replace(",", ".");
205
+ else if (commaCount > 1) {
206
+ if (!opts.allowTrailingInvalid) return NaN;
207
+ const firstCommaIndex = quantityAsString.indexOf(",");
208
+ const secondCommaIndex = quantityAsString.indexOf(",", firstCommaIndex + 1);
209
+ const beforeSecondComma = quantityAsString.substring(0, secondCommaIndex).replaceAll(".", "_").replace(",", ".");
210
+ const afterSecondComma = quantityAsString.substring(secondCommaIndex + 1);
211
+ normalizedString = opts.allowTrailingInvalid ? beforeSecondComma + "&" + afterSecondComma : beforeSecondComma;
212
+ } else normalizedString = quantityAsString.replaceAll(".", "_");
213
+ }
214
+ const regexResult = (opts.allowTrailingInvalid ? numericRegexWithTrailingInvalid : numericRegex).exec(normalizedString);
215
+ if (!regexResult) return opts.romanNumerals ? parseRomanNumerals(quantityAsString) : NaN;
216
+ const [, dash, ng1temp, ng2temp] = regexResult;
217
+ const numberGroup1 = ng1temp.replaceAll(",", "").replaceAll("_", "");
218
+ const numberGroup2 = ng2temp === null || ng2temp === void 0 ? void 0 : ng2temp.replaceAll(",", "").replaceAll("_", "");
219
+ if (!numberGroup1 && numberGroup2 && numberGroup2.startsWith(".")) finalResult = 0;
220
+ else {
221
+ if (opts.bigIntOnOverflow) {
222
+ const asBigInt = dash ? BigInt(`-${numberGroup1}`) : BigInt(numberGroup1);
223
+ if (asBigInt > BigInt(Number.MAX_SAFE_INTEGER) || asBigInt < BigInt(Number.MIN_SAFE_INTEGER)) return asBigInt;
224
+ }
225
+ finalResult = parseInt(numberGroup1);
226
+ }
227
+ if (!numberGroup2) return dash ? finalResult * -1 : finalResult;
228
+ const roundingFactor = opts.round === false ? NaN : parseFloat(`1e${Math.floor(Math.max(0, opts.round))}`);
229
+ if (numberGroup2.startsWith(".") || numberGroup2.startsWith("e") || numberGroup2.startsWith("E")) {
230
+ const decimalValue = parseFloat(`${finalResult}${numberGroup2}`);
231
+ finalResult = isNaN(roundingFactor) ? decimalValue : Math.round(decimalValue * roundingFactor) / roundingFactor;
232
+ } else if (spaceThenSlashRegex.test(numberGroup2)) {
233
+ const numerator = parseInt(numberGroup1);
234
+ const denominator = parseInt(numberGroup2.replace("/", ""));
235
+ finalResult = isNaN(roundingFactor) ? numerator / denominator : Math.round(numerator * roundingFactor / denominator) / roundingFactor;
236
+ } else {
237
+ const fractionArray = numberGroup2.split("/");
238
+ const [numerator, denominator] = fractionArray.map((v) => parseInt(v));
239
+ finalResult += isNaN(roundingFactor) ? numerator / denominator : Math.round(numerator * roundingFactor / denominator) / roundingFactor;
240
+ }
241
+ return dash ? finalResult * -1 : finalResult;
242
+ }
243
+
244
+ //#endregion
245
+ exports.defaultOptions = defaultOptions;
246
+ exports.numericQuantity = numericQuantity;
247
+ exports.numericRegex = numericRegex;
248
+ exports.numericRegexWithTrailingInvalid = numericRegexWithTrailingInvalid;
249
+ exports.parseRomanNumerals = parseRomanNumerals;
250
+ exports.romanNumeralRegex = romanNumeralRegex;
251
+ exports.romanNumeralUnicodeRegex = romanNumeralUnicodeRegex;
252
+ exports.romanNumeralUnicodeToAsciiMap = romanNumeralUnicodeToAsciiMap;
253
+ exports.romanNumeralValues = romanNumeralValues;
254
+ exports.vulgarFractionToAsciiMap = vulgarFractionToAsciiMap;
255
+ exports.vulgarFractionsRegex = vulgarFractionsRegex;
255
256
  //# sourceMappingURL=numeric-quantity.cjs.development.js.map