@fable-org/fable-library-ts 1.10.0 → 2.0.0-beta.2
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/Array.ts +1378 -1378
- package/Async.ts +13 -14
- package/BigInt.ts +48 -22
- package/CHANGELOG.md +18 -1
- package/Choice.ts +301 -301
- package/Date.ts +47 -41
- package/Decimal.ts +29 -1
- package/FSharp.Collections.ts +34 -34
- package/FSharp.Core.CompilerServices.ts +37 -37
- package/FSharp.Core.ts +184 -184
- package/Global.ts +37 -37
- package/List.ts +1417 -1417
- package/Map.ts +1552 -1552
- package/MapUtil.ts +3 -0
- package/MutableMap.ts +345 -345
- package/MutableSet.ts +249 -249
- package/Native.ts +11 -11
- package/Numeric.ts +8 -3
- package/Random.ts +181 -181
- package/Range.ts +56 -56
- package/Result.ts +196 -196
- package/Seq.ts +1525 -1525
- package/Seq2.ts +129 -129
- package/Set.ts +1955 -1955
- package/String.ts +81 -10
- package/System.Collections.Generic.ts +380 -380
- package/System.Text.ts +203 -203
- package/Types.ts +1 -1
- package/package.json +1 -1
package/String.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toString as dateToString } from "./Date.js";
|
|
2
|
-
import { compare as numericCompare, isNumeric, multiply, Numeric, toExponential, toFixed, toHex, toPrecision } from "./Numeric.js";
|
|
2
|
+
import { compare as numericCompare, isNumeric, isIntegral, multiply, Numeric, toExponential, toFixed, toHex, toPrecision } from "./Numeric.js";
|
|
3
3
|
import { escape } from "./RegExp.js";
|
|
4
4
|
import { toString } from "./Types.js";
|
|
5
5
|
|
|
@@ -295,6 +295,19 @@ export function fsFormat(str: string) {
|
|
|
295
295
|
};
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
function splitIntAndDecimalPart(value: string) {
|
|
299
|
+
let [repInt, repDecimal] = value.split(".");
|
|
300
|
+
repDecimal === undefined && (repDecimal = "");
|
|
301
|
+
return {
|
|
302
|
+
integral: repInt,
|
|
303
|
+
decimal: repDecimal
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function thousandSeparate(value: string) {
|
|
308
|
+
return value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
309
|
+
}
|
|
310
|
+
|
|
298
311
|
export function format(str: string | object, ...args: any[]) {
|
|
299
312
|
let str2: string;
|
|
300
313
|
if (typeof str === "object") {
|
|
@@ -310,31 +323,89 @@ export function format(str: string | object, ...args: any[]) {
|
|
|
310
323
|
throw new Error("Index must be greater or equal to zero and less than the arguments' length.")
|
|
311
324
|
}
|
|
312
325
|
let rep = args[idx];
|
|
326
|
+
let parts;
|
|
313
327
|
if (isNumeric(rep)) {
|
|
314
|
-
precision = precision ==
|
|
328
|
+
precision = precision == "" ? null : parseInt(precision, 10);
|
|
315
329
|
switch (format) {
|
|
330
|
+
case "b": case "B":
|
|
331
|
+
if (!isIntegral(rep)) {
|
|
332
|
+
throw new Error("Format specifier was invalid.");
|
|
333
|
+
}
|
|
334
|
+
rep = (rep >>> 0).toString(2).replace(/^0+/, "").padStart(precision || 1, "0");
|
|
335
|
+
break;
|
|
336
|
+
case "c": case "C":
|
|
337
|
+
const isNegative = isLessThan(rep, 0);
|
|
338
|
+
if (isLessThan(rep, 0)) {
|
|
339
|
+
rep = multiply(rep, -1);
|
|
340
|
+
}
|
|
341
|
+
precision = precision == null ? 2 : precision;
|
|
342
|
+
rep = toFixed(rep, precision);
|
|
343
|
+
parts = splitIntAndDecimalPart(rep);
|
|
344
|
+
rep = "¤" + thousandSeparate(parts.integral) + "." + padRight(parts.decimal, precision, "0");
|
|
345
|
+
if (isNegative) {
|
|
346
|
+
rep = "(" + rep + ")";
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
case "d": case "D":
|
|
350
|
+
if (!isIntegral(rep)) {
|
|
351
|
+
throw new Error("Format specifier was invalid.");
|
|
352
|
+
}
|
|
353
|
+
rep = String(rep);
|
|
354
|
+
if (precision != null) {
|
|
355
|
+
if (rep.startsWith("-")) {
|
|
356
|
+
rep = "-" + padLeft(rep.substring(1), precision, "0");
|
|
357
|
+
} else {
|
|
358
|
+
rep = padLeft(rep, precision, "0");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
case "e": case "E":
|
|
363
|
+
rep = precision != null ? toExponential(rep, precision) : toExponential(rep);
|
|
364
|
+
break;
|
|
316
365
|
case "f": case "F":
|
|
317
366
|
precision = precision != null ? precision : 2;
|
|
318
367
|
rep = toFixed(rep, precision);
|
|
368
|
+
if (precision > 0) {
|
|
369
|
+
parts = splitIntAndDecimalPart(rep);
|
|
370
|
+
rep = parts.integral + "." + padRight(parts.decimal, precision, "0");
|
|
371
|
+
}
|
|
319
372
|
break;
|
|
320
373
|
case "g": case "G":
|
|
321
374
|
rep = precision != null ? toPrecision(rep, precision) : toPrecision(rep);
|
|
375
|
+
// TODO: Check why some numbers are formatted with decimal part
|
|
376
|
+
rep = trimEnd(trimEnd(rep, "0"), ".");
|
|
322
377
|
break;
|
|
323
|
-
case "
|
|
324
|
-
|
|
378
|
+
case "n": case "N":
|
|
379
|
+
precision = precision != null ? precision : 2;
|
|
380
|
+
rep = toFixed(rep, precision);
|
|
381
|
+
parts = splitIntAndDecimalPart(rep);
|
|
382
|
+
rep = thousandSeparate(parts.integral) + "." + padRight(parts.decimal, precision, "0");
|
|
325
383
|
break;
|
|
326
384
|
case "p": case "P":
|
|
327
385
|
precision = precision != null ? precision : 2;
|
|
328
|
-
rep = toFixed(multiply(rep, 100), precision)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
rep = precision != null ? padLeft(String(rep), precision, "0") : String(rep);
|
|
386
|
+
rep = toFixed(multiply(rep, 100), precision)
|
|
387
|
+
parts = splitIntAndDecimalPart(rep);
|
|
388
|
+
rep = thousandSeparate(parts.integral) + "." + padRight(parts.decimal, precision, "0") + " %";
|
|
332
389
|
break;
|
|
390
|
+
case "r": case "R":
|
|
391
|
+
throw new Error("The round-trip format is not supported by Fable");
|
|
333
392
|
case "x": case "X":
|
|
334
|
-
|
|
335
|
-
|
|
393
|
+
if (!isIntegral(rep)) {
|
|
394
|
+
throw new Error("Format specifier was invalid.");
|
|
395
|
+
}
|
|
396
|
+
precision = precision != null ? precision : 2;
|
|
397
|
+
rep = padLeft(toHex(rep), precision, "0");
|
|
398
|
+
if (format === "X") {
|
|
399
|
+
rep = rep.toUpperCase();
|
|
400
|
+
}
|
|
336
401
|
break;
|
|
337
402
|
default:
|
|
403
|
+
// If we have format and were not able to handle it throw
|
|
404
|
+
// See: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#standard-format-specifiers
|
|
405
|
+
if (format) {
|
|
406
|
+
throw new Error("Format specifier was invalid.");
|
|
407
|
+
}
|
|
408
|
+
|
|
338
409
|
if (pattern) {
|
|
339
410
|
let sign = "";
|
|
340
411
|
rep = (pattern as string).replace(/([0#,]+)(\.[0#]+)?/, (_, intPart: string, decimalPart: string) => {
|