UNPKG

4.61 kBJavaScriptView Raw
1import exponent from "./exponent";
2import formatGroup from "./formatGroup";
3import formatSpecifier from "./formatSpecifier";
4import formatTypes from "./formatTypes";
5import {prefixExponent} from "./formatPrefixAuto";
6
7var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
8
9function identity(x) {
10 return x;
11}
12
13export default function(locale) {
14 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
15 currency = locale.currency,
16 decimal = locale.decimal;
17
18 function format(specifier) {
19 specifier = formatSpecifier(specifier);
20
21 var fill = specifier.fill,
22 align = specifier.align,
23 sign = specifier.sign,
24 symbol = specifier.symbol,
25 zero = specifier.zero,
26 width = specifier.width,
27 comma = specifier.comma,
28 precision = specifier.precision,
29 type = specifier.type;
30
31 // Compute the prefix and suffix.
32 // For SI-prefix, the suffix is lazily computed.
33 var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
34 suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
35
36 // What format function should we use?
37 // Is this an integer type?
38 // Can this type generate exponential notation?
39 var formatType = formatTypes[type],
40 maybeSuffix = !type || /[defgprs%]/.test(type);
41
42 // Set the default precision if not specified,
43 // or clamp the specified precision to the supported range.
44 // For significant precision, it must be in [1, 21].
45 // For fixed precision, it must be in [0, 20].
46 precision = precision == null ? (type ? 6 : 12)
47 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
48 : Math.max(0, Math.min(20, precision));
49
50 return function(value) {
51 var valuePrefix = prefix,
52 valueSuffix = suffix;
53
54 if (type === "c") {
55 valueSuffix = formatType(value) + valueSuffix;
56 value = "";
57 } else {
58 value = +value;
59
60 // Convert negative to positive, and compute the prefix.
61 // Note that -0 is not less than 0, but 1 / -0 is!
62 var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
63
64 // Perform the initial formatting.
65 value = formatType(value, precision);
66
67 // Compute the prefix and suffix.
68 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
69 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
70
71 // Break the formatted value into the integer “value” part that can be
72 // grouped, and fractional or exponential “suffix” part that is not.
73 if (maybeSuffix) {
74 var i = -1, n = value.length, c;
75 while (++i < n) {
76 if (c = value.charCodeAt(i), 48 > c || c > 57) {
77 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
78 value = value.slice(0, i);
79 break;
80 }
81 }
82 }
83 }
84
85 // If the fill character is not "0", grouping is applied before padding.
86 if (comma && !zero) value = group(value, Infinity);
87
88 // Compute the padding.
89 var length = valuePrefix.length + value.length + valueSuffix.length,
90 padding = length < width ? new Array(width - length + 1).join(fill) : "";
91
92 // If the fill character is "0", grouping is applied after padding.
93 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
94
95 // Reconstruct the final output based on the desired alignment.
96 switch (align) {
97 case "<": return valuePrefix + value + valueSuffix + padding;
98 case "=": return valuePrefix + padding + value + valueSuffix;
99 case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
100 }
101 return padding + valuePrefix + value + valueSuffix;
102 };
103 }
104
105 function formatPrefix(specifier, value) {
106 var f = format((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
107 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
108 k = Math.pow(10, -e),
109 prefix = prefixes[8 + e / 3];
110 return function(value) {
111 return f(k * value) + prefix;
112 };
113 }
114
115 return {
116 format: format,
117 formatPrefix: formatPrefix
118 };
119};