forked from d3/d3-format
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit dacab59
Showing
14 changed files
with
598 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*.sublime-workspace | ||
.DS_Store | ||
build/ | ||
node_modules | ||
npm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
index.sublime-workspace | ||
index.sublime-project | ||
test/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Copyright 2010-2015 Mike Bostock | ||
Copyright 2001 Robert Penner | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without modification, | ||
are permitted provided that the following conditions are met: | ||
|
||
* Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
* Neither the name of the author nor the names of contributors may be used to | ||
endorse or promote products derived from this software without specific prior | ||
written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# d3-format | ||
|
||
Number formatting is one of those things you don’t normally think about until an ugly 0.30000000000000004 appears on your axis labels. Maybe you want to group thousands and use fixed precision, such as $1,240.10. Or maybe you want to display only the significant digits of a particular number. | ||
|
||
Formatting numbers for humans is the purpose of the d3-format module. For example, to create a function that zero-fills to four digits, say: | ||
|
||
```javascript | ||
var zeroPad = format("04d"); | ||
``` | ||
|
||
Now you can conveniently format numbers: | ||
|
||
```javascript | ||
zeroPad(2); // "0002" | ||
zeroPad(123); // "0123" | ||
``` | ||
|
||
<a name="format" href="#format">#</a> <b>format</b>(<i>specifier</i>[, <i>locale</i>]) | ||
|
||
Returns a new format function with the given string *specifier*. TODO Document optional *locale* argument, which defaults to U.S. English if not present. | ||
|
||
The returned function takes a number as the only argument, and returns a string representing the formatted number. The format specifier is modeled after Python 3.1’s [format specification mini-language](http://docs.python.org/release/3.1.3/library/string.html#formatspec). The general form of a specifier is: | ||
|
||
``` | ||
[[fill]align][sign][symbol][0][width][,][.precision][type] | ||
``` | ||
|
||
The *fill* can be any character other than `"{"` or `"}"`. The presence of a fill character is signaled by the character following it, which must be one of the *align* options. | ||
|
||
The *align* can be: | ||
|
||
* (`"<"`) Forces the field to be left-aligned within the available space. | ||
* (`">"`) Forces the field to be right-aligned within the available space. (This is the default). | ||
* (`"^"`) Forces the field to be centered within the available space. | ||
|
||
The *sign* can be: | ||
|
||
* plus (`"+"`) - a sign should be used for both positive and negative numbers. | ||
* minus (`"-"`) - a sign should be used only for negative numbers. (This is the default.) | ||
* space (`" "`) - a leading space should be used on positive numbers, and a minus sign on negative numbers. | ||
|
||
The *symbol* can be: | ||
|
||
* currency (`"$"`) - a currency symbol should be prefixed (or suffixed) per the locale. | ||
* base (`"#"`) - for binary, octal, or hexadecimal output, prefix by `"0b"`, `"0o"`, or `"0x"`, respectively. | ||
|
||
The `"0"` option enables zero-padding. | ||
|
||
The *width* defines the minimum field width. If not specified, then the width will be determined by the content. | ||
|
||
The *comma* (`","`) option enables the use of a comma for a thousands separator. | ||
|
||
The *precision* indicates how many digits should be displayed after the decimal point for a value formatted with types `"f"` and `"%"`, or before and after the decimal point for a value formatted with types `"g"`, `"r"` and `"p"`. | ||
|
||
The available *type* values are: | ||
|
||
* exponent (`"e"`) - use [Number.toExponential](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toExponential). | ||
* general (`"g"`) - use [Number.toPrecision](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toPrecision). | ||
* fixed (`"f"`) - use [Number.toFixed](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toFixed). | ||
* integer (`"d"`) - use [Number.toString](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toString), but ignore any non-integer values. | ||
* rounded (`"r"`) - round to *precision* significant digits, padding with zeroes where necessary in similar fashion to fixed (`"f"`). If no *precision* is specified, falls back to general notation. | ||
* percentage (`"%") - `like fixed, but multiply by 100 and suffix with "%". | ||
* rounded percentage (`"p"`) - like rounded, but multiply by 100 and suffix with "%". | ||
* binary (`"b"`) - outputs the number in base 2. | ||
* octal (`"o"`) - outputs the number in base 8. | ||
* hexadecimal (`"x"`) - outputs the number in base 16, using lower-case letters for the digits above 9. | ||
* hexadecimal (`"X"`) - outputs the number in base 16, using upper-case letters for the digits above 9. | ||
* character (`"c"`) - converts the integer to the corresponding unicode character before printing. | ||
* SI-prefix (`"s"`) - like rounded, but with a unit suffixed such as `"9.5M"` for mega, or `"1.00µ"` for micro. | ||
|
||
The type `"n"` is also supported as shorthand for `",g"`. | ||
|
||
<a name="formatPrefix" href="#formatPrefix">#</a> <b>formatPrefix</b>(<i>value</i>[, <i>precision</i>]) | ||
|
||
Returns the [SI prefix](https://en.wikipedia.org/wiki/Metric_prefix) for the specified *value*. If an optional *precision* is specified, the *value* is rounded accordingly using [round](#round) before computing the prefix. The returned prefix object has two properties: | ||
|
||
* symbol - the prefix symbol, such as `"M"` for millions. | ||
* scale - the scale function, for converting numbers to the appropriate prefixed scale. | ||
|
||
For example: | ||
|
||
```js | ||
var prefix = formatPrefix(1.21e9); | ||
console.log(prefix.symbol); // "G" | ||
console.log(prefix.scale(1.21e9)); // 1.21 | ||
``` | ||
|
||
This method is used by [format](#format) for the `"s"` format type. | ||
|
||
<a name="round" href="#round">#</a> <b>round</b>(<i>x</i>[, <i>n</i>]) | ||
|
||
Returns the value *x* rounded to *n* digits after the decimal point. If *n* is omitted, it defaults to zero. The result is a number. Values are rounded to the closest multiple of 10 to the power minus *n*; if two multiples are equally close, the value is rounded up in accordance with the built-in [Math.round](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Math/round]) function. For example: | ||
|
||
```js | ||
round(1.23); // 1 | ||
round(1.23, 1); // 1.2 | ||
round(1.25, 1); // 1.3 | ||
round(12.5, 0); // 13 | ||
round(12, -1); // 10 | ||
``` | ||
|
||
Note that the resulting number when converted to a string may be imprecise due to IEEE floating point precision; to format a number to a string with a fixed number of decimal points, use [format](#format) instead. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"folders": [ | ||
{ | ||
"path": ".", | ||
"file_exclude_patterns": [ | ||
"*.sublime-workspace" | ||
], | ||
"folder_exclude_patterns": [ | ||
"build" | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import format from "./src/format"; | ||
import formatPrefix from "./src/formatPrefix"; | ||
import formatPrecision from "./src/formatPrecision"; | ||
import round from "./src/round"; | ||
|
||
export { | ||
format, | ||
formatPrefix, | ||
formatPrecision, | ||
round | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "d3-format", | ||
"version": "0.0.1", | ||
"description": "Format numbers for humans.", | ||
"keywords": [ | ||
"d3", | ||
"format" | ||
], | ||
"homepage": "https://github.com/d3/d3-format", | ||
"license": "BSD-3-Clause", | ||
"author": { | ||
"name": "Mike Bostock", | ||
"url": "http://bost.ocks.org/mike" | ||
}, | ||
"main": "build/format", | ||
"jsnext:main": "index", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/d3/d3-format.git" | ||
}, | ||
"scripts": { | ||
"pretest": "mkdir -p build && d3-bundler --format=umd --name=format -- index.js > build/format.js", | ||
"test": "faucet `find test -name '*-test.js'`", | ||
"prepublish": "npm run test && uglifyjs build/format.js -c -m -o build/format.min.js" | ||
}, | ||
"devDependencies": { | ||
"d3-bundler": "~0.2.5", | ||
"faucet": "0.0", | ||
"tape": "4", | ||
"uglifyjs": "2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import formatPrefix from "./formatPrefix"; | ||
import formatPrecision from "./formatPrecision"; | ||
import round from "./round"; | ||
|
||
var enUS = { | ||
decimal: ".", | ||
thousands: ",", | ||
grouping: [3], | ||
currency: ["$", ""] | ||
}; | ||
|
||
// [[fill]align][sign][symbol][0][width][,][.precision][type] | ||
var formatRe = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; | ||
|
||
var formatTypes = { | ||
b: function(x) { return x.toString(2); }, | ||
c: function(x) { return String.fromCharCode(x); }, | ||
o: function(x) { return x.toString(8); }, | ||
x: function(x) { return x.toString(16); }, | ||
X: function(x) { return x.toString(16).toUpperCase(); }, | ||
g: function(x, p) { return x.toPrecision(p); }, | ||
e: function(x, p) { return x.toExponential(p); }, | ||
f: function(x, p) { return x.toFixed(p); }, | ||
r: function(x, p) { return (x = round(x, formatPrecision(x, p))).toFixed(Math.max(0, Math.min(20, formatPrecision(x * (1 + 1e-15), p)))); } | ||
}; | ||
|
||
function stringOf(x) { | ||
return x + ""; | ||
} | ||
|
||
function identity(x) { | ||
return x; | ||
} | ||
|
||
function formatGroup(grouping, thousands) { | ||
return function(value, width) { | ||
var i = value.length, | ||
t = [], | ||
j = 0, | ||
g = grouping[0], | ||
length = 0; | ||
|
||
while (i > 0 && g > 0) { | ||
if (length + g + 1 > width) g = Math.max(1, width - length); | ||
t.push(value.substring(i -= g, i + g)); | ||
if ((length += g + 1) > width) break; | ||
g = grouping[j = (j + 1) % grouping.length]; | ||
} | ||
|
||
return t.reverse().join(thousands); | ||
}; | ||
} | ||
|
||
export default function(specifier, locale) { | ||
if (!locale) locale = enUS; | ||
|
||
var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity, | ||
match = formatRe.exec(specifier), | ||
fill = match[1] || " ", | ||
align = match[2] || ">", | ||
sign = match[3] || "-", | ||
symbol = match[4] || "", | ||
zfill = match[5], | ||
width = +match[6], | ||
comma = match[7], | ||
precision = match[8], | ||
type = match[9], | ||
scale = 1, | ||
prefix = "", | ||
suffix = "", | ||
integer = false, | ||
exponent = true; | ||
|
||
if (precision) precision = +precision.substring(1); | ||
|
||
if (zfill || fill === "0" && align === "=") { | ||
zfill = fill = "0"; | ||
align = "="; | ||
} | ||
|
||
switch (type) { | ||
case "n": comma = true; type = "g"; break; | ||
case "%": scale = 100; suffix = "%"; type = "f"; break; | ||
case "p": scale = 100; suffix = "%"; type = "r"; break; | ||
case "b": | ||
case "o": | ||
case "x": | ||
case "X": if (symbol === "#") prefix = "0" + type.toLowerCase(); | ||
case "c": exponent = false; | ||
case "d": integer = true; precision = 0; break; | ||
case "s": scale = -1; type = "r"; break; | ||
} | ||
|
||
if (symbol === "$") prefix = locale.currency[0], suffix = locale.currency[1]; | ||
|
||
// If no precision is specified for r, fallback to general notation. | ||
if (type == "r" && !precision) type = "g"; | ||
|
||
// Ensure that the requested precision is in the supported range. | ||
if (precision != null) { | ||
if (type == "g") precision = Math.max(1, Math.min(21, precision)); | ||
else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); | ||
} | ||
|
||
type = formatTypes[type] || stringOf; | ||
|
||
var zcomma = zfill && comma; | ||
|
||
return function(value) { | ||
|
||
// Return the empty string for floats formatted as ints. | ||
if (integer && (value % 1)) return ""; | ||
|
||
// Convert negative to positive, and record the sign prefix. | ||
var valueSign = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign, | ||
valueSuffix = suffix; | ||
|
||
// Apply the scale, computing it from the value’s exponent for si format. | ||
// Preserve the existing suffix, if any, such as the currency symbol. | ||
if (scale < 0) { | ||
var valuePrefix = formatPrefix(value, precision); | ||
value = valuePrefix.scale(value); | ||
valueSuffix = valuePrefix.symbol + suffix; | ||
} else { | ||
value *= scale; | ||
} | ||
|
||
// Convert to the desired precision. | ||
value = type(value, precision); | ||
|
||
// Break the value into the integer part (before) and decimal part (after). | ||
var i = value.lastIndexOf("."), | ||
before, | ||
after; | ||
|
||
// If there is no decimal, break on "e" where appropriate. | ||
if (i < 0) { | ||
var j = exponent ? value.lastIndexOf("e") : -1; | ||
if (j < 0) before = value, after = ""; | ||
else before = value.substring(0, j), after = value.substring(j); | ||
} else { | ||
before = value.substring(0, i); | ||
after = locale.decimal + value.substring(i + 1); | ||
} | ||
|
||
// If the fill character is not "0", grouping is applied before padding. | ||
if (!zfill && comma) before = group(before, Infinity); | ||
|
||
var length = prefix.length + before.length + after.length + (zcomma ? 0 : valueSign.length), | ||
padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; | ||
|
||
// If the fill character is "0", grouping is applied after padding. | ||
if (zcomma) before = group(padding + before, padding.length ? width - after.length : Infinity); | ||
|
||
// Apply prefix. | ||
valueSign += prefix; | ||
|
||
// Rejoin integer and decimal parts. | ||
value = before + after; | ||
|
||
return (align === "<" ? valueSign + value + padding | ||
: align === ">" ? padding + valueSign + value | ||
: align === "^" ? padding.substring(0, length >>= 1) + valueSign + value + padding.substring(length) | ||
: valueSign + (zcomma ? value : padding + value)) + valueSuffix; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function(x, p) { | ||
return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import formatPrecision from "./formatPrecision"; | ||
import round from "./round"; | ||
|
||
var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(function(d, i) { | ||
var k = Math.pow(10, Math.abs(8 - i) * 3); | ||
return { | ||
scale: i > 8 ? function(d) { return d / k; } : function(d) { return d * k; }, | ||
symbol: d | ||
}; | ||
}); | ||
|
||
export default function(value, precision) { | ||
var i = 0; | ||
if (value = +value) { | ||
if (value < 0) value *= -1; | ||
if (precision) value = round(value, formatPrecision(value, precision)); | ||
i = Math.max(-24, Math.min(24, Math.floor((1e-12 + Math.log(value)) / (Math.LN10 * 3)) * 3)); | ||
} | ||
return prefixes[8 + i / 3]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export default function(x, n) { | ||
return n | ||
? Math.round(x * (n = Math.pow(10, n))) / n | ||
: Math.round(x); | ||
}; |
Oops, something went wrong.