UNPKG

4.96 kBJavaScriptView Raw
1import exponent from "./exponent";
2import formatGroup from "./formatGroup";
3import formatNumerals from "./formatNumerals";
4import formatSpecifier from "./formatSpecifier";
5import formatTypes from "./formatTypes";
6import {prefixExponent} from "./formatPrefixAuto";
7import identity from "./identity";
8
9var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
10
11export default function(locale) {
12 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
13 currency = locale.currency,
14 decimal = locale.decimal,
15 numerals = locale.numerals ? formatNumerals(locale.numerals) : identity,
16 percent = locale.percent || "%";
17
18 function newFormat(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) ? percent : "";
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 function format(value) {
51 var valuePrefix = prefix,
52 valueSuffix = suffix,
53 i, n, c;
54
55 if (type === "c") {
56 valueSuffix = formatType(value) + valueSuffix;
57 value = "";
58 } else {
59 value = +value;
60
61 // Perform the initial formatting.
62 var valueNegative = value < 0;
63 value = formatType(Math.abs(value), precision);
64
65 // If a negative value rounds to zero during formatting, treat as positive.
66 if (valueNegative && +value === 0) valueNegative = false;
67
68 // Compute the prefix and suffix.
69 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
70 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
71
72 // Break the formatted value into the integer “value” part that can be
73 // grouped, and fractional or exponential “suffix” part that is not.
74 if (maybeSuffix) {
75 i = -1, n = value.length;
76 while (++i < n) {
77 if (c = value.charCodeAt(i), 48 > c || c > 57) {
78 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
79 value = value.slice(0, i);
80 break;
81 }
82 }
83 }
84 }
85
86 // If the fill character is not "0", grouping is applied before padding.
87 if (comma && !zero) value = group(value, Infinity);
88
89 // Compute the padding.
90 var length = valuePrefix.length + value.length + valueSuffix.length,
91 padding = length < width ? new Array(width - length + 1).join(fill) : "";
92
93 // If the fill character is "0", grouping is applied after padding.
94 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
95
96 // Reconstruct the final output based on the desired alignment.
97 switch (align) {
98 case "<": value = valuePrefix + value + valueSuffix + padding; break;
99 case "=": value = valuePrefix + padding + value + valueSuffix; break;
100 case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
101 default: value = padding + valuePrefix + value + valueSuffix; break;
102 }
103
104 return numerals(value);
105 }
106
107 format.toString = function() {
108 return specifier + "";
109 };
110
111 return format;
112 }
113
114 function formatPrefix(specifier, value) {
115 var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
116 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
117 k = Math.pow(10, -e),
118 prefix = prefixes[8 + e / 3];
119 return function(value) {
120 return f(k * value) + prefix;
121 };
122 }
123
124 return {
125 format: newFormat,
126 formatPrefix: formatPrefix
127 };
128}